gwenhywfar 5.10.1
src/base/args.c
Go to the documentation of this file.
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
45int 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);
76 }
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:
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);
103 }
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 */
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);
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);
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);
146 }
147 p=GWEN_Buffer_GetStart(tbuf);
148 switch (tmpArgs->type) {
152 tmpArgs->name, p);
153 break;
154
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);
162 }
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);
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);
182 }
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 */
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);
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);
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);
243 }
244 switch (tmpArgs->type) {
248 tmpArgs->name, v);
249 break;
250
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);
259 }
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);
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);
279 }
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);
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);
324 }
325
326 /* check maxnum */
327 if (tmpArgs->maxNum && ((unsigned int)c>tmpArgs->maxNum)) {
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);
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
346int 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
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, "-");
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 {
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
435{
436 return 0;
437}
438
439
440
441int GWEN_Args_Usage(const GWEN_ARGS *args, GWEN_BUFFER *ubuf,
443{
444 int rv;
445
446 switch (ot) {
448 rv=GWEN_Args_UsageTXT(args, ubuf);
449 break;
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
466{
467 return 0;
468}
469
470
471
472
473
474
475
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:42
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
Definition: buffer.c:650
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:89
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:989
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:235
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:394
GWEN_DB_NODE * GWEN_DB_Group_new(const char *name)
Definition: db.c:173
int GWEN_DB_SetIntValue(GWEN_DB_NODE *n, uint32_t flags, const char *path, int val)
Definition: db.c:1202
int GWEN_DB_SetCharValue(GWEN_DB_NODE *n, uint32_t flags, const char *path, const char *val)
Definition: db.c:997
int GWEN_DB_GetIntValue(GWEN_DB_NODE *n, const char *path, int idx, int defVal)
Definition: db.c:1163
void GWEN_DB_Group_free(GWEN_DB_NODE *n)
Definition: db.c:421
#define GWEN_DB_FLAGS_DEFAULT
Definition: db.h:168
#define GWEN_DB_FLAGS_OVERWRITE_VARS
Definition: db.h:121
struct GWEN_DB_NODE GWEN_DB_NODE
Definition: db.h:228
#define DBG_DEBUG(dbg_logger, format, args...)
Definition: debug.h:214
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:181
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:38
int GWEN_Gui_ReadString(const char *text, GWEN_BUFFER *tbuf)
Definition: gui_utils.c:183
#define GWEN_UNUSED
#define GWEN_LOGDOMAIN
Definition: logger.h:35
int GWEN_Args__AppendTXT(GWEN_BUFFER *ubuf, const char *s, unsigned int ins)
int GWEN_Args_Check(int argc, char **argv, int startAt, uint32_t mode, const GWEN_ARGS *args, GWEN_DB_NODE *db)
Definition: src/base/args.c:45
int GWEN_Args_Usage(const GWEN_ARGS *args, GWEN_BUFFER *ubuf, GWEN_ARGS_OUTTYPE ot)
int GWEN_Args_UsageHTML(GWEN_UNUSED const GWEN_ARGS *args, GWEN_UNUSED GWEN_BUFFER *ubuf)
int GWEN_Args_ShortUsage(GWEN_UNUSED const GWEN_ARGS *args, GWEN_UNUSED GWEN_BUFFER *ubuf, GWEN_UNUSED GWEN_ARGS_OUTTYPE ot)
int GWEN_Args_UsageTXT(const GWEN_ARGS *args, GWEN_BUFFER *ubuf)
#define GWEN_ARGS_FLAGS_HAS_ARGUMENT
Definition: src/base/args.h:50
#define GWEN_ARGS_RESULT_ERROR
Definition: src/base/args.h:57
#define GWEN_ARGS_MODE_STOP_AT_FREEPARAM
Definition: src/base/args.h:55
#define GWEN_ARGS_MODE_ALLOW_FREEPARAM
Definition: src/base/args.h:54
#define GWEN_ARGS_FLAGS_HELP
Definition: src/base/args.h:52
#define GWEN_ARGS_FLAGS_LAST
Definition: src/base/args.h:51
GWEN_ARGS_OUTTYPE
Definition: src/base/args.h:67
@ GWEN_ArgsOutType_Txt
Definition: src/base/args.h:68
@ GWEN_ArgsOutType_Html
Definition: src/base/args.h:69
@ GWEN_ArgsType_Int
Definition: src/base/args.h:63
@ GWEN_ArgsType_Char
Definition: src/base/args.h:62
#define GWEN_ARGS_RESULT_HELP
Definition: src/base/args.h:58
unsigned int minNum
Definition: src/base/args.h:83
const char * shortOption
Definition: src/base/args.h:85
uint32_t flags
Definition: src/base/args.h:80
const char * longOption
Definition: src/base/args.h:86
GWEN_ARGS_TYPE type
Definition: src/base/args.h:81
const char * longDescription
Definition: src/base/args.h:88
unsigned int maxNum
Definition: src/base/args.h:84
const char * name
Definition: src/base/args.h:82
const char * shortDescription
Definition: src/base/args.h:87