Graphviz  2.35.20130930.0449
dot.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  * Written by Stephen North and Eleftherios Koutsofios.
16  */
17 
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21 
22 #include "gvc.h"
23 #include "gvio.h"
24 
25 #ifdef WIN32_DLL
26 __declspec(dllimport) boolean MemTest;
27 __declspec(dllimport) int GvExitOnUsage;
28 /*gvc.lib cgraph.lib*/
29 #ifdef WITH_CGRAPH
30  #pragma comment( lib, "cgraph.lib" )
31 #else
32  #pragma comment( lib, "graph.lib" )
33 #endif
34  #pragma comment( lib, "gvc.lib" )
35 #else /* not WIN32_DLL */
36 #include "globals.h"
37 #endif
38 
39 #include <stdlib.h>
40 #include <time.h>
41 #ifdef HAVE_UNISTD_H
42 #include <unistd.h>
43 #endif
44 
45 #if defined(HAVE_FENV_H) && defined(HAVE_FEENABLEEXCEPT)
46 /* _GNU_SOURCE is needed for feenableexcept to be defined in fenv.h on GNU
47  * systems. Presumably it will do no harm on other systems. */
48 #ifndef _GNU_SOURCE
49 #define _GNU_SOURCE
50 #endif
51 # include <fenv.h>
52 #elif HAVE_FPU_CONTROL_H
53 # include <fpu_control.h>
54 #elif HAVE_SYS_FPU_H
55 # include <sys/fpu.h>
56 #endif
57 
58 static GVC_t *Gvc;
59 static graph_t * G;
60 
61 #ifndef WIN32
62 static void intr(int s)
63 {
64 /* if interrupted we try to produce a partial rendering before exiting */
65  if (G)
66  gvRenderJobs(Gvc, G);
67 /* Note that we don't call gvFinalize() so that we don't start event-driven
68  * devices like -Tgtk or -Txlib */
69  exit (gvFreeContext(Gvc));
70 }
71 
72 #ifndef NO_FPERR
73 static void fperr(int s)
74 {
75  fprintf(stderr, "caught SIGFPE %d\n", s);
76  /* signal (s, SIG_DFL); raise (s); */
77  exit(1);
78 }
79 
80 static void fpinit(void)
81 {
82 #if defined(HAVE_FENV_H) && defined(HAVE_FEENABLEEXCEPT)
83  int exc = 0;
84 # ifdef FE_DIVBYZERO
85  exc |= FE_DIVBYZERO;
86 # endif
87 # ifdef FE_OVERFLOW
88  exc |= FE_OVERFLOW;
89 # endif
90 # ifdef FE_INVALID
91  exc |= FE_INVALID;
92 # endif
93  feenableexcept(exc);
94 
95 #ifdef HAVE_FESETENV
96 #ifdef FE_NONIEEE_ENV
97  fesetenv (FE_NONIEEE_ENV);
98 #endif
99 #endif
100 
101 #elif HAVE_FPU_CONTROL_H
102  /* On s390-ibm-linux, the header exists, but the definitions
103  * of the masks do not. I assume this is temporary, but until
104  * there's a real implementation, it's probably safest to not
105  * adjust the FPU on this platform.
106  */
107 # if defined(_FPU_MASK_IM) && defined(_FPU_MASK_DM) && defined(_FPU_MASK_ZM) && defined(_FPU_GETCW)
108  fpu_control_t fpe_flags = 0;
109  _FPU_GETCW(fpe_flags);
110  fpe_flags &= ~_FPU_MASK_IM; /* invalid operation */
111  fpe_flags &= ~_FPU_MASK_DM; /* denormalized operand */
112  fpe_flags &= ~_FPU_MASK_ZM; /* zero-divide */
113  /*fpe_flags &= ~_FPU_MASK_OM; overflow */
114  /*fpe_flags &= ~_FPU_MASK_UM; underflow */
115  /*fpe_flags &= ~_FPU_MASK_PM; precision (inexact result) */
116  _FPU_SETCW(fpe_flags);
117 # endif
118 #endif
119 }
120 #endif
121 #endif
122 
123 static graph_t *create_test_graph(void)
124 {
125 #define NUMNODES 5
126 
128  Agedge_t *e;
129  Agraph_t *g;
130  Agraph_t *sg;
131  int j, k;
132  char name[10];
133 
134  /* Create a new graph */
135 #ifndef WITH_CGRAPH
136  aginit();
138  g = agopen("new_graph", AGDIGRAPH);
139 #else /* WITH_CGRAPH */
140  g = agopen("new_graph", Agdirected,NIL(Agdisc_t *));
141 #endif /* WITH_CGRAPH */
142 
143  /* Add nodes */
144  for (j = 0; j < NUMNODES; j++) {
145  sprintf(name, "%d", j);
146 #ifndef WITH_CGRAPH
147  node[j] = agnode(g, name);
148 #else /* WITH_CGRAPH */
149  node[j] = agnode(g, name, 1);
150  agbindrec(node[j], "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); //node custom data
151 #endif /* WITH_CGRAPH */
152  }
153 
154  /* Connect nodes */
155  for (j = 0; j < NUMNODES; j++) {
156  for (k = j + 1; k < NUMNODES; k++) {
157 #ifndef WITH_CGRAPH
158  agedge(g, node[j], node[k]);
159 #else /* WITH_CGRAPH */
160  e = agedge(g, node[j], node[k], NULL, 1);
161  agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), TRUE); //edge custom data
162 #endif /* WITH_CGRAPH */
163  }
164  }
165 
166 #ifndef WITH_CGRAPH
167  sg = agsubg (g, "cluster1");
168  aginsert (sg, node[0]);
169 #else /* WITH_CGRAPH */
170  sg = agsubg (g, "cluster1", 1);
171  agsubnode (sg, node[0], 1);
172 #endif /* WITH_CGRAPH */
173 
174  return g;
175 }
176 
177 int main(int argc, char **argv)
178 {
179  graph_t *prev = NULL;
180  int r, rc = 0;
181 
182  Gvc = gvContextPlugins(lt_preloaded_symbols, DEMAND_LOADING);
183  GvExitOnUsage = 1;
184  gvParseArgs(Gvc, argc, argv);
185 #ifndef WIN32
186  signal(SIGUSR1, gvToggle);
187  signal(SIGINT, intr);
188 #ifndef NO_FPERR
189  fpinit();
190  signal(SIGFPE, fperr);
191 #endif
192 #endif
193 
194  if (MemTest) {
195  while (MemTest--) {
196  /* Create a test graph */
197  G = create_test_graph();
198 
199  /* Perform layout and cleanup */
200  gvLayoutJobs(Gvc, G); /* take layout engine from command line */
201  gvFreeLayout(Gvc, G);
202  agclose (G);
203  }
204  }
205  else if ((G = gvPluginsGraph(Gvc))) {
206  gvLayoutJobs(Gvc, G); /* take layout engine from command line */
207  gvRenderJobs(Gvc, G);
208  }
209  else {
210  while ((G = gvNextInputGraph(Gvc))) {
211  if (prev) {
212  gvFreeLayout(Gvc, prev);
213  agclose(prev);
214  }
215  gvLayoutJobs(Gvc, G); /* take layout engine from command line */
216  gvRenderJobs(Gvc, G);
217  r = agreseterrors();
218  rc = MAX(rc,r);
219  prev = G;
220  }
221  }
222  gvFinalize(Gvc);
223 
224  r = gvFreeContext(Gvc);
225  return (MAX(rc,r));
226 }