Graphviz 12.0.1~dev.20240715.2254
Loading...
Searching...
No Matches
input.c
Go to the documentation of this file.
1
3/*************************************************************************
4 * Copyright (c) 2011 AT&T Intellectual Property
5 * All rights reserved. This program and the accompanying materials
6 * are made available under the terms of the Eclipse Public License v1.0
7 * which accompanies this distribution, and is available at
8 * https://www.eclipse.org/legal/epl-v10.html
9 *
10 * Contributors: Details at https://graphviz.org
11 *************************************************************************/
12
13#include <common/render.h>
14#include <common/htmltable.h>
15#include <errno.h>
16#include <gvc/gvc.h>
17#include <xdot/xdot.h>
18#include <cgraph/agxbuf.h>
19#include <cgraph/alloc.h>
20#include <cgraph/gv_ctype.h>
21#include <cgraph/gv_math.h>
22#include <cgraph/exit.h>
23#include <cgraph/startswith.h>
24#include <cgraph/strcasecmp.h>
25#include <cgraph/streq.h>
26#include <limits.h>
27#include <stdbool.h>
28#include <stdlib.h>
29#include <string.h>
30
31static char *usageFmt =
32 "Usage: %s [-Vv?] [-(GNE)name=val] [-(KTlso)<val>] <dot files>\n";
33
34static char *genericItems = "\n\
35 -V - Print version and exit\n\
36 -v - Enable verbose mode \n\
37 -Gname=val - Set graph attribute 'name' to 'val'\n\
38 -Nname=val - Set node attribute 'name' to 'val'\n\
39 -Ename=val - Set edge attribute 'name' to 'val'\n\
40 -Tv - Set output format to 'v'\n\
41 -Kv - Set layout engine to 'v' (overrides default based on command name)\n\
42 -lv - Use external library 'v'\n\
43 -ofile - Write output to 'file'\n\
44 -O - Automatically generate an output filename based on the input filename with a .'format' appended. (Causes all -ofile options to be ignored.) \n\
45 -P - Internally generate a graph of the current plugins. \n\
46 -q[l] - Set level of message suppression (=1)\n\
47 -s[v] - Scale input by 'v' (=72)\n\
48 -y - Invert y coordinate in output\n";
49
50static char *neatoFlags =
51 "(additional options for neato) [-x] [-n<v>]\n";
52static char *neatoItems = "\n\
53 -n[v] - No layout mode 'v' (=1)\n\
54 -x - Reduce graph\n";
55
56static char *fdpFlags =
57 "(additional options for fdp) [-L(gO)] [-L(nUCT)<val>]\n";
58static char *fdpItems = "\n\
59 -Lg - Don't use grid\n\
60 -LO - Use old attractive force\n\
61 -Ln<i> - Set number of iterations to i\n\
62 -LU<i> - Set unscaled factor to i\n\
63 -LC<v> - Set overlap expansion factor to v\n\
64 -LT[*]<v> - Set temperature (temperature factor) to v\n";
65
66static char *configFlags = "(additional options for config) [-cv]\n";
67static char *configItems = "\n\
68 -c - Configure plugins (Writes $prefix/lib/graphviz/config \n\
69 with available plugin information. Needs write privilege.)\n\
70 -? - Print usage and exit\n";
71
72/* Print usage information. If GvExitOnUsage is set, exit with
73 * given exval, else return exval+1.
74 */
75int dotneato_usage(int exval)
76{
77 FILE *outs;
78
79 if (exval > 0)
80 outs = stderr;
81 else
82 outs = stdout;
83
84 fprintf(outs, usageFmt, CmdName);
85 fputs(neatoFlags, outs);
86 fputs(fdpFlags, outs);
87 fputs(configFlags, outs);
88 fputs(genericItems, outs);
89 fputs(neatoItems, outs);
90 fputs(fdpItems, outs);
91 fputs(configItems, outs);
92
93 if (GvExitOnUsage && exval >= 0)
94 graphviz_exit(exval);
95 return exval + 1;
96}
97
98/* Look for flag parameter. idx is index of current argument.
99 * We assume argv[*idx] has the form "-x..." If there are characters
100 * after the x, return
101 * these, else if there are more arguments, return the next one,
102 * else return NULL.
103 */
104static char *getFlagOpt(int argc, char **argv, int *idx)
105{
106 int i = *idx;
107 char *arg = argv[i];
108
109 if (arg[2])
110 return arg + 2;
111 if (i < argc - 1) {
112 i++;
113 arg = argv[i];
114 if (*arg && *arg != '-') {
115 *idx = i;
116 return arg;
117 }
118 }
119 return 0;
120}
121
122/* Partial implementation of real basename.
123 * Skip over any trailing slashes or backslashes; then
124 * find next (back)slash moving left; return string to the right.
125 * If no next slash is found, return the whole string.
126 */
127static char *dotneato_basename(char *pathname) {
128 char* ret;
129 char* s = pathname;
130 if (*s == '\0') return pathname; /* empty string */
131#ifdef _WIN32
132 /* On Windows, executables, by convention, end in ".exe". Thus,
133 * this may be part of the path name and must be removed for
134 * matching to work.
135 */
136 {
137 char* dotp = strrchr (s, '.');
138 if (dotp && !strcasecmp(dotp+1,"exe")) *dotp = '\0';
139 }
140#endif
141 while (*s) s++;
142 s--;
143 /* skip over trailing slashes, nulling out as we go */
144 while (s > pathname && (*s == '/' || *s == '\\'))
145 *s-- = '\0';
146 if (s == pathname) ret = pathname;
147 else {
148 while (s > pathname && *s != '/' && *s != '\\') s--;
149 if (*s == '/' || *s == '\\') ret = s+1;
150 else ret = pathname;
151 }
152#ifdef _WIN32
153 /* On Windows, names are case-insensitive, so make name lower-case
154 */
155 gv_tolower_str(ret);
156#endif
157 return ret;
158}
159
160static void use_library(GVC_t *gvc, const char *name)
161{
162 static size_t cnt = 0;
163 if (name) {
164 const size_t old_nmemb = cnt == 0 ? cnt : cnt + 1;
165 Lib = gv_recalloc(Lib, old_nmemb, cnt + 2, sizeof(const char *));
166 Lib[cnt++] = name;
167 Lib[cnt] = NULL;
168 }
169 gvc->common.lib = Lib;
170}
171
172static void global_def(char *dcl, int kind) {
173 char *p;
174 char *rhs = "true";
175 agxbuf xb = {0};
176
177 attrsym_t *sym;
178 if ((p = strchr(dcl, '='))) {
179 agxbput_n(&xb, dcl, (size_t)(p - dcl));
180 rhs = p+1;
181 }
182 else
183 agxbput(&xb, dcl);
184 sym = agattr(NULL, kind, agxbuse(&xb), rhs);
185 sym->fixed = 1;
186 agxbfree(&xb);
187}
188
189static int gvg_init(GVC_t *gvc, graph_t *g, char *fn, int gidx)
190{
191 GVG_t *gvg = gv_alloc(sizeof(GVG_t));
192 if (!gvc->gvgs)
193 gvc->gvgs = gvg;
194 else
195 gvc->gvg->next = gvg;
196 gvc->gvg = gvg;
197 gvg->gvc = gvc;
198 gvg->g = g;
199 gvg->input_filename = fn;
200 gvg->graph_index = gidx;
201 return 0;
202}
203
205
207{
208 gvg_init(gvc, P_graph, "<internal>", 0);
209 return P_graph;
210}
211
212/* Scan argv[] for allowed flags.
213 * Return 0 on success; v+1 if calling function should call exit(v).
214 * If -c is set, config file is created and we exit.
215 */
216int dotneato_args_initialize(GVC_t * gvc, int argc, char **argv)
217{
218 char c, *rest, *layout;
219 const char *val;
220 int i, v;
221 int Kflag = 0;
222
223 /* establish if we are running in a CGI environment */
224 HTTPServerEnVar = getenv("SERVER_NAME");
225
226 // test `$GV_FILE_PATH`, a legacy knob, is not set
227 if (getenv("GV_FILE_PATH") != NULL) {
228 fprintf(stderr, "$GV_FILE_PATH environment variable set; exiting\n"
229 "\n"
230 "This sandboxing mechanism is no longer supported\n");
231 graphviz_exit(EXIT_FAILURE);
232 }
233
235 if (gvc->common.verbose) {
236 fprintf(stderr, "%s - %s version %s (%s)\n",
238 gvc->common.info[1], gvc->common.info[2]);
239 }
240
241 /* configure for available plugins */
242 /* needs to know if "dot -c" is set (gvc->common.config) */
243 /* must happen before trying to select any plugins */
244 if (gvc->common.config) {
246 graphviz_exit(0);
247 }
248
249 /* feed the globals */
250 Verbose = gvc->common.verbose > UCHAR_MAX
251 ? UCHAR_MAX
252 : (unsigned char)gvc->common.verbose;
254
255 size_t nfiles = 0;
256 for (i = 1; i < argc; i++)
257 if (argv[i] && argv[i][0] != '-')
258 nfiles++;
259 gvc->input_filenames = gv_calloc(nfiles + 1, sizeof(char *));
260 nfiles = 0;
261 for (i = 1; i < argc; i++) {
262 if (argv[i] &&
263 (startswith(argv[i], "-V") || strcmp(argv[i], "--version") == 0)) {
264 fprintf(stderr, "%s - %s version %s (%s)\n",
266 gvc->common.info[1], gvc->common.info[2]);
268 return 1;
269 } else if (argv[i] &&
270 (startswith(argv[i], "-?") || strcmp(argv[i], "--help") == 0)) {
271 return dotneato_usage(0);
272 } else if (argv[i] && startswith(argv[i], "--filepath=")) {
274 Gvfilepath = gv_strdup(argv[i] + strlen("--filepath="));
275 } else if (argv[i] && argv[i][0] == '-') {
276 rest = &argv[i][2];
277 switch (c = argv[i][1]) {
278 case 'G':
279 if (*rest)
280 global_def(rest, AGRAPH);
281 else {
282 fprintf(stderr, "Missing argument for -G flag\n");
283 return dotneato_usage(1);
284 }
285 break;
286 case 'N':
287 if (*rest)
288 global_def(rest, AGNODE);
289 else {
290 fprintf(stderr, "Missing argument for -N flag\n");
291 return dotneato_usage(1);
292 }
293 break;
294 case 'E':
295 if (*rest)
296 global_def(rest, AGEDGE);
297 else {
298 fprintf(stderr, "Missing argument for -E flag\n");
299 return dotneato_usage(1);
300 }
301 break;
302 case 'T':
303 val = getFlagOpt(argc, argv, &i);
304 if (!val) {
305 fprintf(stderr, "Missing argument for -T flag\n");
306 return dotneato_usage(1);
307 }
308 if (!gvjobs_output_langname(gvc, val)) {
309 /* TODO: Detect empty results from gvplugin_list() and prompt to configure with '-c' */
310 char *fmts;
311 fprintf(stderr, "Format: \"%s\" not recognized.", val);
312 fmts = gvplugin_list(gvc, API_device, val);
313 if (strlen(fmts) > 1) {
314 fprintf(stderr, " Use one of:%s\n", fmts);
315 } else {
316 /* Q: Should 'dot -c' be suggested generally or only when val = "dot"? */
317 fprintf(stderr, " No formats found.\nPerhaps \"dot -c\" needs to be run (with installer's privileges) to register the plugins?\n");
318 }
320 return(2);
321 }
322 break;
323 case 'K':
324 val = getFlagOpt(argc, argv, &i);
325 if (!val) {
326 fprintf(stderr, "Missing argument for -K flag\n");
327 return dotneato_usage(1);
328 }
329 v = gvlayout_select(gvc, val);
330 if (v == NO_SUPPORT) {
331 fprintf(stderr, "There is no layout engine support for \"%s\"\n", val);
332 if (streq(val, "dot")) {
333 fprintf(stderr, "Perhaps \"dot -c\" needs to be run (with installer's privileges) to register the plugins?\n");
334 }
335 else {
336 /* TODO: Detect empty results from gvplugin_list() and prompt to configure with '-c' */
337 /* fprintf(stderr, "Use one of:%s\n", gvplugin_list(gvc, API_layout, val)); */
338 char *lyts;
339 lyts = gvplugin_list(gvc, API_layout, val);
340 if (strlen(lyts) > 1) {
341 fprintf(stderr, " Use one of:%s\n", lyts);
342 } else {
343 /* Q: Should 'dot -c' be suggested generally or only when val = "dot"? */
344 fprintf(stderr, " No layouts found.\nPerhaps \"dot -c\" needs to be run (with installer's privileges) to register the plugins?\n");
345 }
346 }
348 return(2);
349 }
350 Kflag = 1;
351 break;
352 case 'P':
354 break;
355 case 'l':
356 val = getFlagOpt(argc, argv, &i);
357 if (!val) {
358 fprintf(stderr, "Missing argument for -l flag\n");
359 return dotneato_usage(1);
360 }
361 use_library(gvc, val);
362 break;
363 case 'o':
364 val = getFlagOpt(argc, argv, &i);
365 if (!val) {
366 fprintf(stderr, "Missing argument for -o flag\n");
367 return dotneato_usage(1);
368 }
371 break;
372 case 'q':
373 if (*rest) {
374 v = atoi(rest);
375 if (v <= 0) {
376 fprintf(stderr,
377 "Invalid parameter \"%s\" for -q flag - ignored\n",
378 rest);
379 } else if (v == 1)
381 else
383 } else
385 break;
386 case 's':
387 if (*rest) {
388 PSinputscale = atof(rest);
389 if (PSinputscale < 0) {
390 fprintf(stderr,
391 "Invalid parameter \"%s\" for -s flag\n",
392 rest);
393 return dotneato_usage(1);
394 }
397 } else
399 break;
400 case 'x':
401 Reduce = true;
402 break;
403 case 'y':
404 Y_invert = true;
405 break;
406 default:
407 agerrorf("%s: option -%c unrecognized\n\n", gvc->common.cmdname,
408 c);
409 return dotneato_usage(1);
410 }
411 } else if (argv[i])
412 gvc->input_filenames[nfiles++] = argv[i];
413 }
414
415 /* if no -K, use cmd name to set layout type */
416 if (!Kflag) {
418 if (streq(layout, "dot_static")
419 || streq(layout, "dot_builtins")
420 || streq(layout, "lt-dot")
421 || streq(layout, "lt-dot_builtins")
422 || streq(layout, "") /* when run as a process from Gvedit on Windows */
423 )
424 layout = "dot";
426 if (i == NO_SUPPORT) {
427 fprintf(stderr, "There is no layout engine support for \"%s\"\n", layout);
428 if (streq(layout, "dot")) {
429 fprintf(stderr, "Perhaps \"dot -c\" needs to be run (with installer's privileges) to register the plugins?\n");
430 } else {
431 /* TODO: Detect empty results from gvplugin_list() and prompt to configure with '-c' */
432 /* fprintf(stderr, "Use one of:%s\n", gvplugin_list(gvc, API_layout, "")); */
433 char *lyts;
434 lyts = gvplugin_list(gvc, API_layout, "");
435 if (strlen(lyts) > 1) {
436 fprintf(stderr, " Use one of:%s\n", lyts);
437 } else {
438 /* Q: Should 'dot -c' be suggested generally or only when val = "dot"? */
439 fprintf(stderr, " No layouts found.\nPerhaps \"dot -c\" needs to be run (with installer's privileges) to register the plugins?\n");
440 }
441 }
442
444 return 2;
445 }
446 }
447
448 /* if no -Txxx, then set default format */
449 if (!gvc->jobs || !gvc->jobs->output_langname) {
450 if (!gvjobs_output_langname(gvc, "dot")) {
451 fprintf(stderr,
452 "Unable to find even the default \"-Tdot\" renderer. Has the config\nfile been generated by running \"dot -c\" with installer's privileges?\n");
453 return 2;
454 }
455 }
456
457 /* set persistent attributes here (if not already set from command line options) */
458 if (!agattr(NULL, AGNODE, "label", 0))
459 agattr(NULL, AGNODE, "label", NODENAME_ESC);
460 return 0;
461}
462
463/* converts a graph attribute in inches to a pointf in points.
464 * If only one number is given, it is used for both x and y.
465 * Returns true if the attribute ends in '!'.
466 */
467static bool getdoubles2ptf(graph_t *g, char *name, pointf *result) {
468 char *p;
469 int i;
470 double xf, yf;
471 char c = '\0';
472 bool rv = false;
473
474 if ((p = agget(g, name))) {
475 i = sscanf(p, "%lf,%lf%c", &xf, &yf, &c);
476 if (i > 1 && xf > 0 && yf > 0) {
477 result->x = POINTS(xf);
478 result->y = POINTS(yf);
479 if (c == '!')
480 rv = true;
481 }
482 else {
483 c = '\0';
484 i = sscanf(p, "%lf%c", &xf, &c);
485 if (i > 0 && xf > 0) {
486 result->y = result->x = POINTS(xf);
487 if (c == '!') rv = true;
488 }
489 }
490 }
491 return rv;
492}
493
494void getdouble(graph_t * g, char *name, double *result)
495{
496 char *p;
497 double f;
498
499 if ((p = agget(g, name))) {
500 if (sscanf(p, "%lf", &f) >= 1)
501 *result = f;
502 }
503}
504
506{
507 graph_t *g = NULL;
508 static char *fn;
509 static FILE *fp;
510 static FILE *oldfp;
511 static int gidx;
512
513 while (!g) {
514 if (!fp) {
515 if (!(fn = gvc->input_filenames[0])) {
516 if (gvc->fidx++ == 0)
517 fp = stdin;
518 }
519 else {
520 while ((fn = gvc->input_filenames[gvc->fidx++]) && !(fp = fopen(fn, "r"))) {
521 agerrorf("%s: can't open %s: %s\n", gvc->common.cmdname, fn, strerror(errno));
523 }
524 }
525 }
526 if (fp == NULL)
527 break;
528 if (oldfp != fp) {
529 agsetfile(fn ? fn : "<stdin>");
530 oldfp = fp;
531 }
532 g = agread(fp,NULL);
533 if (g) {
534 gvg_init(gvc, g, fn, gidx++);
535 break;
536 }
537 if (fp != stdin)
538 fclose (fp);
539 oldfp = fp = NULL;
540 gidx = 0;
541 }
542 return g;
543}
544
545/* Check if the charset attribute is defined for the graph and, if
546 * so, return the corresponding internal value. If undefined, return
547 * CHAR_UTF8
548 */
549static unsigned char findCharset(graph_t *g) {
550 char* p;
551
552 p = late_nnstring(g,agfindgraphattr(g,"charset"),"utf-8");
553 if (!strcasecmp(p,"latin-1")
554 || !strcasecmp(p,"latin1")
555 || !strcasecmp(p,"l1")
556 || !strcasecmp(p,"ISO-8859-1")
557 || !strcasecmp(p,"ISO_8859-1")
558 || !strcasecmp(p,"ISO8859-1")
559 || !strcasecmp(p,"ISO-IR-100"))
560 return CHAR_LATIN1;
561 if (!strcasecmp(p,"big-5")
562 || !strcasecmp(p,"big5"))
563 return CHAR_BIG5;
564 if (!strcasecmp(p,"utf-8")
565 || !strcasecmp(p,"utf8"))
566 return CHAR_UTF8;
567 agwarningf("Unsupported charset \"%s\" - assuming utf-8\n", p);
568 return CHAR_UTF8;
569}
570
572static void setRatio(graph_t * g)
573{
574 char *p;
575 double ratio;
576
577 if ((p = agget(g, "ratio"))) {
578 if (streq(p, "auto")) {
579 GD_drawing(g)->ratio_kind = R_AUTO;
580 } else if (streq(p, "compress")) {
581 GD_drawing(g)->ratio_kind = R_COMPRESS;
582 } else if (streq(p, "expand")) {
583 GD_drawing(g)->ratio_kind = R_EXPAND;
584 } else if (streq(p, "fill")) {
585 GD_drawing(g)->ratio_kind = R_FILL;
586 } else {
587 ratio = atof(p);
588 if (ratio > 0.0) {
589 GD_drawing(g)->ratio_kind = R_VALUE;
590 GD_drawing(g)->ratio = ratio;
591 }
592 }
593 }
594}
595
596void graph_init(graph_t * g, bool use_rankdir)
597{
598 char *p;
599 double xf;
600 static char *rankname[] = { "local", "global", "none", NULL };
601 static int rankcode[] = { LOCAL, GLOBAL, NOCLUST, LOCAL };
602 static char *fontnamenames[] = {"gd","ps","svg", NULL};
603 static int fontnamecodes[] = {NATIVEFONTS,PSFONTS,SVGFONTS,-1};
604 int rankdir;
605 GD_drawing(g) = gv_alloc(sizeof(layout_t));
606
607 /* reparseable input */
608 if ((p = agget(g, "postaction"))) { /* requires a graph wrapper for yyparse */
609 agxbuf buf = {0};
610 agxbprint(&buf, "%s { %s }", agisdirected(g) ? "digraph" : "graph", p);
611 agmemconcat(g, agxbuse(&buf));
612 agxbfree(&buf);
613 }
614
615 /* set this up fairly early in case any string sizes are needed */
616 if ((p = agget(g, "fontpath")) || (p = getenv("DOTFONTPATH"))) {
617 /* overide GDFONTPATH in local environment if dot
618 * wants its own */
619#ifdef HAVE_SETENV
620 setenv("GDFONTPATH", p, 1);
621#else
622 static agxbuf buf;
623 agxbprint(&buf, "GDFONTPATH=%s", p);
624 putenv(agxbuse(&buf));
625#endif
626 }
627
628 GD_charset(g) = findCharset (g);
629
630 if (!HTTPServerEnVar) {
631 Gvimagepath = agget (g, "imagepath");
632 if (!Gvimagepath) {
634 }
635 }
636
637 GD_drawing(g)->quantum =
638 late_double(g, agfindgraphattr(g, "quantum"), 0.0, 0.0);
639
640 /* setting rankdir=LR is only defined in dot,
641 * but having it set causes shape code and others to use it.
642 * The result is confused output, so we turn it off unless requested.
643 * This effective rankdir is stored in the bottom 2 bits of g->u.rankdir.
644 * Sometimes, the code really needs the graph's rankdir, e.g., neato -n
645 * with record shapes, so we store the real rankdir in the next 2 bits.
646 */
647 rankdir = RANKDIR_TB;
648 if ((p = agget(g, "rankdir"))) {
649 if (streq(p, "LR"))
650 rankdir = RANKDIR_LR;
651 else if (streq(p, "BT"))
652 rankdir = RANKDIR_BT;
653 else if (streq(p, "RL"))
654 rankdir = RANKDIR_RL;
655 }
656 if (use_rankdir)
657 SET_RANKDIR (g, (rankdir << 2) | rankdir);
658 else
659 SET_RANKDIR(g, rankdir << 2);
660
661 xf = late_double(g, agfindgraphattr(g, "nodesep"),
663 GD_nodesep(g) = POINTS(xf);
664
665 p = late_string(g, agfindgraphattr(g, "ranksep"), NULL);
666 if (p) {
667 if (sscanf(p, "%lf", &xf) == 0)
668 xf = DEFAULT_RANKSEP;
669 else {
670 if (xf < MIN_RANKSEP)
671 xf = MIN_RANKSEP;
672 }
673 if (strstr(p, "equally"))
674 GD_exact_ranksep(g) = true;
675 } else
676 xf = DEFAULT_RANKSEP;
677 GD_ranksep(g) = POINTS(xf);
678
679 {
680 int showboxes = late_int(g, agfindgraphattr(g, "showboxes"), 0, 0);
681 if (showboxes > UCHAR_MAX) {
682 showboxes = UCHAR_MAX;
683 }
684 GD_showboxes(g) = (unsigned char)showboxes;
685 }
686 p = late_string(g, agfindgraphattr(g, "fontnames"), NULL);
687 GD_fontnames(g) = maptoken(p, fontnamenames, fontnamecodes);
688
689 setRatio(g);
690 GD_drawing(g)->filled = getdoubles2ptf(g, "size", &GD_drawing(g)->size);
691 getdoubles2ptf(g, "page", &GD_drawing(g)->page);
692
693 GD_drawing(g)->centered = mapbool(agget(g, "center"));
694
695 if ((p = agget(g, "rotate")))
696 GD_drawing(g)->landscape = atoi(p) == 90;
697 else if ((p = agget(g, "orientation")))
698 GD_drawing(g)->landscape = p[0] == 'l' || p[0] == 'L';
699 else if ((p = agget(g, "landscape")))
700 GD_drawing(g)->landscape = mapbool(p);
701
702 p = agget(g, "clusterrank");
703 CL_type = maptoken(p, rankname, rankcode);
704 p = agget(g, "concentrate");
705 Concentrate = mapbool(p);
706 State = GVBEGIN;
707 EdgeLabelsDone = 0;
708
709 GD_drawing(g)->dpi = 0.0;
710 if (((p = agget(g, "dpi")) && p[0])
711 || ((p = agget(g, "resolution")) && p[0]))
712 GD_drawing(g)->dpi = atof(p);
713
715
717
718 G_ordering = agfindgraphattr(g, "ordering");
719 G_gradientangle = agfindgraphattr(g,"gradientangle");
720 G_margin = agfindgraphattr(g, "margin");
721
722 /* initialize nodes */
723 N_height = agfindnodeattr(g, "height");
724 N_width = agfindnodeattr(g, "width");
725 N_shape = agfindnodeattr(g, "shape");
726 N_color = agfindnodeattr(g, "color");
727 N_fillcolor = agfindnodeattr(g, "fillcolor");
728 N_style = agfindnodeattr(g, "style");
729 N_fontsize = agfindnodeattr(g, "fontsize");
730 N_fontname = agfindnodeattr(g, "fontname");
731 N_fontcolor = agfindnodeattr(g, "fontcolor");
732 N_label = agfindnodeattr(g, "label");
733 if (!N_label)
734 N_label = agattr(g, AGNODE, "label", NODENAME_ESC);
735 N_xlabel = agfindnodeattr(g, "xlabel");
736 N_showboxes = agfindnodeattr(g, "showboxes");
737 N_penwidth = agfindnodeattr(g, "penwidth");
738 N_ordering = agfindnodeattr(g, "ordering");
739 N_margin = agfindnodeattr(g, "margin");
740 /* attribs for polygon shapes */
741 N_sides = agfindnodeattr(g, "sides");
742 N_peripheries = agfindnodeattr(g, "peripheries");
743 N_skew = agfindnodeattr(g, "skew");
744 N_orientation = agfindnodeattr(g, "orientation");
745 N_distortion = agfindnodeattr(g, "distortion");
746 N_fixed = agfindnodeattr(g, "fixedsize");
747 N_imagescale = agfindnodeattr(g, "imagescale");
748 N_imagepos = agfindnodeattr(g, "imagepos");
749 N_nojustify = agfindnodeattr(g, "nojustify");
750 N_layer = agfindnodeattr(g, "layer");
751 N_group = agfindnodeattr(g, "group");
752 N_comment = agfindnodeattr(g, "comment");
753 N_vertices = agfindnodeattr(g, "vertices");
754 N_z = agfindnodeattr(g, "z");
755 N_gradientangle = agfindnodeattr(g,"gradientangle");
756
757 /* initialize edges */
758 E_weight = agfindedgeattr(g, "weight");
759 E_color = agfindedgeattr(g, "color");
760 E_fillcolor = agfindedgeattr(g, "fillcolor");
761 E_fontsize = agfindedgeattr(g, "fontsize");
762 E_fontname = agfindedgeattr(g, "fontname");
763 E_fontcolor = agfindedgeattr(g, "fontcolor");
764 E_label = agfindedgeattr(g, "label");
765 E_xlabel = agfindedgeattr(g, "xlabel");
766 E_label_float = agfindedgeattr(g, "labelfloat");
767 E_dir = agfindedgeattr(g, "dir");
768 E_arrowhead = agfindedgeattr(g, "arrowhead");
769 E_arrowtail = agfindedgeattr(g, "arrowtail");
770 E_headlabel = agfindedgeattr(g, "headlabel");
771 E_taillabel = agfindedgeattr(g, "taillabel");
772 E_labelfontsize = agfindedgeattr(g, "labelfontsize");
773 E_labelfontname = agfindedgeattr(g, "labelfontname");
774 E_labelfontcolor = agfindedgeattr(g, "labelfontcolor");
775 E_labeldistance = agfindedgeattr(g, "labeldistance");
776 E_labelangle = agfindedgeattr(g, "labelangle");
777 E_minlen = agfindedgeattr(g, "minlen");
778 E_showboxes = agfindedgeattr(g, "showboxes");
779 E_style = agfindedgeattr(g, "style");
780 E_decorate = agfindedgeattr(g, "decorate");
781 E_arrowsz = agfindedgeattr(g, "arrowsize");
782 E_constr = agfindedgeattr(g, "constraint");
783 E_layer = agfindedgeattr(g, "layer");
784 E_comment = agfindedgeattr(g, "comment");
785 E_tailclip = agfindedgeattr(g, "tailclip");
786 E_headclip = agfindedgeattr(g, "headclip");
787 E_penwidth = agfindedgeattr(g, "penwidth");
788
789 /* background */
790 GD_drawing(g)->xdots = init_xdot (g);
791
792 /* initialize id, if any */
793 if ((p = agget(g, "id")) && *p)
794 GD_drawing(g)->id = strdup_and_subst_obj(p, g);
795}
796
798{
799 if (GD_drawing(g) && GD_drawing(g)->xdots)
800 freeXDot(GD_drawing(g)->xdots);
801 if (GD_drawing(g))
802 free (GD_drawing(g)->id);
803 free(GD_drawing(g));
804 GD_drawing(g) = NULL;
806 //FIX HERE , STILL SHALLOW
807 //memset(&(g->u), 0, sizeof(Agraphinfo_t));
808 agclean(g, AGRAPH,"Agraphinfo_t");
809}
810
812char*
814{
815 char* s;
816
817 switch (c) {
818 case CHAR_UTF8 :
819 s = "UTF-8";
820 break;
821 case CHAR_LATIN1 :
822 s = "ISO-8859-1";
823 break;
824 case CHAR_BIG5 :
825 s = "BIG-5";
826 break;
827 default :
828 agerrorf("Unsupported charset value %d\n", c);
829 s = "UTF-8";
830 break;
831 }
832 return s;
833}
834
837{
838 char *str, *pos, *just;
839 int pos_ix;
840
841 /* it would be nice to allow multiple graph labels in the future */
842 if ((str = agget(sg, "label")) && *str != '\0') {
843 char pos_flag;
844 pointf dimen;
845
847
849 late_double(sg, agfindgraphattr(sg, "fontsize"),
851 late_nnstring(sg, agfindgraphattr(sg, "fontname"),
853 late_nnstring(sg, agfindgraphattr(sg, "fontcolor"),
855
856 /* set label position */
857 pos = agget(sg, "labelloc");
858 if (sg != agroot(sg)) {
859 if (pos && pos[0] == 'b')
860 pos_flag = LABEL_AT_BOTTOM;
861 else
862 pos_flag = LABEL_AT_TOP;
863 } else {
864 if (pos && pos[0] == 't')
865 pos_flag = LABEL_AT_TOP;
866 else
867 pos_flag = LABEL_AT_BOTTOM;
868 }
869 just = agget(sg, "labeljust");
870 if (just) {
871 if (just[0] == 'l')
872 pos_flag |= LABEL_AT_LEFT;
873 else if (just[0] == 'r')
874 pos_flag |= LABEL_AT_RIGHT;
875 }
876 GD_label_pos(sg) = pos_flag;
877
878 if (sg == agroot(sg))
879 return;
880
881 /* Set border information for cluster labels to allow space
882 */
883 dimen = GD_label(sg)->dimen;
884 PAD(dimen);
885 if (!GD_flip(agroot(sg))) {
886 if (GD_label_pos(sg) & LABEL_AT_TOP)
887 pos_ix = TOP_IX;
888 else
889 pos_ix = BOTTOM_IX;
890 GD_border(sg)[pos_ix] = dimen;
891 } else {
892 /* when rotated, the labels will be restored to TOP or BOTTOM */
893 if (GD_label_pos(sg) & LABEL_AT_TOP)
894 pos_ix = RIGHT_IX;
895 else
896 pos_ix = LEFT_IX;
897 GD_border(sg)[pos_ix].x = dimen.y;
898 GD_border(sg)[pos_ix].y = dimen.x;
899 }
900 }
901}
static void agxbfree(agxbuf *xb)
free any malloced resources
Definition agxbuf.h:77
static size_t agxbput(agxbuf *xb, const char *s)
append string s into xb
Definition agxbuf.h:249
static size_t agxbput_n(agxbuf *xb, const char *s, size_t ssz)
append string s of length ssz into xb
Definition agxbuf.h:229
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
Definition agxbuf.h:213
static char * agxbuse(agxbuf *xb)
Definition agxbuf.h:286
Memory allocation wrappers that exit on failure.
static void * gv_recalloc(void *ptr, size_t old_nmemb, size_t new_nmemb, size_t size)
Definition alloc.h:73
static char * gv_strdup(const char *original)
Definition alloc.h:101
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
static void * gv_alloc(size_t size)
Definition alloc.h:47
char * late_nnstring(void *obj, attrsym_t *attr, char *defaultValue)
Definition utils.c:84
bool mapbool(const char *p)
Definition utils.c:336
char * late_string(void *obj, attrsym_t *attr, char *defaultValue)
Definition utils.c:78
int late_int(void *obj, attrsym_t *attr, int defaultValue, int minimum)
Definition utils.c:33
int maptoken(char *p, char **name, int *val)
Definition utils.c:310
double late_double(void *obj, attrsym_t *attr, double defaultValue, double minimum)
Definition utils.c:48
#define DEFAULT_RANKSEP
Definition const.h:87
#define CHAR_UTF8
Definition const.h:196
#define LABEL_AT_LEFT
Definition const.h:186
#define BOTTOM_IX
Definition const.h:111
#define TOP_IX
Definition const.h:113
#define CHAR_LATIN1
Definition const.h:197
#define NO_SUPPORT
Definition const.h:147
#define MIN_NODESEP
Definition const.h:86
#define MIN_RANKSEP
Definition const.h:88
#define GRAPH_LABEL
Definition const.h:179
#define NODENAME_ESC
Definition const.h:80
#define LOCAL
Definition const.h:43
#define RANKDIR_BT
Definition const.h:192
#define GLOBAL
Definition const.h:44
#define DEFAULT_NODESEP
Definition const.h:85
#define LEFT_IX
Definition const.h:114
#define RANKDIR_TB
Definition const.h:190
#define CHAR_BIG5
Definition const.h:198
#define DEFAULT_COLOR
Definition const.h:48
#define RANKDIR_LR
Definition const.h:191
#define LABEL_AT_TOP
Definition const.h:185
#define MYHUGE
Definition const.h:168
#define DEFAULT_FONTSIZE
Definition const.h:61
#define MIN_FONTSIZE
Definition const.h:63
#define NOCLUST
Definition const.h:45
#define LT_NONE
Definition const.h:237
#define DEFAULT_FONTNAME
Definition const.h:67
#define LABEL_AT_RIGHT
Definition const.h:187
#define GVBEGIN
Definition const.h:172
#define RANKDIR_RL
Definition const.h:193
#define LABEL_AT_BOTTOM
Definition const.h:184
#define LT_HTML
Definition const.h:238
#define RIGHT_IX
Definition const.h:112
static char * CmdName
Definition cvtgxl.c:36
void * init_xdot(Agraph_t *g)
Definition emit.c:55
static NORETURN void graphviz_exit(int status)
Definition exit.h:23
#define POINTS(a_inches)
Definition geom.h:68
#define POINTS_PER_INCH
Definition geom.h:64
Agsym_t * N_fontsize
Definition globals.h:84
Agsym_t * E_labelfontsize
Definition globals.h:103
Agsym_t * E_fontcolor
Definition globals.h:96
Agsym_t * N_group
Definition globals.h:88
Agsym_t * N_imagescale
Definition globals.h:87
Agsym_t * N_width
Definition globals.h:79
Agsym_t * N_layer
Definition globals.h:87
Agsym_t * E_weight
Definition globals.h:91
int State
Definition globals.h:65
Agsym_t * E_comment
Definition globals.h:99
Agsym_t * N_orientation
Definition globals.h:86
Agsym_t * N_sides
Definition globals.h:86
bool Concentrate
Definition globals.h:61
Agsym_t * E_arrowtail
Definition globals.h:101
double Initial_dist
Definition globals.h:67
Agsym_t * E_headclip
Definition globals.h:105
Agsym_t * E_arrowhead
Definition globals.h:101
int GvExitOnUsage
Definition globals.h:70
Agsym_t * E_decorate
Definition globals.h:97
Agsym_t * E_headlabel
Definition globals.h:102
Agsym_t * E_style
Definition globals.h:97
Agsym_t * G_margin
Definition globals.h:77
Agsym_t * N_showboxes
Definition globals.h:85
int graphviz_errors
Definition globals.h:56
Agsym_t * N_fontname
Definition globals.h:84
Agsym_t * N_z
Definition globals.h:88
Agsym_t * E_fontname
Definition globals.h:96
Agsym_t * N_comment
Definition globals.h:88
Agsym_t * N_style
Definition globals.h:85
char * HTTPServerEnVar
Definition globals.h:55
int EdgeLabelsDone
Definition globals.h:66
Agsym_t * N_penwidth
Definition globals.h:89
char * Gvimagepath
Definition globals.h:51
Agsym_t * N_gradientangle
Definition globals.h:89
Agsym_t * E_fillcolor
Definition globals.h:91
Agsym_t * E_dir
Definition globals.h:97
Agsym_t * E_label
Definition globals.h:97
Agsym_t * N_skew
Definition globals.h:87
double PSinputscale
Definition globals.h:58
char * Gvfilepath
Definition globals.h:50
Agsym_t * E_minlen
Definition globals.h:91
Agsym_t * N_shape
Definition globals.h:79
Agsym_t * N_xlabel
Definition globals.h:85
int CL_type
Definition globals.h:60
Agsym_t * E_label_float
Definition globals.h:99
Agsym_t * N_nojustify
Definition globals.h:85
Agsym_t * E_color
Definition globals.h:91
Agsym_t * E_taillabel
Definition globals.h:102
bool Reduce
Definition globals.h:54
Agsym_t * N_label
Definition globals.h:85
Agsym_t * E_labelangle
Definition globals.h:104
Agsym_t * N_fillcolor
Definition globals.h:79
Agsym_t * E_fontsize
Definition globals.h:96
Agsym_t * E_arrowsz
Definition globals.h:98
Agsym_t * G_gradientangle
Definition globals.h:77
Agsym_t * N_vertices
Definition globals.h:88
Agsym_t * N_fixed
Definition globals.h:87
Agsym_t * N_peripheries
Definition globals.h:86
Agsym_t * E_labelfontname
Definition globals.h:103
Agsym_t * N_distortion
Definition globals.h:87
Agsym_t * G_ordering
Definition globals.h:76
Agsym_t * N_imagepos
Definition globals.h:87
bool Y_invert
invert y in dot & plain output
Definition globals.h:69
Agsym_t * E_xlabel
Definition globals.h:97
Agsym_t * E_penwidth
Definition globals.h:106
Agsym_t * E_layer
Definition globals.h:98
Agsym_t * E_constr
Definition globals.h:98
Agsym_t * N_fontcolor
Definition globals.h:84
Agsym_t * E_labelfontcolor
Definition globals.h:103
Agsym_t * E_tailclip
Definition globals.h:105
Agsym_t * N_color
Definition globals.h:79
Agsym_t * N_margin
Definition globals.h:84
Agsym_t * E_showboxes
Definition globals.h:98
Agsym_t * E_labeldistance
Definition globals.h:104
Agsym_t * N_ordering
Definition globals.h:86
Agsym_t * N_height
Definition globals.h:79
const char ** Lib
Definition globals.h:48
static int Verbose
Definition gml2gv.c:22
void free(void *)
node NULL
Definition grammar.y:149
static int cnt(Dict_t *d, Dtlink_t **set)
Definition graph.c:199
Agsym_t * agattr(Agraph_t *g, int kind, char *name, const char *value)
creates or looks up attributes of a graph
Definition attr.c:341
char * agget(void *obj, char *name)
Definition attr.c:442
#define agfindedgeattr(g, a)
Definition types.h:617
void agwarningf(const char *fmt,...)
Definition agerror.c:173
void agerrorf(const char *fmt,...)
Definition agerror.c:165
agerrlevel_t agseterr(agerrlevel_t lvl)
Definition agerror.c:38
@ AGMAX
Definition cgraph.h:858
@ AGERR
Definition cgraph.h:858
#define agfindgraphattr(g, a)
Definition types.h:613
#define GD_fontnames(g)
Definition types.h:402
#define GD_drawing(g)
Definition types.h:353
#define GD_border(g)
Definition types.h:359
#define GD_has_labels(g)
Definition types.h:368
int agisdirected(Agraph_t *g)
Definition graph.c:179
#define GD_label_pos(g)
Definition types.h:400
#define GD_showboxes(g)
Definition types.h:401
Agraph_t * agmemconcat(Agraph_t *g, const char *cp)
Definition io.c:102
#define GD_label(g)
Definition types.h:374
#define GD_nodesep(g)
Definition types.h:394
#define GD_charset(g)
Definition types.h:367
void agsetfile(const char *)
sets the current file name for subsequent error reporting
Definition scan.c:839
#define GD_flip(g)
Definition types.h:378
Agraph_t * agread(void *chan, Agdisc_t *disc)
constructs a new graph
Definition grammar.c:2274
#define GD_exact_ranksep(g)
Definition types.h:363
#define GD_ranksep(g)
Definition types.h:397
#define agfindnodeattr(g, a)
Definition types.h:615
Agraph_t * agroot(void *obj)
Definition obj.c:167
@ AGEDGE
Definition cgraph.h:207
@ AGNODE
Definition cgraph.h:207
@ AGRAPH
Definition cgraph.h:207
void agclean(Agraph_t *g, int kind, char *rec_name)
calls agdelrec for all objects of the same class in an entire graph
Definition rec.c:201
int aghtmlstr(const char *)
Definition refstr.c:163
graph_t * gvNextInputGraph(GVC_t *gvc)
Definition input.c:505
graph_t * gvPluginsGraph(GVC_t *gvc)
Definition input.c:206
replacements for ctype.h functions
static void gv_tolower_str(char *s)
Definition gv_ctype.h:87
Arithmetic helper functions.
static bool is_exactly_zero(double v)
is a value precisely 0.0?
Definition gv_math.h:62
Graphviz context library.
void gvconfig(GVC_t *gvc, bool rescan)
Definition gvconfig.c:549
void gvjobs_output_filename(GVC_t *gvc, const char *name)
Definition gvjobs.c:44
bool gvjobs_output_langname(GVC_t *gvc, const char *name)
Definition gvjobs.c:63
int gvlayout_select(GVC_t *gvc, const char *str)
Definition gvlayout.c:31
Agraph_t * gvplugin_graph(GVC_t *gvc)
Definition gvplugin.c:474
char * gvplugin_list(GVC_t *gvc, api_t api, const char *str)
Definition gvplugin.c:356
static Agdesc_t kind
Definition gvpack.cpp:88
GVC_t * gvc
Definition htmlparse.c:99
agxbuf * str
Definition htmlparse.c:97
static char * configFlags
Definition input.c:66
static char * fdpItems
Definition input.c:58
static char * configItems
Definition input.c:67
static char * usageFmt
Definition input.c:31
static void use_library(GVC_t *gvc, const char *name)
Definition input.c:160
static char * fdpFlags
Definition input.c:56
static void setRatio(graph_t *g)
Checks "ratio" attribute, if any, and sets enum type.
Definition input.c:572
char * charsetToStr(int c)
Given an internal charset value, return a canonical string representation.
Definition input.c:813
static char * neatoFlags
Definition input.c:50
void graph_init(graph_t *g, bool use_rankdir)
Definition input.c:596
int dotneato_args_initialize(GVC_t *gvc, int argc, char **argv)
Definition input.c:216
static void global_def(char *dcl, int kind)
Definition input.c:172
static char * neatoItems
Definition input.c:52
static int gvg_init(GVC_t *gvc, graph_t *g, char *fn, int gidx)
Definition input.c:189
static unsigned char findCharset(graph_t *g)
Definition input.c:549
static char * dotneato_basename(char *pathname)
Definition input.c:127
void graph_cleanup(graph_t *g)
Definition input.c:797
void getdouble(graph_t *g, char *name, double *result)
Definition input.c:494
static char * genericItems
Definition input.c:34
int dotneato_usage(int exval)
Definition input.c:75
void do_graph_label(graph_t *sg)
Set characteristics of graph label if it exists.
Definition input.c:836
static graph_t * P_graph
Definition input.c:204
static char * getFlagOpt(int argc, char **argv, int *idx)
Definition input.c:104
static bool getdoubles2ptf(graph_t *g, char *name, pointf *result)
Definition input.c:467
char * strdup_and_subst_obj(char *str, void *obj)
Definition labels.c:385
textlabel_t * make_label(void *obj, char *str, int kind, double fontsize, char *fontname, char *fontcolor)
Definition labels.c:108
void free_label(textlabel_t *p)
Definition labels.c:199
static int layout(graph_t *g, layout_info *infop)
Definition layout.c:809
#define PAD(d)
Definition macros.h:29
static bool startswith(const char *s, const char *prefix)
does the string s begin with the string prefix?
Definition startswith.h:11
platform abstraction for case-insensitive string functions
static bool streq(const char *a, const char *b)
are a and b equal?
Definition streq.h:11
graph or subgraph
Definition cgraph.h:425
Agraph_t * root
subgraphs - ancestors
Definition cgraph.h:434
string attribute descriptor symbol in Agattr_s.dict
Definition cgraph.h:639
unsigned char fixed
Definition cgraph.h:645
char * cmdname
Definition gvcommon.h:21
bool auto_outfile_names
Definition gvcommon.h:23
const char ** lib
Definition gvcommon.h:26
char ** info
Definition gvcommon.h:20
bool config
Definition gvcommon.h:23
int verbose
Definition gvcommon.h:22
Definition gvcint.h:80
int fidx
Definition gvcint.h:88
GVG_t * gvgs
Definition gvcint.h:91
GVCOMMON_t common
Definition gvcint.h:81
GVG_t * gvg
Definition gvcint.h:92
GVJ_t * jobs
Definition gvcint.h:114
char ** input_filenames
Definition gvcint.h:87
Definition gvcint.h:69
char * input_filename
Definition gvcint.h:73
GVG_t * next
Definition gvcint.h:71
int graph_index
Definition gvcint.h:74
GVC_t * gvc
Definition gvcint.h:70
graph_t * g
Definition gvcint.h:75
const char * output_langname
Definition gvcjob.h:282
double x
Definition geom.h:29
double y
Definition geom.h:29
@ NATIVEFONTS
Definition types.h:274
@ PSFONTS
Definition types.h:274
@ SVGFONTS
Definition types.h:274
#define SET_RANKDIR(g, rd)
Definition types.h:607
@ R_AUTO
Definition types.h:216
@ R_COMPRESS
Definition types.h:216
@ R_VALUE
Definition types.h:216
@ R_FILL
Definition types.h:216
@ R_EXPAND
Definition types.h:216
Definition grammar.c:93
void freeXDot(xdot *x)
Definition xdot.c:782
parsing and deparsing of xdot operations