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/*
16 * Written by Emden R. Gansner and Krishnam Pericherla
17 */
18
19#include "config.h"
20
21#include <ctype.h>
22#include <getopt.h>
23
24#include "convert.h"
25#include "ingraphs.h"
26
27typedef enum { Unset, ToGV, ToGXL } mode;
28
29static FILE *outFile;
30static char *CmdName;
31static char **Files;
32static mode act = Unset;
33
34#ifdef HAVE_EXPAT
35static FILE *getFile(void)
36{
37 FILE *rv = NULL;
38 static FILE *savef = NULL;
39 static int cnt = 0;
40
41 if (Files == NULL) {
42 if (cnt++ == 0) {
43 rv = stdin;
44 }
45 } else {
46 if (savef)
47 fclose(savef);
48 while (Files[cnt]) {
49 if ((rv = fopen(Files[cnt++], "r")) != 0)
50 break;
51 else
52 fprintf(stderr, "Can't open %s\n", Files[cnt - 1]);
53 }
54 }
55 savef = rv;
56 return rv;
57}
58#endif
59
60static FILE *openFile(char *name, char *mode)
61{
62 FILE *fp;
63 char *modestr;
64
65 fp = fopen(name, mode);
66 if (!fp) {
67 if (*mode == 'r')
68 modestr = "reading";
69 else
70 modestr = "writing";
71 fprintf(stderr, "%s: could not open file %s for %s\n",
72 CmdName, name, modestr);
73 perror(name);
74 exit(1);
75 }
76 return fp;
77}
78
79static const char *use = "Usage: %s [-gd?] [-o<file>] [<graphs>]\n\
80 -g : convert to GXL\n\
81 -d : convert to GV\n\
82 -o<file> : output to <file> (stdout)\n\
83 -? : usage\n";
84
85static void usage(int v)
86{
87 fprintf(stderr, use, CmdName);
88 exit(v);
89}
90
91static char *cmdName(char *path)
92{
93 char *sp;
94
95 sp = strrchr(path, '/');
96 if (sp)
97 sp++;
98 else
99 sp = path;
100 return sp;
101}
102
103static void checkInput(void)
104{
105 char *ep;
106
107 ep = strrchr(*Files, '.');
108 if (!ep)
109 return;
110 ep++;
111 if (strcmp(ep, "gv") == 0)
112 act = ToGXL;
113 else if (strcmp(ep, "dot") == 0)
114 act = ToGXL;
115 else if (strcmp(ep, "gxl") == 0)
116 act = ToGV;
117}
118
119static void setAction(void)
120{
121 if (tolower(CmdName[0]) == 'd')
122 act = ToGXL;
123 else if (tolower(CmdName[0]) == 'g') {
124 if (tolower(CmdName[1]) == 'v')
125 act = ToGXL;
126 else
127 act = ToGV;
128 }
129 else if (Files)
130 checkInput();
131
132 if (act == Unset) {
133 fprintf(stderr, "Cannot determine conversion type\n");
134 usage(1);
135 }
136}
137
138static void initargs(int argc, char **argv)
139{
140 int c;
141
142 CmdName = cmdName(argv[0]);
143 opterr = 0;
144 while ((c = getopt(argc, argv, ":gdo:")) != -1) {
145 switch (c) {
146 case 'd':
147 act = ToGV;
148 break;
149 case 'g':
150 act = ToGXL;
151 break;
152 case 'o':
153 outFile = openFile(optarg, "w");
154 break;
155 case ':':
156 fprintf(stderr, "%s: option -%c missing argument\n", CmdName, optopt);
157 break;
158 case '?':
159 if (optopt == '?')
160 usage(0);
161 else {
162 fprintf(stderr, "%s: option -%c unrecognized\n", CmdName,
163 optopt);
164 exit(1);
165 }
166 }
167 }
168
169 argv += optind;
170 argc -= optind;
171
172 if (argc > 0)
173 Files = argv;
174 if (!outFile)
175 outFile = stdout;
176 if (act == Unset)
177 setAction();
178}
179
180static Agraph_t *gread(FILE * fp)
181{
182 return agread(fp, (Agdisc_t *) 0);
183}
184
185int main(int argc, char **argv)
186{
187 Agraph_t *G;
188 Agraph_t *prev = 0;
189
190 initargs(argc, argv);
191 if (act == ToGXL) {
192 ingraph_state ig;
193 newIngraph(&ig, Files, gread);
194
195 while ((G = nextGraph(&ig))) {
196 if (prev)
197 agclose(prev);
198 prev = G;
199 gv_to_gxl(G, outFile);
200 fflush(outFile);
201 }
202 } else {
203#ifdef HAVE_EXPAT
204 FILE *inFile;
205 while ((inFile = getFile())) {
206 while ((G = gxl_to_gv(inFile))) {
207 if (prev)
208 agclose(prev);
209 prev = G;
210 agwrite(G, outFile);
211 fflush(outFile);
212 }
213 }
214#else
215 fputs("cvtgxl: not configured for conversion from GXL to GV\n",
216 stderr);
217 exit(1);
218
219#endif
220 }
221 exit(0);
222}
223