Graphviz 13.0.0~dev.20241220.2304
Loading...
Searching...
No Matches
gvgen.c
Go to the documentation of this file.
1
6/*************************************************************************
7 * Copyright (c) 2011 AT&T Intellectual Property
8 * All rights reserved. This program and the accompanying materials
9 * are made available under the terms of the Eclipse Public License v1.0
10 * which accompanies this distribution, and is available at
11 * https://www.eclipse.org/legal/epl-v10.html
12 *
13 * Contributors: Details at https://graphviz.org
14 *************************************************************************/
15
16/*
17 * Written by Emden Gansner
18 */
19
20#include "config.h"
21
22#include <limits.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <ctype.h>
27#include <getopt.h>
28#include "graph_generator.h"
29#include "openFile.h"
30#include <util/exit.h>
31
32typedef enum { unknown, grid, circle, complete, completeb,
36
37typedef struct {
38 unsigned graphSize1;
39 unsigned graphSize2;
40 unsigned cnt;
41 unsigned parm1;
42 unsigned parm2;
47 FILE *outfile;
48 char* pfx;
49 char* name;
50} opts_t;
51
52static char *cmd;
53
54static char *Usage = "Usage: %s [-dv?] [options]\n\
55 -c<n> : cycle \n\
56 -C<x,y> : cylinder \n\
57 -g[f]<h,w> : grid (folded if f is used)\n\
58 -G[f]<h,w> : partial grid (folded if f is used)\n\
59 -h<x> : hypercube \n\
60 -k<x> : complete \n\
61 -b<x,y> : complete bipartite\n\
62 -B<x,y> : ball\n\
63 -i<n> : generate <n> random\n\
64 -m<x> : triangular mesh\n\
65 -M<x,y> : x by y Moebius strip\n\
66 -n<prefix> : use <prefix> in node names (\"\")\n\
67 -N<name> : use <name> for the graph (\"\")\n\
68 -o<outfile> : put output in <outfile> (stdout)\n\
69 -p<x> : path \n\
70 -r<x>,<n> : random graph\n\
71 -R<n> : random rooted tree on <n> vertices\n\
72 -s<x> : star\n\
73 -S<x> : 2D sierpinski\n\
74 -S<x>,<d> : <d>D sierpinski (<d> = 2,3)\n\
75 -t<x> : binary tree \n\
76 -t<x>,<n> : n-ary tree \n\
77 -T<x,y> : torus \n\
78 -T<x,y,t1,t2> : twisted torus \n\
79 -w<x> : wheel\n\
80 -d : directed graph\n\
81 -v : verbose mode\n\
82 -? : print usage\n";
83
84static void usage(int v)
85{
86 fprintf(v ? stderr : stdout, Usage, cmd);
88}
89
90static void errexit(int opt) {
91 fprintf(stderr, "in flag -%c\n", (char)opt);
92 usage(1);
93}
94
95/* readPos:
96 * Read and return a single unsigned int from s, guaranteed to be >= 1.
97 * A pointer to the next available character from s is stored in e.
98 * Return 0 on error.
99 */
100static unsigned readPos(char *s, char **e) {
101 static const unsigned MIN = 1;
102
103 const unsigned long d = strtoul(s, e, 10);
104 if (s == *e || d > UINT_MAX) {
105 fprintf(stderr, "ill-formed integer \"%s\" ", s);
106 return 0;
107 }
108 if (d < MIN) {
109 fprintf(stderr, "integer \"%s\" less than %d", s, MIN);
110 return 0;
111 }
112 return (unsigned)d;
113}
114
115/* readOne:
116 * Return non-zero on error.
117 */
118static int readOne(char *s, unsigned *ip) {
119 const unsigned d = readPos(s, &(char *){NULL});
120 if (d > 0) {
121 *ip = d;
122 return 0;
123 }
124 return -1;
125}
126
127/* setOne:
128 * Return non-zero on error.
129 */
130static int setOne(char *s, opts_t* opts)
131{
132 return readOne(s, &opts->graphSize1);
133}
134
135/* setTwo:
136 * Return non-zero on error.
137 */
138static int setTwo(char *s, opts_t* opts)
139{
140 char *next;
141
142 unsigned d = readPos(s, &next);
143 if (d == 0)
144 return -1;
145 opts->graphSize1 = d;
146
147 if (*next != ',') {
148 fprintf(stderr, "ill-formed int pair \"%s\" ", s);
149 return -1;
150 }
151
152 s = next + 1;
153 d = readPos(s, &(char *){NULL});
154 if (d > 1) {
155 opts->graphSize2 = d;
156 return 0;
157 }
158 return -1;
159}
160
161/* setTwoTwoOpt:
162 * Read 2 numbers
163 * Read 2 more optional numbers
164 * Return non-zero on error.
165 */
166static int setTwoTwoOpt(char *s, opts_t *opts, unsigned dflt) {
167 char *next;
168
169 unsigned d = readPos(s, &next);
170 if (d == 0)
171 return -1;
172 opts->graphSize1 = d;
173
174 if (*next != ',') {
175 fprintf(stderr, "ill-formed int pair \"%s\" ", s);
176 return -1;
177 }
178
179 s = next + 1;
180 d = readPos(s, &next);
181 if (d == 0) {
182 return 0;
183 }
184 opts->graphSize2 = d;
185
186 if (*next != ',') {
187 opts->parm1 = opts->parm2 = dflt;
188 return 0;
189 }
190
191 s = next + 1;
192 d = readPos(s, &next);
193 if (d == 0)
194 return -1;
195 opts->parm1 = d;
196
197 if (*next != ',') {
198 opts->parm2 = dflt;
199 return 0;
200 }
201
202 s = next + 1;
203 return readOne(s, &opts->parm2);
204}
205
206/* setTwoOpt:
207 * Return non-zero on error.
208 */
209static int setTwoOpt(char *s, opts_t *opts, unsigned dflt) {
210 char *next;
211
212 unsigned d = readPos(s, &next);
213 if (d == 0)
214 return -1;
215 opts->graphSize1 = d;
216
217 if (*next != ',') {
218 opts->graphSize2 = dflt;
219 return 0;
220 }
221
222 s = next + 1;
223 d = readPos(s, &(char *){NULL});
224 if (d > 1) {
225 opts->graphSize2 = d;
226 return 0;
227 }
228 return -1;
229}
230
231static char* setFold(char *s, opts_t* opts)
232{
233 char *next;
234
235 if (*s == 'f') {
236 next = s+1;
237 opts->foldVal = 1;
238 }
239 else
240 next = s;
241
242 return next;
243}
244
245static char *optList = ":i:M:m:n:N:c:C:dg:G:h:k:b:B:o:p:r:R:s:S:X:t:T:vw:";
246
247static GraphType init(int argc, char *argv[], opts_t* opts)
248{
249 int c;
251
252 cmd = argv[0];
253 opterr = 0;
254 while ((c = getopt(argc, argv, optList)) != -1) {
255 switch (c) {
256 case 'c':
258 if (setOne(optarg, opts))
259 errexit(c);
260 break;
261 case 'C':
263 if (setTwo(optarg, opts))
264 errexit(c);
265 break;
266 case 'M':
268 if (setTwo(optarg, opts))
269 errexit(c);
270 break;
271 case 'd':
272 opts->directed = 1;
273 break;
274 case 'G':
275 opts->isPartial = 1;
276 // fall through
277 case 'g':
278 graphType = grid;
279 optarg = setFold (optarg, opts);
280 if (setTwo(optarg, opts))
281 errexit(c);
282 break;
283 case 'h':
285 if (setOne(optarg, opts))
286 errexit(c);
287 break;
288 case 'k':
290 if (setOne(optarg, opts))
291 errexit(c);
292 break;
293 case 'b':
295 if (setTwo(optarg, opts))
296 errexit(c);
297 break;
298 case 'B':
299 graphType = ball;
300 if (setTwo(optarg, opts))
301 errexit(c);
302 break;
303 case 'm':
305 if (setOne(optarg, opts))
306 errexit(c);
307 break;
308 case 'r':
310 if (setTwo(optarg, opts))
311 errexit(c);
312 break;
313 case 'R':
315 if (setOne(optarg, opts))
316 errexit(c);
317 break;
318 case 'n':
319 opts->pfx = optarg;
320 break;
321 case 'N':
322 opts->name = optarg;
323 break;
324 case 'o':
325 opts->outfile = openFile(cmd, optarg, "w");
326 break;
327 case 'p':
328 graphType = path;
329 if (setOne(optarg, opts))
330 errexit(c);
331 break;
332 case 'S':
334 if (setTwoOpt(optarg, opts, 2))
335 errexit(c);
336 if (opts->graphSize2 > 3) {
337 fprintf(stderr, "%uD Sierpinski not implemented - use 2 or 3 ",
339 errexit(c);
340 }
341 break;
342 case 's':
343 graphType = star;
344 if (setOne(optarg, opts))
345 errexit(c);
346 break;
347 case 't':
348 graphType = tree;
349 if (setTwoOpt(optarg, opts, 2))
350 errexit(c);
351 break;
352 case 'T':
354 if (setTwoTwoOpt(optarg, opts, 0))
355 errexit(c);
356 break;
357 case 'i':
358 if (readOne(optarg, &opts->cnt))
359 errexit(c);
360 break;
361 case 'v':
362 opts->Verbose = 1;
363 break;
364 case 'w':
366 if (setOne(optarg, opts))
367 errexit(c);
368 break;
369 case '?':
370 if (optopt == '?')
371 usage(0);
372 else
373 fprintf(stderr, "Unrecognized flag \"-%c\" - ignored\n",
374 optopt);
375 break;
376 default:
377 fprintf(stderr, "Unexpected error\n");
378 usage(EXIT_FAILURE);
379 }
380 }
381
382 argc -= optind;
383 argv += optind;
384 if (!opts->outfile)
385 opts->outfile = stdout;
386 if (graphType == unknown) {
387 fprintf(stderr, "Graph type not set\n");
388 usage(1);
389 }
390
391 return graphType;
392}
393
395
396static void dirfn(unsigned t, unsigned h) {
397 if (h > 0)
398 fprintf(opts.outfile, " %s%u -> %s%u\n", opts.pfx, t, opts.pfx, h);
399 else
400 fprintf(opts.outfile, " %s%u\n", opts.pfx, t);
401}
402
403static void undirfn(unsigned t, unsigned h) {
404 if (h > 0)
405 fprintf(opts.outfile, " %s%u -- %s%u\n", opts.pfx, t, opts.pfx, h);
406 else
407 fprintf(opts.outfile, " %s%u\n", opts.pfx, t);
408}
409
410static void
412{
413 if (opts.directed)
414 fprintf(opts.outfile, "}\ndigraph {\n");
415 else
416 fprintf(opts.outfile, "}\ngraph {\n");
417}
418
419int main(int argc, char *argv[])
420{
422 edgefn ef;
423
424 opts.pfx = "";
425 opts.name = "";
426 opts.cnt = 1;
427 graphType = init(argc, argv, &opts);
428 if (opts.directed) {
429 fprintf(opts.outfile, "digraph %s{\n", opts.name);
430 ef = dirfn;
431 }
432 else {
433 fprintf(opts.outfile, "graph %s{\n", opts.name);
434 ef = undirfn;
435 }
436
437 switch (graphType) {
438 case grid:
441 break;
442 case circle:
444 break;
445 case path:
447 break;
448 case tree:
449 if (opts.graphSize2 == 2)
451 else
453 break;
454 case trimesh:
456 break;
457 case ball:
459 break;
460 case torus:
461 if (opts.parm1 == 0 && opts.parm2 == 0)
463 else
465 break;
466 case cylinder:
468 break;
469 case mobius:
471 break;
472 case sierpinski:
473 if (opts.graphSize2 == 2)
475 else
477 break;
478 case complete:
480 break;
481 case randomg:
483 break;
484 case randomt:
485 {
487 for (unsigned i = 1; i <= opts.cnt; i++) {
488 makeRandomTree (tg, ef);
489 if (i != opts.cnt) closeOpen ();
490 }
491 freeTreeGen (tg);
492 }
494 break;
495 case completeb:
497 break;
498 case hypercube:
500 break;
501 case star:
503 break;
504 case wheel:
506 break;
507 default:
508 /* can't happen */
509 break;
510 }
511 fprintf(opts.outfile, "}\n");
512
513 graphviz_exit(0);
514}
#define MIN(a, b)
Definition arith.h:28
static NORETURN void graphviz_exit(int status)
Definition exit.h:23
node NULL
Definition grammar.y:163
void makeTriMesh(unsigned sz, edgefn ef)
void makeHypercube(unsigned dim, edgefn ef)
void makeCircle(unsigned n, edgefn ef)
void makeTree(unsigned depth, unsigned nary, edgefn ef)
void makeWheel(unsigned n, edgefn ef)
void makeSquareGrid(unsigned dim1, unsigned dim2, int connect_corners, int partial, edgefn ef)
void makeBinaryTree(unsigned depth, edgefn ef)
void makeComplete(unsigned n, edgefn ef)
void makeMobius(unsigned w, unsigned h, edgefn ef)
treegen_t * makeTreeGen(unsigned N)
void makeCompleteB(unsigned dim1, unsigned dim2, edgefn ef)
void makeBall(unsigned w, unsigned h, edgefn ef)
void makePath(unsigned n, edgefn ef)
void makeTetrix(unsigned depth, edgefn ef)
void makeCylinder(unsigned dim1, unsigned dim2, edgefn ef)
void makeStar(unsigned n, edgefn ef)
void freeTreeGen(treegen_t *tg)
void makeTorus(unsigned dim1, unsigned dim2, edgefn ef)
void makeTwistedTorus(unsigned dim1, unsigned dim2, unsigned t1, unsigned t2, edgefn ef)
void makeRandomTree(treegen_t *tg, edgefn ef)
void makeRandom(unsigned h, unsigned w, edgefn ef)
void makeSierpinski(unsigned depth, edgefn ef)
static int setTwoTwoOpt(char *s, opts_t *opts, unsigned dflt)
Definition gvgen.c:166
GraphType
Definition gvgen.c:32
@ ball
Definition gvgen.c:33
@ completeb
Definition gvgen.c:32
@ circle
Definition gvgen.c:32
@ sierpinski
Definition gvgen.c:34
@ randomt
Definition gvgen.c:33
@ unknown
Definition gvgen.c:32
@ hypercube
Definition gvgen.c:34
@ mobius
Definition gvgen.c:33
@ cylinder
Definition gvgen.c:33
@ wheel
Definition gvgen.c:34
@ tree
Definition gvgen.c:33
@ trimesh
Definition gvgen.c:34
@ grid
Definition gvgen.c:32
@ star
Definition gvgen.c:34
@ torus
Definition gvgen.c:33
@ path
Definition gvgen.c:33
@ complete
Definition gvgen.c:32
@ randomg
Definition gvgen.c:33
static void dirfn(unsigned t, unsigned h)
Definition gvgen.c:396
static int setOne(char *s, opts_t *opts)
Definition gvgen.c:130
static int setTwoOpt(char *s, opts_t *opts, unsigned dflt)
Definition gvgen.c:209
static GraphType init(int argc, char *argv[], opts_t *opts)
Definition gvgen.c:247
static unsigned readPos(char *s, char **e)
Definition gvgen.c:100
static int readOne(char *s, unsigned *ip)
Definition gvgen.c:118
static int setTwo(char *s, opts_t *opts)
Definition gvgen.c:138
static char * cmd
Definition gvgen.c:52
static char * optList
Definition gvgen.c:245
static void errexit(int opt)
Definition gvgen.c:90
static void closeOpen(void)
Definition gvgen.c:411
static opts_t opts
Definition gvgen.c:394
static char * setFold(char *s, opts_t *opts)
Definition gvgen.c:231
static void undirfn(unsigned t, unsigned h)
Definition gvgen.c:403
static char * Usage
Definition gvgen.c:54
static const char * usage
Definition gvpr.c:51
static FILE * openFile(const char *argv0, const char *name, const char *mode)
Definition openFile.h:8
static int graphType
Definition scan.c:832
int directed
Definition gvgen.c:46
unsigned parm2
Definition gvgen.c:42
int Verbose
Definition gvgen.c:43
FILE * outfile
Definition gvgen.c:47
unsigned graphSize2
Definition gvgen.c:39
int foldVal
Definition gvgen.c:45
int isPartial
Definition gvgen.c:44
unsigned parm1
Definition gvgen.c:41
unsigned cnt
Definition gvgen.c:40
char * pfx
Definition gvgen.c:48
unsigned graphSize1
Definition gvgen.c:38
char * name
Definition gvgen.c:49
int main()
void(* edgefn)(Agraph_t *, Agedge_t *, glCompColor)
Definition grammar.c:93