Graphviz 13.1.0~dev.20250626.0830
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
23 /* Generate a reentrant parser with no global state. */
24%define api.pure full
25 /* aagparse() gets an argument defined by flex. */
26%param { aagscan_t scanner }
27
28
29%code requires {
30#include <cghdr.h>
31#include <common/const.h>
32#include <util/agxbuf.h>
33
34struct gstack_s;
35
36struct aagextra_s {
37 /* Common */
38 Agdisc_t *Disc; /* discipline passed to agread or agconcat */
39 void *Ifile;
40 Agraph_t *G; /* top level graph */
41 /* Parser */
42 int SubgraphDepth;
43 struct gstack_s *S;
44 /* Lexer */
45 int line_num; // = 1;
46 int html_nest; /* nesting level for html strings */
47 const char *InputFile;
49 int graphType;
50 /* buffer for arbitrary length strings */
52};
53
54}
55
56%code provides {
57 /* defined in/generated by scan.l */
58 void aagerror(aagscan_t, const char*);
60}
61
62%{
63
64#include <stdbool.h>
65#include <stdio.h>
66#include <cghdr.h>
67#include <stdlib.h>
68#include <util/alloc.h>
69#include <util/streq.h>
70#include <util/unreachable.h>
71
72static const char Key[] = "key";
73
74typedef union s { /* possible items in generic list */
75 Agnode_t *n;
77 Agedge_t *e;
78 Agsym_t *asym; /* bound attribute */
79 char *name; /* unbound attribute */
80 struct item_s *list; /* list-of-lists (for edgestmt) */
81} val_t;
82
83typedef struct item_s { /* generic list */
84 int tag; /* T_node, T_subgraph, T_edge, T_attr */
85 val_t u; /* primary element */
86 char *str; /* secondary value - port or attr value */
87 struct item_s *next;
88} item;
89
90typedef struct list_s { /* maintain head and tail ptrs for fast append */
91 item *first;
92 item *last;
93} list_t;
94
95typedef struct gstack_s {
96 Agraph_t *g;
99 struct gstack_s *down;
100} gstack_t;
101
102/* functions */
103static void appendnode(aagscan_t scanner, char *name, char *port, char *sport);
104static void attrstmt(aagscan_t scanner, int tkind, char *macroname);
105static void startgraph(aagscan_t scanner, char *name, bool directed, bool strict);
106static void getedgeitems(aagscan_t scanner);
107static void newedge(aagscan_t scanner, Agnode_t *t, char *tport, Agnode_t *h, char *hport, char *key);
108static void edgerhs(aagscan_t scanner, Agnode_t *n, char *tport, item *hlist, char *key);
109static void appendattr(aagscan_t scanner, char *name, char *value);
110static void bindattrs(aagextra_t *ctx, int kind);
111static void applyattrs(aagextra_t *ctx, void *obj);
112static void endgraph(aagscan_t scanner);
113static void endnode(aagscan_t scanner);
114static void endedge(aagscan_t scanner);
115static void freestack(aagscan_t scanner);
116static char* concat(aagscan_t scanner, char*, char*);
117static char* concatPort(Agraph_t *G, char*, char*);
118
119static void opensubg(aagscan_t scanner, char *name);
120static void closesubg(aagscan_t scanner);
121static void graph_error(aagscan_t scanner);
122
123%}
124
125%union {
126 int i;
127 char *str;
128 struct Agnode_s *n;
129}
130
132 /* T_list, T_attr are internal tags, not really tokens */
133%token T_list T_attr
134%token <str> T_atom T_qatom
135
136%type <i> optstrict graphtype rcompound attrtype
137%type <str> optsubghdr optgraphname optmacroname atom qatom
138
139
140%%
141
144 | /* empty */
145 ;
146
147body : '{' optstmtlist '}' ;
148
149hdr : optstrict graphtype optgraphname {startgraph(scanner,$3,$2 != 0,$1 != 0);}
150 ;
151
152optgraphname: atom {$$=$1;} | /* empty */ {$$=0;} ;
153
154optstrict : T_strict {$$=1;} | /* empty */ {$$=0;} ;
155
156graphtype : T_graph {$$ = 0;} | T_digraph {$$ = 1;} ;
157
158optstmtlist : stmtlist | /* empty */ ;
159
160stmtlist : stmtlist stmt | stmt ;
161
162optsemi : ';' | ;
163
164stmt : attrstmt optsemi
165 | compound optsemi
166 ;
167
168compound : simple rcompound optattr
170 ;
171
172simple : nodelist | subgraph ;
173
175 | /* empty */ {$$ = 0;}
176 ;
177
178
179nodelist : node | nodelist ',' node ;
180
182 | atom ':' atom {appendnode(scanner,$1,$3,NULL);}
183 | atom ':' atom ':' atom {appendnode(scanner,$1,$3,$5);}
184 ;
185
186attrstmt : attrtype optmacroname attrlist {attrstmt(scanner,$1,$2);}
188 ;
189
190attrtype : T_graph {$$ = T_graph;}
193 ;
194
195optmacroname : atom '=' {$$ = $1;}
196 | /* empty */ {$$ = NULL; }
197 ;
198
199optattr : attrlist | /* empty */ ;
200
201attrlist : optattr '[' optattrdefs ']' ;
202
203optattrdefs : optattrdefs attrdefs
204 | /* empty */ ;
205
206attrdefs : attrassignment optseparator
207 ;
208
209attrassignment : atom '=' atom {appendattr(scanner,$1,$3);}
210 ;
211
212graphattrdefs : attrassignment
213 ;
214
215subgraph : optsubghdr {opensubg(scanner,$1);} body {closesubg(scanner);}
216 ;
217
218optsubghdr : T_subgraph atom {$$=$2;}
220 | /* empty */ {$$=NULL;}
221 ;
222
223optseparator : ';' | ',' | /*empty*/ ;
224
225atom : T_atom {$$ = $1;}
226 | qatom {$$ = $1;}
227 ;
228
231 ;
232%%
233
234static item *newitem(int tag, void *p0, char *p1)
235{
236 item *rv = gv_alloc(sizeof(item));
237 rv->tag = tag;
238 rv->u.name = p0;
239 rv->str = p1;
240 return rv;
241}
242
243static item *cons_node(Agnode_t *n, char *port)
244 { return newitem(T_node,n,port); }
245
246static item *cons_attr(char *name, char *value)
247 { return newitem(T_atom,name,value); }
248
249static item *cons_list(item *list)
250 { return newitem(T_list,list,NULL); }
251
252static item *cons_subg(Agraph_t *subg)
253 { return newitem(T_subgraph,subg,NULL); }
254
255static gstack_t *push(gstack_t *s, Agraph_t *subg) {
256 gstack_t *rv = gv_alloc(sizeof(gstack_t));
257 rv->down = s;
258 rv->g = subg;
259 return rv;
260}
261
263{
264 gstack_t *rv;
265 rv = s->down;
266 free(s);
267 return rv;
268}
269
270static void delete_items(Agraph_t *G, item *ilist)
271{
272 item *p,*pn;
273
274 for (p = ilist; p; p = pn) {
275 pn = p->next;
276 if (p->tag == T_list) delete_items(G, p->u.list);
277 if (p->tag == T_atom) agstrfree(G, p->str, aghtmlstr(p->str));
278 free(p);
279 }
280}
281
282static void deletelist(Agraph_t *G, list_t *list)
283{
284 delete_items(G,list->first);
285 list->first = list->last = NULL;
286}
287
288static void listapp(list_t *list, item *v)
289{
290 if (list->last) list->last->next = v;
291 list->last = v;
292 if (list->first == NULL) list->first = v;
293}
294
295
296/* attrs */
297static void appendattr(aagscan_t scanner, char *name, char *value)
298{
299 item *v;
301
302 assert(value != NULL);
303 v = cons_attr(name,value);
304 listapp(&ctx->S->attrlist, v);
305}
306
307static void bindattrs(aagextra_t *ctx, int kind)
308{
309 item *aptr;
310 char *name;
311
312 for (aptr = ctx->S->attrlist.first; aptr; aptr = aptr->next) {
313 assert(aptr->tag == T_atom); /* signifies unbound attr */
314 name = aptr->u.name;
315 if (kind == AGEDGE && streq(name,Key)) continue;
316 if ((aptr->u.asym = agattr_text(ctx->S->g,kind,name,NULL)) == NULL)
317 aptr->u.asym = agattr_text(ctx->S->g,kind,name,"");
318 aptr->tag = T_attr; /* signifies bound attr */
319 agstrfree(ctx->G, name, false);
320 }
321}
322
323/* attach node/edge specific attributes */
324static void applyattrs(aagextra_t *ctx, void *obj)
325{
326 item *aptr;
327
328 for (aptr = ctx->S->attrlist.first; aptr; aptr = aptr->next) {
329 if (aptr->tag == T_attr) {
330 if (aptr->u.asym) {
331 if (aghtmlstr(aptr->str)) {
332 agxset_html(obj, aptr->u.asym, aptr->str);
333 } else {
334 agxset(obj, aptr->u.asym, aptr->str);
335 }
336 }
337 }
338 else {
339 assert(AGTYPE(obj) == AGINEDGE || AGTYPE(obj) == AGOUTEDGE);
340 assert(aptr->tag == T_atom);
341 assert(streq(aptr->u.name,Key));
342 }
343 }
344}
345
346static void nomacros(void)
347{
348 agwarningf("attribute macros not implemented");
349}
350
351/* attrstmt:
352 * First argument is always attrtype, so switch covers all cases.
353 * This function is used to handle default attribute value assignment.
354 */
355static void attrstmt(aagscan_t scanner, int tkind, char *macroname)
356{
357 item *aptr;
358 int kind = 0;
360 Agsym_t* sym;
361 Agraph_t *G = ctx->G;
362 gstack_t *S = ctx->S;
363
364 /* creating a macro def */
365 if (macroname) nomacros();
366 /* invoking a macro def */
367 for (aptr = S->attrlist.first; aptr; aptr = aptr->next)
368 if (aptr->str == NULL) nomacros();
369
370 switch(tkind) {
371 case T_graph: kind = AGRAPH; break;
372 case T_node: kind = AGNODE; break;
373 case T_edge: kind = AGEDGE; break;
374 default: UNREACHABLE();
375 }
376 bindattrs(ctx, kind); /* set up defaults for new attributes */
377 for (aptr = S->attrlist.first; aptr; aptr = aptr->next) {
378 /* If the tag is still T_atom, aptr->u.asym has not been set */
379 if (aptr->tag == T_atom) continue;
380 if (!aptr->u.asym->fixed || S->g != G) {
381 if (aghtmlstr(aptr->str)) {
382 sym = agattr_html(S->g, kind, aptr->u.asym->name, aptr->str);
383 } else {
384 sym = agattr_text(S->g, kind, aptr->u.asym->name, aptr->str);
385 }
386 } else
387 sym = aptr->u.asym;
388 if (S->g == G)
389 sym->print = true;
390 }
391 deletelist(G, &S->attrlist);
392}
393
394/* nodes */
395
396static void appendnode(aagscan_t scanner, char *name, char *port, char *sport)
397{
398 item *elt;
400 Agraph_t *G = ctx->G;
401 gstack_t *S = ctx->S;
402
403 if (sport) {
404 port = concatPort (G, port, sport);
405 }
406 elt = cons_node(agnode(S->g, name, 1), port);
407 listapp(&S->nodelist, elt);
408 agstrfree(G, name, false);
409}
410
411/* apply current optional attrs to nodelist and clean up lists */
412/* what's bad is that this could also be endsubg. also, you can't
413clean up S->subg in closesubg() because S->subg might be needed
414to construct edges. these are the sort of notes you write to yourself
415in the future. */
417{
418 item *ptr;
420 Agraph_t *G = ctx->G;
421 gstack_t *S = ctx->S;
422
423 bindattrs(ctx, AGNODE);
424 for (ptr = S->nodelist.first; ptr; ptr = ptr->next)
425 applyattrs(ctx, ptr->u.n);
426 deletelist(G, &S->nodelist);
427 deletelist(G, &S->attrlist);
428 deletelist(G, &S->edgelist);
429 S->subg = 0; /* notice a pattern here? :-( */
430}
431
432/* edges - store up node/subg lists until optional edge key can be seen */
433
435{
437 gstack_t *S = ctx->S;
438 item *v = 0;
439
440 if (S->nodelist.first) {
441 v = cons_list(S->nodelist.first);
442 S->nodelist.first = S->nodelist.last = NULL;
443 }
444 else {if (S->subg) v = cons_subg(S->subg); S->subg = 0;}
445 /* else nil append */
446 if (v) listapp(&S->edgelist, v);
447}
448
450{
451 char *key;
452 item *aptr,*tptr,*p;
453
454 Agnode_t *t;
455 Agraph_t *subg;
457 Agraph_t *G = ctx->G;
458
459 bindattrs(ctx, AGEDGE);
460
461 /* look for "key" pseudo-attribute */
462 key = NULL;
463 for (aptr = ctx->S->attrlist.first; aptr; aptr = aptr->next) {
464 if (aptr->tag == T_atom && streq(aptr->u.name,Key))
465 key = aptr->str;
466 }
467
468 /* can make edges with node lists or subgraphs */
469 for (p = ctx->S->edgelist.first; p->next; p = p->next) {
470 if (p->tag == T_subgraph) {
471 subg = p->u.subg;
472 for (t = agfstnode(subg); t; t = agnxtnode(subg,t))
473 edgerhs(scanner,agsubnode(ctx->S->g, t, 0), NULL, p->next, key);
474 }
475 else {
476 for (tptr = p->u.list; tptr; tptr = tptr->next)
477 edgerhs(scanner,tptr->u.n,tptr->str,p->next,key);
478 }
479 }
480 deletelist(G, &ctx->S->nodelist);
481 deletelist(G, &ctx->S->edgelist);
482 deletelist(G, &ctx->S->attrlist);
483 ctx->S->subg = 0;
484}
485
486/* concat:
487 */
488static char*
489concat (aagscan_t scanner, char* s1, char* s2)
490{
491 char* s;
492 char buf[BUFSIZ];
493 char* sym;
495 size_t len = strlen(s1) + strlen(s2) + 1;
496
497 if (len <= BUFSIZ) sym = buf;
498 else sym = gv_alloc(len);
499 strcpy(sym,s1);
500 strcat(sym,s2);
501 s = agstrdup (G,sym);
502 agstrfree(G, s1, false);
503 agstrfree(G, s2, false);
504 if (sym != buf) free (sym);
505 return s;
506}
507
508static char*
509concatPort (Agraph_t *G, char* s1, char* s2)
510{
511 agxbuf buf = {0};
512
513 agxbprint(&buf, "%s:%s", s1, s2);
514 char *s = agstrdup(G, agxbuse(&buf));
515 agstrfree(G, s1, false);
516 agstrfree(G, s2, false);
517 agxbfree(&buf);
518 return s;
519}
520
521
522static void edgerhs(aagscan_t scanner, Agnode_t *tail, char *tport, item *hlist, char *key)
523{
524 Agnode_t *head;
525 Agraph_t *subg;
526 item *hptr;
528
529 if (hlist->tag == T_subgraph) {
530 subg = hlist->u.subg;
531 for (head = agfstnode(subg); head; head = agnxtnode(subg,head))
532 newedge(scanner, tail, tport, agsubnode(ctx->S->g, head, 0), NULL, key);
533 }
534 else {
535 for (hptr = hlist->u.list; hptr; hptr = hptr->next)
536 newedge(scanner, tail, tport, agsubnode(ctx->S->g, hptr->u.n, 0), hptr->str, key);
537 }
538}
539
540static void mkport(aagscan_t scanner, Agedge_t *e, char *name, char *val)
541{
542 Agsym_t *attr;
544
545 if (val) {
546 if ((attr = agattr_text(ctx->S->g,AGEDGE,name,NULL)) == NULL)
547 attr = agattr_text(ctx->S->g,AGEDGE,name,"");
548 agxset(e,attr,val);
549 }
550}
551
552static void newedge(aagscan_t scanner, Agnode_t *t, char *tport, Agnode_t *h, char *hport, char *key)
553{
554 Agedge_t *e;
556
557 e = agedge(ctx->S->g, t, h, key, 1);
558 if (e) { /* can fail if graph is strict and t==h */
559 char *tp = tport;
560 char *hp = hport;
561 if (agtail(e) != aghead(e) && aghead(e) == t) {
562 /* could happen with an undirected edge */
563 char *temp;
564 temp = tp; tp = hp; hp = temp;
565 }
568 applyattrs(ctx, e);
569 }
570}
571
572/* graphs and subgraphs */
573
574
575static void startgraph(aagscan_t scanner, char *name, bool directed, bool strict)
576{
578 if (ctx->G == NULL) {
579 ctx->SubgraphDepth = 0;
580 Agdesc_t req = {.directed = directed, .strict = strict, .maingraph = true};
581 ctx->G = agopen(name,req,ctx->Disc);
582 }
583 ctx->S = push(ctx->S,ctx->G);
584 agstrfree(NULL, name, false);
585}
586
592
593static void opensubg(aagscan_t scanner, char *name)
594{
596
597 if (++ctx->SubgraphDepth >= YYMAXDEPTH/2) {
598 agerrorf("subgraphs nested more than %d deep", YYMAXDEPTH);
599 }
600 ctx->S = push(ctx->S, agsubg(ctx->S->g, name, 1));
601 agstrfree(ctx->G, name, false);
602}
603
605{
607 Agraph_t *subg = ctx->S->g;
608
609 --ctx->SubgraphDepth;
610 ctx->S = pop(ctx->S);
611 ctx->S->subg = subg;
612 assert(subg);
613}
614
616{
618 while (ctx->S) {
619 deletelist(ctx->G, &ctx->S->nodelist);
620 deletelist(ctx->G, &ctx->S->attrlist);
621 deletelist(ctx->G, &ctx->S->edgelist);
622 ctx->S = pop(ctx->S);
623 }
624}
625
627{
629 if (ctx->G) {
632 agclose(ctx->G);
633 ctx->G = NULL;
634 }
635}
636
637Agraph_t *agconcat(Agraph_t *g, const char *filename, void *chan,
638 Agdisc_t *disc) {
639 // if the proto graph’s default node label has not yet been set, set it now
640 if (agattr_text(NULL, AGNODE, "label", NULL) == NULL) {
642 }
643
645 aagextra_t extra = {
646 .Disc = disc ? disc : &AgDefaultDisc,
647 .Ifile = chan,
648 .G = g,
649 .line_num = 1,
650 .InputFile = filename,
651 };
652 if (aaglex_init_extra(&extra, &scanner)) {
653 return NULL;
654 }
655 aagset_in(chan, scanner);
657 if (extra.G == NULL) aglexbad(scanner);
660 agxbfree(&extra.Sbuf);
661 return extra.G;
662}
663
665 return agconcat(NULL, NULL, fp, disc);
666}
667
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
int aagparse(aagscan_t scanner)
int aaglex_destroy(aagscan_t)
void aagset_in(FILE *, aagscan_t)
void aglexeof(aagscan_t yyscanner)
Definition scan.l:191
int aaglex_init_extra(aagextra_t *user_defined, aagscan_t *scanner)
void aglexbad(aagscan_t yyscanner)
Definition scan.l:196
aagextra_t * aagget_extra(aagscan_t yyscanner)
void * aagscan_t
Definition cghdr.h:107
static Agnode_t * pop(void)
Definition ccomps.c:221
#define NODENAME_ESC
Definition const.h:80
#define head
Definition dthdr.h:15
static Dtdisc_t disc
Definition exparse.y:207
#define S
Definition expr.h:72
#define G
Definition gdefs.h:7
static double len(glCompPoint p)
Definition glutils.c:136
#define YYMAXDEPTH
Definition gmlparse.c:1102
void free(void *)
NAME attrlist
Definition gmlparse.y:290
static const char Key[]
Definition grammar.c:87
struct list_s list_t
struct item_s item
struct gstack_s gstack_t
union s val_t
#define T_atom
Definition grammar.h:122
#define T_attr
Definition grammar.h:121
void aagerror(aagscan_t, const char *)
Definition scan.l:151
#define T_strict
Definition grammar.h:118
int aaglex(AAGSTYPE *, aagscan_t)
#define T_graph
Definition grammar.h:113
#define T_list
Definition grammar.h:120
#define T_edgeop
Definition grammar.h:119
static char * concatPort(Agraph_t *G, char *s1, char *s2)
Definition grammar.y:509
atom $5
Definition grammar.y:183
static void attrstmt(aagscan_t scanner, int tkind, char *macroname)
Definition grammar.y:355
body
Definition grammar.y:215
static void opensubg(aagscan_t scanner, char *name)
Definition grammar.y:593
static gstack_t * push(gstack_t *s, Agraph_t *subg)
Definition grammar.y:255
static void bindattrs(aagextra_t *ctx, int kind)
Definition grammar.y:307
T_subgraph
Definition grammar.y:219
hdr $2
Definition grammar.y:149
static void applyattrs(aagextra_t *ctx, void *obj)
Definition grammar.y:324
static void appendnode(aagscan_t scanner, char *name, char *port, char *sport)
Definition grammar.y:396
node NULL
Definition grammar.y:181
simple
Definition grammar.y:174
hdr $3
Definition grammar.y:149
graphattrdefs
Definition grammar.y:187
static void deletelist(Agraph_t *G, list_t *list)
Definition grammar.y:282
static void mkport(aagscan_t scanner, Agedge_t *e, char *name, char *val)
Definition grammar.y:540
static item * cons_attr(char *name, char *value)
Definition grammar.y:246
static void newedge(aagscan_t scanner, Agnode_t *t, char *tport, Agnode_t *h, char *hport, char *key)
Definition grammar.y:552
static void appendattr(aagscan_t scanner, char *name, char *value)
Definition grammar.y:297
static void startgraph(aagscan_t scanner, char *name, bool directed, bool strict)
Definition grammar.y:575
qatom T_qatom
Definition grammar.y:230
static void delete_items(Agraph_t *G, item *ilist)
Definition grammar.y:270
static item * cons_subg(Agraph_t *subg)
Definition grammar.y:252
static item * cons_node(Agnode_t *n, char *port)
Definition grammar.y:243
hdr $1
Definition grammar.y:149
static void freestack(aagscan_t scanner)
Definition grammar.y:615
static item * cons_list(item *list)
Definition grammar.y:249
static void closesubg(aagscan_t scanner)
Definition grammar.y:604
T_node
Definition grammar.y:191
static char * concat(aagscan_t scanner, char *s1, char *s2)
Definition grammar.y:489
static item * newitem(int tag, void *p0, char *p1)
Definition grammar.y:234
static void endedge(aagscan_t scanner)
Definition grammar.y:449
static void listapp(list_t *list, item *v)
Definition grammar.y:288
T_edge
Definition grammar.y:192
nodelist node
Definition grammar.y:179
qatom
Definition grammar.y:226
rcompound
Definition grammar.y:174
static void graph_error(aagscan_t scanner)
Definition grammar.y:626
T_digraph
Definition grammar.y:156
static void getedgeitems(aagscan_t scanner)
Definition grammar.y:434
else endnode(scanner)
static void nomacros(void)
Definition grammar.y:346
static void edgerhs(aagscan_t scanner, Agnode_t *tail, char *tport, item *hlist, char *key)
Definition grammar.y:522
static void endgraph(aagscan_t scanner)
Definition grammar.y:587
void aginternalmapclearlocalnames(Agraph_t *g)
Definition imap.c:165
Agsym_t * agattr_text(Agraph_t *g, int kind, char *name, const char *value)
creates or looks up text attributes of a graph
Definition attr.c:348
int agxset(void *obj, Agsym_t *sym, const char *value)
Definition attr.c:536
int agxset_html(void *obj, Agsym_t *sym, const char *value)
Definition attr.c:555
Agsym_t * agattr_html(Agraph_t *g, int kind, char *name, const char *value)
agattr_text, but creates HTML-like values
Definition attr.c:352
Agdisc_t AgDefaultDisc
Definition graph.c:277
Agedge_t * agedge(Agraph_t *g, Agnode_t *t, Agnode_t *h, char *name, int createflag)
Definition edge.c:253
#define TAILPORT_ID
Definition cgraph.h:995
#define HEADPORT_ID
Definition cgraph.h:996
#define agtail(e)
Definition cgraph.h:988
#define aghead(e)
Definition cgraph.h:989
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:95
Agraph_t * agconcat(Agraph_t *g, const char *filename, void *chan, Agdisc_t *disc)
merges the file contents with a pre-existing graph
Definition grammar.y:637
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
Agraph_t * agread(void *fp, Agdisc_t *disc)
constructs a new graph
Definition grammar.y:664
Agnode_t * agnode(Agraph_t *g, char *name, int createflag)
Definition node.c:141
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition node.c:48
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:41
Agnode_t * agsubnode(Agraph_t *g, Agnode_t *n, int createflag)
Definition node.c:252
#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:438
int agstrfree(Agraph_t *, const char *, bool is_html)
Definition refstr.c:415
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:399
Agraph_t * agsubg(Agraph_t *g, char *name, int cflag)
Definition subg.c:53
Agraph_t * graph(char *name)
Definition gv.cpp:30
textitem scanner parser str
Definition htmlparse.y:224
table Syntax error
Definition htmlparse.y:294
cleanup & scanner
Definition htmlparse.y:295
$$
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:651
unsigned char print
Definition cgraph.h:658
int graphType
Definition grammar.h:77
int html_nest
Definition grammar.h:74
Agraph_t * G
Definition grammar.h:68
void * Ifile
Definition grammar.h:67
const char * InputFile
Definition grammar.h:75
int SubgraphDepth
Definition grammar.h:70
int line_num
Definition grammar.h:73
agxbuf Sbuf
Definition grammar.h:79
Agdisc_t * Disc
Definition grammar.h:66
agxbuf InputFileBuffer
Definition grammar.h:76
struct gstack_s * S
Definition grammar.h:71
list_t attrlist
Definition grammar.c:113
list_t edgelist
Definition grammar.c:113
list_t nodelist
Definition grammar.c:113
Agraph_t * g
Definition grammar.c:111
Agraph_t * subg
Definition grammar.c:112
struct gstack_s * down
Definition grammar.c:114
char * str
Definition grammar.c:101
val_t u
Definition grammar.c:100
struct item_s * next
Definition grammar.c:102
int tag
Definition grammar.c:99
Definition utils.c:749
item * last
Definition grammar.c:107
item * first
Definition grammar.c:106
Definition types.h:48
Definition grammar.c:89
Agedge_t * e
Definition grammar.c:92
Agraph_t * subg
Definition grammar.c:91
Agsym_t * asym
Definition grammar.c:93
Agnode_t * n
Definition grammar.c:90
struct item_s * list
Definition grammar.c:95
char * name
Definition grammar.c:94
#define UNREACHABLE()
Definition unreachable.h:30