51#define GD_cc_subg(g) (((graphinfo_t *)(g->base.data))->cc_subg)
52#define Node_mark(n) (((nodeinfo_t *)(n->base.data))->mark)
53#define ND_ptr(n) (((nodeinfo_t *)(n->base.data))->ptr)
54#define ND_dn(n) ((Agnode_t *)ND_ptr(n))
55#define Node_clust(n) ((Agraph_t *)ND_ptr(n))
81 "Usage: ccomps [-svenCx?] [-X[#%]s[-f]] [-o<out template>] <files>\n\
84 -X - extract component\n\
86 -e - do not induce edges\n\
87 -n - do not induce subgraphs\n\
89 -o - output file template\n\
90 -z - sort by size, largest first\n\
92If no files are specified, stdin is used\n";
100 char *sfx = strrchr(
outfile,
'.');
103 size_t size = (size_t)(sfx -
outfile);
110static void init(
int argc,
char *argv[]) {
115 while ((c = getopt(argc, argv,
":zo:xCX:nesv?")) != -1) {
137 if (*optarg ==
'#' || *optarg ==
'%') {
138 char *p = optarg + 1;
144 x_index = (int)strtol(p, &endp, 10);
153 "ccomps: final index %d < start index %d in -X%s flag "
160 "ccomps: number expected in -X%s flag - ignored\n",
166 fprintf(stderr,
"ccomps: number expected in -X%s flag - ignored\n",
180 fprintf(stderr,
"ccomps: option -%c missing argument - ignored\n",
184 if (optopt ==
'\0' || optopt ==
'?')
187 fprintf(stderr,
"ccomps: option -%c unrecognized\n", optopt);
218 node_stack_push_back(&
Stk, np);
222 if (node_stack_is_empty(&
Stk)) {
225 return node_stack_pop_back(&
Stk);
233 while ((n =
pop())) {
238 if ((other =
agtail(e)) == n)
269 FILE *
const outf = fopen(name,
"w");
271 fprintf(stderr,
"Could not open %s for writing\n", name);
299 if (!proj && inCluster) {
320 if ((proj =
projectG(subg, g, inCluster))) {
330#define PFX2 "%s_cc_%" PRISIZE_T
345 "Error: node \"%s\" belongs to two non-nested clusters "
346 "\"%s\" and \"%s\"\n",
404static int cmp(
const void *x,
const void *y) {
409#pragma GCC diagnostic push
410#pragma GCC diagnostic ignored "-Wcast-qual"
415#pragma GCC diagnostic pop
443 "ccomps: component %d not found in graph %s - ignored\n",
457 for (i = (
size_t)
sortIndex; i <= endi; i++) {
466 for (i = 0; i < c_cnt; i++) {
479 for (i = 0; i < c_cnt; i++) {
492 bool extracted =
false;
499 fprintf(stderr,
"ccomps: node %s not found in graph %s\n",
x_node,
507 dout =
agsubg(dg, name, 1);
514 const long n_cnt =
dfs(dg, dn, dout);
523 fprintf(stderr,
" %7ld nodes %7" PRISIZE_T " edges\n", n_cnt, e_cnt);
535 dout =
agsubg(dg, name, 1);
541 const long n_cnt =
dfs(dg, dn, dout);
575 c_cnt, n_cnt, e_cnt);
579 fprintf(stderr,
"ccomps: component %d not found in graph %s - ignored\n",
591 " %7d nodes %7d edges %7" PRISIZE_T " components %s\n",
596 return c_cnt ? 1 : 0;
609 bool extracted =
false;
620 fprintf(stderr,
"ccomps: node %s not found in graph %s - ignored\n",
632 const long n_cnt =
dfs(g, n,
out);
640 fprintf(stderr,
" %7ld nodes %7" PRISIZE_T " edges\n", n_cnt, e_cnt);
656 const long n_cnt =
dfs(g, n,
out);
688 c_cnt, n_cnt, e_cnt);
692 fprintf(stderr,
"ccomps: component %d not found in graph %s - ignored\n",
704 " %7d nodes %7d edges %7" PRISIZE_T " components %s\n",
730int main(
int argc,
char *argv[]) {
742 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)
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