49#define GD_cc_subg(g) (((graphinfo_t*)(g->base.data))->cc_subg)
50#define Node_mark(n) (((nodeinfo_t*)(n->base.data))->mark)
51#define ND_ptr(n) (((nodeinfo_t*)(n->base.data))->ptr)
52#define ND_dn(n) ((Agnode_t*)ND_ptr(n))
53#define Node_clust(n) ((Agraph_t*)ND_ptr(n))
83 "Usage: ccomps [-svenCx?] [-X[#%]s[-f]] [-o<out template>] <files>\n\
86 -X - extract component\n\
88 -e - do not induce edges\n\
89 -n - do not induce subgraphs\n\
91 -o - output file template\n\
92 -z - sort by size, largest first\n\
94If no files are specified, stdin is used\n";
108 size_t size = (size_t)(sfx -
outfile);
115static void init(
int argc,
char *argv[])
121 while ((c = getopt(argc, argv,
":zo:xCX:nesv?")) != -1) {
143 if (*optarg ==
'#' || *optarg ==
'%') {
144 char *p = optarg + 1;
148 x_index = (int)strtol (p, &endp, 10);
157 "ccomps: final index %d < start index %d in -X%s flag - ignored\n",
164 "ccomps: number expected in -X%s flag - ignored\n",
172 "ccomps: number expected in -X%s flag - ignored\n",
187 "ccomps: option -%c missing argument - ignored\n", optopt);
190 if (optopt ==
'\0' || optopt ==
'?')
194 "ccomps: option -%c unrecognized\n", optopt);
228 node_stack_push_back(&
Stk, np);
233 if (node_stack_is_empty(&
Stk)) {
236 return node_stack_pop_back(&
Stk);
246 while ((n =
pop())) {
251 if ((other =
agtail(e)) == n)
287 outf = fopen(name,
"w");
289 fprintf(stderr,
"Could not open %s for writing\n", name);
320 if (!proj && inCluster) {
345 if ((proj =
projectG(subg, g, inCluster))) {
359#define PFX2 "%s_cc_%ld"
379 fprintf (stderr,
"Error: node \"%s\" belongs to two non-nested clusters \"%s\" and \"%s\"\n",
452static int cmp(
const void *x,
const void *y) {
457#pragma GCC diagnostic push
458#pragma GCC diagnostic ignored "-Wcast-qual"
463#pragma GCC diagnostic pop
494 "ccomps: component %d not found in graph %s - ignored\n",
501 if (endi >= c_cnt) endi = c_cnt-1;
515 for (i = 0; i < c_cnt ; i++) {
526 else for (i = 0; i < c_cnt; i++) {
546 bool extracted =
false;
553 fprintf(stderr,
"ccomps: node %s not found in graph %s\n",
561 dout =
agsubg(dg, name, 1);
568 n_cnt =
dfs(dg, dn, dout);
577 fprintf(stderr,
" %7ld nodes %7" PRISIZE_T " edges\n", n_cnt,
590 dout =
agsubg(dg, name, 1);
596 n_cnt =
dfs(dg, dn, dout);
630 fprintf(stderr,
"(%4ld) %7ld nodes %7" PRISIZE_T " edges\n",
631 c_cnt, n_cnt, e_cnt);
636 "ccomps: component %d not found in graph %s - ignored\n",
647 fprintf(stderr,
" %7d nodes %7d edges %7ld components %s\n",
652 return (c_cnt ? 1 : 0);
674 bool extracted =
false;
686 "ccomps: node %s not found in graph %s - ignored\n",
706 fprintf(stderr,
" %7ld nodes %7" PRISIZE_T " edges\n", n_cnt,
755 fprintf(stderr,
"(%4ld) %7ld nodes %7" PRISIZE_T " edges\n",
756 c_cnt, n_cnt, e_cnt);
761 "ccomps: component %d not found in graph %s - ignored\n",
772 fprintf(stderr,
" %7d nodes %7d edges %7ld components %s\n",
794 if (*
s !=
'%')
return s;
800int main(
int argc,
char *argv[])
813 node_stack_free(&
Stk);
static void out(agerrlevel_t level, const char *fmt, va_list args)
Report messages using a user-supplied or default write function.
static void agxbfree(agxbuf *xb)
free any malloced resources
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
static WUR char * agxbuse(agxbuf *xb)
static char * agxbdisown(agxbuf *xb)
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
abstract graph C library, Cgraph API
bool is_a_cluster(Agraph_t *g)
static NORETURN void graphviz_exit(int status)
static int cnt(Dict_t *d, Dtlink_t **set)
int agnedges(Agraph_t *g)
int agnnodes(Agraph_t *g)
size_t graphviz_node_induce(Agraph_t *g, Agraph_t *edgeset)
int agcopyattr(void *oldobj, void *newobj)
copies all of the attributes from one object to another
Agedge_t * agedge(Agraph_t *g, Agnode_t *t, Agnode_t *h, char *name, int createflag)
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Agedge_t * agnxtedge(Agraph_t *g, Agedge_t *e, Agnode_t *n)
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Agedge_t * agfstedge(Agraph_t *g, Agnode_t *n)
Agdesc_t Agstrictundirected
strict undirected
int agclose(Agraph_t *g)
deletes a graph, freeing its associated storage
Agraph_t * agopen(char *name, Agdesc_t desc, Agdisc_t *disc)
creates a new graph with the given name and kind
int agwrite(Agraph_t *g, void *chan)
Return 0 on success, EOF on failure.
Agnode_t * agnode(Agraph_t *g, char *name, int createflag)
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Agnode_t * agfstnode(Agraph_t *g)
Agnode_t * agsubnode(Agraph_t *g, Agnode_t *n, int createflag)
char * agnameof(void *)
returns a string descriptor for the object.
#define AGTYPE(obj)
returns AGRAPH, AGNODE, or AGEDGE depending on the type of the object
int agdelete(Agraph_t *g, void *obj)
deletes object. Equivalent to agclose, agdelnode, and agdeledge for obj being a graph,...
void aginit(Agraph_t *g, int kind, const char *rec_name, int rec_size, int move_to_front)
attach new records to objects of specified kind
void * agbindrec(void *obj, const char *name, unsigned int recsize, int move_to_front)
attaches a new record of the given size to the object
Agraph_t * agfstsubg(Agraph_t *g)
Agraph_t * agnxtsubg(Agraph_t *subg)
Agraph_t * agsubg(Agraph_t *g, char *name, int cflag)
replacements for ctype.h functions
static bool gv_isdigit(int c)
static const char * usage
Agraph_t * nextGraph(ingraph_state *sp)
ingraph_state * newIngraph(ingraph_state *sp, char **files)
supports user-supplied data
#define DEFINE_LIST(name, type)
#define PRISIZE_T
PRIu64 alike for printing size_t
a generic header of Agraph_s, Agnode_s and Agedge_s
implementation of Agrec_t
bool cc_subg
true iff subgraph corresponds to a component
a non-owning string reference
const char * data
start of the pointed to string
size_t size
extent of the string in bytes
Non-owning string references.
static strview_t strview(const char *referent, char terminator)
create a string reference