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/* FIXME
15 * This is an ugly mess.
16 *
17 * Args should be made independent of layout engine and arg values
18 * should be stored in gvc or gvc->job. All globals should be eliminated.
19 *
20 * Needs to be fixed before layout engines can be plugins.
21 */
22
23#include <ctype.h>
24#include "render.h"
25#include "tlayout.h"
26#include "gvc.h"
27#include "fdp.h"
28
29/* neato_extra_args:
30 * Handle special neato arguments.
31 * Return number of unprocessed arguments; return < 0 on error.
32 */
33static int
34neato_extra_args(GVC_t *gvc, int argc, char** argv)
35{
36 char** p = argv+1;
37 int i;
38 char* arg;
39 int cnt = 1;
40
41 for (i = 1; i < argc; i++) {
42 arg = argv[i];
43 if (arg && *arg == '-') {
44 switch (arg[1]) {
45 case 'x' : Reduce = TRUE; break;
46 case 'n':
47 if (arg[2]) {
48 Nop = atoi(arg+2);
49 if (Nop <= 0) {
50 agerr (AGERR, "Invalid parameter \"%s\" for -n flag\n", arg+2);
51 dotneato_usage (1);
52 return -1;
53 }
54 }
55 else Nop = 1;
56 break;
57 default :
58 cnt++;
59 if (*p != arg) *p = arg;
60 p++;
61 break;
62 }
63 }
64 else {
65 cnt++;
66 if (*p != arg) *p = arg;
67 p++;
68 }
69 }
70 *p = 0;
71 return cnt;
72}
73
74/* memtest_extra_args:
75 * Handle special memtest arguments.
76 * Return number of unprocessed arguments; return < 0 on error.
77 */
78static int
79memtest_extra_args(GVC_t *gvc, int argc, char** argv)
80{
81 char** p = argv+1;
82 int i;
83 char* arg;
84 int cnt = 1;
85
86 for (i = 1; i < argc; i++) {
87 arg = argv[i];
88 if (arg && *arg == '-') {
89 switch (arg[1]) {
90 case 'm' :
91 if (arg[2]) {
92 MemTest = atoi(arg+2);
93 if (MemTest <= 0) {
94 agerr (AGERR, "Invalid parameter \"%s\" for -m flag\n", arg+2);
95 dotneato_usage (1);
96 return -1;
97 }
98 }
99 else MemTest = -1;
100 break;
101 default :
102 cnt++;
103 if (*p != arg) *p = arg;
104 p++;
105 break;
106 }
107 }
108 else {
109 cnt++;
110 if (*p != arg) *p = arg;
111 p++;
112 }
113 }
114 *p = 0;
115 return cnt;
116}
117
118/* config_extra_args:
119 * Handle special config arguments.
120 * Return number of unprocessed arguments; return < 0 on error.
121 */
122static int
123config_extra_args(GVC_t *gvc, int argc, char** argv)
124{
125 char** p = argv+1;
126 int i;
127 char* arg;
128 int cnt = 1;
129
130 for (i = 1; i < argc; i++) {
131 arg = argv[i];
132 if (arg && *arg == '-') {
133 switch (arg[1]) {
134 case 'v':
135 gvc->common.verbose = 1;
136 if (isdigit(arg[2]))
137 gvc->common.verbose = atoi(&arg[2]);
138 break;
139 case 'O' :
140 gvc->common.auto_outfile_names = TRUE;
141 break;
142 case 'c' :
143 gvc->common.config = TRUE;
144 break;
145 default :
146 cnt++;
147 if (*p != arg) *p = arg;
148 p++;
149 break;
150 }
151 }
152 else {
153 cnt++;
154 if (*p != arg) *p = arg;
155 p++;
156 }
157 }
158 *p = 0;
159 return cnt;
160}
161
162/* setDouble:
163 * If arg is an double, value is stored in v
164 * and functions returns 0; otherwise, returns 1.
165 */
166static int
167setDouble (double* v, char* arg)
168{
169 char* p;
170 double d;
171
172 d = strtod(arg,&p);
173 if (p == arg) {
174 agerr (AGERR, "bad value in flag -L%s - ignored\n", arg-1);
175 return 1;
176 }
177 *v = d;
178 return 0;
179}
180
181/* setInt:
182 * If arg is an integer, value is stored in v
183 * and functions returns 0; otherwise, returns 1.
184 */
185static int
186setInt (int* v, char* arg)
187{
188 char* p;
189 int i;
190
191 i = (int)strtol(arg,&p,10);
192 if (p == arg) {
193 agerr (AGERR, "bad value in flag -L%s - ignored\n", arg-1);
194 return 1;
195 }
196 *v = i;
197 return 0;
198}
199
200/* setFDPAttr:
201 * Actions for fdp specific flags
202 */
203static int
204setFDPAttr (char* arg)
205{
206 switch (*arg++) {
207 case 'g' :
208 fdp_parms->useGrid = 0;
209 break;
210 case 'O' :
211 fdp_parms->useNew = 0;
212 break;
213 case 'n' :
214 if (setInt (&fdp_parms->numIters, arg)) return 1;
215 break;
216 case 'U' :
217 if (setInt (&fdp_parms->unscaled, arg)) return 1;
218 break;
219 case 'C' :
220 if (setDouble (&fdp_parms->C, arg)) return 1;
221 break;
222 case 'T' :
223 if (*arg == '*') {
224 if (setDouble (&fdp_parms->Tfact, arg+1)) return 1;
225 }
226 else {
227 if (setDouble (&fdp_parms->T0, arg)) return 1;
228 }
229 break;
230 default :
231 agerr (AGWARN, "unknown flag -L%s - ignored\n", arg-1);
232 break;
233 }
234 return 0;
235}
236
237/* fdp_extra_args:
238 * Handle fdp specific arguments.
239 * These have the form -L<name>=<value>.
240 * Return number of unprocessed arguments; return < 0 on error.
241 */
242static int
243fdp_extra_args (GVC_t *gvc, int argc, char** argv)
244{
245 char** p = argv+1;
246 int i;
247 char* arg;
248 int cnt = 1;
249
250 for (i = 1; i < argc; i++) {
251 arg = argv[i];
252 if (arg && (*arg == '-') && (*(arg+1) == 'L')) {
253 if (setFDPAttr (arg+2)) {
254 dotneato_usage(1);
255 return -1;
256 }
257 }
258 else {
259 cnt++;
260 if (*p != arg) *p = arg;
261 p++;
262 }
263 }
264 *p = 0;
265 return cnt;
266}
267
268/* gvParseArgs:
269 * Return 0 on success.
270 * Return x if calling function should call exit(x-1).
271 */
272int gvParseArgs(GVC_t *gvc, int argc, char** argv)
273{
274 int rv;
275 if ((argc = neato_extra_args(gvc, argc, argv)) < 0)
276 return (1-argc);
277 if ((argc = fdp_extra_args(gvc, argc, argv)) < 0)
278 return (1-argc);
279 if ((argc = memtest_extra_args(gvc, argc, argv)) < 0)
280 return (1-argc);
281 if ((argc = config_extra_args(gvc, argc, argv)) < 0)
282 return (1-argc);
283 if ((rv = dotneato_args_initialize(gvc, argc, argv)))
284 return rv;
285 if (Verbose)
286 gvplugin_write_status(gvc);
287 return 0;
288}
289