Graphviz 14.1.2~dev.20260118.1035
Loading...
Searching...
No Matches
gv2gml.c
Go to the documentation of this file.
1
6/**********************************************************
7* This software is part of the graphviz package *
8* https://graphviz.org *
9* *
10* Copyright (c) 1994-2004 AT&T Corp. *
11* and is licensed under the *
12* Common Public License, Version 1.0 *
13* by AT&T Corp. *
14* *
15* Information and Software Systems Research *
16* AT&T Research, Florham Park NJ *
17**********************************************************/
18
19#include "config.h"
20
21#include <stdbool.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <inttypes.h>
25
26#include <getopt.h>
27
28#include <cgraph/cgraph.h>
29#include <cgraph/ingraphs.h>
30#include <util/exit.h>
31#include <util/gv_ctype.h>
32#include <util/streq.h>
33#include <util/strview.h>
34#include <util/tokenize.h>
35#include <util/unreachable.h>
36#include <util/xml.h>
37#include "openFile.h"
38
39static FILE *outFile;
40static char *CmdName;
41static char **Files;
42static uint64_t id;
43static bool yworks;
44
45#define POS_SET (1<<0)
46#define W_SET (1<<1)
47#define H_SET (1<<2)
48#define INVIS (1<<3)
49#define FILL (1<<4)
50#define LINE (1<<5)
51#define DASH (1<<6)
52#define DOT (1<<7)
53#define BOLD (1<<8)
54
55typedef struct {
56 unsigned int flags;
57/* graphics */
58 double x;
59 double y;
60 double w;
61 double h;
62 char* type; /* shape */
63 char* image;
64 char* fill; /* fillcolor */
65 char* outline; /* pencolor */
66 char* width; /* penwidth */
68/* label graphics */
69 char* fontColor;
70 char* fontSize;
71 char* fontName;
73
74typedef struct {
75 unsigned int flags;
76/* graphics */
77 char* width; /* penwidth */
78 char* fill; /* pencolor */
79 char* arrow; /* dir */
80 char* arrowhead; /* arrowhead */
81 char* arrowtail; /* arrowtail */
82 char* pos;
83/* label graphics */
84 char* fontColor;
85 char* fontSize;
86 char* fontName;
88
89typedef struct {
91 uint64_t id;
93
94#define ID(n) (((Local_Agnodeinfo_t*)(n->base.data))->id)
95
96static void indent(int ix) {
97 while (ix--)
98 fprintf (outFile, " ");
99}
100
102static bool isNumber(char* s) {
103 char* ep = s;
104 strtod(s, &ep);
105 if (s != ep) {
106 while (gv_isspace(*ep)) ep++;
107 if (*ep) return false;
108 return true;
109 }
110 return false;
111}
112
114static int
116{
117 int flags = 0;
118 char* sep = " \t,";
119
120 for (tok_t t = tok(s, sep); !tok_end(&t); tok_next(&t)) {
121 strview_t ip = tok_get(&t);
122 if (strview_str_eq(ip, "invis")) flags |= INVIS;
123 else if (strview_str_eq(ip, "filled")) flags |= FILL;
124 else if (strview_str_eq(ip, "dashed")) flags |= DASH;
125 else if (strview_str_eq(ip, "dotted")) flags |= DOT;
126 else if (strview_str_eq(ip, "solid")) flags |= LINE;
127 else if (strview_str_eq(ip, "bold")) flags |= BOLD;
128 }
129
130 return flags;
131}
132
133static void emitInt(char *name, int value, int ix) {
134 indent(ix);
135 fprintf (outFile, "%s %d\n", name, value);
136}
137
138static void emitReal(char *name, double value, int ix) {
139 indent(ix);
140 fprintf (outFile, "%s %g\n", name, value);
141}
142
143static void emitPoint(double x, double y, int ix) {
144 indent(ix);
145 fprintf (outFile, "point [ x %g y %g ]\n", x, y);
146}
147
148static char*
149skipWS (char* s)
150{
151 while (gv_isspace(*s)) s++;
152 return s;
153}
154
155/* Return NULL if unsuccessful
156 */
157static char*
158readPoint (char* s, double* xp, double* yp)
159{
160 char* endp;
161
162 s = skipWS(s);
163 *xp = strtod (s, &endp);
164 if (s == endp) return NULL;
165 endp++; /* skip comma */
166 s = endp;
167 *yp = strtod (s, &endp);
168 if (s == endp) return NULL;
169 else return endp;
170}
171
172static char*
173arrowEnd (char* s0, char* pfx, int* fp, double* xp, double* yp)
174{
175 char* s = skipWS(s0);
176
177 if (strncmp(s,pfx,2)) return s;
178 s += 2; /* skip prefix */
179 s = readPoint (s, xp, yp);
180 if (s == NULL) {
181 fprintf (stderr, "Illegal spline end: %s\n", s0);
182 graphviz_exit(1);
183 }
184 *fp = 1;
185 return s;
186}
187
188static void emitSpline(char *s, int ix) {
189 double sx, sy, ex, ey;
190 int sarrow = 0;
191 int earrow = 0;
192
193 s = arrowEnd (s, "e,", &earrow, &ex, &ey);
194 s = arrowEnd (s, "s,", &sarrow, &sx, &sy);
195 indent(ix);
196 fprintf (outFile, "Line [\n");
197 if (sarrow)
198 emitPoint(sx, sy, ix+1);
199 while ((s = readPoint (s, &sx, &sy)))
200 emitPoint(sx, sy, ix+1);
201 if (earrow)
202 emitPoint(ex, ey, ix+1);
203 indent(ix);
204 fprintf (outFile, "]\n");
205
206}
207
208// `fputs` wrapper to handle the difference in calling convention to what
209// `gv_xml_escape`’s `cb` expects
210static inline int put(void *stream, const char *s) {
211 return fputs(s, stream);
212}
213
214// write a string to the given file, XML-escaping the input
215static inline int xml_puts(FILE *stream, const char *s) {
216 const xml_flags_t flags = {.dash = 1, .nbsp = 1};
217 return gv_xml_escape(s, flags, put, stream);
218}
219
220static void emitAttr(char *name, char *value, int ix) {
221 indent(ix);
222 if (isNumber (value))
223 fprintf (outFile, "%s %s\n", name, value);
224 else {
225 fprintf(outFile, "%s \"", name);
226 xml_puts(outFile, value);
227 fputs("\"\n", outFile);
228 }
229}
230
231/* node attributes:
232 * label
233 * graphics
234 * LabelGraphics
235 */
236static void emitNodeAttrs(Agraph_t *G, Agnode_t *np, int ix) {
237 Agsym_t* s;
238 char* v;
239 node_attrs attrs = {0};
240 int doGraphics = 0;
241 int doLabelGraphics = 0;
242 char* label = 0;
243 int style;
244 double x, y;
245
246 /* First, process the attributes, saving the graphics attributes */
247 for (s = agnxtattr (G, AGNODE, NULL); s; s = agnxtattr (G, AGNODE, s)) {
248 if (streq(s->name, "style")) { /* hasFill outlineStyle invis */
249 if (*(v = agxget (np, s))) {
250 style = parseStyle (v);
251 if (style & INVIS)
252 attrs.flags |= INVIS;
253 if (style & FILL)
254 attrs.flags |= FILL;
255 if (style & LINE)
256 attrs.outlineStyle = "line";
257 if (style & DASH)
258 attrs.outlineStyle = "dashed";
259 if (style & DOT)
260 attrs.outlineStyle = "dotted";
261 doGraphics = 1;
262 }
263 }
264 else if (streq(s->name, "label")) {
265 v = agxget (np, s);
266 if (streq("\\N", v)) {
267 label = agnameof(np);
268 emitAttr(s->name, label, ix);
269 doLabelGraphics = 1;
270 }
271 else if (*v) {
272 label = v;
273 emitAttr(s->name, label, ix);
274 doLabelGraphics = 1;
275 }
276 }
277 else if (streq(s->name, "penwidth")) {
278 if (*(v = agxget (np, s))) {
279 attrs.width = v;
280 doGraphics = 1;
281 }
282 }
283 else if (streq(s->name, "width")) {
284 v = agxget (np, s);
285 if (*v) {
286 attrs.w = 72.0*atof (v);
287 attrs.flags |= W_SET;
288 doGraphics = 1;
289 }
290 }
291 else if (streq(s->name, "height")) {
292 v = agxget (np, s);
293 if (*v) {
294 attrs.h = 72.0*atof (v);
295 attrs.flags |= H_SET;
296 doGraphics = 1;
297 }
298 }
299 else if (streq(s->name, "pos")) {
300 v = agxget (np, s);
301 if (sscanf (v, "%lf,%lf", &x, &y) == 2) {
302 doGraphics = 1;
303 attrs.x = x;
304 attrs.y = y;
305 attrs.flags |= POS_SET;
306 }
307 }
308 else if (streq(s->name, "shape")) { /* type */
309 if (*(v = agxget (np, s))) {
310 attrs.type = v;
311 doGraphics = 1;
312 }
313 }
314 else if (streq(s->name, "color")) {
315 if (*(v = agxget (np, s))) {
316 attrs.fill = v;
317 attrs.outline = v;
318 doGraphics = 1;
319 }
320 }
321 else if (streq(s->name, "fillcolor")) {
322 if (*(v = agxget (np, s))) {
323 attrs.fill = v;
324 doGraphics = 1;
325 }
326 }
327 else if (streq(s->name, "pencolor")) {
328 if (*(v = agxget (np, s))) {
329 attrs.outline = v;
330 doGraphics = 1;
331 }
332 }
333 else if (streq(s->name, "fontname")) { /* fontName */
334 if (*(v = agxget (np, s))) {
335 attrs.fontName = v;
336 doLabelGraphics = 1;
337 }
338 }
339 else if (streq(s->name, "fontsize")) { /* fontSize */
340 if (*(v = agxget (np, s))) {
341 attrs.fontSize = v;
342 doLabelGraphics = 1;
343 }
344 }
345 else if (streq(s->name, "fontcolor")) { /* fontColor */
346 if (*(v = agxget (np, s))) {
347 attrs.fontColor = v;
348 doLabelGraphics = 1;
349 }
350 }
351 else {
352 v = agxget (np, s);
353 emitAttr(s->name, v, ix);
354 }
355 }
356
357 /* Then, print them, if any */
358 if (doGraphics) {
359 fprintf (outFile, " graphics [\n");
360 if (attrs.flags & POS_SET) {
361 emitReal("x", attrs.x, ix+1);
362 emitReal("y", attrs.y, ix+1);
363 }
364 if (attrs.flags & W_SET) {
365 emitReal("w", attrs.w, ix+1);
366 }
367 if (attrs.flags & H_SET) {
368 emitReal("H", attrs.h, ix+1);
369 }
370 if (attrs.flags & INVIS) {
371 emitInt("visible", 0, ix+1);
372 }
373 if (attrs.flags & FILL) {
374 emitInt("hasFill", 1, ix+1);
375 }
376 if (attrs.type) {
377 emitAttr("type", attrs.type, ix+1);
378 }
379 if (attrs.image) {
380 emitAttr("image", attrs.image, ix+1);
381 }
382 if (attrs.fill) {
383 emitAttr("fill", attrs.fill, ix+1);
384 }
385 if (attrs.outline) {
386 emitAttr("outline", attrs.outline, ix+1);
387 }
388 if (attrs.width) {
389 emitAttr("width", attrs.width, ix+1);
390 }
391 if (attrs.outlineStyle) {
392 emitAttr("outlineStyle", attrs.outlineStyle, ix+1);
393 }
394 fprintf (outFile, " ]\n");
395 }
396
397 if (doLabelGraphics) {
398 fprintf (outFile, " LabelGraphics [\n");
399 if (label) emitAttr("text", label, ix+1);
400 if (attrs.fontColor) {
401 emitAttr(yworks ? "color" : "fontColor", attrs.fontColor, ix+1);
402 }
403 if (attrs.fontSize) {
404 emitAttr("fontSize", attrs.fontSize, ix+1);
405 }
406 if (attrs.fontName) {
407 emitAttr("fontName", attrs.fontName, ix+1);
408 }
409 fprintf (outFile, " ]\n");
410 }
411}
412
413/* emitNode:
414 * set node id
415 * label, width height, x, y, type fillcolor
416 */
417static void emitNode(Agraph_t *G, Agnode_t *n) {
418 agbindrec(n, "nodeinfo", sizeof(Local_Agnodeinfo_t), true);
419 fprintf(outFile, " node [\n id %" PRIu64 "\n name \"%s\"\n", id,
420 agnameof(n));
421 ID(n) = id++;
422 emitNodeAttrs(G, n, 2);
423 fprintf (outFile, " ]\n");
424
425}
426
427/* edge attributes:
428 * label
429 * graphics
430 * LabelGraphics
431 */
432static void emitEdgeAttrs(Agraph_t *G, Agedge_t *ep, int ix) {
433 Agsym_t* s;
434 char* v;
435 edge_attrs attrs = {0};
436 int doGraphics = 0;
437 int doLabelGraphics = 0;
438 char* label = 0;
439 int style;
440
441 /* First, process the attributes, saving the graphics attributes */
442 for (s = agnxtattr (G, AGEDGE, NULL); s; s = agnxtattr (G, AGEDGE, s)) {
443 if (streq(s->name, "style")) { /* hasFill outlineStyle invis */
444 if (*(v = agxget (ep, s))) {
445 style = parseStyle (v);
446 if (style & INVIS)
447 attrs.flags |= INVIS;
448 if (style & LINE)
449 attrs.flags |= LINE;
450 if (style & DASH)
451 attrs.flags |= DASH;
452 if (style & DOT)
453 attrs.flags |= DOT;
454 if (style & BOLD)
455 attrs.width = "2";
456 doGraphics = 1;
457 }
458 }
459 else if (streq(s->name, "label")) {
460 if (*(v = agxget (ep, s))) {
461 label = v;
462 emitAttr(s->name, label, ix);
463 doLabelGraphics = 1;
464 }
465 }
466 else if (streq(s->name, "penwidth")) {
467 if (*(v = agxget (ep, s))) {
468 attrs.width = v;
469 doGraphics = 1;
470 }
471 }
472 else if (streq(s->name, "pos")) {
473 if (*(v = agxget (ep, s))) {
474 doGraphics = 1;
475 attrs.pos = v;
476 }
477 }
478 else if (streq(s->name, "dir")) {
479 if (*(v = agxget (ep, s))) {
480 doGraphics = 1;
481 attrs.arrow = v;
482 }
483 }
484 else if (streq(s->name, "color")) {
485 if (*(v = agxget (ep, s))) {
486 attrs.fill = v;
487 doGraphics = 1;
488 }
489 }
490 else if (streq(s->name, "pencolor")) {
491 if (*(v = agxget (ep, s))) {
492 attrs.fill = v;
493 doGraphics = 1;
494 }
495 }
496 else if (streq(s->name, "arrowhead")) {
497 if (*(v = agxget (ep, s))) {
498 attrs.arrowhead = v;
499 doGraphics = 1;
500 }
501 }
502 else if (streq(s->name, "arrowtail")) {
503 if (*(v = agxget (ep, s))) {
504 attrs.arrowtail = v;
505 doGraphics = 1;
506 }
507 }
508 else if (streq(s->name, "fontname")) { /* fontName */
509 if (*(v = agxget (ep, s))) {
510 attrs.fontName = v;
511 doLabelGraphics = 1;
512 }
513 }
514 else if (streq(s->name, "fontsize")) { /* fontSize */
515 if (*(v = agxget (ep, s))) {
516 attrs.fontSize = v;
517 doLabelGraphics = 1;
518 }
519 }
520 else if (streq(s->name, "fontcolor")) { /* fontColor */
521 if (*(v = agxget (ep, s))) {
522 attrs.fontColor = v;
523 doLabelGraphics = 1;
524 }
525 }
526 else {
527 v = agxget (ep, s);
528 emitAttr(s->name, v, ix);
529 }
530 }
531
532 /* Then, print them, if any */
533 if (doGraphics) {
534 fprintf (outFile, " graphics [\n");
535 if (attrs.pos) {
536 emitSpline(attrs.pos, ix+1);
537 }
538 if (attrs.flags & INVIS) {
539 emitInt("visible", 0, ix+1);
540 }
541 if (attrs.fill) {
542 emitAttr("fill", attrs.fill, ix+1);
543 }
544 if (attrs.width) {
545 emitAttr("width", attrs.width, ix+1);
546 }
547 if (attrs.arrowhead) {
548 emitAttr("targetArrow", attrs.arrowhead, ix+1);
549 }
550 if (attrs.arrowtail) {
551 emitAttr("sourceArrow", attrs.arrowtail, ix+1);
552 }
553 if (attrs.flags & DASH) {
554 emitAttr("style", "dashed", ix+1);
555 }
556 else if (attrs.flags & DOT) {
557 emitAttr("style", "dotted", ix+1);
558 }
559 else if (attrs.flags & LINE) {
560 emitAttr("style", "line", ix+1);
561 }
562 if (attrs.arrow) {
563 if (streq(attrs.arrow,"forward"))
564 emitAttr("arrow", "first", ix+1);
565 else if (streq(attrs.arrow,"back"))
566 emitAttr("arrow", "last", ix+1);
567 else if (streq(attrs.arrow,"both"))
568 emitAttr("arrow", "both", ix+1);
569 else if (streq(attrs.arrow,"none"))
570 emitAttr("arrow", "none", ix+1);
571 }
572 fprintf (outFile, " ]\n");
573 }
574
575 if (doLabelGraphics) {
576 fprintf (outFile, " LabelGraphics [\n");
577 if (label) emitAttr("text", label, ix+1);
578 if (attrs.fontColor) {
579 emitAttr(yworks ? "color" : "fontColor", attrs.fontColor, ix+1);
580 }
581 if (attrs.fontSize) {
582 emitAttr("fontSize", attrs.fontSize, ix+1);
583 }
584 if (attrs.fontName) {
585 emitAttr("fontName", attrs.fontName, ix+1);
586 }
587 fprintf (outFile, " ]\n");
588 }
589}
590
591static void emitEdge(Agraph_t *G, Agedge_t *e) {
592 fprintf(outFile, " edge [\n id %" PRIu64 "\n", (uint64_t)AGSEQ(e));
593 fprintf(outFile, " source %" PRIu64 "\n", ID(agtail(e)));
594 fprintf(outFile, " target %" PRIu64 "\n", ID(aghead(e)));
595 emitEdgeAttrs(G, e, 2);
596 fprintf (outFile, " ]\n");
597}
598
599static void emitGraphAttrs(Agraph_t *G) {
600 char* v;
601
602 for (Agsym_t *s = agnxtattr(G, AGRAPH, NULL); s; s = agnxtattr(G, AGRAPH, s)) {
603 if (*(v = agxget (G, s))) {
604 emitAttr(s->name, v, 1);
605 }
606 }
607}
608
609static void gv_to_gml(Agraph_t *G) {
610 Agnode_t* n;
611 Agedge_t* e;
612
613 fprintf (outFile, "graph [\n version 2\n");
614 if (agisdirected(G))
615 fprintf (outFile, " directed 1\n");
616 else
617 fprintf (outFile, " directed 0\n");
618
620
621 /* FIX: Not sure how to handle default attributes or subgraphs */
622
623 for (n = agfstnode(G); n; n = agnxtnode (G, n)) {
624 emitNode(G, n);
625 }
626
627 for (n = agfstnode(G); n; n = agnxtnode (G, n)) {
628 for (e = agfstout(G, n); e; e = agnxtout (G, e)) {
629 emitEdge(G, e);
630 }
631 }
632 fprintf (outFile, "]\n");
633}
634
635static char *useString = "Usage: %s [-y] [-?] <files>\n\
636 -o<file> : output to <file> (stdout)\n\
637 -y : output yWorks.com GML variant\n\
638 -? - print usage\n\
639If no files are specified, stdin is used\n";
640
641static void usage(int v)
642{
643 printf(useString, CmdName);
644 graphviz_exit(v);
645}
646
647static char *cmdName(char *cmd)
648{
649 char *sp;
650
651 sp = strrchr(cmd, '/');
652 if (sp)
653 sp++;
654 else
655 sp = cmd;
656 return sp;
657}
658
659static void initargs(int argc, char **argv)
660{
661 int c;
662
663 CmdName = cmdName(argv[0]);
664 opterr = 0;
665 while ((c = getopt(argc, argv, ":o:y")) != -1) {
666 switch (c) {
667 case 'o':
668 if (outFile != NULL)
669 fclose(outFile);
670 outFile = openFile(CmdName, optarg, "w");
671 break;
672 case 'y':
673 yworks = true;
674 break;
675 case ':':
676 fprintf(stderr, "%s: option -%c missing parameter\n", CmdName, optopt);
677 usage(1);
678 break;
679 case '?':
680 if (optopt == '?')
681 usage(0);
682 else {
683 fprintf(stderr, "%s: option -%c unrecognized\n", CmdName,
684 optopt);
685 usage(1);
686 }
687 break;
688 default:
689 UNREACHABLE();
690 }
691 }
692
693 argv += optind;
694 argc -= optind;
695
696 if (argc)
697 Files = argv;
698 if (!outFile)
699 outFile = stdout;
700}
701
702int main(int argc, char **argv)
703{
704 Agraph_t *G;
705 Agraph_t *prev = 0;
706 int rv;
707 ingraph_state ig;
708
709 rv = 0;
710 initargs(argc, argv);
711 newIngraph(&ig, Files);
712
713 while ((G = nextGraph(&ig))) {
714 if (prev) {
715 id = 0;
716 agclose(prev);
717 }
718 prev = G;
719 gv_to_gml(G);
720 fflush(outFile);
721 }
722 graphviz_exit(rv);
723}
abstract graph C library, Cgraph API
static char * cmd
Definition acyclic.c:42
static NORETURN void graphviz_exit(int status)
Definition exit.h:23
static int flags
Definition gc.c:63
#define G
Definition gdefs.h:7
node NULL
Definition grammar.y:181
Agsym_t * agnxtattr(Agraph_t *g, int kind, Agsym_t *attr)
permits traversing the list of attributes of a given type
Definition attr.c:365
char * agxget(void *obj, Agsym_t *sym)
Definition attr.c:460
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Definition edge.c:28
#define agtail(e)
Definition cgraph.h:977
#define aghead(e)
Definition cgraph.h:978
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Definition edge.c:43
int agisdirected(Agraph_t *g)
Definition graph.c:178
int agclose(Agraph_t *g)
deletes a graph, freeing its associated storage
Definition graph.c:97
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition node.c:50
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:43
char * agnameof(void *)
returns a string descriptor for the object.
Definition id.c:145
#define AGSEQ(obj)
Definition cgraph.h:225
@ AGEDGE
Definition cgraph.h:207
@ AGNODE
Definition cgraph.h:207
@ AGRAPH
Definition cgraph.h:207
void * agbindrec(void *obj, const char *name, unsigned int recsize, int move_to_front)
attaches a new record of the given size to the object
Definition rec.c:91
static void emitNode(Agraph_t *G, Agnode_t *n)
Definition gv2gml.c:417
#define BOLD
Definition gv2gml.c:53
#define POS_SET
Definition gv2gml.c:45
static void emitSpline(char *s, int ix)
Definition gv2gml.c:188
static char * readPoint(char *s, double *xp, double *yp)
Definition gv2gml.c:158
static void emitEdgeAttrs(Agraph_t *G, Agedge_t *ep, int ix)
Definition gv2gml.c:432
#define W_SET
Definition gv2gml.c:46
static void emitInt(char *name, int value, int ix)
Definition gv2gml.c:133
static void emitGraphAttrs(Agraph_t *G)
Definition gv2gml.c:599
#define INVIS
Definition gv2gml.c:48
#define ID(n)
Definition gv2gml.c:94
static void emitReal(char *name, double value, int ix)
Definition gv2gml.c:138
static char * arrowEnd(char *s0, char *pfx, int *fp, double *xp, double *yp)
Definition gv2gml.c:173
static FILE * outFile
Definition gv2gml.c:39
static int xml_puts(FILE *stream, const char *s)
Definition gv2gml.c:215
static void initargs(int argc, char **argv)
Definition gv2gml.c:659
#define DASH
Definition gv2gml.c:51
static void emitNodeAttrs(Agraph_t *G, Agnode_t *np, int ix)
Definition gv2gml.c:236
#define FILL
Definition gv2gml.c:49
static int put(void *stream, const char *s)
Definition gv2gml.c:210
static uint64_t id
Definition gv2gml.c:42
static char * skipWS(char *s)
Definition gv2gml.c:149
#define DOT
Definition gv2gml.c:52
static void emitEdge(Agraph_t *G, Agedge_t *e)
Definition gv2gml.c:591
#define H_SET
Definition gv2gml.c:47
static bool yworks
use yWorks.com variant of GML?
Definition gv2gml.c:43
static void emitAttr(char *name, char *value, int ix)
Definition gv2gml.c:220
static void indent(int ix)
Definition gv2gml.c:96
static char * useString
Definition gv2gml.c:635
static void gv_to_gml(Agraph_t *G)
Definition gv2gml.c:609
static char ** Files
Definition gv2gml.c:41
static int parseStyle(char *s)
Simple implementation for parsing style attribute.
Definition gv2gml.c:115
static bool isNumber(char *s)
Return true if input string is number.
Definition gv2gml.c:102
static char * CmdName
Definition gv2gml.c:40
#define LINE
Definition gv2gml.c:50
static char * cmdName(char *cmd)
Definition gv2gml.c:647
static void emitPoint(double x, double y, int ix)
Definition gv2gml.c:143
replacements for ctype.h functions
static bool gv_isspace(int c)
Definition gv_ctype.h:55
static const char * usage
Definition gvpr.c:54
$2 prev
Definition htmlparse.y:291
Agraph_t * nextGraph(ingraph_state *sp)
Definition ingraphs.c:61
ingraph_state * newIngraph(ingraph_state *sp, char **files)
Definition ingraphs.c:140
supports user-supplied data
static FILE * openFile(const char *argv0, const char *name, const char *mode)
Definition openFile.h:8
static int label(Agnode_t *n, int nodecnt, int *edgecnt)
Definition sccmap.c:163
static bool streq(const char *a, const char *b)
are a and b equal?
Definition streq.h:11
graph or subgraph
Definition cgraph.h:424
implementation of Agrec_t
Definition cgraph.h:172
string attribute descriptor symbol in Agattr_s.dict
Definition cgraph.h:640
uint64_t id
Definition gv2gml.c:91
char * fill
Definition gv2gml.c:78
char * width
Definition gv2gml.c:77
unsigned int flags
Definition gv2gml.c:75
char * fontName
Definition gv2gml.c:86
char * fontColor
Definition gv2gml.c:84
char * arrowhead
Definition gv2gml.c:80
char * arrow
Definition gv2gml.c:79
char * fontSize
Definition gv2gml.c:85
char * pos
Definition gv2gml.c:82
char * arrowtail
Definition gv2gml.c:81
char * outline
Definition gv2gml.c:65
double x
Definition gv2gml.c:58
double w
Definition gv2gml.c:60
double y
Definition gv2gml.c:59
char * type
Definition gv2gml.c:62
char * fontColor
Definition gv2gml.c:69
unsigned int flags
Definition gv2gml.c:56
double h
Definition gv2gml.c:61
char * fill
Definition gv2gml.c:64
char * fontSize
Definition gv2gml.c:70
char * outlineStyle
Definition gv2gml.c:67
char * fontName
Definition gv2gml.c:71
char * image
Definition gv2gml.c:63
char * width
Definition gv2gml.c:66
a non-owning string reference
Definition strview.h:20
state for an in-progress string tokenization
Definition tokenize.h:36
options to tweak the behavior of XML escaping
Definition xml.h:13
unsigned dash
escape '-'
Definition xml.h:17
Non-owning string references.
static bool strview_str_eq(strview_t a, const char *b)
compare a string reference to a string for equality
Definition strview.h:98
int main()
String tokenization.
static strview_t tok_get(const tok_t *t)
get the current token
Definition tokenize.h:76
static tok_t tok(const char *input, const char *separators)
begin tokenization of a new string
Definition tokenize.h:43
static bool tok_end(const tok_t *t)
is this tokenizer exhausted?
Definition tokenize.h:68
static void tok_next(tok_t *t)
advance to the next token in the string being scanned
Definition tokenize.h:85
Definition grammar.c:90
char * name
Definition grammar.c:95
#define UNREACHABLE()
Definition unreachable.h:30
int gv_xml_escape(const char *s, xml_flags_t flags, int(*cb)(void *state, const char *s), void *state)
Definition xml.c:185
XML escaping functionality.