Agedge_t *findedge(Agnode_t *t, Agnode_t *h) { if (!t || !h) return NULL; if (AGTYPE(t) == AGRAPH || AGTYPE(h) == AGRAPH) return NULL; return agfindedge(agraphof(t), t, h); }
Agraph_t *graphof(Agedge_t *e) { if (!e) return NULL; if (AGTYPE(e) == AGRAPH) return (Agraph_t*)e; /* graph of protoedge is itself recast */ return agraphof(agtail(e)); }
Agsym_t *firstattr(Agnode_t *n) { Agraph_t *g; if (!n) return NULL; g = agraphof(n); return agnxtattr(g,AGNODE,NULL); }
Agsym_t *firstattr(Agedge_t *e) { Agraph_t *g; if (!e) return NULL; g = agraphof(agtail(e)); return agnxtattr(g,AGEDGE,NULL); }
Agedge_t *edge(Agnode_t *t, Agnode_t *h) { if (!gvc || !t || !h) return NULL; // edges from/to the protonode are not permitted if (AGTYPE(t) == AGRAPH || AGTYPE(h) == AGRAPH) return NULL; return agedge(agraphof(t), t, h, NULL, 1); }
/* cloneEdge: * Make a copy of e in e's graph but using ct and ch as nodes */ static edge_t *cloneEdge(edge_t * e, node_t * ct, node_t * ch) { graph_t *g = agraphof(ct); edge_t *ce = agedge(g, ct, ch,NULL,1); agbindrec(ce, "Agedgeinfo_t", sizeof(Agedgeinfo_t), TRUE); agcopyattr(e, ce); return ce; }
Agsym_t *nextattr(Agnode_t *n, Agsym_t *a) { Agraph_t *g; int i; if (!n || !a) return NULL; g = agraphof(n); return agnxtattr(g,AGNODE,a); }
/* copyAttr; * Copy attributes from src to tgt. Overrides currently * defined values. * FIX: we should probably use the default value of the source * graph when initializing the attribute, rather than "". * NOTE: We do not assume src and tgt have the same kind. */ int copyAttr(Agobj_t * src, Agobj_t * tgt) { Agraph_t *srcg; Agraph_t *tgtg; Agsym_t *sym = 0; Agsym_t *tsym = 0; int skind = AGTYPE(src); int tkind = AGTYPE(tgt); srcg = agraphof(src); tgtg = agraphof(tgt); while ((sym = agnxtattr(srcg, skind, sym))) { tsym = agattrsym(tgt, sym->name); if (!tsym) tsym = agattr(tgtg, tkind, sym->name, ""); agxset(tgt, tsym, agxget(src, sym)); } return 0; }
Agsym_t *nextattr(Agedge_t *e, Agsym_t *a) { Agraph_t *g; int i; if (!e || !a) return NULL; g = agraphof(agtail(e)); return agnxtattr(g,AGEDGE,a); }
bool rm(Agnode_t *n) { if (!n) return false; // removal of the protonode is not permitted if (agnameof(n)[0] == '\001' && strcmp (agnameof(n), "\001proto") ==0) return false; agdelete(agraphof(n), n); return true; }
/* sameG: * Return common root if objects belong to same root graph. * NULL otherwise */ Agraph_t *sameG(void *p1, void *p2, char *fn, char *msg) { Agobj_t *obj1 = OBJ(p1); Agobj_t *obj2 = OBJ(p2); Agraph_t *root; root = agroot(agraphof(obj1)); if (root != agroot(agraphof(obj2))) { if (msg) error(ERROR_WARNING, "%s in %s() belong to different graphs", msg, fn); else error(ERROR_WARNING, "%s and %s in %s() belong to different graphs", KINDS(obj1), KINDS(obj2), fn); return 0; } else return root; }
Agnode_t *firsttail(Agnode_t *n) { Agedge_t *e; if (!n) return NULL; e = agfstin(agraphof(n), n); if (!e) return NULL; return agtail(e); }
Agnode_t *firsthead(Agnode_t *n) { Agedge_t *e; if (!n) return NULL; e = agfstout(agraphof(n), n); if (!e) return NULL; return aghead(e); }
bool rm(Agedge_t *e) { if (!e) return false; // removal of the protoedge is not permitted if ((agnameof(aghead(e))[0] == '\001' && strcmp (agnameof(aghead(e)), "\001proto") == 0) || (agnameof(agtail(e))[0] == '\001' && strcmp (agnameof(agtail(e)), "\001proto") == 0)) return false; agdelete(agroot(agraphof(aghead(e))), e); return true; }
/*-------------------------------------------------------------------------*\ * Property: n.graph * Determines the graph to which of a node belongs. * Returns graph userdata. * Example: * rv = n.graph \*-------------------------------------------------------------------------*/ int gr_graphof(lua_State *L) { gr_node_t *ud = tonode(L, 1, STRICT); Agraph_t *g = agraphof(ud->n); if (g == NULL){ lua_pushnil(L); lua_pushstring(L, "no graph"); return 2; } return get_object(L, g); }
static void writenodeandport(FILE * f, node_t * node, char *port) { char *name; if (IS_CLUST_NODE(node)) name = canon (agraphof(node), strchr(agnameof(node), ':') + 1); else name = agcanonStr (agnameof(node)); printstring(f, " ", name); /* slimey i know */ if (port && *port) printstring(f, ":", agcanonStr(port)); }
static void dot_init_node(node_t * n) { agbindrec(n, "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); //graph custom data common_init_node(n); gv_nodesize(n, GD_flip(agraphof(n))); alloc_elist(4, ND_in(n)); alloc_elist(4, ND_out(n)); alloc_elist(2, ND_flat_in(n)); alloc_elist(2, ND_flat_out(n)); alloc_elist(2, ND_other(n)); ND_UF_size(n) = 1; }
char *getv(Agedge_t *e, char *attr) { Agraph_t *g; Agsym_t *a; if (!e || !attr) return NULL; if (AGTYPE(e) == AGRAPH) // protoedge return NULL; // FIXME ?? g = agraphof(agtail(e)); a = agattr(g, AGEDGE, attr, NULL); return myagxget(e, a); }
char *getv(Agnode_t *n, char *attr) { Agraph_t *g; Agsym_t *a; if (!n || !attr) return NULL; if (AGTYPE(n) == AGRAPH) // protonode return NULL; // FIXME ?? g = agroot(agraphof(n)); a = agattr(g, AGNODE, attr, NULL); return myagxget(n, a); }
static v_data *makeGraph(Agraph_t* gg, int *nedges) { int i; int ne = agnedges(gg); int nv = agnnodes(gg); v_data *graph = N_NEW(nv, v_data); int *edges = N_NEW(2 * ne + nv, int); /* reserve space for self loops */ float *ewgts = N_NEW(2 * ne + nv, float); Agnode_t *np; Agedge_t *ep; Agraph_t *g = NULL; int i_nedges; ne = 0; i=0; // for (i = 0; i < nv; i++) { for (np = agfstnode(gg); np; np = agnxtnode(gg, np)) { graph[i].edges = edges++; /* reserve space for the self loop */ graph[i].ewgts = ewgts++; #ifdef STYLES graph[i].styles = NULL; #endif i_nedges = 1; /* one for the self */ if (!g) g = agraphof(np); for (ep = agfstedge(g, np); ep; ep = agnxtedge(g, ep, np)) { Agnode_t *vp; Agnode_t *tp = agtail(ep); Agnode_t *hp = aghead(ep); assert(hp != tp); /* FIX: handle multiedges */ vp = (tp == np ? hp : tp); ne++; i_nedges++; // *edges++ = ((temp_node_record *) AGDATA(vp))->TVref; *edges++ = ND_TVref(vp); *ewgts++ = 1; } graph[i].nedges = i_nedges; graph[i].edges[0] = i; graph[i].ewgts[0] = 1 - i_nedges; i++; } ne /= 2; /* each edge counted twice */ *nedges = ne; return graph; }
static void myagxset(void *obj, Agsym_t *a, char *val) { int len; char *hs; if (a->name[0] == 'l' && val[0] == '<' && strcmp(a->name, "label") == 0) { len = strlen(val); if (val[len-1] == '>') { hs = strdup(val+1); *(hs+len-2) = '\0'; val = agstrdup_html(agraphof(obj),hs); free(hs); } } agxset(obj, a, val); }
/* _write_plain: */ void write_plain(GVJ_t * job, graph_t * g, FILE * f, boolean extend) { int i, j, splinePoints; char *tport, *hport; node_t *n; edge_t *e; bezier bz; pointf pt; char *lbl; char* fillcolor; #ifdef WITH_CGRAPH putstr = g->clos->disc.io->putstr; #endif // setup_graph(job, g); setYInvert(g); pt = GD_bb(g).UR; printdouble(f, "graph ", job->zoom); printdouble(f, " ", PS2INCH(pt.x)); printdouble(f, " ", PS2INCH(pt.y)); agputc('\n', f); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (IS_CLUST_NODE(n)) continue; printstring(f, "node ", agcanonStr(agnameof(n))); printpoint(f, ND_coord(n)); if (ND_label(n)->html) /* if html, get original text */ #ifndef WITH_CGRAPH lbl = agcanonStr (agxget(n, N_label->index)); #else lbl = agcanonStr (agxget(n, N_label)); #endif else lbl = canon(agraphof(n),ND_label(n)->text); printdouble(f, " ", ND_width(n)); printdouble(f, " ", ND_height(n)); printstring(f, " ", lbl); printstring(f, " ", late_nnstring(n, N_style, "solid")); printstring(f, " ", ND_shape(n)->name); printstring(f, " ", late_nnstring(n, N_color, DEFAULT_COLOR)); fillcolor = late_nnstring(n, N_fillcolor, ""); if (fillcolor[0] == '\0') fillcolor = late_nnstring(n, N_color, DEFAULT_FILL); printstring(f, " ", fillcolor); agputc('\n', f); }
static void dot_cleanup_node(node_t * n) { free_list(ND_in(n)); free_list(ND_out(n)); free_list(ND_flat_out(n)); free_list(ND_flat_in(n)); free_list(ND_other(n)); free_label(ND_label(n)); if (ND_shape(n)) ND_shape(n)->fns->freefn(n); #ifndef WITH_CGRAPH memset(&(n->u), 0, sizeof(Agnodeinfo_t)); #else /* WITH_CGRAPH */ agclean(agraphof(n), AGNODE,"Agnodeinfo_t"); #endif /* WITH_CGRAPH */ }
static v_data *makeGraph(topview * tv, int *nedges) { int i; int ne = tv->Edgecount; /* upper bound */ int nv = tv->Nodecount; v_data *graph = N_NEW(nv, v_data); int *edges = N_NEW(2 * ne + nv, int); /* reserve space for self loops */ float *ewgts = N_NEW(2 * ne + nv, float); Agnode_t *np; Agedge_t *ep; Agraph_t *g = NULL; int i_nedges; ne = 0; for (i = 0; i < nv; i++) { graph[i].edges = edges++; /* reserve space for the self loop */ graph[i].ewgts = ewgts++; #ifdef STYLES graph[i].styles = NULL; #endif i_nedges = 1; /* one for the self */ np = tv->Nodes[i].Node; if (!g) g = agraphof(np); for (ep = agfstedge(g, np); ep; ep = agnxtedge(g, ep, np)) { Agnode_t *vp; Agnode_t *tp = agtail(ep); Agnode_t *hp = aghead(ep); assert(hp != tp); /* FIX: handle multiedges */ vp = (tp == np ? hp : tp); ne++; i_nedges++; *edges++ = OD_TVRef(vp); *ewgts++ = 1; } graph[i].nedges = i_nedges; graph[i].edges[0] = i; graph[i].ewgts[0] = 1 - i_nedges; } ne /= 2; /* each edge counted twice */ *nedges = ne; return graph; }
Agnode_t *nexthead(Agnode_t *n, Agnode_t *h) { Agedge_t *e; Agraph_t *g; if (!n || !h) return NULL; g = agraphof(n); e = agfindedge(g, n, h); if (!e) return NULL; do { e = agnxtout(g, e); if (!e) return NULL; } while (aghead(e) == h); return aghead(e); }
Agnode_t *nexttail(Agnode_t *n, Agnode_t *t) { Agedge_t *e; Agraph_t *g; if (!n || !t) return NULL; g = agraphof(n); e = agfindedge(g, t, n); if (!e) return NULL; do { e = agnxtin(g, e); if (!e) return NULL; } while (agtail(e) == t); return agtail(e); }
static int visit(Agnode_t *n, Agraph_t* map, Stack* sp, sccstate* st) { unsigned int m,min; Agnode_t* t; Agraph_t* subg; Agedge_t* e; min = ++(st->ID); setval(n,min); push (sp, n); for (e = agfstout(n); e; e = agnxtout(e)) { t = aghead(e); if (getval(t) == 0) m = visit(t,map,sp,st); else m = getval(t); if (m < min) min = m; } if (getval(n) == min) { if (!wantDegenerateComp && (top(sp) == n)) { setval(n,INF); pop(sp); } else { char name[32]; Agraph_t* G = agraphof(n);; sprintf(name,"cluster_%d",(st->Comp)++); subg = agsubg(G,name,TRUE); agbindrec(subg,"scc_graph",sizeof(Agraphinfo_t),TRUE); setrep(subg,agnode(map,name,TRUE)); do { t = pop(sp); agsubnode(subg,t,TRUE); setval(t,INF); setscc(t,subg); st->N_nodes_in_nontriv_SCC++; } while (t != n); nodeInduce(subg); if (!Silent) agwrite(subg,stdout); } } return min; }
/*-------------------------------------------------------------------------* \ * Method: n.delete(self) * Delete a node. All associated edges are deleted as well. * Returns non-nil on success. * Example: * rv, err = n:delete(h) \*-------------------------------------------------------------------------*/ static int gr_delete(lua_State *L) { Agraph_t *g; gr_node_t *ud = tonode(L, 1, NONSTRICT); if (ud->n != NULL){ /* Delete all associated edges with tail on this node */ g = agraphof(ud->n); if (ud->status == ALIVE){ TRACE(" n.delete(): deleting node '%s' ud=%p id=0x%0lx (%s %d) \n", agnameof(ud->n), (void *) ud, (unsigned long) AGID(ud->n), __FILE__, __LINE__); agdelnode(g, ud->n); } } else { TRACE(" n:delete(): ud=%p already closed (%s %d)\n", (void *)ud, __FILE__, __LINE__); } lua_pushnumber(L, 0); return 1; }
/*-------------------------------------------------------------------------*\ * Write info about a node to stdout. * Example: * n:info() \*-------------------------------------------------------------------------*/ static int gr_info(lua_State *L) { Agraph_t *g; gr_node_t *ud = tonode(L, 1, STRICT); Agedge_t *se; Agsym_t *sym; g = agraphof(ud->n); printf("INFO NODE '%s' '%s' id=%lu seq=%d\n", agnameof(ud->n), ud->name, (unsigned long) AGID(ud->n), AGSEQ(ud->n)); printf(" ptr: %p\n", ud->n); printf(" Symbols:\n"); se = agfstout(g, ud->n); sym=0; while ((sym = agnxtattr(g,AGNODE,sym))!=NULL) printf(" %s = '%s'\n",sym->name,sym->defval); #if 0 printf(" Out edges: d-out=%d u-out=%d\n", agdegree(g, ud->n, 0, 1), agcountuniqedges(g, ud->n, 0, 1)); #endif while (se) { printf(" name: '%s', head: '%s', tail: '%s' id=%lud, seq=%d %p\n", agnameof(se), agnameof(aghead(se)), agnameof(agtail(se)), (unsigned long) AGID(se), AGSEQ(se), (void*)se); se = agnxtout(g, se); } #if 0 printf(" In edges: d-in=%d u-in=%d\n", agdegree(g, ud->n, 1, 0), agcountuniqedges(g, ud->n, 1, 0)); #endif se = agfstin(g, ud->n); while (se) { printf(" name: '%s', head: '%s', tail: '%s' îd=%lu seq=%d %p\n", agnameof(se), agnameof(aghead(se)), agnameof(agtail(se)), (unsigned long) AGID(se), AGSEQ(se), (void*)se); se = agnxtin(g, se); } #if 0 printf(" Edges: d-io=%d u-io=%d\n", agdegree(g, ud->n, 1, 1), agcountuniqedges(g, ud->n, 1, 1)); #endif se = agfstedge(g, ud->n); while (se) { printf(" name: '%s', head: '%s', tail: '%s' id=%lud seq=%d %p\n", agnameof(se), agnameof(aghead(se)), agnameof(agtail(se)), (unsigned long) AGID(se), AGSEQ(se), (void*)se); se = agnxtedge(g, se, ud->n); } return 0; }
char *setv(Agedge_t *e, char *attr, char *val) { Agraph_t *g; Agsym_t *a; if (!e || !attr || !val) return NULL; if (AGTYPE(e) == AGRAPH) { // protoedge g = (Agraph_t*)e; a = agattr(g, AGEDGE, attr, val); // create default attribute in pseudo protoedge // FIXME? - deal with html in "label" attributes return val; } g = agroot(agraphof(agtail(e))); a = agattr(g, AGEDGE, attr, NULL); if (!a) a = agattr(g, AGEDGE, attr, emptystring); myagxset(e, a, val); return val; }