Graphviz 13.0.0~dev.20250121.0651
Loading...
Searching...
No Matches
grammar.y
Go to the documentation of this file.
1
5/*************************************************************************
6 * Copyright (c) 2011 AT&T Intellectual Property
7 * All rights reserved. This program and the accompanying materials
8 * are made available under the terms of the Eclipse Public License v1.0
9 * which accompanies this distribution, and is available at
10 * https://www.eclipse.org/legal/epl-v10.html
11 *
12 * Contributors: Details at https://graphviz.org
13 *************************************************************************/
14
15%require "3.0"
16
17 /* By default, Bison emits a parser using symbols prefixed with "yy". Graphviz
18 * contains multiple Bison-generated parsers, so we alter this prefix to avoid
19 * symbol clashes.
20 */
21%define api.prefix {aag}
22%code requires {
23#include <cghdr.h>
24#include <util/agxbuf.h>
25
26struct gstack_s;
27
28struct aagextra_s {
29 int dummy; /* struct must not be empty */
30 /* Common */
31 /* Parser */
32 /* Lexer */
33};
34
35}
36
37%{
38
39#include <stdbool.h>
40#include <stdio.h>
41#include <cghdr.h>
42#include <stdlib.h>
43#include <util/alloc.h>
44#include <util/streq.h>
45#include <util/unreachable.h>
46
47extern void aagerror(const char*);
48
49static const char Key[] = "key";
50static int SubgraphDepth = 0;
51
52typedef union s { /* possible items in generic list */
53 Agnode_t *n;
55 Agedge_t *e;
56 Agsym_t *asym; /* bound attribute */
57 char *name; /* unbound attribute */
58 struct item_s *list; /* list-of-lists (for edgestmt) */
59} val_t;
60
61typedef struct item_s { /* generic list */
62 int tag; /* T_node, T_subgraph, T_edge, T_attr */
63 val_t u; /* primary element */
64 char *str; /* secondary value - port or attr value */
65 struct item_s *next;
66} item;
67
68typedef struct list_s { /* maintain head and tail ptrs for fast append */
69 item *first;
70 item *last;
71} list_t;
72
73typedef struct gstack_s {
74 Agraph_t *g;
77 struct gstack_s *down;
78} gstack_t;
79
80/* functions */
81static void appendnode(char *name, char *port, char *sport);
82static void attrstmt(int tkind, char *macroname);
83static void startgraph(char *name, bool directed, bool strict);
84static void getedgeitems(void);
85static void newedge(Agnode_t *t, char *tport, Agnode_t *h, char *hport, char *key);
86static void edgerhs(Agnode_t *n, char *tport, item *hlist, char *key);
87static void appendattr(char *name, char *value);
88static void bindattrs(int kind);
89static void applyattrs(void *obj);
90static void endgraph(void);
91static void endnode(void);
92static void endedge(void);
93static void freestack(void);
94static char* concat(char*, char*);
95static char* concatPort(char*, char*);
96
97static void opensubg(char *name);
98static void closesubg(void);
99
100/* global */
101static Agraph_t *G; /* top level graph */
102static Agdisc_t *Disc; /* discipline passed to agread or agconcat */
103static gstack_t *S;
104
105%}
106
107%union {
108 int i;
109 char *str;
110 struct Agnode_s *n;
111}
112
114 /* T_list, T_attr are internal tags, not really tokens */
115%token T_list T_attr
116%token <str> T_atom T_qatom
117
118%type <i> optstrict graphtype rcompound attrtype
119%type <str> optsubghdr optgraphname optmacroname atom qatom
120
121
122%%
123
124graph : hdr body {freestack(); endgraph();}
125 | error {if (G) {freestack(); endgraph(); agclose(G); G = Ag_G_global = NULL;}}
126 | /* empty */
127 ;
128
129body : '{' optstmtlist '}' ;
130
131hdr : optstrict graphtype optgraphname {startgraph($3,$2 != 0,$1 != 0);}
132 ;
133
134optgraphname: atom {$$=$1;} | /* empty */ {$$=0;} ;
135
136optstrict : T_strict {$$=1;} | /* empty */ {$$=0;} ;
137
138graphtype : T_graph {$$ = 0;} | T_digraph {$$ = 1;} ;
139
140optstmtlist : stmtlist | /* empty */ ;
141
142stmtlist : stmtlist stmt | stmt ;
143
144optsemi : ';' | ;
145
146stmt : attrstmt optsemi
147 | compound optsemi
148 ;
149
150compound : simple rcompound optattr
151 {if ($2) endedge(); else endnode();}
152 ;
153
154simple : nodelist | subgraph ;
155
157 | /* empty */ {$$ = 0;}
158 ;
159
160
161nodelist : node | nodelist ',' node ;
162
164 | atom ':' atom {appendnode($1,$3,NULL);}
165 | atom ':' atom ':' atom {appendnode($1,$3,$5);}
166 ;
167
168attrstmt : attrtype optmacroname attrlist {attrstmt($1,$2);}
170 ;
171
172attrtype : T_graph {$$ = T_graph;}
175 ;
176
177optmacroname : atom '=' {$$ = $1;}
178 | /* empty */ {$$ = NULL; }
179 ;
180
181optattr : attrlist | /* empty */ ;
182
183attrlist : optattr '[' optattrdefs ']' ;
184
185optattrdefs : optattrdefs attrdefs
186 | /* empty */ ;
187
188attrdefs : attrassignment optseparator
189 ;
190
191attrassignment : atom '=' atom {appendattr($1,$3);}
192 ;
193
194graphattrdefs : attrassignment
195 ;
196
197subgraph : optsubghdr {opensubg($1);} body {closesubg();}
198 ;
199
200optsubghdr : T_subgraph atom {$$=$2;}
202 | /* empty */ {$$=NULL;}
203 ;
204
205optseparator : ';' | ',' | /*empty*/ ;
206
207atom : T_atom {$$ = $1;}
208 | qatom {$$ = $1;}
209 ;
210
213 ;
214%%
215
216static item *newitem(int tag, void *p0, char *p1)
217{
218 item *rv = gv_alloc(sizeof(item));
219 rv->tag = tag;
220 rv->u.name = p0;
221 rv->str = p1;
222 return rv;
223}
224
225static item *cons_node(Agnode_t *n, char *port)
226 { return newitem(T_node,n,port); }
227
228static item *cons_attr(char *name, char *value)
229 { return newitem(T_atom,name,value); }
230
231static item *cons_list(item *list)
232 { return newitem(T_list,list,NULL); }
233
234static item *cons_subg(Agraph_t *subg)
235 { return newitem(T_subgraph,subg,NULL); }
236
237static gstack_t *push(gstack_t *s, Agraph_t *subg) {
238 gstack_t *rv = gv_alloc(sizeof(gstack_t));
239 rv->down = s;
240 rv->g = subg;
241 return rv;
242}
243
245{
246 gstack_t *rv;
247 rv = s->down;
248 free(s);
249 return rv;
250}
251
252static void delete_items(item *ilist)
253{
254 item *p,*pn;
255
256 for (p = ilist; p; p = pn) {
257 pn = p->next;
258 if (p->tag == T_list) delete_items(p->u.list);
259 if (p->tag == T_atom) agstrfree(G, p->str, aghtmlstr(p->str));
260 free(p);
261 }
262}
263
264static void deletelist(list_t *list)
265{
266 delete_items(list->first);
267 list->first = list->last = NULL;
268}
269
270static void listapp(list_t *list, item *v)
271{
272 if (list->last) list->last->next = v;
273 list->last = v;
274 if (list->first == NULL) list->first = v;
275}
276
277
278/* attrs */
279static void appendattr(char *name, char *value)
280{
281 item *v;
282
283 assert(value != NULL);
284 v = cons_attr(name,value);
285 listapp(&S->attrlist, v);
286}
287
288static void bindattrs(int kind)
289{
290 item *aptr;
291 char *name;
292
293 for (aptr = S->attrlist.first; aptr; aptr = aptr->next) {
294 assert(aptr->tag == T_atom); /* signifies unbound attr */
295 name = aptr->u.name;
296 if (kind == AGEDGE && streq(name,Key)) continue;
297 if ((aptr->u.asym = agattr(S->g,kind,name,NULL)) == NULL)
298 aptr->u.asym = agattr(S->g,kind,name,"");
299 aptr->tag = T_attr; /* signifies bound attr */
300 agstrfree(G, name, false);
301 }
302}
303
304/* attach node/edge specific attributes */
305static void applyattrs(void *obj)
306{
307 item *aptr;
308
309 for (aptr = S->attrlist.first; aptr; aptr = aptr->next) {
310 if (aptr->tag == T_attr) {
311 if (aptr->u.asym) {
312 if (aghtmlstr(aptr->str)) {
313 agxset_html(obj, aptr->u.asym, aptr->str);
314 } else {
315 agxset(obj, aptr->u.asym, aptr->str);
316 }
317 }
318 }
319 else {
320 assert(AGTYPE(obj) == AGINEDGE || AGTYPE(obj) == AGOUTEDGE);
321 assert(aptr->tag == T_atom);
322 assert(streq(aptr->u.name,Key));
323 }
324 }
325}
326
327static void nomacros(void)
328{
329 agwarningf("attribute macros not implemented");
330}
331
332/* attrstmt:
333 * First argument is always attrtype, so switch covers all cases.
334 * This function is used to handle default attribute value assignment.
335 */
336static void attrstmt(int tkind, char *macroname)
337{
338 item *aptr;
339 int kind = 0;
340 Agsym_t* sym;
341
342 /* creating a macro def */
343 if (macroname) nomacros();
344 /* invoking a macro def */
345 for (aptr = S->attrlist.first; aptr; aptr = aptr->next)
346 if (aptr->str == NULL) nomacros();
347
348 switch(tkind) {
349 case T_graph: kind = AGRAPH; break;
350 case T_node: kind = AGNODE; break;
351 case T_edge: kind = AGEDGE; break;
352 default: UNREACHABLE();
353 }
354 bindattrs(kind); /* set up defaults for new attributes */
355 for (aptr = S->attrlist.first; aptr; aptr = aptr->next) {
356 /* If the tag is still T_atom, aptr->u.asym has not been set */
357 if (aptr->tag == T_atom) continue;
358 if (!aptr->u.asym->fixed || S->g != G) {
359 if (aghtmlstr(aptr->str)) {
360 sym = agattr_html(S->g, kind, aptr->u.asym->name, aptr->str);
361 } else {
362 sym = agattr(S->g, kind, aptr->u.asym->name, aptr->str);
363 }
364 } else
365 sym = aptr->u.asym;
366 if (S->g == G)
367 sym->print = true;
368 }
369 deletelist(&S->attrlist);
370}
371
372/* nodes */
373
374static void appendnode(char *name, char *port, char *sport)
375{
376 item *elt;
377
378 if (sport) {
379 port = concatPort (port, sport);
380 }
381 elt = cons_node(agnode(S->g, name, 1), port);
382 listapp(&S->nodelist, elt);
383 agstrfree(G, name, false);
384}
385
386/* apply current optional attrs to nodelist and clean up lists */
387/* what's bad is that this could also be endsubg. also, you can't
388clean up S->subg in closesubg() because S->subg might be needed
389to construct edges. these are the sort of notes you write to yourself
390in the future. */
391static void endnode(void)
392{
393 item *ptr;
394
396 for (ptr = S->nodelist.first; ptr; ptr = ptr->next)
397 applyattrs(ptr->u.n);
398 deletelist(&S->nodelist);
399 deletelist(&S->attrlist);
400 deletelist(&S->edgelist);
401 S->subg = 0; /* notice a pattern here? :-( */
402}
403
404/* edges - store up node/subg lists until optional edge key can be seen */
405
406static void getedgeitems(void)
407{
408 item *v = 0;
409
410 if (S->nodelist.first) {
411 v = cons_list(S->nodelist.first);
412 S->nodelist.first = S->nodelist.last = NULL;
413 }
414 else {if (S->subg) v = cons_subg(S->subg); S->subg = 0;}
415 /* else nil append */
416 if (v) listapp(&S->edgelist, v);
417}
418
419static void endedge(void)
420{
421 char *key;
422 item *aptr,*tptr,*p;
423
424 Agnode_t *t;
425 Agraph_t *subg;
426
428
429 /* look for "key" pseudo-attribute */
430 key = NULL;
431 for (aptr = S->attrlist.first; aptr; aptr = aptr->next) {
432 if (aptr->tag == T_atom && streq(aptr->u.name,Key))
433 key = aptr->str;
434 }
435
436 /* can make edges with node lists or subgraphs */
437 for (p = S->edgelist.first; p->next; p = p->next) {
438 if (p->tag == T_subgraph) {
439 subg = p->u.subg;
440 for (t = agfstnode(subg); t; t = agnxtnode(subg,t))
441 edgerhs(agsubnode(S->g, t, 0), NULL, p->next, key);
442 }
443 else {
444 for (tptr = p->u.list; tptr; tptr = tptr->next)
445 edgerhs(tptr->u.n,tptr->str,p->next,key);
446 }
447 }
448 deletelist(&S->nodelist);
449 deletelist(&S->edgelist);
450 deletelist(&S->attrlist);
451 S->subg = 0;
452}
453
454/* concat:
455 */
456static char*
457concat (char* s1, char* s2)
458{
459 char* s;
460 char buf[BUFSIZ];
461 char* sym;
462 size_t len = strlen(s1) + strlen(s2) + 1;
463
464 if (len <= BUFSIZ) sym = buf;
465 else sym = gv_alloc(len);
466 strcpy(sym,s1);
467 strcat(sym,s2);
468 s = agstrdup (G,sym);
469 agstrfree(G, s1, false);
470 agstrfree(G, s2, false);
471 if (sym != buf) free (sym);
472 return s;
473}
474
475static char*
476concatPort (char* s1, char* s2)
477{
478 agxbuf buf = {0};
479
480 agxbprint(&buf, "%s:%s", s1, s2);
481 char *s = agstrdup(G, agxbuse(&buf));
482 agstrfree(G, s1, false);
483 agstrfree(G, s2, false);
484 agxbfree(&buf);
485 return s;
486}
487
488
489static void edgerhs(Agnode_t *tail, char *tport, item *hlist, char *key)
490{
491 Agnode_t *head;
492 Agraph_t *subg;
493 item *hptr;
494
495 if (hlist->tag == T_subgraph) {
496 subg = hlist->u.subg;
497 for (head = agfstnode(subg); head; head = agnxtnode(subg,head))
498 newedge(tail, tport, agsubnode(S->g, head, 0), NULL, key);
499 }
500 else {
501 for (hptr = hlist->u.list; hptr; hptr = hptr->next)
502 newedge(tail, tport, agsubnode(S->g, hptr->u.n, 0), hptr->str, key);
503 }
504}
505
506static void mkport(Agedge_t *e, char *name, char *val)
507{
508 Agsym_t *attr;
509 if (val) {
510 if ((attr = agattr(S->g,AGEDGE,name,NULL)) == NULL)
511 attr = agattr(S->g,AGEDGE,name,"");
512 agxset(e,attr,val);
513 }
514}
515
516static void newedge(Agnode_t *t, char *tport, Agnode_t *h, char *hport, char *key)
517{
518 Agedge_t *e;
519
520 e = agedge(S->g, t, h, key, 1);
521 if (e) { /* can fail if graph is strict and t==h */
522 char *tp = tport;
523 char *hp = hport;
524 if (agtail(e) != aghead(e) && aghead(e) == t) {
525 /* could happen with an undirected edge */
526 char *temp;
527 temp = tp; tp = hp; hp = temp;
528 }
529 mkport(e,TAILPORT_ID,tp);
530 mkport(e,HEADPORT_ID,hp);
531 applyattrs(e);
532 }
533}
534
535/* graphs and subgraphs */
536
537
538static void startgraph(char *name, bool directed, bool strict)
539{
540 if (G == NULL) {
541 SubgraphDepth = 0;
542 Agdesc_t req = {.directed = directed, .strict = strict, .maingraph = true};
543 Ag_G_global = G = agopen(name,req,Disc);
544 }
545 else {
546 Ag_G_global = G;
547 }
548 S = push(S,G);
549 agstrfree(NULL, name, false);
550}
551
552static void endgraph(void)
553{
554 aglexeof();
556}
557
558static void opensubg(char *name)
559{
560 if (++SubgraphDepth >= YYMAXDEPTH/2) {
561 agerrorf("subgraphs nested more than %d deep", YYMAXDEPTH);
562 }
563 S = push(S, agsubg(S->g, name, 1));
564 agstrfree(G, name, false);
565}
566
567static void closesubg(void)
568{
569 Agraph_t *subg = S->g;
571 S = pop(S);
572 S->subg = subg;
573 assert(subg);
574}
575
576static void freestack(void)
577{
578 while (S) {
579 deletelist(&S->nodelist);
580 deletelist(&S->attrlist);
581 deletelist(&S->edgelist);
582 S = pop(S);
583 }
584}
585
586extern FILE *aagin;
588{
589 aagin = chan;
590 G = g;
592 Disc = (disc? disc : &AgDefaultDisc);
593 aglexinit(Disc, chan);
594 aagparse();
595 if (Ag_G_global == NULL) aglexbad();
596 return Ag_G_global;
597}
598
599Agraph_t *agread(void *fp, Agdisc_t *disc) {return agconcat(NULL,fp,disc); }
600
static void agxbfree(agxbuf *xb)
free any malloced resources
Definition agxbuf.h:78
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
Definition agxbuf.h:234
static WUR char * agxbuse(agxbuf *xb)
Definition agxbuf.h:307
Memory allocation wrappers that exit on failure.
static void * gv_alloc(size_t size)
Definition alloc.h:47
cgraph.h additions
void aglexbad(void)
Definition scan.c:2402
void aglexinit(Agdisc_t *disc, void *ifile)
Definition scan.c:2421
Agraph_t * Ag_G_global
Definition graph.c:24
int aagparse(void)
void aglexeof(void)
Definition scan.c:2400
static Agnode_t * pop(void)
Definition ccomps.c:231
#define head
Definition dthdr.h:15
static Dtdisc_t disc
Definition exparse.y:209
#define S
Definition expr.h:72
#define G
Definition gdefs.h:7
static double len(glCompPoint p)
Definition glutils.c:150
#define YYMAXDEPTH
Definition gmlparse.c:1147
void free(void *)
NAME attrlist
Definition gmlparse.y:291
static const char Key[]
Definition grammar.c:90
#define T_atom
Definition grammar.c:243
static Agdisc_t * Disc
Definition grammar.c:143
struct list_s list_t
#define T_attr
Definition grammar.c:242
static int SubgraphDepth
Definition grammar.c:91
struct item_s item
void aagerror(const char *)
Definition scan.l:147
#define T_strict
Definition grammar.c:239
struct gstack_s gstack_t
union s val_t
#define T_graph
Definition grammar.c:234
#define T_list
Definition grammar.c:241
#define T_edgeop
Definition grammar.c:240
atom $5
Definition grammar.y:165
static void freestack(void)
Definition grammar.y:576
body
Definition grammar.y:197
static gstack_t * push(gstack_t *s, Agraph_t *subg)
Definition grammar.y:237
static void appendattr(char *name, char *value)
Definition grammar.y:279
static char * concat(char *s1, char *s2)
Definition grammar.y:457
T_subgraph
Definition grammar.y:201
hdr $2
Definition grammar.y:131
static void delete_items(item *ilist)
Definition grammar.y:252
static void bindattrs(int kind)
Definition grammar.y:288
node NULL
Definition grammar.y:163
simple
Definition grammar.y:156
static void newedge(Agnode_t *t, char *tport, Agnode_t *h, char *hport, char *key)
Definition grammar.y:516
atom $3
Definition grammar.y:164
graphattrdefs
Definition grammar.y:169
static void applyattrs(void *obj)
Definition grammar.y:305
static void getedgeitems(void)
Definition grammar.y:406
static item * cons_attr(char *name, char *value)
Definition grammar.y:228
static void opensubg(char *name)
Definition grammar.y:558
qatom T_qatom
Definition grammar.y:212
else endnode()
Definition grammar.y:391
static void endgraph(void)
Definition grammar.y:552
static void appendnode(char *name, char *port, char *sport)
Definition grammar.y:374
static item * cons_subg(Agraph_t *subg)
Definition grammar.y:234
static void endedge(void)
Definition grammar.y:419
static void closesubg(void)
Definition grammar.y:567
FILE * aagin
static item * cons_node(Agnode_t *n, char *port)
Definition grammar.y:225
static item * cons_list(item *list)
Definition grammar.y:231
static void mkport(Agedge_t *e, char *name, char *val)
Definition grammar.y:506
T_node
Definition grammar.y:173
hdr $1
Definition grammar.y:131
static item * newitem(int tag, void *p0, char *p1)
Definition grammar.y:216
static void listapp(list_t *list, item *v)
Definition grammar.y:270
static char * concatPort(char *s1, char *s2)
Definition grammar.y:476
T_edge
Definition grammar.y:174
nodelist node
Definition grammar.y:161
qatom
Definition grammar.y:208
rcompound
Definition grammar.y:156
T_digraph
Definition grammar.y:138
static void attrstmt(int tkind, char *macroname)
Definition grammar.y:336
static void edgerhs(Agnode_t *tail, char *tport, item *hlist, char *key)
Definition grammar.y:489
static void nomacros(void)
Definition grammar.y:327
static void startgraph(char *name, bool directed, bool strict)
Definition grammar.y:538
static void deletelist(list_t *list)
Definition grammar.y:264
void aginternalmapclearlocalnames(Agraph_t *g)
Definition imap.c:165
Agsym_t * agattr(Agraph_t *g, int kind, char *name, const char *value)
creates or looks up attributes of a graph
Definition attr.c:371
int agxset(void *obj, Agsym_t *sym, const char *value)
Definition attr.c:532
int agxset_html(void *obj, Agsym_t *sym, const char *value)
Definition attr.c:536
Agsym_t * agattr_html(Agraph_t *g, int kind, char *name, const char *value)
agattr, but creates HTML-like values
Definition attr.c:375
Agdisc_t AgDefaultDisc
Definition graph.c:285
Agedge_t * agedge(Agraph_t *g, Agnode_t *t, Agnode_t *h, char *name, int createflag)
Definition edge.c:256
#define TAILPORT_ID
Definition cgraph.h:895
#define HEADPORT_ID
Definition cgraph.h:896
#define agtail(e)
Definition cgraph.h:888
#define aghead(e)
Definition cgraph.h:889
void agwarningf(const char *fmt,...)
Definition agerror.c:173
void agerrorf(const char *fmt,...)
Definition agerror.c:165
int agclose(Agraph_t *g)
deletes a graph, freeing its associated storage
Definition graph.c:99
Agraph_t * agconcat(Agraph_t *g, void *chan, Agdisc_t *disc)
merges the file contents with a pre-existing graph
Definition grammar.y:587
Agraph_t * agopen(char *name, Agdesc_t desc, Agdisc_t *disc)
creates a new graph with the given name and kind
Definition graph.c:44
Agraph_t * agread(void *fp, Agdisc_t *disc)
constructs a new graph
Definition grammar.y:599
Agnode_t * agnode(Agraph_t *g, char *name, int createflag)
Definition node.c:140
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition node.c:47
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:40
Agnode_t * agsubnode(Agraph_t *g, Agnode_t *n, int createflag)
Definition node.c:254
#define AGTYPE(obj)
returns AGRAPH, AGNODE, or AGEDGE depending on the type of the object
Definition cgraph.h:216
@ AGOUTEDGE
Definition cgraph.h:207
@ AGEDGE
Definition cgraph.h:207
@ AGNODE
Definition cgraph.h:207
@ AGINEDGE
Definition cgraph.h:207
@ AGRAPH
Definition cgraph.h:207
int aghtmlstr(const char *)
Definition refstr.c:401
int agstrfree(Agraph_t *, const char *, bool is_html)
Definition refstr.c:378
char * agstrdup(Agraph_t *, const char *)
returns a pointer to a reference-counted copy of the argument string, creating one if necessary
Definition refstr.c:370
Agraph_t * agsubg(Agraph_t *g, char *name, int cflag)
Definition subg.c:55
Agraph_t * graph(char *name)
Definition gv.cpp:30
textitem scanner parser str
Definition htmlparse.y:224
table Syntax error
Definition htmlparse.y:294
$$
Definition htmlparse.y:327
NEATOPROCS_API void s1(graph_t *, node_t *)
Definition stuff.c:671
static bool streq(const char *a, const char *b)
are a and b equal?
Definition streq.h:11
graph descriptor
Definition cgraph.h:284
unsigned directed
Definition cgraph.h:285
user's discipline
Definition cgraph.h:336
graph or subgraph
Definition cgraph.h:424
string attribute descriptor symbol in Agattr_s.dict
Definition cgraph.h:641
unsigned char print
Definition cgraph.h:648
int dummy
Definition grammar.c:206
list_t attrlist
Definition grammar.c:117
list_t edgelist
Definition grammar.c:117
list_t nodelist
Definition grammar.c:117
Agraph_t * g
Definition grammar.c:115
Agraph_t * subg
Definition grammar.c:116
struct gstack_s * down
Definition grammar.c:118
char * str
Definition grammar.c:105
val_t u
Definition grammar.c:104
struct item_s * next
Definition grammar.c:106
int tag
Definition grammar.c:103
Definition utils.c:749
item * last
Definition grammar.c:111
item * first
Definition grammar.c:110
Definition types.h:48
Definition grammar.c:93
Agedge_t * e
Definition grammar.c:96
Agraph_t * subg
Definition grammar.c:95
Agsym_t * asym
Definition grammar.c:97
Agnode_t * n
Definition grammar.c:94
struct item_s * list
Definition grammar.c:99
char * name
Definition grammar.c:98
#define UNREACHABLE()
Definition unreachable.h:30