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