1 /***************************************************************************
2 $RCSfile$
3 -------------------
4 cvs : $Id$
5 begin : Sat Apr 24 2004
6 copyright : (C) 2004 by Martin Preuss
7 email : martin@libchipcard.de
8
9 ***************************************************************************
10 * *
11 * This library is free software; you can redistribute it and/or *
12 * modify it under the terms of the GNU Lesser General Public *
13 * License as published by the Free Software Foundation; either *
14 * version 2.1 of the License, or (at your option) any later version. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
19 * Lesser General Public License for more details. *
20 * *
21 * You should have received a copy of the GNU Lesser General Public *
22 * License along with this library; if not, write to the Free Software *
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
24 * MA 02111-1307 USA *
25 * *
26 ***************************************************************************/
27
28
29 #ifdef HAVE_CONFIG_H
30 # include <config.h>
31 #endif
32
33 #include "args_p.h"
34 #include "gui_l.h"
35 #include <gwenhywfar/misc.h>
36 #include <gwenhywfar/debug.h>
37 #include <gwenhywfar/text.h>
38 #include <string.h>
39
40 #define DISABLE_DEBUGLOG
41
42
43
44
GWEN_Args_Check(int argc,char ** argv,int startAt,uint32_t mode,const GWEN_ARGS * args,GWEN_DB_NODE * db)45 int GWEN_Args_Check(int argc, char **argv,
46 int startAt,
47 uint32_t mode,
48 const GWEN_ARGS *args,
49 GWEN_DB_NODE *db)
50 {
51 int i;
52 const char *p;
53 const GWEN_ARGS *tmpArgs;
54 GWEN_DB_NODE *counts;
55 GWEN_BUFFER *tbuf;
56 int stop;
57
58 i=startAt;
59
60 tbuf=GWEN_Buffer_new(0, 256, 0, 1);
61 counts=GWEN_DB_Group_new("counts");
62
63 stop=0;
64 while (i<argc && !stop) {
65 GWEN_ARGS_ELEMENT_TYPE t;
66 char *tmpBuf;
67 const char *v;
68 int value;
69
70 DBG_INFO(GWEN_LOGDOMAIN, "Argument[%d] is \"%s\"", i, argv[i]);
71 if (GWEN_Gui_ReadString(argv[i], tbuf)) {
72 DBG_ERROR(GWEN_LOGDOMAIN, "Error parsing \"%s\"", argv[i]);
73 GWEN_DB_Group_free(counts);
74 GWEN_Buffer_free(tbuf);
75 return GWEN_ARGS_RESULT_ERROR;
76 }
77 p=GWEN_Buffer_GetStart(tbuf);
78 if (*p=='-') {
79 p++;
80 if (*p=='-') {
81 p++;
82 t=GWEN_ArgsElementTypeLong;
83 }
84 else
85 t=GWEN_ArgsElementTypeShort;
86 }
87 else
88 t=GWEN_ArgsElementTypeFreeParam;
89
90 switch (t) {
91 case GWEN_ArgsElementTypeFreeParam:
92 if (mode & GWEN_ARGS_MODE_ALLOW_FREEPARAM) {
93 GWEN_DB_SetCharValue(db,
94 GWEN_DB_FLAGS_DEFAULT,
95 "params", p);
96 i++;
97 }
98 else {
99 DBG_ERROR(GWEN_LOGDOMAIN, "Only options are allowed, but argument \"%s\" was not recognized as a known option.", p);
100 GWEN_DB_Group_free(counts);
101 GWEN_Buffer_free(tbuf);
102 return GWEN_ARGS_RESULT_ERROR;
103 }
104 if (mode & GWEN_ARGS_MODE_STOP_AT_FREEPARAM) {
105 DBG_DEBUG(GWEN_LOGDOMAIN, "Free parameter found, stopping as requested");
106 stop=1;
107 }
108 break;
109
110 case GWEN_ArgsElementTypeShort:
111 for (tmpArgs=args;; tmpArgs++) {
112 if (tmpArgs->shortOption) {
113 if (strcmp(tmpArgs->shortOption, p)==0) {
114 /* found option */
115 GWEN_DB_SetIntValue(counts, GWEN_DB_FLAGS_OVERWRITE_VARS,
116 tmpArgs->name,
117 GWEN_DB_GetIntValue(counts,
118 tmpArgs->name, 0, 0)+1);
119 break;
120 }
121 } /* if shortOption */
122
123 if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST) {
124 DBG_ERROR(GWEN_LOGDOMAIN, "Unknown short option \"%s\"", p);
125 GWEN_DB_Group_free(counts);
126 GWEN_Buffer_free(tbuf);
127 return GWEN_ARGS_RESULT_ERROR;
128 }
129 } /* for */
130 i++;
131
132 if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT) {
133 /* argument needed */
134 if (i>=argc) {
135 DBG_ERROR(GWEN_LOGDOMAIN, "Argument needed for option \"%s\"", tmpArgs->name);
136 GWEN_DB_Group_free(counts);
137 GWEN_Buffer_free(tbuf);
138 return GWEN_ARGS_RESULT_ERROR;
139 }
140 GWEN_Buffer_Reset(tbuf);
141 if (GWEN_Gui_ReadString(argv[i], tbuf)) {
142 DBG_ERROR(GWEN_LOGDOMAIN, "Error parsing \"%s\"", argv[i]);
143 GWEN_DB_Group_free(counts);
144 GWEN_Buffer_free(tbuf);
145 return GWEN_ARGS_RESULT_ERROR;
146 }
147 p=GWEN_Buffer_GetStart(tbuf);
148 switch (tmpArgs->type) {
149 case GWEN_ArgsType_Char:
150 GWEN_DB_SetCharValue(db,
151 GWEN_DB_FLAGS_DEFAULT,
152 tmpArgs->name, p);
153 break;
154
155 case GWEN_ArgsType_Int:
156 if (sscanf(p, "%i", &value)!=1) {
157 DBG_ERROR(GWEN_LOGDOMAIN, "Non-integer argument for short option \"%s\"",
158 tmpArgs->shortOption);
159 GWEN_DB_Group_free(counts);
160 GWEN_Buffer_free(tbuf);
161 return GWEN_ARGS_RESULT_ERROR;
162 }
163 GWEN_DB_SetIntValue(db,
164 GWEN_DB_FLAGS_DEFAULT,
165 tmpArgs->name, value);
166 break;
167
168 default:
169 DBG_ERROR(GWEN_LOGDOMAIN, "Unknown option type \"%d\"",
170 tmpArgs->type);
171 GWEN_DB_Group_free(counts);
172 GWEN_Buffer_free(tbuf);
173 return GWEN_ARGS_RESULT_ERROR;
174 } /* switch */
175 i++;
176 }
177 else {
178 if (tmpArgs->flags & GWEN_ARGS_FLAGS_HELP) {
179 GWEN_DB_Group_free(counts);
180 GWEN_Buffer_free(tbuf);
181 return GWEN_ARGS_RESULT_HELP;
182 }
183 GWEN_DB_SetIntValue(db,
184 GWEN_DB_FLAGS_OVERWRITE_VARS,
185 tmpArgs->name,
186 GWEN_DB_GetIntValue(counts, tmpArgs->name, 0, 0));
187 }
188 break;
189
190 case GWEN_ArgsElementTypeLong:
191 /* copy option name up to (but excluding) the "=" if any,
192 * determine the start of possible argument */
193 v=p;
194 while (*v && *v!='=')
195 v++;
196 tmpBuf=(char *)malloc(v-p+1);
197 assert(tmpBuf);
198 memmove(tmpBuf, p, v-p);
199 tmpBuf[v-p]=0;
200
201 for (tmpArgs=args;; tmpArgs++) {
202 if (tmpArgs->longOption) {
203 if (strcmp(tmpArgs->longOption, tmpBuf)==0) {
204 /* found option */
205 GWEN_DB_SetIntValue(counts, GWEN_DB_FLAGS_OVERWRITE_VARS,
206 tmpArgs->name,
207 GWEN_DB_GetIntValue(counts,
208 tmpArgs->name, 0, 0)+1);
209 break;
210 }
211 } /* if longOption */
212
213 if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST) {
214 DBG_ERROR(GWEN_LOGDOMAIN, "Unknown long option \"%s\"", tmpBuf);
215 free(tmpBuf);
216 GWEN_DB_Group_free(counts);
217 GWEN_Buffer_free(tbuf);
218 return GWEN_ARGS_RESULT_ERROR;
219 }
220 } /* for */
221 i++;
222
223 if (*v=='=') {
224 if (!(tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT)) {
225 DBG_ERROR(GWEN_LOGDOMAIN, "No argument allowed for option \"%s\"",
226 tmpArgs->name);
227 free(tmpBuf);
228 GWEN_DB_Group_free(counts);
229 GWEN_Buffer_free(tbuf);
230 return GWEN_ARGS_RESULT_ERROR;
231 }
232 v++;
233 }
234
235 if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT) {
236 /* argument needed */
237 if (*v==0) {
238 DBG_ERROR(GWEN_LOGDOMAIN, "Argument needed for option \"%s\"", tmpArgs->name);
239 free(tmpBuf);
240 GWEN_DB_Group_free(counts);
241 GWEN_Buffer_free(tbuf);
242 return GWEN_ARGS_RESULT_ERROR;
243 }
244 switch (tmpArgs->type) {
245 case GWEN_ArgsType_Char:
246 GWEN_DB_SetCharValue(db,
247 GWEN_DB_FLAGS_DEFAULT,
248 tmpArgs->name, v);
249 break;
250
251 case GWEN_ArgsType_Int:
252 if (sscanf(v, "%i", &value)!=1) {
253 DBG_ERROR(GWEN_LOGDOMAIN, "Non-integer argument for long option \"%s\"",
254 tmpBuf);
255 free(tmpBuf);
256 GWEN_DB_Group_free(counts);
257 GWEN_Buffer_free(tbuf);
258 return GWEN_ARGS_RESULT_ERROR;
259 }
260 GWEN_DB_SetIntValue(db,
261 GWEN_DB_FLAGS_DEFAULT,
262 tmpArgs->name, value);
263 break;
264
265 default:
266 DBG_ERROR(GWEN_LOGDOMAIN, "Unknown option type \"%d\"", tmpArgs->type);
267 free(tmpBuf);
268 GWEN_DB_Group_free(counts);
269 GWEN_Buffer_free(tbuf);
270 return GWEN_ARGS_RESULT_ERROR;
271 } /* switch */
272 }
273 else {
274 if (tmpArgs->flags & GWEN_ARGS_FLAGS_HELP) {
275 free(tmpBuf);
276 GWEN_DB_Group_free(counts);
277 GWEN_Buffer_free(tbuf);
278 return GWEN_ARGS_RESULT_HELP;
279 }
280 GWEN_DB_SetIntValue(db,
281 GWEN_DB_FLAGS_OVERWRITE_VARS,
282 tmpArgs->name,
283 GWEN_DB_GetIntValue(counts, tmpArgs->name, 0, 0));
284 }
285 free(tmpBuf);
286
287 break;
288
289 default:
290 DBG_ERROR(GWEN_LOGDOMAIN, "Internal error (unknown argv type \"%d\")",
291 t);
292 GWEN_DB_Group_free(counts);
293 GWEN_Buffer_free(tbuf);
294 return GWEN_ARGS_RESULT_ERROR;
295 break;
296 } /* switch */
297 GWEN_Buffer_Reset(tbuf);
298 } /* while */
299
300 /* check argument counts */
301 for (tmpArgs=args;; tmpArgs++) {
302 const char *s;
303 int c;
304
305 if (tmpArgs->longOption)
306 s=tmpArgs->longOption;
307 else
308 s=tmpArgs->shortOption;
309
310 c=GWEN_DB_GetIntValue(counts, tmpArgs->name, 0, 0);
311
312 /* check minnum */
313 if (tmpArgs->minNum && ((unsigned int)c<tmpArgs->minNum)) {
314 if (tmpArgs->minNum>1) {
315 DBG_ERROR(GWEN_LOGDOMAIN, "Option \"%s\" needed %d times (have %d)",
316 s, tmpArgs->minNum, c);
317 }
318 else {
319 DBG_ERROR(GWEN_LOGDOMAIN, "Option \"%s\" needed", s);
320 }
321 GWEN_DB_Group_free(counts);
322 GWEN_Buffer_free(tbuf);
323 return GWEN_ARGS_RESULT_ERROR;
324 }
325
326 /* check maxnum */
327 if (tmpArgs->maxNum && ((unsigned int)c>tmpArgs->maxNum)) {
328 DBG_ERROR(GWEN_LOGDOMAIN,
329 "Option \"%s\" needed at most %d times (have %d)",
330 s, tmpArgs->maxNum, c);
331 GWEN_DB_Group_free(counts);
332 GWEN_Buffer_free(tbuf);
333 return GWEN_ARGS_RESULT_ERROR;
334 }
335
336 if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST)
337 break;
338 } /* for */
339 GWEN_DB_Group_free(counts);
340 GWEN_Buffer_free(tbuf);
341
342 return i;
343 }
344
345
GWEN_Args__AppendTXT(GWEN_BUFFER * ubuf,const char * s,unsigned int ins)346 int GWEN_Args__AppendTXT(GWEN_BUFFER *ubuf, const char *s, unsigned int ins)
347 {
348 unsigned int i;
349
350 while (*s) {
351 for (i=0; i<ins; i++)
352 GWEN_Buffer_AppendByte(ubuf, ' ');
353 while (*s) {
354 char c;
355
356 c=*s;
357 s++;
358 GWEN_Buffer_AppendByte(ubuf, c);
359 if (c=='\n')
360 break;
361 } /* while */
362 } /* while */
363
364 return 0;
365 }
366
367
368
GWEN_Args_UsageTXT(const GWEN_ARGS * args,GWEN_BUFFER * ubuf)369 int GWEN_Args_UsageTXT(const GWEN_ARGS *args, GWEN_BUFFER *ubuf)
370 {
371 const GWEN_ARGS *tmpArgs;
372
373 for (tmpArgs=args;; tmpArgs++) {
374 const char *s;
375
376 GWEN_Buffer_AppendString(ubuf, "\n");
377 if (tmpArgs->shortOption || tmpArgs->longOption) {
378 if (tmpArgs->shortOption) {
379 GWEN_Buffer_AppendString(ubuf, " ");
380 if (tmpArgs->minNum==0)
381 GWEN_Buffer_AppendString(ubuf, "[");
382 else
383 GWEN_Buffer_AppendString(ubuf, " ");
384 GWEN_Buffer_AppendString(ubuf, "-");
385 GWEN_Buffer_AppendString(ubuf, tmpArgs->shortOption);
386 if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT)
387 GWEN_Buffer_AppendString(ubuf, " PARAM");
388 if (tmpArgs->minNum==0)
389 GWEN_Buffer_AppendString(ubuf, "]");
390 GWEN_Buffer_AppendString(ubuf, "\n");
391 } /* if short option */
392
393 if (tmpArgs->longOption) {
394 GWEN_Buffer_AppendString(ubuf, " ");
395 if (tmpArgs->minNum==0)
396 GWEN_Buffer_AppendString(ubuf, "[");
397 else
398 GWEN_Buffer_AppendString(ubuf, " ");
399 GWEN_Buffer_AppendString(ubuf, "--");
400 GWEN_Buffer_AppendString(ubuf, tmpArgs->longOption);
401 if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT)
402 GWEN_Buffer_AppendString(ubuf, "=PARAM");
403 if (tmpArgs->minNum==0)
404 GWEN_Buffer_AppendString(ubuf, "]");
405 GWEN_Buffer_AppendString(ubuf, "\n");
406 } /* if short option */
407
408 s=tmpArgs->longDescription;
409 if (!s)
410 s=tmpArgs->shortDescription;
411
412 if (s) {
413 GWEN_Args__AppendTXT(ubuf, s, 3);
414 GWEN_Buffer_AppendString(ubuf, "\n");
415 }
416 } /* if any option */
417 else {
418 DBG_ERROR(GWEN_LOGDOMAIN,
419 "Option \"%s\" has neither a long nor a short name",
420 tmpArgs->name);
421 return -1;
422 }
423
424 if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST)
425 break;
426 } /* for */
427
428 return 0;
429 }
430
431
432
GWEN_Args_UsageHTML(GWEN_UNUSED const GWEN_ARGS * args,GWEN_UNUSED GWEN_BUFFER * ubuf)433 int GWEN_Args_UsageHTML(GWEN_UNUSED const GWEN_ARGS *args,
434 GWEN_UNUSED GWEN_BUFFER *ubuf)
435 {
436 return 0;
437 }
438
439
440
GWEN_Args_Usage(const GWEN_ARGS * args,GWEN_BUFFER * ubuf,GWEN_ARGS_OUTTYPE ot)441 int GWEN_Args_Usage(const GWEN_ARGS *args, GWEN_BUFFER *ubuf,
442 GWEN_ARGS_OUTTYPE ot)
443 {
444 int rv;
445
446 switch (ot) {
447 case GWEN_ArgsOutType_Txt:
448 rv=GWEN_Args_UsageTXT(args, ubuf);
449 break;
450 case GWEN_ArgsOutType_Html:
451 rv=GWEN_Args_UsageHTML(args, ubuf);
452 break;
453 default:
454 DBG_ERROR(GWEN_LOGDOMAIN, "Unknown output type %d", ot);
455 rv=-1;
456 } /* switch */
457
458 return rv;
459 }
460
461
462
GWEN_Args_ShortUsage(GWEN_UNUSED const GWEN_ARGS * args,GWEN_UNUSED GWEN_BUFFER * ubuf,GWEN_UNUSED GWEN_ARGS_OUTTYPE ot)463 int GWEN_Args_ShortUsage(GWEN_UNUSED const GWEN_ARGS *args,
464 GWEN_UNUSED GWEN_BUFFER *ubuf,
465 GWEN_UNUSED GWEN_ARGS_OUTTYPE ot)
466 {
467 return 0;
468 }
469
470
471
472
473
474
475
476