|
Graphviz
2.29.20120524.0446
|
00001 /* $Id$ $Revision$ */ 00002 /* vim:set shiftwidth=4 ts=8: */ 00003 00004 /************************************************************************* 00005 * Copyright (c) 2011 AT&T Intellectual Property 00006 * All rights reserved. This program and the accompanying materials 00007 * are made available under the terms of the Eclipse Public License v1.0 00008 * which accompanies this distribution, and is available at 00009 * http://www.eclipse.org/legal/epl-v10.html 00010 * 00011 * Contributors: See CVS logs. Details at http://www.graphviz.org/ 00012 *************************************************************************/ 00013 00014 #include <string.h> 00015 #include <stdlib.h> 00016 #include "gvc.h" 00017 00018 extern "C" { 00019 extern void gv_string_writer_init(GVC_t *gvc); 00020 extern void gv_channel_writer_init(GVC_t *gvc); 00021 } 00022 00023 #ifdef WITH_CGRAPH 00024 #define agfindattr(x,s) agattrsym(x,s) 00025 #define agraphattr(g,n,s) agattr(g,AGRAPH,n,s) 00026 #define agnodeattr(g,n,s) agattr(g,AGNODE,n,s) 00027 #define agedgeattr(g,n,s) agattr(g,AGEDGE,n,s) 00028 #endif 00029 00030 static char emptystring[] = {'\0'}; 00031 00032 static GVC_t *gvc; 00033 00034 static void gv_init(void) { 00035 /* list of builtins, enable demand loading */ 00036 gvc = gvContextPlugins(lt_preloaded_symbols, DEMAND_LOADING); 00037 } 00038 00039 Agraph_t *graph(char *name) 00040 { 00041 if (!gvc) 00042 gv_init(); 00043 #ifdef WITH_CGRAPH 00044 return agopen(name, Agundirected, 0); 00045 #else 00046 return agopen(name, AGRAPH); 00047 #endif 00048 } 00049 00050 Agraph_t *digraph(char *name) 00051 { 00052 if (!gvc) 00053 gv_init(); 00054 #ifdef WITH_CGRAPH 00055 return agopen(name, Agdirected, 0); 00056 #else 00057 return agopen(name, AGDIGRAPH); 00058 #endif 00059 } 00060 00061 Agraph_t *strictgraph(char *name) 00062 { 00063 if (!gvc) 00064 gv_init(); 00065 #ifdef WITH_CGRAPH 00066 return agopen(name, Agstrictundirected, 0); 00067 #else 00068 return agopen(name, AGRAPHSTRICT); 00069 #endif 00070 } 00071 00072 Agraph_t *strictdigraph(char *name) 00073 { 00074 if (!gvc) 00075 gv_init(); 00076 #ifdef WITH_CGRAPH 00077 return agopen(name, Agstrictdirected, 0); 00078 #else 00079 return agopen(name, AGDIGRAPHSTRICT); 00080 #endif 00081 } 00082 00083 Agraph_t *readstring(char *string) 00084 { 00085 if (!gvc) 00086 gv_init(); 00087 return agmemread(string); 00088 } 00089 00090 Agraph_t *read(FILE *f) 00091 { 00092 if (!gvc) 00093 gv_init(); 00094 #ifdef WITH_CGRAPH 00095 return agread(f, NULL); 00096 #else 00097 return agread(f); 00098 #endif 00099 } 00100 00101 Agraph_t *read(const char *filename) 00102 { 00103 FILE *f; 00104 Agraph_t *g; 00105 00106 f = fopen(filename, "r"); 00107 if (!f) 00108 return NULL; 00109 if (!gvc) 00110 gv_init(); 00111 #ifdef WITH_CGRAPH 00112 g = agread(f, NULL); 00113 #else 00114 g = agread(f); 00115 #endif 00116 fclose(f); 00117 return g; 00118 } 00119 00120 //------------------------------------------------- 00121 Agraph_t *graph(Agraph_t *g, char *name) 00122 { 00123 if (!gvc) 00124 gv_init(); 00125 #ifdef WITH_CGRAPH 00126 return agsubg(g, name, 1); 00127 #else 00128 return agsubg(g, name); 00129 #endif 00130 } 00131 00132 Agnode_t *node(Agraph_t *g, char *name) 00133 { 00134 if (!gvc) 00135 return NULL; 00136 #ifdef WITH_CGRAPH 00137 return agnode(g, name, 1); 00138 #else 00139 // creating a protonode is not permitted 00140 if (name[0] == '\001' && strcmp (name, "\001proto") == 0) 00141 return NULL; 00142 return agnode(g, name); 00143 #endif 00144 } 00145 00146 Agedge_t *edge(Agnode_t *t, Agnode_t *h) 00147 { 00148 if (!gvc || !t || !h) 00149 return NULL; 00150 #ifdef WITH_CGRAPH 00151 // edges from/to the protonode are not permitted 00152 if (AGTYPE(t) == AGRAPH || AGTYPE(h) == AGRAPH) 00153 return NULL; 00154 return agedge(agraphof(t), t, h, NULL, 1); 00155 #else 00156 // edges from/to the protonode are not permitted 00157 if ((agnameof(t)[0] == '\001' && strcmp (agnameof(t), "\001proto") == 0) 00158 || (agnameof(h)[0] == '\001' && strcmp (agnameof(h), "\001proto") == 0)) 00159 return NULL; 00160 return agedge(t->graph, t, h); 00161 #endif 00162 } 00163 00164 // induce tail if necessary 00165 Agedge_t *edge(char *tname, Agnode_t *h) 00166 { 00167 #ifdef WITH_CGRAPH 00168 return edge(node(agraphof(h), tname), h); 00169 #else 00170 return edge(node(h->graph, tname), h); 00171 #endif 00172 } 00173 00174 // induce head if necessary 00175 Agedge_t *edge(Agnode_t *t, char *hname) 00176 { 00177 #ifdef WITH_CGRAPH 00178 return edge(t, node(agraphof(t), hname)); 00179 #else 00180 return edge(t, node(t->graph, hname)); 00181 #endif 00182 } 00183 00184 // induce tail/head if necessary 00185 Agedge_t *edge(Agraph_t *g, char *tname, char *hname) 00186 { 00187 return edge(node(g, tname), node(g, hname)); 00188 } 00189 00190 //------------------------------------------------- 00191 static char* myagxget(void *obj, Agsym_t *a) 00192 { 00193 int len; 00194 char *val, *hs; 00195 00196 if (!obj || !a) 00197 return emptystring; 00198 #ifndef WITH_CGRAPH 00199 val = agxget(obj, a->index); 00200 #else 00201 val = agxget(obj, a); 00202 #endif 00203 if (!val) 00204 return emptystring; 00205 if (a->name[0] == 'l' && strcmp(a->name, "label") == 0 && aghtmlstr(val)) { 00206 len = strlen(val); 00207 hs = (char*)malloc(len + 3); 00208 hs[0] = '<'; 00209 strcpy(hs+1, val); 00210 hs[len+1] = '>'; 00211 hs[len+2] = '\0'; 00212 return hs; 00213 } 00214 return val; 00215 } 00216 char *getv(Agraph_t *g, Agsym_t *a) 00217 { 00218 return myagxget(g, a); 00219 } 00220 char *getv(Agraph_t *g, char *attr) 00221 { 00222 Agsym_t *a; 00223 00224 if (!g || !attr) 00225 return NULL; 00226 a = agfindattr(agroot(g), attr); 00227 return myagxget(g, a); 00228 } 00229 static void myagxset(void *obj, Agsym_t *a, char *val) 00230 { 00231 int len; 00232 char *hs; 00233 00234 if (a->name[0] == 'l' && val[0] == '<' && strcmp(a->name, "label") == 0) { 00235 len = strlen(val); 00236 if (val[len-1] == '>') { 00237 hs = strdup(val+1); 00238 *(hs+len-2) = '\0'; 00239 #ifdef WITH_CGRAPH 00240 val = agstrdup_html(agraphof(obj),hs); 00241 #else 00242 val = agstrdup_html(hs); 00243 #endif 00244 free(hs); 00245 } 00246 } 00247 #ifndef WITH_CGRAPH 00248 agxset(obj, a->index, val); 00249 #else 00250 agxset(obj, a, val); 00251 #endif 00252 } 00253 char *setv(Agraph_t *g, Agsym_t *a, char *val) 00254 { 00255 if (!g || !a || !val) 00256 return NULL; 00257 myagxset(g, a, val); 00258 return val; 00259 } 00260 char *setv(Agraph_t *g, char *attr, char *val) 00261 { 00262 Agsym_t *a; 00263 00264 if (!g || !attr || !val) 00265 return NULL; 00266 a = agfindattr(agroot(g), attr); 00267 if (!a) 00268 a = agraphattr(g->root, attr, emptystring); 00269 myagxset(g, a, val); 00270 return val; 00271 } 00272 //------------------------------------------------- 00273 char *getv(Agnode_t *n, Agsym_t *a) 00274 { 00275 if (!n || !a) 00276 return NULL; 00277 #ifdef WITH_CGRAPH 00278 if (AGTYPE(n) == AGRAPH) // protonode 00279 return NULL; // FIXME ?? 00280 #endif 00281 return myagxget(n, a); 00282 } 00283 char *getv(Agnode_t *n, char *attr) 00284 { 00285 Agraph_t *g; 00286 Agsym_t *a; 00287 00288 if (!n || !attr) 00289 return NULL; 00290 #ifdef WITH_CGRAPH 00291 if (AGTYPE(n) == AGRAPH) // protonode 00292 return NULL; // FIXME ?? 00293 #endif 00294 g = agroot(agraphof(n)); 00295 #ifdef WITH_CGRAPH 00296 a = agattr(g, AGNODE, attr, NULL); 00297 #else 00298 a = agfindattr(g->proto->n, attr); 00299 #endif 00300 return myagxget(n, a); 00301 } 00302 char *setv(Agnode_t *n, Agsym_t *a, char *val) 00303 { 00304 if (!n || !a || !val) 00305 return NULL; 00306 #ifdef WITH_CGRAPH 00307 if (AGTYPE(n) == AGRAPH) // protonode 00308 return NULL; // FIXME ?? 00309 #endif 00310 myagxset(n, a, val); 00311 return val; 00312 } 00313 char *setv(Agnode_t *n, char *attr, char *val) 00314 { 00315 Agraph_t *g; 00316 Agsym_t *a; 00317 00318 if (!n || !attr || !val) 00319 return NULL; 00320 #ifdef WITH_CGRAPH 00321 if (AGTYPE(n) == AGRAPH) { // protonode 00322 g = (Agraph_t*)n; 00323 a = agattr(g, AGNODE, attr, val); // create default attribute in psuodo protonode 00324 // FIXME? - deal with html in "label" attributes 00325 return val; 00326 } 00327 #endif 00328 g = agroot(agraphof(n)); 00329 #ifdef WITH_CGRAPH 00330 a = agattr(g, AGNODE, attr, NULL); 00331 #else 00332 a = agfindattr(g->proto->n, attr); 00333 #endif 00334 if (!a) 00335 a = agnodeattr(g, attr, emptystring); 00336 myagxset(n, a, val); 00337 return val; 00338 } 00339 //------------------------------------------------- 00340 char *getv(Agedge_t *e, Agsym_t *a) 00341 { 00342 if (!e || !a) 00343 return NULL; 00344 #ifdef WITH_CGRAPH 00345 if (AGTYPE(e) == AGRAPH) // protoedge 00346 return NULL; // FIXME ?? 00347 #endif 00348 return myagxget(e, a); 00349 } 00350 char *getv(Agedge_t *e, char *attr) 00351 { 00352 Agraph_t *g; 00353 Agsym_t *a; 00354 00355 if (!e || !attr) 00356 return NULL; 00357 #ifdef WITH_CGRAPH 00358 if (AGTYPE(e) == AGRAPH) // protoedge 00359 return NULL; // FIXME ?? 00360 #endif 00361 g = agraphof(agtail(e)); 00362 #ifndef WITH_CGRAPH 00363 a = agfindattr(g->proto->e, attr); 00364 #else 00365 a = agattr(g, AGEDGE, attr, NULL); 00366 #endif 00367 return myagxget(e, a); 00368 } 00369 char *setv(Agedge_t *e, Agsym_t *a, char *val) 00370 { 00371 if (!e || !a || !val) 00372 return NULL; 00373 #ifdef WITH_CGRAPH 00374 if (AGTYPE(e) == AGRAPH) // protoedge 00375 return NULL; // FIXME ?? 00376 #endif 00377 myagxset(e, a, val); 00378 return val; 00379 } 00380 char *setv(Agedge_t *e, char *attr, char *val) 00381 { 00382 Agraph_t *g; 00383 Agsym_t *a; 00384 00385 if (!e || !attr || !val) 00386 return NULL; 00387 #ifdef WITH_CGRAPH 00388 if (AGTYPE(e) == AGRAPH) { // protoedge 00389 g = (Agraph_t*)e; 00390 a = agattr(g, AGEDGE, attr, val); // create default attribute in pseudo protoedge 00391 // FIXME? - deal with html in "label" attributes 00392 return val; 00393 } 00394 #endif 00395 g = agroot(agraphof(agtail(e))); 00396 #ifndef WITH_CGRAPH 00397 a = agfindattr(g->proto->e, attr); 00398 if (!a) 00399 a = agedgeattr(g, attr, emptystring); 00400 #else 00401 a = agattr(g, AGEDGE, attr, NULL); 00402 if (!a) 00403 a = agattr(g, AGEDGE, attr, emptystring); 00404 #endif 00405 myagxset(e, a, val); 00406 return val; 00407 } 00408 //------------------------------------------------- 00409 Agraph_t *findsubg(Agraph_t *g, char *name) 00410 { 00411 if (!g || !name) 00412 return NULL; 00413 #ifndef WITH_CGRAPH 00414 return agfindsubg(g, name); 00415 #else 00416 return agsubg(g, name, 0); 00417 #endif 00418 } 00419 00420 Agnode_t *findnode(Agraph_t *g, char *name) 00421 { 00422 if (!g || !name) 00423 return NULL; 00424 #ifndef WITH_CGRAPH 00425 return agfindnode(g, name); 00426 #else 00427 return agnode(g, name, 0); 00428 #endif 00429 } 00430 00431 Agedge_t *findedge(Agnode_t *t, Agnode_t *h) 00432 { 00433 if (!t || !h) 00434 return NULL; 00435 #ifdef WITH_CGRAPH 00436 if (AGTYPE(t) == AGRAPH || AGTYPE(h) == AGRAPH) 00437 return NULL; 00438 #endif 00439 return agfindedge(agraphof(t), t, h); 00440 } 00441 00442 Agsym_t *findattr(Agraph_t *g, char *name) 00443 { 00444 if (!g || !name) 00445 return NULL; 00446 return agfindattr(g, name); 00447 } 00448 00449 Agsym_t *findattr(Agnode_t *n, char *name) 00450 { 00451 if (!n || !name) 00452 return NULL; 00453 return agfindattr(n, name); 00454 } 00455 00456 Agsym_t *findattr(Agedge_t *e, char *name) 00457 { 00458 if (!e || !name) 00459 return NULL; 00460 return agfindattr(e, name); 00461 } 00462 00463 //------------------------------------------------- 00464 00465 Agnode_t *headof(Agedge_t *e) 00466 { 00467 if (!e) 00468 return NULL; 00469 #ifdef WITH_CGRAPH 00470 if (AGTYPE(e) == AGRAPH) 00471 return NULL; 00472 #endif 00473 return aghead(e); 00474 } 00475 00476 Agnode_t *tailof(Agedge_t *e) 00477 { 00478 if (!e) 00479 return NULL; 00480 #ifdef WITH_CGRAPH 00481 if (AGTYPE(e) == AGRAPH) 00482 return NULL; 00483 #endif 00484 return agtail(e); 00485 } 00486 00487 Agraph_t *graphof(Agraph_t *g) 00488 { 00489 if (!g || g == g->root) 00490 return NULL; 00491 return agroot(g); 00492 } 00493 00494 Agraph_t *graphof(Agedge_t *e) 00495 { 00496 if (!e) 00497 return NULL; 00498 #ifdef WITH_CGRAPH 00499 if (AGTYPE(e) == AGRAPH) 00500 return (Agraph_t*)e; /* graph of protoedge is itself recast */ 00501 #endif 00502 return agraphof(agtail(e)); 00503 } 00504 00505 Agraph_t *graphof(Agnode_t *n) 00506 { 00507 if (!n) 00508 return NULL; 00509 #ifdef WITH_CGRAPH 00510 if (AGTYPE(n) == AGRAPH) 00511 return (Agraph_t*)n; /* graph of protonode is itself recast */ 00512 #endif 00513 return agraphof(n); 00514 } 00515 00516 Agraph_t *rootof(Agraph_t *g) 00517 { 00518 if (!g) 00519 return NULL; 00520 return agroot(g); 00521 } 00522 00523 //------------------------------------------------- 00524 Agnode_t *protonode(Agraph_t *g) 00525 { 00526 if (!g) 00527 return NULL; 00528 #ifdef WITH_CGRAPH 00529 return (Agnode_t *)g; // gross abuse of the type system! 00530 #else 00531 return g->proto->n; 00532 #endif 00533 } 00534 00535 Agedge_t *protoedge(Agraph_t *g) 00536 { 00537 if (!g) 00538 return NULL; 00539 #ifdef WITH_CGRAPH 00540 return (Agedge_t *)g; // gross abuse of the type system! 00541 #else 00542 return g->proto->e; 00543 #endif 00544 } 00545 00546 //------------------------------------------------- 00547 char *nameof(Agraph_t *g) 00548 { 00549 if (!g) 00550 return NULL; 00551 return agnameof(g); 00552 } 00553 char *nameof(Agnode_t *n) 00554 { 00555 if (!n) 00556 return NULL; 00557 #ifdef WITH_CGRAPH 00558 if (AGTYPE(n) == AGRAPH) 00559 return NULL; 00560 #endif 00561 return agnameof(n); 00562 } 00563 //char *nameof(Agedge_t *e) 00564 //{ 00565 // if (!e) 00566 // return NULL; 00567 //#ifdef WITH_CGRAPH 00568 // if (AGTYPE(e) == AGRAPH) 00569 // return NULL; 00570 //#endif 00571 // return agnameof(e); 00572 //} 00573 char *nameof(Agsym_t *a) 00574 { 00575 if (!a) 00576 return NULL; 00577 return a->name; 00578 } 00579 00580 //------------------------------------------------- 00581 bool ok(Agraph_t *g) 00582 { 00583 if (!g) 00584 return false; 00585 return true; 00586 } 00587 bool ok(Agnode_t *n) 00588 { 00589 if (!n) 00590 return false; 00591 return true; 00592 } 00593 bool ok(Agedge_t *e) 00594 { 00595 if (!e) 00596 return false; 00597 return true; 00598 } 00599 bool ok(Agsym_t *a) 00600 { 00601 if (!a) 00602 return false; 00603 return true; 00604 } 00605 //------------------------------------------------- 00606 Agraph_t *firstsubg(Agraph_t *g) 00607 { 00608 #ifndef WITH_CGRAPH 00609 Agraph_t *mg; 00610 Agnode_t *n; 00611 Agedge_t *e; 00612 #endif 00613 00614 if (!g) 00615 return NULL; 00616 #ifdef WITH_CGRAPH 00617 return agfstsubg(g); 00618 #else 00619 n = g->meta_node; 00620 if (!n) 00621 return NULL; 00622 mg = agraphof(n); 00623 if (!mg) 00624 return NULL; 00625 e = agfstout(mg, n); 00626 if (!e) 00627 return NULL; 00628 return agusergraph(aghead(e)); 00629 #endif 00630 } 00631 00632 Agraph_t *nextsubg(Agraph_t *g, Agraph_t *sg) 00633 { 00634 #ifndef WITH_CGRAPH 00635 Agraph_t *mg; 00636 Agnode_t *ng, *nsg; 00637 Agedge_t *e; 00638 #endif 00639 00640 if (!g || !sg) 00641 return NULL; 00642 #ifdef WITH_CGRAPH 00643 return agnxtsubg(sg); 00644 #else 00645 ng = g->meta_node; 00646 nsg = sg->meta_node; 00647 if (!ng || !nsg) 00648 return NULL; 00649 mg = agraphof(ng); 00650 if (!mg) 00651 return NULL; 00652 e = agfindedge(mg, ng, nsg); 00653 if (!e) 00654 return NULL; 00655 e = agnxtout(mg, e); 00656 if (!e) 00657 return NULL; 00658 return agusergraph(aghead(e)); 00659 #endif 00660 } 00661 00662 #ifdef WITH_CGRAPH 00663 Agraph_t *firstsupg(Agraph_t *g) 00664 { 00665 return g->parent; 00666 } 00667 00668 Agraph_t *nextsupg(Agraph_t *g, Agraph_t *sg) 00669 { 00670 return NULL; 00671 } 00672 #else 00673 Agraph_t *firstsupg(Agraph_t *g) 00674 { 00675 Agraph_t *mg; 00676 Agnode_t *n; 00677 Agedge_t *e; 00678 00679 if (!g) 00680 return NULL; 00681 n = g->meta_node; 00682 if (!n) 00683 return NULL; 00684 mg = agraphof(n); 00685 if (!mg) 00686 return NULL; 00687 e = agfstin(mg, n); 00688 if (!e) 00689 return NULL; 00690 return agusergraph(agtail(e)); 00691 } 00692 00693 Agraph_t *nextsupg(Agraph_t *g, Agraph_t *sg) 00694 { 00695 Agraph_t *mg; 00696 Agnode_t *ng, *nsg; 00697 Agedge_t *e; 00698 00699 if (!g || !sg) 00700 return NULL; 00701 ng = g->meta_node; 00702 nsg = sg->meta_node; 00703 if (!ng || !nsg) 00704 return NULL; 00705 mg = agraphof(ng); 00706 if (!mg) 00707 return NULL; 00708 e = agfindedge(mg, nsg, ng); 00709 if (!e) 00710 return NULL; 00711 e = agnxtin(mg, e); 00712 if (!e) 00713 return NULL; 00714 return agusergraph(agtail(e)); 00715 } 00716 #endif 00717 00718 Agedge_t *firstout(Agraph_t *g) 00719 { 00720 Agnode_t *n; 00721 Agedge_t *e; 00722 00723 if (!g) 00724 return NULL; 00725 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00726 e = agfstout(g, n); 00727 if (e) return e; 00728 } 00729 return NULL; 00730 } 00731 00732 Agedge_t *nextout(Agraph_t *g, Agedge_t *e) 00733 { 00734 Agnode_t *n; 00735 Agedge_t *ne; 00736 00737 if (!g || !e) 00738 return NULL; 00739 ne = agnxtout(g, e); 00740 if (ne) 00741 return (ne); 00742 for (n = agnxtnode(g, agtail(e)); n; n = agnxtnode(g, n)) { 00743 ne = agfstout(g, n); 00744 if (ne) return ne; 00745 } 00746 return NULL; 00747 } 00748 00749 Agedge_t *firstedge(Agraph_t *g) 00750 { 00751 return firstout(g); 00752 } 00753 00754 Agedge_t *nextedge(Agraph_t *g, Agedge_t *e) 00755 { 00756 return nextout(g, e); 00757 } 00758 00759 Agedge_t *firstout(Agnode_t *n) 00760 { 00761 if (!n) 00762 return NULL; 00763 return agfstout(agraphof(n), n); 00764 } 00765 00766 Agedge_t *nextout(Agnode_t *n, Agedge_t *e) 00767 { 00768 if (!n || !e) 00769 return NULL; 00770 return agnxtout(agraphof(n), e); 00771 } 00772 00773 Agnode_t *firsthead(Agnode_t *n) 00774 { 00775 Agedge_t *e; 00776 00777 if (!n) 00778 return NULL; 00779 e = agfstout(agraphof(n), n); 00780 if (!e) 00781 return NULL; 00782 return aghead(e); 00783 } 00784 00785 Agnode_t *nexthead(Agnode_t *n, Agnode_t *h) 00786 { 00787 Agedge_t *e; 00788 Agraph_t *g; 00789 00790 if (!n || !h) 00791 return NULL; 00792 g = agraphof(n); 00793 e = agfindedge(g, n, h); 00794 if (!e) 00795 return NULL; 00796 do { 00797 e = agnxtout(g, e); 00798 if (!e) 00799 return NULL; 00800 } while (aghead(e) == h); 00801 return aghead(e); 00802 } 00803 00804 Agedge_t *firstedge(Agnode_t *n) 00805 { 00806 if (!n) 00807 return NULL; 00808 return agfstedge(agraphof(n), n); 00809 } 00810 00811 Agedge_t *nextedge(Agnode_t *n, Agedge_t *e) 00812 { 00813 if (!n || !e) 00814 return NULL; 00815 return agnxtedge(agraphof(n), e, n); 00816 } 00817 00818 Agedge_t *firstin(Agraph_t *g) 00819 { 00820 Agnode_t *n; 00821 00822 if (!g) 00823 return NULL; 00824 n = agfstnode(g); 00825 if (!n) 00826 return NULL; 00827 return agfstin(g, n); 00828 } 00829 00830 Agedge_t *nextin(Agraph_t *g, Agedge_t *e) 00831 { 00832 Agnode_t *n; 00833 Agedge_t *ne; 00834 00835 if (!g || !e) 00836 return NULL; 00837 ne = agnxtin(g, e); 00838 if (ne) 00839 return (ne); 00840 n = agnxtnode(g, aghead(e)); 00841 if (!n) 00842 return NULL; 00843 return agfstin(g, n); 00844 } 00845 00846 Agedge_t *firstin(Agnode_t *n) 00847 { 00848 if (!n) 00849 return NULL; 00850 return agfstin(agraphof(n), n); 00851 } 00852 00853 Agedge_t *nextin(Agnode_t *n, Agedge_t *e) 00854 { 00855 if (!n || !e) 00856 return NULL; 00857 return agnxtin(agraphof(n), e); 00858 } 00859 00860 Agnode_t *firsttail(Agnode_t *n) 00861 { 00862 Agedge_t *e; 00863 00864 if (!n) 00865 return NULL; 00866 e = agfstin(agraphof(n), n); 00867 if (!e) 00868 return NULL; 00869 return agtail(e); 00870 } 00871 00872 Agnode_t *nexttail(Agnode_t *n, Agnode_t *t) 00873 { 00874 Agedge_t *e; 00875 Agraph_t *g; 00876 00877 if (!n || !t) 00878 return NULL; 00879 g = agraphof(n); 00880 e = agfindedge(g, t, n); 00881 if (!e) 00882 return NULL; 00883 do { 00884 e = agnxtout(g, e); 00885 if (!e) 00886 return NULL; 00887 } while (agtail(e) == t); 00888 return agtail(e); 00889 } 00890 00891 Agnode_t *firstnode(Agraph_t *g) 00892 { 00893 if (!g) 00894 return NULL; 00895 return agfstnode(g); 00896 } 00897 00898 Agnode_t *nextnode(Agraph_t *g, Agnode_t *n) 00899 { 00900 if (!g || !n) 00901 return NULL; 00902 return agnxtnode(g, n); 00903 } 00904 00905 Agnode_t *firstnode(Agedge_t *e) 00906 { 00907 if (!e) 00908 return NULL; 00909 return agtail(e); 00910 } 00911 00912 Agnode_t *nextnode(Agedge_t *e, Agnode_t *n) 00913 { 00914 if (!e || n != agtail(e)) 00915 return NULL; 00916 return aghead(e); 00917 } 00918 00919 Agsym_t *firstattr(Agraph_t *g) 00920 { 00921 if (!g) 00922 return NULL; 00923 g = agroot(g); 00924 #ifdef WITH_CGRAPH 00925 return agnxtattr(g,AGRAPH,NULL); 00926 #else 00927 if (dtsize(g->univ->globattr->dict) == 0) 00928 return NULL; 00929 return g->univ->globattr->list[0]; 00930 #endif 00931 } 00932 00933 Agsym_t *nextattr(Agraph_t *g, Agsym_t *a) 00934 { 00935 int i; 00936 00937 if (!g || !a) 00938 return NULL; 00939 g = agroot(g); 00940 #ifdef WITH_CGRAPH 00941 return agnxtattr(g,AGRAPH,a); 00942 #else 00943 for (i = 0; i < dtsize(g->univ->globattr->dict); i++) 00944 if (a == g->univ->globattr->list[i]) 00945 break; 00946 i++; 00947 if (i > dtsize(g->univ->globattr->dict)) 00948 return NULL; 00949 return g->univ->globattr->list[i]; 00950 #endif 00951 } 00952 00953 Agsym_t *firstattr(Agnode_t *n) 00954 { 00955 Agraph_t *g; 00956 00957 if (!n) 00958 return NULL; 00959 g = agraphof(n); 00960 #ifdef WITH_CGRAPH 00961 return agnxtattr(g,AGNODE,NULL); 00962 #else 00963 if (dtsize(g->univ->nodeattr->dict) == 0) 00964 return NULL; 00965 return g->univ->nodeattr->list[0]; 00966 #endif 00967 } 00968 00969 Agsym_t *nextattr(Agnode_t *n, Agsym_t *a) 00970 { 00971 Agraph_t *g; 00972 int i; 00973 00974 if (!n || !a) 00975 return NULL; 00976 g = agraphof(n); 00977 #ifdef WITH_CGRAPH 00978 return agnxtattr(g,AGNODE,a); 00979 #else 00980 for (i = 0; i < dtsize(g->univ->nodeattr->dict); i++) 00981 if (a == g->univ->nodeattr->list[i]) 00982 break; 00983 i++; 00984 if (i > dtsize(g->univ->nodeattr->dict)) 00985 return NULL; 00986 return g->univ->nodeattr->list[i]; 00987 #endif 00988 } 00989 00990 Agsym_t *firstattr(Agedge_t *e) 00991 { 00992 Agraph_t *g; 00993 00994 if (!e) 00995 return NULL; 00996 g = agraphof(agtail(e)); 00997 #ifdef WITH_CGRAPH 00998 return agnxtattr(g,AGEDGE,NULL); 00999 #else 01000 if (dtsize(g->univ->edgeattr->dict) == 0) 01001 return NULL; 01002 return g->univ->edgeattr->list[0]; 01003 #endif 01004 } 01005 01006 Agsym_t *nextattr(Agedge_t *e, Agsym_t *a) 01007 { 01008 Agraph_t *g; 01009 int i; 01010 01011 if (!e || !a) 01012 return NULL; 01013 g = agraphof(agtail(e)); 01014 #ifdef WITH_CGRAPH 01015 return agnxtattr(g,AGEDGE,a); 01016 #else 01017 for (i = 0; i < dtsize(g->univ->edgeattr->dict); i++) 01018 if (a == g->univ->edgeattr->list[i]) 01019 break; 01020 i++; 01021 if (i > dtsize(g->univ->edgeattr->dict)) 01022 return NULL; 01023 return g->univ->edgeattr->list[i]; 01024 #endif 01025 } 01026 01027 bool rm(Agraph_t *g) 01028 { 01029 Agedge_t *e; 01030 01031 if (!g) 01032 return false; 01033 #ifdef WITH_CGRAPH 01034 Agraph_t* sg; 01035 for (sg = agfstsubg (g); sg; sg = agnxtsubg (sg)) 01036 rm(sg); 01037 if (g == agroot(g)) 01038 agclose(g); 01039 else 01040 agdelete(agroot(g), g); 01041 return true; 01042 #else 01043 if (g->meta_node) { 01044 for (e = agfstout(g->meta_node->graph, g->meta_node); e; 01045 e = agnxtout(g->meta_node->graph, e)) { 01046 rm(agusergraph(aghead(e))); 01047 } 01048 if (g == agroot(g)) { 01049 agclose(g); 01050 } else { 01051 agdelete(g->meta_node->graph, g); 01052 } 01053 return true; 01054 } 01055 fprintf(stderr, "subgraph has no meta_node\n"); 01056 return false; 01057 #endif 01058 } 01059 01060 bool rm(Agnode_t *n) 01061 { 01062 if (!n) 01063 return false; 01064 // removal of the protonode is not permitted 01065 if (agnameof(n)[0] == '\001' && strcmp (agnameof(n), "\001proto") ==0) 01066 return false; 01067 agdelete(agraphof(n), n); 01068 return true; 01069 } 01070 01071 bool rm(Agedge_t *e) 01072 { 01073 if (!e) 01074 return false; 01075 // removal of the protoedge is not permitted 01076 if ((agnameof(aghead(e))[0] == '\001' && strcmp (agnameof(aghead(e)), "\001proto") == 0) 01077 || (agnameof(agtail(e))[0] == '\001' && strcmp (agnameof(agtail(e)), "\001proto") == 0)) 01078 return false; 01079 agdelete(agroot(agraphof(aghead(e))), e); 01080 return true; 01081 } 01082 01083 bool layout(Agraph_t *g, const char *engine) 01084 { 01085 int err; 01086 01087 if (!g) 01088 return false; 01089 err = gvFreeLayout(gvc, g); /* ignore errors */ 01090 err = gvLayout(gvc, g, engine); 01091 return (! err); 01092 } 01093 01094 // annotate the graph with layout information 01095 bool render(Agraph_t *g) 01096 { 01097 if (!g) 01098 return false; 01099 attach_attrs(g); 01100 return true; 01101 } 01102 01103 // render to stdout 01104 bool render(Agraph_t *g, const char *format) 01105 { 01106 int err; 01107 01108 if (!g) 01109 return false; 01110 err = gvRender(gvc, g, format, stdout); 01111 return (! err); 01112 } 01113 01114 // render to an open FILE 01115 bool render(Agraph_t *g, const char *format, FILE *f) 01116 { 01117 int err; 01118 01119 if (!g) 01120 return false; 01121 err = gvRender(gvc, g, format, f); 01122 return (! err); 01123 } 01124 01125 // render to an open channel 01126 bool renderchannel(Agraph_t *g, const char *format, const char *channelname) 01127 { 01128 int err; 01129 01130 if (!g) 01131 return false; 01132 gv_channel_writer_init(gvc); 01133 err = gvRender(gvc, g, format, (FILE*)channelname); 01134 return (! err); 01135 } 01136 01137 // render to a filename 01138 bool render(Agraph_t *g, const char *format, const char *filename) 01139 { 01140 int err; 01141 01142 if (!g) 01143 return false; 01144 err = gvRenderFilename(gvc, g, format, filename); 01145 return (! err); 01146 } 01147 01148 // render to string result, using binding-dependent gv_string_writer() 01149 void renderresult(Agraph_t *g, const char *format, char *outdata) 01150 { 01151 int err; 01152 01153 if (!g) 01154 return; 01155 gv_string_writer_init(gvc); 01156 err = gvRender(gvc, g, format, (FILE*)outdata); 01157 } 01158 01159 // render to a malloc'ed data string, to be free'd by caller. 01160 char* renderdata(Agraph_t *g, const char *format) 01161 { 01162 int err; 01163 char *data; 01164 unsigned int length; 01165 01166 if (!g) 01167 return NULL; 01168 err = gvRenderData(gvc, g, format, &data, &length); 01169 if (err) 01170 return NULL; 01171 data = (char*)realloc(data, length + 1); 01172 return data; 01173 } 01174 01175 bool write(Agraph_t *g, FILE *f) 01176 { 01177 int err; 01178 01179 if (!g) 01180 return false; 01181 err = agwrite(g, f); 01182 return (! err); 01183 } 01184 01185 bool write(Agraph_t *g, const char *filename) 01186 { 01187 FILE *f; 01188 int err; 01189 01190 if (!g) 01191 return false; 01192 f = fopen(filename, "w"); 01193 if (!f) 01194 return false; 01195 err = agwrite(g, f); 01196 fclose(f); 01197 return (! err); 01198 }
1.7.5