Graphviz 13.1.3~dev.20250831.0023
Loading...
Searching...
No Matches
gmlparse.y
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11%require "3.0"
12
13 /* By default, Bison emits a parser using symbols prefixed with "yy". Graphviz
14 * contains multiple Bison-generated parsers, so we alter this prefix to avoid
15 * symbol clashes.
16 */
17%define api.prefix {gml}
18
19%{
20#include <stdlib.h>
21#include <string.h>
22#include <arith.h>
23#include <gml2gv.h>
24#include <assert.h>
25#include <util/agxbuf.h>
26#include <util/alloc.h>
27#include <util/exit.h>
28#include <util/list.h>
29
30static gmlgraph* G;
31static gmlnode* N;
32static gmledge* E;
33
34static attrs_t *L;
35
36static void free_attrs(attrs_t *a) {
37 LIST_FREE(a);
38 free(a);
39}
40
41static LIST(attrs_t *) liststk = {.dtor = free_attrs};
42
43static char *sortToStr(unsigned short sort);
44
45static void free_node(gmlnode *p) {
46 if (!p) return;
48 free(p->id);
49 free (p);
50}
51
52static void free_edge(gmledge *p) {
53 if (!p) return;
55 free (p);
56}
57
58static void free_graph(gmlgraph *p) {
59 if (!p) return;
60 LIST_FREE(&p->nodelist);
61 LIST_FREE(&p->edgelist);
63 LIST_FREE(&p->graphlist);
64 free (p);
65}
66
67static void
68cleanup (void)
69{
70 LIST_CLEAR(&liststk);
71 if (L) {
73 L = NULL;
74 }
75 if (N) {
76 free_node(N);
77 N = NULL;
78 }
79 if (E) {
80 free_edge(E);
81 E = NULL;
82 }
83 if (G) {
85 G = NULL;
86 }
87}
88
89static void free_attr(gmlattr *p);
90
91static void
92pushAlist (void)
93{
94 attrs_t *const lp = gv_alloc(sizeof(attrs_t));
95 lp->dtor = free_attr;
96
97 if (L) {
98 LIST_PUSH_BACK(&liststk, L);
99 }
100 L = lp;
101}
102
103static attrs_t *popAlist(void) {
104 attrs_t *lp = L;
105
106 if (!LIST_IS_EMPTY(&liststk))
107 L = LIST_POP_BACK(&liststk);
108 else
109 L = NULL;
110
111 return lp;
112}
113
114static void
115popG (void)
116{
117 G = G->parent;
118}
119
120static void
121pushG (void)
122{
123 gmlgraph* g = gv_alloc(sizeof(gmlgraph));
124
125 g->attrlist.dtor = free_attr;
126 g->nodelist.dtor = free_node;
127 g->edgelist.dtor = free_edge;
128 g->graphlist.dtor = free_graph;
129 g->parent = G;
130 g->directed = -1;
131
132 if (G)
133 LIST_APPEND(&G->graphlist, g);
134
135 G = g;
136}
137
138static gmlnode*
139mkNode (void)
140{
141 gmlnode *const n = gv_alloc(sizeof(gmlnode));
142 n->attrlist.dtor = free_attr;
143 return n;
144}
145
146static gmledge*
147mkEdge (void)
148{
149 gmledge* ep = gv_alloc(sizeof(gmledge));
150 ep->attrlist.dtor = free_attr;
151 return ep;
152}
153
154static gmlattr *mkAttr(char* name, unsigned short sort, unsigned short kind,
155 char* str, attrs_t* list) {
156 gmlattr* gp = gv_alloc(sizeof(gmlattr));
157
158 assert (name || sort);
159 if (!name)
160 name = gv_strdup (sortToStr (sort));
161 gp->sort = sort;
162 gp->kind = kind;
163 gp->name = name;
164 if (str)
165 gp->u.value = str;
166 else {
167 if (list != NULL && LIST_IS_EMPTY(list)) {
168 free_attrs(list);
169 list = 0;
170 }
171 gp->u.lp = list;
172 }
173 return gp;
174}
175
176static int
177setDir (char* d)
178{
179 gmlgraph* g;
180 int dir = atoi (d);
181
182 free (d);
183 if (dir < 0) dir = -1;
184 else if (dir > 0) dir = 1;
185 else dir = 0;
186 G->directed = dir;
187
188 if (dir >= 0) {
189 for (g = G->parent; g; g = g->parent) {
190 if (g->directed < 0)
191 g->directed = dir;
192 else if (g->directed != dir)
193 return 1;
194 }
195 }
196
197 return 0;
198}
199
200%}
201%union {
202 int i;
203 char *str;
204 gmlnode* np;
205 gmledge* ep;
206 gmlattr* ap;
207 attrs_t *list;
208}
209
213%token STYLE LINE POINT
215%token <str> INTEGER REAL STRING ID NAME
216%token <list> GML_LIST
217
218%type <np> node
219%type <ep> edge
220%type <list> attrlist
221%type <ap> alistitem
222
223%%
224graph : optalist hdr body {gmllexeof(); if (G->parent) popG(); }
225 | error { cleanup(); YYABORT; }
226 |
227 ;
228
229hdr : GRAPH { pushG(); }
230 ;
231
232body : '[' optglist ']'
233 ;
234
235optglist : glist
236 | /* empty */
237 ;
238
239glist : glist glistitem
240 | glistitem
241 ;
242
243glistitem : node { LIST_APPEND(&G->nodelist, $1); }
244 | edge { LIST_APPEND(&G->edgelist, $1); }
245 | hdr body
247 if (setDir($2)) {
248 yyerror("mixed directed and undirected graphs");
249 cleanup ();
250 YYABORT;
251 }
252 }
253 | ID INTEGER { LIST_APPEND(&G->attrlist, mkAttr(gv_strdup("id"), 0, INTEGER, $2, 0)); }
254 | alistitem { LIST_APPEND(&G->attrlist, $1); }
255 ;
256
257node : NODE { N = mkNode(); } '[' nlist ']' { $$ = N; N = NULL; }
258 ;
259
260nlist : nlist nlistitem
261 | nlistitem
262 ;
263
264nlistitem : ID INTEGER { N->id = $2; }
265 | alistitem { LIST_APPEND(&N->attrlist, $1); }
266 ;
267
268edge : EDGE { E = mkEdge(); } '[' elist ']' { $$ = E; E = NULL; }
269 ;
270
271elist : elist elistitem
272 | elistitem
273 ;
274
275elistitem : SOURCE INTEGER { E->source = $2; }
276 | TARGET INTEGER { E->target = $2; }
277 | ID INTEGER { LIST_APPEND(&E->attrlist, mkAttr(gv_strdup("id"), 0, INTEGER, $2, 0)); }
278 | alistitem { LIST_APPEND(&E->attrlist, $1); }
279 ;
280
281attrlist : '[' {pushAlist(); } optalist ']' { $$ = popAlist(); }
282 ;
283
284optalist : alist
285 | /* empty */
286 ;
287
288alist : alist alistitem { LIST_APPEND(L, $2); }
289 | alistitem { LIST_APPEND(L, $1); }
290 ;
291
293 | NAME REAL { $$ = mkAttr ($1, 0, REAL, $2, 0); }
294 | NAME STRING { $$ = mkAttr ($1, 0, STRING, $2, 0); }
295 | NAME attrlist { $$ = mkAttr ($1, 0, GML_LIST, 0, $2); }
296 | XVAL REAL { $$ = mkAttr (0, XVAL, REAL, $2, 0); }
297 | XVAL INTEGER { $$ = mkAttr (0, XVAL, REAL, $2, 0); }
298 | YVAL REAL { $$ = mkAttr (0, YVAL, REAL, $2, 0); }
299 | WVAL REAL { $$ = mkAttr (0, WVAL, REAL, $2, 0); }
300 | HVAL REAL { $$ = mkAttr (0, HVAL, REAL, $2, 0); }
301 | LABEL STRING { $$ = mkAttr (0, LABEL, STRING, $2, 0); }
302 | GRAPHICS attrlist { $$ = mkAttr (0, GRAPHICS, GML_LIST, 0, $2); }
304 | TYPE STRING { $$ = mkAttr (0, TYPE, STRING, $2, 0); }
305 | FILL STRING { $$ = mkAttr (0, FILL, STRING, $2, 0); }
306 | OUTLINE STRING { $$ = mkAttr (0, OUTLINE, STRING, $2, 0); }
309 | WIDTH REAL { $$ = mkAttr (0, WIDTH, REAL, $2, 0); }
310 | WIDTH INTEGER { $$ = mkAttr (0, WIDTH, INTEGER, $2, 0); }
311 | STYLE STRING { $$ = mkAttr (0, STYLE, STRING, $2, 0); }
312 | STYLE attrlist { $$ = mkAttr (0, STYLE, GML_LIST, 0, $2); }
313 | LINE attrlist { $$ = mkAttr (0, LINE, GML_LIST, 0, $2); }
314 | POINT attrlist { $$ = mkAttr (0, POINT, GML_LIST, 0, $2); }
315 | TEXT STRING { $$ = mkAttr (0, TEXT, STRING, $2, 0); }
316 | FONTNAME STRING { $$ = mkAttr (0, FONTNAME, STRING, $2, 0); }
317 | FONTSIZE INTEGER { $$ = mkAttr (0, FONTNAME, INTEGER, $2, 0); }
318 | COLOR STRING { $$ = mkAttr (0, COLOR, STRING, $2, 0); }
319 ;
320
321%%
322
323static void free_attr(gmlattr *p) {
324 if (!p) return;
325 if (p->kind == GML_LIST && p->u.lp)
326 free_attrs(p->u.lp);
327 else
328 free (p->u.value);
329 free (p->name);
330 free (p);
331}
332
333static void deparseList(attrs_t *alist, agxbuf *xb);
334
335static void
337{
338 if (ap->kind == GML_LIST) {
339 agxbprint (xb, "%s ", ap->name);
340 deparseList (ap->u.lp, xb);
341 }
342 else if (ap->kind == STRING) {
343 agxbprint (xb, "%s \"%s\"", ap->name, ap->u.value);
344 }
345 else {
346 agxbprint (xb, "%s %s", ap->name, ap->u.value);
347 }
348}
349
350static void deparseList(attrs_t *alist, agxbuf *xb) {
351 agxbput (xb, "[ ");
352 for (size_t i = 0; alist != NULL && i < LIST_SIZE(alist); ++i) {
353 gmlattr *const ap = LIST_GET(alist, i);
354 deparseAttr (ap, xb);
355 agxbputc (xb, ' ');
356 }
357 agxbput (xb, "]");
358
359}
360
361static void
363{
364 char* str;
365
366 if (ap->kind == GML_LIST) {
367 deparseList (ap->u.lp, xb);
368 str = agxbuse (xb);
369 }
370 else
371 str = ap->u.value;
372
373 agsafeset (obj, ap->name, str, "");
374}
375
376static void addNodeLabelGraphics(Agnode_t *np, attrs_t *alist, agxbuf *unk) {
377 int cnt = 0;
378
379 if (!alist)
380 return;
381
382 for (size_t i = 0; i < LIST_SIZE(alist); ++i) {
383 gmlattr *const ap = LIST_GET(alist, i);
384 if (ap->sort == TEXT) {
385 agsafeset (np, "label", ap->u.value, "");
386 }
387 else if (ap->sort == COLOR) {
388 agsafeset (np, "fontcolor", ap->u.value, "");
389 }
390 else if (ap->sort == FONTSIZE) {
391 agsafeset (np, "fontsize", ap->u.value, "");
392 }
393 else if (ap->sort == FONTNAME) {
394 agsafeset (np, "fontname", ap->u.value, "");
395 }
396 else {
397 if (cnt)
398 agxbputc (unk, ' ');
399 else {
400 agxbput (unk, "[ ");
401 }
402 deparseAttr (ap, unk);
403 cnt++;
404 }
405 }
406
407 if (cnt) {
408 agxbput (unk, " ]");
409 agsafeset (np, "LabelGraphics", agxbuse (unk), "");
410 }
411 else
412 agxbclear (unk);
413}
414
415static void addEdgeLabelGraphics(Agedge_t *ep, attrs_t *alist, agxbuf *xb,
416 agxbuf *unk) {
417 char* x = "0";
418 char* y = "0";
419 int cnt = 0;
420
421 if (!alist)
422 return;
423
424 for (size_t i = 0; i < LIST_SIZE(alist); ++i) {
425 gmlattr *const ap = LIST_GET(alist, i);
426 if (ap->sort == TEXT) {
427 agsafeset (ep, "label", ap->u.value, "");
428 }
429 else if (ap->sort == COLOR) {
430 agsafeset (ep, "fontcolor", ap->u.value, "");
431 }
432 else if (ap->sort == FONTSIZE) {
433 agsafeset (ep, "fontsize", ap->u.value, "");
434 }
435 else if (ap->sort == FONTNAME) {
436 agsafeset (ep, "fontname", ap->u.value, "");
437 }
438 else if (ap->sort == XVAL) {
439 x = ap->u.value;
440 }
441 else if (ap->sort == YVAL) {
442 y = ap->u.value;
443 }
444 else {
445 if (cnt)
446 agxbputc (unk, ' ');
447 else {
448 agxbput (unk, "[ ");
449 }
450 deparseAttr (ap, unk);
451 cnt++;
452 }
453 }
454
455 agxbprint (xb, "%s,%s", x, y);
456 agsafeset (ep, "lp", agxbuse (xb), "");
457
458 if (cnt) {
459 agxbput (unk, " ]");
460 agsafeset (ep, "LabelGraphics", agxbuse (unk), "");
461 }
462 else
463 agxbclear (unk);
464}
465
466static void addNodeGraphics(Agnode_t *np, attrs_t *alist, agxbuf *xb,
467 agxbuf *unk) {
468 char* x = "0";
469 char* y = "0";
470 char buf[BUFSIZ];
471 double d;
472 int cnt = 0;
473
474 for (size_t i = 0; alist != NULL && i < LIST_SIZE(alist); ++i) {
475 gmlattr *const ap = LIST_GET(alist, i);
476 if (ap->sort == XVAL) {
477 x = ap->u.value;
478 }
479 else if (ap->sort == YVAL) {
480 y = ap->u.value;
481 }
482 else if (ap->sort == WVAL) {
483 d = atof (ap->u.value);
484 snprintf(buf, sizeof(buf), "%.04f", d/72.0);
485 agsafeset (np, "width", buf, "");
486 }
487 else if (ap->sort == HVAL) {
488 d = atof (ap->u.value);
489 snprintf(buf, sizeof(buf), "%.04f", d/72.0);
490 agsafeset (np, "height", buf, "");
491 }
492 else if (ap->sort == TYPE) {
493 agsafeset (np, "shape", ap->u.value, "");
494 }
495 else if (ap->sort == FILL) {
496 agsafeset (np, "color", ap->u.value, "");
497 }
498 else if (ap->sort == OUTLINE) {
499 agsafeset (np, "pencolor", ap->u.value, "");
500 }
501 else if (ap->sort == WIDTH || ap->sort == OUTLINEWIDTH) {
502 agsafeset (np, "penwidth", ap->u.value, "");
503 }
504 else if (ap->sort == STYLE || ap->sort == OUTLINESTYLE) {
505 agsafeset (np, "style", ap->u.value, "");
506 }
507 else {
508 if (cnt)
509 agxbputc (unk, ' ');
510 else {
511 agxbput (unk, "[ ");
512 }
513 deparseAttr (ap, unk);
514 cnt++;
515 }
516 }
517
518 agxbprint (xb, "%s,%s", x, y);
519 agsafeset (np, "pos", agxbuse (xb), "");
520
521 if (cnt) {
522 agxbput (unk, " ]");
523 agsafeset (np, "graphics", agxbuse (unk), "");
524 }
525 else
526 agxbclear (unk);
527}
528
529static void addEdgePoint(Agedge_t *ep, attrs_t *alist, agxbuf *xb) {
530 char* x = "0";
531 char* y = "0";
532
533 for (size_t i = 0; alist != NULL && i < LIST_SIZE(alist); ++i) {
534 gmlattr *const ap = LIST_GET(alist, i);
535 if (ap->sort == XVAL) {
536 x = ap->u.value;
537 }
538 else if (ap->sort == YVAL) {
539 y = ap->u.value;
540 }
541 else {
542 fprintf (stderr, "non-X/Y field in point attribute");
543 unknown ((Agobj_t*)ep, ap, xb);
544 }
545 }
546
547 if (agxblen(xb)) agxbputc (xb, ' ');
548 agxbprint (xb, "%s,%s", x, y);
549}
550
551static void addEdgePos(Agedge_t *ep, attrs_t *alist, agxbuf *xb) {
552 if (!alist) return;
553 for (size_t i = 0; i < LIST_SIZE(alist); ++i) {
554 gmlattr *const ap = LIST_GET(alist, i);
555 if (ap->sort == POINT) {
556 addEdgePoint (ep, ap->u.lp, xb);
557 }
558 else {
559 fprintf (stderr, "non-point field in line attribute");
560 unknown ((Agobj_t*)ep, ap, xb);
561 }
562 }
563 agsafeset (ep, "pos", agxbuse (xb), "");
564}
565
566static void addEdgeGraphics(Agedge_t *ep, attrs_t *alist, agxbuf *xb,
567 agxbuf *unk) {
568 int cnt = 0;
569
570 for (size_t i = 0; alist != NULL && i < LIST_SIZE(alist); ++i) {
571 gmlattr *const ap = LIST_GET(alist, i);
572 if (ap->sort == WIDTH) {
573 agsafeset (ep, "penwidth", ap->u.value, "");
574 }
575 else if (ap->sort == STYLE) {
576 agsafeset (ep, "style", ap->u.value, "");
577 }
578 else if (ap->sort == FILL) {
579 agsafeset (ep, "color", ap->u.value, "");
580 }
581 else if (ap->sort == LINE) {
582 addEdgePos (ep, ap->u.lp, xb);
583 }
584 else {
585 if (cnt)
586 agxbputc (unk, ' ');
587 else {
588 agxbput (unk, "[ ");
589 }
590 deparseAttr (ap, unk);
591 cnt++;
592 }
593 }
594
595 if (cnt) {
596 agxbput (unk, " ]");
597 agsafeset (ep, "graphics", agxbuse (unk), "");
598 }
599 else
600 agxbclear(unk);
601}
602
603static void addAttrs(Agobj_t *obj, attrs_t *alist, agxbuf *xb, agxbuf *unk) {
604 for (size_t i = 0; i < LIST_SIZE(alist); ++i) {
605 gmlattr *const ap = LIST_GET(alist, i);
606 if (ap->sort == GRAPHICS) {
607 if (AGTYPE(obj) == AGNODE)
608 addNodeGraphics ((Agnode_t*)obj, ap->u.lp, xb, unk);
609 else if (AGTYPE(obj) == AGEDGE)
610 addEdgeGraphics ((Agedge_t*)obj, ap->u.lp, xb, unk);
611 else
612 unknown (obj, ap, xb);
613 }
614 else if (ap->sort == LABELGRAPHICS) {
615 if (AGTYPE(obj) == AGNODE)
616 addNodeLabelGraphics ((Agnode_t*)obj, ap->u.lp, unk);
617 else if (AGTYPE(obj) == AGEDGE)
618 addEdgeLabelGraphics ((Agedge_t*)obj, ap->u.lp, xb, unk);
619 else
620 unknown (obj, ap, xb);
621 }
622 else
623 unknown (obj, ap, xb);
624 }
625}
626
628 agxbuf *xb, agxbuf *unk) {
629 Agraph_t* g;
630 Agnode_t* n;
631 Agnode_t* h;
632 Agedge_t* e;
633
634 if (parent) {
635 g = agsubg (parent, NULL, 1);
636 }
637 else if (graph->directed >= 1)
638 g = agopen (name, Agdirected, 0);
639 else
640 g = agopen (name, Agundirected, 0);
641
642 if (!parent && L) {
643 addAttrs ((Agobj_t*)g, L, xb, unk);
644 }
645 for (size_t i = 0; i < LIST_SIZE(&graph->nodelist); ++i) {
646 gmlnode *const np = LIST_GET(&graph->nodelist, i);
647 if (!np->id) {
648 fprintf (stderr, "node without an id attribute");
649 graphviz_exit (1);
650 }
651 n = agnode (g, np->id, 1);
652 addAttrs((Agobj_t*)n, &np->attrlist, xb, unk);
653 }
654
655 for (size_t i = 0; i < LIST_SIZE(&graph->edgelist); ++i) {
656 gmledge *ep = LIST_GET(&graph->edgelist, i);
657 if (!ep->source) {
658 fprintf (stderr, "edge without an source attribute");
659 graphviz_exit (1);
660 }
661 if (!ep->target) {
662 fprintf (stderr, "node without an target attribute");
663 graphviz_exit (1);
664 }
665 n = agnode (g, ep->source, 1);
666 h = agnode (g, ep->target, 1);
667 e = agedge (g, n, h, NULL, 1);
668 addAttrs((Agobj_t*)e, &ep->attrlist, xb, unk);
669 }
670 for (size_t i = 0; i < LIST_SIZE(&graph->graphlist); ++i) {
671 gmlgraph *const gp = LIST_GET(&graph->graphlist, i);
672 mkGraph (gp, g, NULL, xb, unk);
673 }
674
675 addAttrs((Agobj_t*)g, &graph->attrlist, xb, unk);
676
677 return g;
678}
679
681gml_to_gv (char* name, FILE* fp, int cnt, int* errors)
682{
683 Agraph_t* g;
684 int error;
685
686 if (cnt == 0)
687 initgmlscan(fp);
688 else
689 initgmlscan(0);
690
691 L = NULL;
692 pushAlist ();
693 gmlparse ();
694
695 error = gmlerrors();
696 *errors |= error;
697 if (!G || error)
698 g = NULL;
699 else {
700 agxbuf xb = {0};
701 agxbuf unk = {0};
702 g = mkGraph (G, NULL, name, &xb, &unk);
703 agxbfree (&xb);
704 agxbfree(&unk);
705 }
706
707 cleanup ();
708
709 return g;
710}
711
712static char *sortToStr(unsigned short sort) {
713 char* s;
714
715 switch (sort) {
716 case GRAPH :
717 s = "graph"; break;
718 case NODE :
719 s = "node"; break;
720 case EDGE :
721 s = "edge"; break;
722 case DIRECTED :
723 s = "directed"; break;
724 case ID :
725 s = "id"; break;
726 case SOURCE :
727 s = "source"; break;
728 case TARGET :
729 s = "target"; break;
730 case XVAL :
731 s = "xval"; break;
732 case YVAL :
733 s = "yval"; break;
734 case WVAL :
735 s = "wval"; break;
736 case HVAL :
737 s = "hval"; break;
738 case LABEL :
739 s = "label"; break;
740 case GRAPHICS :
741 s = "graphics"; break;
742 case LABELGRAPHICS :
743 s = "labelGraphics"; break;
744 case TYPE :
745 s = "type"; break;
746 case FILL :
747 s = "fill"; break;
748 case OUTLINE :
749 s = "outline"; break;
750 case OUTLINESTYLE :
751 s = "outlineStyle"; break;
752 case OUTLINEWIDTH :
753 s = "outlineWidth"; break;
754 case WIDTH :
755 s = "width"; break;
756 case STYLE :
757 s = "style"; break;
758 case LINE :
759 s = "line"; break;
760 case POINT :
761 s = "point"; break;
762 case TEXT :
763 s = "text"; break;
764 case FONTSIZE :
765 s = "fontSize"; break;
766 case FONTNAME :
767 s = "fontName"; break;
768 case COLOR :
769 s = "color"; break;
770 case INTEGER :
771 s = "integer"; break;
772 case REAL :
773 s = "real"; break;
774 case STRING :
775 s = "string"; break;
776 case NAME :
777 s = "name"; break;
778 case GML_LIST :
779 s = "list"; break;
780 case '[' :
781 s = "["; break;
782 case ']' :
783 s = "]"; break;
784 default :
785 s = NULL;break;
786 }
787
788 return s;
789}
static void agxbfree(agxbuf *xb)
free any malloced resources
Definition agxbuf.h:77
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
Definition agxbuf.h:233
static void agxbclear(agxbuf *xb)
resets pointer to data
Definition agxbuf.h:293
static WUR char * agxbuse(agxbuf *xb)
Definition agxbuf.h:306
static size_t agxblen(const agxbuf *xb)
return number of characters currently stored
Definition agxbuf.h:88
static int agxbputc(agxbuf *xb, char c)
add character to buffer
Definition agxbuf.h:276
Memory allocation wrappers that exit on failure.
static char * gv_strdup(const char *original)
Definition alloc.h:101
static void * gv_alloc(size_t size)
Definition alloc.h:47
#define parent(i)
Definition closest.c:81
static NORETURN void graphviz_exit(int status)
Definition exit.h:23
#define DIRECTED
Definition gc.c:48
#define G
Definition gdefs.h:7
GML-DOT converter
int gmlerrors(void)
Definition gmlscan.l:121
void initgmlscan(FILE *)
Definition gmlscan.c:850
void gmllexeof(void)
Definition gmlscan.l:126
static void free_attrs(attrs_t *a)
Definition gmlparse.c:96
#define YYABORT
Definition gmlparse.c:938
static attrs_t * L
Definition gmlparse.c:94
static void cleanup(void)
Definition gmlparse.c:128
static gmlnode * mkNode(void)
Definition gmlparse.c:199
static int setDir(char *d)
Definition gmlparse.c:237
static void free_edge(gmledge *p)
Definition gmlparse.c:112
static void free_node(gmlnode *p)
Definition gmlparse.c:105
static gmledge * mkEdge(void)
Definition gmlparse.c:207
static void pushAlist(void)
Definition gmlparse.c:152
static void free_graph(gmlgraph *p)
Definition gmlparse.c:118
static void popG(void)
Definition gmlparse.c:175
static gmlattr * mkAttr(char *name, unsigned short sort, unsigned short kind, char *str, attrs_t *list)
Definition gmlparse.c:214
void free(void *)
static void pushG(void)
Definition gmlparse.c:181
#define yyerror
Definition gmlparse.c:71
static attrs_t * popAlist(void)
Definition gmlparse.c:163
#define LABEL
Definition gmlparse.h:115
#define OUTLINESTYLE
Definition gmlparse.h:121
#define WIDTH
Definition gmlparse.h:123
#define GRAPHICS
Definition gmlparse.h:116
#define POINT
Definition gmlparse.h:126
#define NAME
Definition gmlparse.h:135
#define COLOR
Definition gmlparse.h:130
#define TEXT
Definition gmlparse.h:127
#define TYPE
Definition gmlparse.h:118
#define FONTSIZE
Definition gmlparse.h:128
#define GML_LIST
Definition gmlparse.h:136
#define FILL
Definition gmlparse.h:119
#define ID
Definition gmlparse.h:134
#define OUTLINEWIDTH
Definition gmlparse.h:122
#define SOURCE
Definition gmlparse.h:109
int gmlparse(void)
#define NODE
Definition gmlparse.h:106
#define TARGET
Definition gmlparse.h:110
#define WVAL
Definition gmlparse.h:113
#define EDGE
Definition gmlparse.h:107
#define STYLE
Definition gmlparse.h:124
#define HVAL
Definition gmlparse.h:114
#define YVAL
Definition gmlparse.h:112
#define FONTNAME
Definition gmlparse.h:129
#define LABELGRAPHICS
Definition gmlparse.h:117
#define XVAL
Definition gmlparse.h:111
#define LINE
Definition gmlparse.h:125
#define OUTLINE
Definition gmlparse.h:120
#define GRAPH
Definition gmlparse.h:105
static char * sortToStr(unsigned short sort)
Definition gmlparse.y:712
static void addEdgeGraphics(Agedge_t *ep, attrs_t *alist, agxbuf *xb, agxbuf *unk)
Definition gmlparse.y:566
static void addAttrs(Agobj_t *obj, attrs_t *alist, agxbuf *xb, agxbuf *unk)
Definition gmlparse.y:603
static void deparseAttr(gmlattr *ap, agxbuf *xb)
Definition gmlparse.y:336
alist $2
Definition gmlparse.y:288
static void addEdgeLabelGraphics(Agedge_t *ep, attrs_t *alist, agxbuf *xb, agxbuf *unk)
Definition gmlparse.y:415
glistitem $1
Definition gmlparse.y:243
alistitem NAME REAL
Definition gmlparse.y:293
static void addNodeLabelGraphics(Agnode_t *np, attrs_t *alist, agxbuf *unk)
Definition gmlparse.y:376
edge
Definition gmlparse.y:244
static Agraph_t * mkGraph(gmlgraph *graph, Agraph_t *parent, char *name, agxbuf *xb, agxbuf *unk)
Definition gmlparse.y:627
static void addNodeGraphics(Agnode_t *np, attrs_t *alist, agxbuf *xb, agxbuf *unk)
Definition gmlparse.y:466
static void addEdgePoint(Agedge_t *ep, attrs_t *alist, agxbuf *xb)
Definition gmlparse.y:529
static void addEdgePos(Agedge_t *ep, attrs_t *alist, agxbuf *xb)
Definition gmlparse.y:551
N
Definition gmlparse.y:257
static void free_attr(gmlattr *p)
Definition gmlparse.y:323
E
Definition gmlparse.y:268
NAME STRING
Definition gmlparse.y:294
hdr body DIRECTED INTEGER
Definition gmlparse.y:246
static void deparseList(attrs_t *alist, agxbuf *xb)
Definition gmlparse.y:350
alistitem
Definition gmlparse.y:265
optalist
Definition gmlparse.y:281
NAME attrlist
Definition gmlparse.y:295
Agraph_t * gml_to_gv(char *name, FILE *fp, int cnt, int *errors)
Definition gmlparse.y:681
static int errors
Definition gmlscan.c:847
body
Definition grammar.y:215
node NULL
Definition grammar.y:181
static int cnt(Dict_t *d, Dtlink_t **set)
Definition graph.c:196
int agsafeset(void *obj, char *name, const char *value, const char *def)
set an attribute’s value and default, ensuring it is declared before setting it locally
Definition attr.c:560
Agedge_t * agedge(Agraph_t *g, Agnode_t *t, Agnode_t *h, char *name, int createflag)
Definition edge.c:253
Agdesc_t Agundirected
undirected
Definition graph.c:272
Agraph_t * agopen(char *name, Agdesc_t desc, Agdisc_t *disc)
creates a new graph with the given name and kind
Definition graph.c:42
Agdesc_t Agdirected
directed
Definition graph.c:270
Agnode_t * agnode(Agraph_t *g, char *name, int createflag)
Definition node.c:141
#define AGTYPE(obj)
returns AGRAPH, AGNODE, or AGEDGE depending on the type of the object
Definition cgraph.h:216
@ AGEDGE
Definition cgraph.h:207
@ AGNODE
Definition cgraph.h:207
Agraph_t * agsubg(Agraph_t *g, char *name, int cflag)
Definition subg.c:53
Agraph_t * graph(char *name)
Definition gv.cpp:30
agxbput(xb, staging)
@ unknown
Definition gvgen.c:33
textitem scanner parser str
Definition htmlparse.y:218
table Syntax error
Definition htmlparse.y:288
$$
Definition htmlparse.y:321
type-generic dynamically expanding list
#define LIST(type)
Definition list.h:55
#define LIST_SIZE(list)
Definition list.h:80
#define LIST_CLEAR(list)
Definition list.h:249
#define LIST_APPEND(list, item)
Definition list.h:132
#define LIST_FREE(list)
Definition list.h:379
#define LIST_POP_BACK(list)
Definition list.h:416
#define LIST_IS_EMPTY(list)
Definition list.h:90
#define LIST_PUSH_BACK(list, item)
Definition list.h:393
#define LIST_GET(list, index)
Definition list.h:165
a generic header of Agraph_s, Agnode_s and Agedge_s
Definition cgraph.h:210
graph or subgraph
Definition cgraph.h:424
Definition types.h:251
void * lp
actually an attrs_t *
Definition gml2gv.h:16
char * value
Definition gml2gv.h:15
unsigned short kind
Definition gml2gv.h:11
union gmlattr::@59 u
unsigned short sort
Definition gml2gv.h:12
char * name
Definition gml2gv.h:13
char * source
Definition gml2gv.h:28
attrs_t attrlist
Definition gml2gv.h:30
char * target
Definition gml2gv.h:29
int directed
Definition gml2gv.h:35
struct gmlgraph * parent
Definition gml2gv.h:34
attrs_t attrlist
Definition gml2gv.h:36
attrs_t attrlist
Definition gml2gv.h:24
char * id
Definition gml2gv.h:23
Definition grammar.c:90