Graphviz  2.41.20170921.2350
dbg.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 
15 /* dbg.c:
16  * Written by Emden R. Gansner
17  *
18  * Simple debugging infrastructure
19  */
20 #ifdef DEBUG
21 
22 #define FDP_PRIVATE
23 
24 #include <dbg.h>
25 #include <neatoprocs.h>
26 #include <fdp.h>
27 #include <math.h>
28 
29 static int indent = -1;
30 
31 void incInd()
32 {
33  indent++;
34 }
35 
36 void decInd()
37 {
38  if (indent >= 0)
39  indent--;
40 }
41 
42 void prIndent(void)
43 {
44  int i;
45  for (i = 0; i < indent; i++)
46  fputs(" ", stderr);
47 }
48 
49 void prEdge(edge_t *e,char *s)
50 {
51  fprintf(stderr,"%s --", agnameof(agtail(e)));
52  fprintf(stderr,"%s%s", agnameof(aghead(e)),s);
53 }
54 
55 static void dumpBB(graph_t * g)
56 {
57  boxf bb;
58  boxf b;
59 
60  bb = BB(g);
61  b = GD_bb(g);
62  prIndent();
63  fprintf(stderr, " LL (%f,%f) UR (%f,%f)\n", bb.LL.x, bb.LL.y,
64  bb.UR.x, bb.UR.y);
65  prIndent();
66  fprintf(stderr, " LL (%f,%f) UR (%f,%f)\n", b.LL.x, b.LL.y,
67  b.UR.x, b.UR.y);
68 }
69 
70 static void dumpSG(graph_t * g)
71 {
72  graph_t *subg;
73  int i;
74 
75  if (GD_n_cluster(g) == 0)
76  return;
77  prIndent();
78  fprintf(stderr, " {\n");
79  for (i = 1; i <= GD_n_cluster(g); i++) {
80  subg = (GD_clust(g))[i];
81  prIndent();
82  fprintf(stderr, " subgraph %s : %d nodes\n", agnameof(subg),
83  agnnodes(subg));
84  dumpBB(subg);
85  incInd ();
86  dumpSG(subg);
87  decInd ();
88  }
89  prIndent();
90  fprintf(stderr, " }\n");
91 }
92 
93 /* dumpE:
94  */
95 void dumpE(graph_t * g, int derived)
96 {
97  Agnode_t *n;
98  Agedge_t *e;
99  Agedge_t **ep;
100  Agedge_t *el;
101  int i;
102  int deg;
103 
104  prIndent();
105  fprintf(stderr, "Graph %s : %d nodes %d edges\n", agnameof(g), agnnodes(g),
106  agnedges(g));
107  for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
108  deg = 0;
109  for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
110  deg++;
111  prIndent();
112  prEdge(e,"\n");
113  if (derived) {
114  for (i = 0, ep = (Agedge_t **) ED_to_virt(e);
115  i < ED_count(e); i++, ep++) {
116  el = *ep;
117  prIndent();
118  prEdge(el,"\n");
119  }
120  }
121  }
122  if (deg == 0) { /* no out edges */
123  if (!agfstin(g, n)) /* no in edges */
124  fprintf(stderr, " %s\n", agnameof(n));
125  }
126  }
127  if (!derived) {
128  bport_t *pp;
129  if ((pp = PORTS(g))) {
130  int sz = NPORTS(g);
131  fprintf(stderr, " %d ports\n", sz);
132  while (pp->e) {
133  fprintf(stderr, " %s : ", agnameof(pp->n));
134  prEdge(pp->e,"\n");
135  pp++;
136  }
137  }
138  }
139 }
140 
141 /* dump:
142  */
143 void dump(graph_t * g, int level, int doBB)
144 {
145  node_t *n;
146  boxf bb;
147  double w, h;
148  pointf pos;
149 
150  if (Verbose < level)
151  return;
152  prIndent();
153  fprintf(stderr, "Graph %s : %d nodes\n", agnameof(g), agnnodes(g));
154  dumpBB(g);
155  if (Verbose > level) {
156  incInd();
157  dumpSG(g);
158  decInd();
159  for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
160  pos.x = ND_pos(n)[0];
161  pos.y = ND_pos(n)[1];
162  prIndent();
163  w = ND_width(n);
164  h = ND_height(n);
165  if (doBB) {
166  bb.LL.x = pos.x - w / 2.0;
167  bb.LL.y = pos.y - h / 2.0;
168  bb.UR.x = bb.LL.x + w;
169  bb.UR.y = bb.LL.y + h;
170  fprintf(stderr, "%s: (%f,%f) ((%f,%f) , (%f,%f))\n",
171  agnameof(n), pos.x, pos.y, bb.LL.x, bb.LL.y, bb.UR.x,
172  bb.UR.y);
173  } else {
174  fprintf(stderr, "%s: (%f,%f) (%f,%f) \n",
175  agnameof(n), pos.x, pos.y, w, h);
176  }
177  }
178  }
179 }
180 
181 void dumpG(graph_t * g, char *fname, int expMode)
182 {
183  FILE *fp;
184 
185  fp = fopen(fname, "w");
186  if (!fp) {
187  fprintf(stderr, "Couldn not open %s \n", fname);
188  exit(1);
189  }
190  outputGraph(g, fp, expMode);
191  fclose(fp);
192 }
193 
194 /* #define BOX */
195 
196 /* static char* pos_name = "pos"; */
197 /* static char* lp_name = "lp"; */
198 
199 double Scale = 0.0;
200 double ArrowScale = 1.0;
201 
202 #define ARROW_LENGTH 10
203 #define ARROW_WIDTH 5
204 /* #define DEGREES(rad) ((rad)/M_PI * 180.0) */
205 
206 static char *plog = "%!PS-Adobe-2.0\n\n\
207 /Times-Roman findfont 14 scalefont setfont\n\
208 /lLabel {\n\
209 \tmoveto\n\
210 \tgsave\n\
211 \tshow\n\
212 \tgrestore\n\
213 } def\n\
214 /inch {\n\
215 \t72 mul\n\
216 } def\n\
217 /doBox {\n\
218 \tnewpath\n\
219 \tmoveto\n\
220 \t/ht exch def\n\
221 \t/wd exch def\n\
222 \t0 ht rlineto\n\
223 \twd 0 rlineto\n\
224 \t0 0 ht sub rlineto\n\
225 \tclosepath\n\
226 \tgsave\n\
227 \t\t.9 setgray\n\
228 \t\tfill\n\
229 \tgrestore\n\
230 \tstroke\n\
231 } def\n\
232 /drawCircle {\n\
233 \t/r exch def\n\
234 \t/y exch def\n\
235 \t/x exch def\n\
236 \tnewpath\n\
237 \tx y r 0 360 arc\n\
238 \tstroke\n\
239 } def\n\
240 /fillCircle {\n\
241 \t/r exch def\n\
242 \t/y exch def\n\
243 \t/x exch def\n\
244 \tnewpath\n\
245 \tx y r 0 360 arc\n\
246 \tfill\n\
247 } def\n";
248 
249 static char *elog = "showpage\n";
250 
251 /*
252 static char* arrow = "/doArrow {\n\
253 \t/arrowwidth exch def\n\
254 \t/arrowlength exch def\n\
255 \tgsave\n\
256 \t\t3 1 roll\n\
257 \t\ttranslate\n\
258 \t\t\trotate\n\
259 \t\t\tnewpath\n\
260 \t\t\tarrowlength arrowwidth 2 div moveto\n\
261 \t\t\t0 0 lineto\n\
262 \t\t\tarrowlength arrowwidth -2 div lineto\n\
263 \t\tclosepath fill\n\
264 \t\tstroke\n\
265 \tgrestore\n\
266 } def\n";
267 */
268 
269 static double PSWidth = 550.0;
270 static double PSHeight = 756.0;
271 
272 static void pswrite(Agraph_t * g, FILE * fp, int expMode)
273 {
274  Agnode_t *n;
275  Agnode_t *h;
276  Agedge_t *e;
277  double minx, miny, maxx, maxy;
278  double scale, width, height;
279  int do_arrow;
280  int angle;
281  char *p;
282  double theta;
283  double arrow_w, arrow_l;
284  int portColor;
285 
286  fprintf(fp, "%s", plog);
287 
288 /*
289  if (agisdirected (g) && DoArrow) {
290  do_arrow = 1;
291  fprintf(fp,arrow);
292  }
293  else
294 */
295  do_arrow = 0;
296 
297  n = agfstnode(g);
298  minx = ND_pos(n)[0];
299  miny = ND_pos(n)[1];
300  maxx = ND_pos(n)[0];
301  maxy = ND_pos(n)[1];
302  n = agnxtnode(g, n);
303  for (; n; n = agnxtnode(g, n)) {
304  if (ND_pos(n)[0] < minx)
305  minx = ND_pos(n)[0];
306  if (ND_pos(n)[1] < miny)
307  miny = ND_pos(n)[1];
308  if (ND_pos(n)[0] > maxx)
309  maxx = ND_pos(n)[0];
310  if (ND_pos(n)[1] > maxy)
311  maxy = ND_pos(n)[1];
312  }
313 
314  /* Convert to points
315  */
316  minx *= POINTS_PER_INCH;
317  miny *= POINTS_PER_INCH;
318  maxx *= POINTS_PER_INCH;
319  maxy *= POINTS_PER_INCH;
320 
321  /* Check for rotation
322  */
323  if ((p = agget(g, "rotate")) && (*p != '\0')
324  && ((angle = atoi(p)) != 0)) {
325  fprintf(fp, "306 396 translate\n");
326  fprintf(fp, "%d rotate\n", angle);
327  fprintf(fp, "-306 -396 translate\n");
328  }
329 
330  /* If user gives scale factor, use it.
331  * Else if figure too large for standard PS page, scale it to fit.
332  */
333  if (Scale > 0.0)
334  scale = Scale;
335  else {
336  width = maxx - minx + 20;
337  height = maxy - miny + 20;
338  if (width > PSWidth) {
339  if (height > PSHeight) {
340  scale =
341  (PSWidth / width <
342  PSHeight / height ? PSWidth / width : PSHeight /
343  height);
344  } else
345  scale = PSWidth / width;
346  } else if (height > PSHeight) {
347  scale = PSHeight / height;
348  } else
349  scale = 1.0;
350  }
351 
352  fprintf(fp, "%f %f translate\n",
353  (PSWidth - scale * (minx + maxx)) / 2.0,
354  (PSHeight - scale * (miny + maxy)) / 2.0);
355  fprintf(fp, "%f %f scale\n", scale, scale);
356 
357 /*
358  if (Verbose)
359  fprintf (stderr, "Region (%f,%f) (%f,%f), scale %f\n",
360  minx, miny, maxx, maxy, scale);
361 */
362 
363  if (do_arrow) {
364  arrow_w = ArrowScale * ARROW_WIDTH / scale;
365  arrow_l = ArrowScale * ARROW_LENGTH / scale;
366  }
367 
368  fprintf(fp, "0.0 setlinewidth\n");
369 #ifdef SHOW_GRID
370  if (UseGrid) {
371  int i;
372  fprintf(fp, "%f %f 5 fillCircle\n", 0.0, 0.0);
373  for (i = 0; i < maxx; i += CellW) {
374  fprintf(fp, "%f 0.0 moveto %f %f lineto stroke\n",
375  (float) i, (float) i, maxy);
376  }
377  for (i = 0; i < maxy; i += CellH) {
378  fprintf(fp, "0.0 %f moveto %f %f lineto stroke\n",
379  (float) i, maxx, (float) i);
380  }
381  }
382 #endif
383  for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
384  if (IS_PORT(n)) {
385  double r;
386  r = sqrt(ND_pos(n)[0] * ND_pos(n)[0] +
387  ND_pos(n)[1] * ND_pos(n)[1]);
388  fprintf(fp, "0 0 %f inch drawCircle\n", r);
389  break;
390  }
391  }
392 
393  for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
394  for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
395  h = aghead(e);
396  fprintf(fp, "%f inch %f inch moveto %f inch %f inch lineto\n",
397  ND_pos(n)[0], ND_pos(n)[1], ND_pos(h)[0],
398  ND_pos(h)[1]);
399  fprintf(fp, "stroke\n");
400  if (do_arrow) {
401  theta =
402  atan2(ND_pos(n)[1] - ND_pos(h)[1],
403  ND_pos(n)[0] - ND_pos(h)[0]);
404  fprintf(fp, "%f %f %.2f %.2f %.2f doArrow\n",
405  ND_pos(h)[0], ND_pos(h)[1], DEGREES(theta),
406  arrow_l, arrow_w);
407  }
408 
409  }
410  }
411 
412 #ifdef BOX
413  for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
414  float wd, ht;
415 
416  data = getData(n);
417  wd = data->wd;
418  ht = data->ht;
419  fprintf(fp, "%f %f %f %f doBox\n", wd, ht,
420  data->pos.x - (wd / 2), data->pos.y - (ht / 2));
421  }
422 #else
423  for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
424  fprintf(fp, "%% %s\n", agnameof(n));
425  if (expMode) {
426  double wd, ht;
427  double r;
428  wd = ND_width(n);
429  ht = ND_height(n);
430  r = sqrt((wd * wd / 4) + ht * ht / 4);
431  fprintf(fp, "%f inch %f inch %f inch %f inch doBox\n", wd, ht,
432  ND_pos(n)[0] - (wd / 2), ND_pos(n)[1] - (ht / 2));
433  fprintf(fp, "%f inch %f inch %f inch drawCircle\n",
434  ND_pos(n)[0], ND_pos(n)[1], r);
435  } else {
436  if (IS_PORT(n)) {
437  if (!portColor) {
438  fprintf(fp, "0.667 1.000 1.000 sethsbcolor\n");
439  portColor = 1;
440  }
441  } else {
442  if (portColor) {
443  fprintf(fp, "0.0 0.000 0.000 sethsbcolor\n");
444  portColor = 0;
445  }
446  }
447  }
448  fprintf(fp, "%f inch %f inch %f fillCircle\n", ND_pos(n)[0],
449  ND_pos(n)[1], 3 / scale);
450  }
451 #endif
452 
453  fprintf(fp, "0.667 1.000 1.000 sethsbcolor\n");
454  for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
455  for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
456  h = aghead(e);
457  fprintf(fp, "%f inch %f inch moveto %f inch %f inch lineto\n",
458  ND_pos(n)[0], ND_pos(n)[1], ND_pos(h)[0],
459  ND_pos(h)[1]);
460  fprintf(fp, "stroke\n");
461  if (do_arrow) {
462  theta =
463  atan2(ND_pos(n)[1] - ND_pos(h)[1],
464  ND_pos(n)[0] - ND_pos(h)[0]);
465  fprintf(fp, "%f %f %.2f %.2f %.2f doArrow\n",
466  ND_pos(h)[0], ND_pos(h)[1], DEGREES(theta),
467  arrow_l, arrow_w);
468  }
469 
470  }
471  }
472 
473  fprintf(fp, "%s", elog);
474 }
475 
476 void outputGraph(Agraph_t * g, FILE * fp, int expMode)
477 {
478  pswrite(g, fp, expMode);
479 }
480 
481 #endif /* DEBUG */
#define DEGREES(rad)
Definition: arith.h:86
#define GD_n_cluster(g)
Definition: types.h:396
CGRAPH_API Agedge_t * agfstin(Agraph_t *g, Agnode_t *n)
Definition: edge.c:56
Definition: geom.h:28
#define ND_pos(n)
Definition: types.h:526
CGRAPH_API Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Definition: edge.c:25
#define POINTS_PER_INCH
Definition: geom.h:62
char * agget(void *obj, char *name)
Definition: attr.c:428
CGRAPH_API Agnode_t * agtail(Agedge_t *e)
Definition: edge.c:525
CGRAPH_API Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition: node.c:45
CGRAPH_API Agnode_t * aghead(Agedge_t *e)
Definition: edge.c:533
double y
Definition: geom.h:28
CGRAPH_API char * agnameof(void *)
Definition: id.c:143
#define ND_height(n)
Definition: types.h:504
#define ED_count(e)
Definition: types.h:583
CGRAPH_API Agnode_t * agfstnode(Agraph_t *g)
Definition: node.c:38
Definition: grammar.c:79
#define GD_clust(g)
Definition: types.h:364
#define ND_width(n)
Definition: types.h:542
#define ED_to_virt(e)
Definition: types.h:602
double x
Definition: geom.h:28
EXTERN unsigned char Verbose
Definition: globals.h:64
CGRAPH_API int agnnodes(Agraph_t *g)
Definition: graph.c:162
pointf LL
Definition: geom.h:35
#define ARROW_LENGTH
Definition: arrows.c:20
#define GD_bb(g)
Definition: types.h:357
CGRAPH_API int agnedges(Agraph_t *g)
Definition: graph.c:167
CGRAPH_API Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Definition: edge.c:40
char * el(GVJ_t *job, char *template,...)
pointf UR
Definition: geom.h:35
Definition: geom.h:35
Definition: legal.c:60