gwenhywfar  4.99.8beta
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 
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  int i;
51  const char *p;
52  const GWEN_ARGS *tmpArgs;
53  GWEN_DB_NODE *counts;
54  GWEN_BUFFER *tbuf;
55  int stop;
56 
57  i=startAt;
58 
59  tbuf=GWEN_Buffer_new(0, 256, 0, 1);
60  counts=GWEN_DB_Group_new("counts");
61 
62  stop=0;
63  while(i<argc && !stop) {
64  GWEN_ARGS_ELEMENT_TYPE t;
65  char *tmpBuf;
66  const char *v;
67  int value;
68 
69  DBG_INFO(GWEN_LOGDOMAIN, "Argument[%d] is \"%s\"", i, argv[i]);
70  if (GWEN_Gui_ReadString(argv[i], tbuf)) {
71  DBG_ERROR(GWEN_LOGDOMAIN, "Error parsing \"%s\"", argv[i]);
72  GWEN_DB_Group_free(counts);
73  GWEN_Buffer_free(tbuf);
75  }
76  p=GWEN_Buffer_GetStart(tbuf);
77  if (*p=='-') {
78  p++;
79  if (*p=='-') {
80  p++;
81  t=GWEN_ArgsElementTypeLong;
82  }
83  else
84  t=GWEN_ArgsElementTypeShort;
85  }
86  else
87  t=GWEN_ArgsElementTypeFreeParam;
88 
89  switch(t) {
90  case GWEN_ArgsElementTypeFreeParam:
91  if (mode & GWEN_ARGS_MODE_ALLOW_FREEPARAM) {
94  "params", p);
95  i++;
96  }
97  else {
98  DBG_ERROR(GWEN_LOGDOMAIN, "Only options are allowed, but argument \"%s\" was not recognized as a known option.", p);
99  GWEN_DB_Group_free(counts);
100  GWEN_Buffer_free(tbuf);
101  return GWEN_ARGS_RESULT_ERROR;
102  }
104  DBG_DEBUG(GWEN_LOGDOMAIN, "Free parameter found, stopping as requested");
105  stop=1;
106  }
107  break;
108 
109  case GWEN_ArgsElementTypeShort:
110  for(tmpArgs=args;; tmpArgs++) {
111  if (tmpArgs->shortOption) {
112  if (strcmp(tmpArgs->shortOption, p)==0) {
113  /* found option */
115  tmpArgs->name,
116  GWEN_DB_GetIntValue(counts,
117  tmpArgs->name, 0, 0)+1);
118  break;
119  }
120  } /* if shortOption */
121 
122  if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST) {
123  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown short option \"%s\"", p);
124  GWEN_DB_Group_free(counts);
125  GWEN_Buffer_free(tbuf);
126  return GWEN_ARGS_RESULT_ERROR;
127  }
128  } /* for */
129  i++;
130 
131  if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT) {
132  /* argument needed */
133  if (i>=argc) {
134  DBG_ERROR(GWEN_LOGDOMAIN, "Argument needed for option \"%s\"", tmpArgs->name);
135  GWEN_DB_Group_free(counts);
136  GWEN_Buffer_free(tbuf);
137  return GWEN_ARGS_RESULT_ERROR;
138  }
139  GWEN_Buffer_Reset(tbuf);
140  if (GWEN_Gui_ReadString(argv[i], tbuf)) {
141  DBG_ERROR(GWEN_LOGDOMAIN, "Error parsing \"%s\"", argv[i]);
142  GWEN_DB_Group_free(counts);
143  GWEN_Buffer_free(tbuf);
144  return GWEN_ARGS_RESULT_ERROR;
145  }
146  p=GWEN_Buffer_GetStart(tbuf);
147  switch(tmpArgs->type) {
148  case GWEN_ArgsType_Char:
151  tmpArgs->name, p);
152  break;
153 
154  case GWEN_ArgsType_Int:
155  if (sscanf(p, "%i", &value)!=1) {
156  DBG_ERROR(GWEN_LOGDOMAIN, "Non-integer argument for short option \"%s\"",
157  tmpArgs->shortOption);
158  GWEN_DB_Group_free(counts);
159  GWEN_Buffer_free(tbuf);
160  return GWEN_ARGS_RESULT_ERROR;
161  }
164  tmpArgs->name, value);
165  break;
166 
167  default:
168  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown option type \"%d\"",
169  tmpArgs->type);
170  GWEN_DB_Group_free(counts);
171  GWEN_Buffer_free(tbuf);
172  return GWEN_ARGS_RESULT_ERROR;
173  } /* switch */
174  i++;
175  }
176  else {
177  if (tmpArgs->flags & GWEN_ARGS_FLAGS_HELP) {
178  GWEN_DB_Group_free(counts);
179  GWEN_Buffer_free(tbuf);
180  return GWEN_ARGS_RESULT_HELP;
181  }
184  tmpArgs->name,
185  GWEN_DB_GetIntValue(counts, tmpArgs->name, 0, 0));
186  }
187  break;
188 
189  case GWEN_ArgsElementTypeLong:
190  /* copy option name up to (but excluding) the "=" if any,
191  * determine the start of possible argument */
192  v=p;
193  while(*v && *v!='=') v++;
194  tmpBuf=(char*)malloc(v-p+1);
195  assert(tmpBuf);
196  memmove(tmpBuf, p, v-p);
197  tmpBuf[v-p]=0;
198 
199  for(tmpArgs=args;; tmpArgs++) {
200  if (tmpArgs->longOption) {
201  if (strcmp(tmpArgs->longOption, tmpBuf)==0) {
202  /* found option */
204  tmpArgs->name,
205  GWEN_DB_GetIntValue(counts,
206  tmpArgs->name, 0, 0)+1);
207  break;
208  }
209  } /* if longOption */
210 
211  if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST) {
212  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown long option \"%s\"", tmpBuf);
213  free(tmpBuf);
214  GWEN_DB_Group_free(counts);
215  GWEN_Buffer_free(tbuf);
216  return GWEN_ARGS_RESULT_ERROR;
217  }
218  } /* for */
219  i++;
220 
221  if (*v=='=') {
222  if (!(tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT)) {
223  DBG_ERROR(GWEN_LOGDOMAIN, "No argument allowed for option \"%s\"",
224  tmpArgs->name);
225  free(tmpBuf);
226  GWEN_DB_Group_free(counts);
227  GWEN_Buffer_free(tbuf);
228  return GWEN_ARGS_RESULT_ERROR;
229  }
230  v++;
231  }
232 
233  if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT) {
234  /* argument needed */
235  if (*v==0) {
236  DBG_ERROR(GWEN_LOGDOMAIN, "Argument needed for option \"%s\"", tmpArgs->name);
237  free(tmpBuf);
238  GWEN_DB_Group_free(counts);
239  GWEN_Buffer_free(tbuf);
240  return GWEN_ARGS_RESULT_ERROR;
241  }
242  switch(tmpArgs->type) {
243  case GWEN_ArgsType_Char:
246  tmpArgs->name, v);
247  break;
248 
249  case GWEN_ArgsType_Int:
250  if (sscanf(v, "%i", &value)!=1) {
251  DBG_ERROR(GWEN_LOGDOMAIN, "Non-integer argument for long option \"%s\"",
252  tmpBuf);
253  free(tmpBuf);
254  GWEN_DB_Group_free(counts);
255  GWEN_Buffer_free(tbuf);
256  return GWEN_ARGS_RESULT_ERROR;
257  }
260  tmpArgs->name, value);
261  break;
262 
263  default:
264  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown option type \"%d\"", tmpArgs->type);
265  free(tmpBuf);
266  GWEN_DB_Group_free(counts);
267  GWEN_Buffer_free(tbuf);
268  return GWEN_ARGS_RESULT_ERROR;
269  } /* switch */
270  }
271  else {
272  if (tmpArgs->flags & GWEN_ARGS_FLAGS_HELP) {
273  free(tmpBuf);
274  GWEN_DB_Group_free(counts);
275  GWEN_Buffer_free(tbuf);
276  return GWEN_ARGS_RESULT_HELP;
277  }
280  tmpArgs->name,
281  GWEN_DB_GetIntValue(counts, tmpArgs->name, 0, 0));
282  }
283  free(tmpBuf);
284 
285  break;
286 
287  default:
288  DBG_ERROR(GWEN_LOGDOMAIN, "Internal error (unknown argv type \"%d\")",
289  t);
290  GWEN_DB_Group_free(counts);
291  GWEN_Buffer_free(tbuf);
292  return GWEN_ARGS_RESULT_ERROR;
293  break;
294  } /* switch */
295  GWEN_Buffer_Reset(tbuf);
296  } /* while */
297 
298  /* check argument counts */
299  for(tmpArgs=args;; tmpArgs++) {
300  const char *s;
301  int c;
302 
303  if (tmpArgs->longOption)
304  s=tmpArgs->longOption;
305  else
306  s=tmpArgs->shortOption;
307 
308  c=GWEN_DB_GetIntValue(counts, tmpArgs->name, 0, 0);
309 
310  /* check minnum */
311  if (tmpArgs->minNum && ((unsigned int)c<tmpArgs->minNum)) {
312  if (tmpArgs->minNum>1) {
313  DBG_ERROR(GWEN_LOGDOMAIN, "Option \"%s\" needed %d times (have %d)",
314  s, tmpArgs->minNum, c);
315  }
316  else {
317  DBG_ERROR(GWEN_LOGDOMAIN, "Option \"%s\" needed", s);
318  }
319  GWEN_DB_Group_free(counts);
320  GWEN_Buffer_free(tbuf);
321  return GWEN_ARGS_RESULT_ERROR;
322  }
323 
324  /* check maxnum */
325  if (tmpArgs->maxNum && ((unsigned int)c>tmpArgs->maxNum)) {
327  "Option \"%s\" needed at most %d times (have %d)",
328  s, tmpArgs->maxNum, c);
329  GWEN_DB_Group_free(counts);
330  GWEN_Buffer_free(tbuf);
331  return GWEN_ARGS_RESULT_ERROR;
332  }
333 
334  if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST)
335  break;
336  } /* for */
337  GWEN_DB_Group_free(counts);
338  GWEN_Buffer_free(tbuf);
339 
340  return i;
341 }
342 
343 
344 int GWEN_Args__AppendTXT(GWEN_BUFFER *ubuf, const char *s, unsigned int ins) {
345  unsigned int i;
346 
347  while(*s) {
348  for (i=0; i<ins; i++) GWEN_Buffer_AppendByte(ubuf, ' ');
349  while(*s) {
350  char c;
351 
352  c=*s;
353  s++;
354  GWEN_Buffer_AppendByte(ubuf, c);
355  if (c=='\n')
356  break;
357  } /* while */
358  } /* while */
359 
360  return 0;
361 }
362 
363 
364 
365 int GWEN_Args_UsageTXT(const GWEN_ARGS *args, GWEN_BUFFER *ubuf) {
366  const GWEN_ARGS *tmpArgs;
367 
368  for(tmpArgs=args;; tmpArgs++) {
369  const char *s;
370 
371  GWEN_Buffer_AppendString(ubuf, "\n");
372  if (tmpArgs->shortOption || tmpArgs->longOption) {
373  if (tmpArgs->shortOption) {
374  GWEN_Buffer_AppendString(ubuf, " ");
375  if (tmpArgs->minNum==0)
376  GWEN_Buffer_AppendString(ubuf, "[");
377  else
378  GWEN_Buffer_AppendString(ubuf, " ");
379  GWEN_Buffer_AppendString(ubuf, "-");
380  GWEN_Buffer_AppendString(ubuf, tmpArgs->shortOption);
381  if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT)
382  GWEN_Buffer_AppendString(ubuf, " PARAM");
383  if (tmpArgs->minNum==0)
384  GWEN_Buffer_AppendString(ubuf, "]");
385  GWEN_Buffer_AppendString(ubuf, "\n");
386  } /* if short option */
387 
388  if (tmpArgs->longOption) {
389  GWEN_Buffer_AppendString(ubuf, " ");
390  if (tmpArgs->minNum==0)
391  GWEN_Buffer_AppendString(ubuf, "[");
392  else
393  GWEN_Buffer_AppendString(ubuf, " ");
394  GWEN_Buffer_AppendString(ubuf, "--");
395  GWEN_Buffer_AppendString(ubuf, tmpArgs->longOption);
396  if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT)
397  GWEN_Buffer_AppendString(ubuf, "=PARAM");
398  if (tmpArgs->minNum==0)
399  GWEN_Buffer_AppendString(ubuf, "]");
400  GWEN_Buffer_AppendString(ubuf, "\n");
401  } /* if short option */
402 
403  s=tmpArgs->longDescription;
404  if (!s)
405  s=tmpArgs->shortDescription;
406 
407  if (s) {
408  GWEN_Args__AppendTXT(ubuf, s, 3);
409  GWEN_Buffer_AppendString(ubuf, "\n");
410  }
411  } /* if any option */
412  else {
414  "Option \"%s\" has neither a long nor a short name",
415  tmpArgs->name);
416  return -1;
417  }
418 
419  if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST)
420  break;
421  } /* for */
422 
423  return 0;
424 }
425 
426 
427 
429  GWEN_UNUSED GWEN_BUFFER *ubuf) {
430  return 0;
431 }
432 
433 
434 
435 int GWEN_Args_Usage(const GWEN_ARGS *args, GWEN_BUFFER *ubuf,
436  GWEN_ARGS_OUTTYPE ot) {
437  int rv;
438 
439  switch(ot) {
441  rv=GWEN_Args_UsageTXT(args, ubuf);
442  break;
444  rv=GWEN_Args_UsageHTML(args, ubuf);
445  break;
446  default:
447  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown output type %d", ot);
448  rv=-1;
449  } /* switch */
450 
451  return rv;
452 }
453 
454 
455 
457  GWEN_UNUSED GWEN_BUFFER *ubuf,
459  return 0;
460 }
461 
462 
463 
464 
465 
466 
467 
int GWEN_Args__AppendTXT(GWEN_BUFFER *ubuf, const char *s, unsigned int ins)
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:223
const char * shortDescription
Definition: src/base/args.h:87
#define GWEN_DB_FLAGS_OVERWRITE_VARS
Definition: db.h:121
struct GWEN_DB_NODE GWEN_DB_NODE
Definition: db.h:228
void GWEN_DB_Group_free(GWEN_DB_NODE *n)
Definition: db.c:369
unsigned int maxNum
Definition: src/base/args.h:84
const char * longOption
Definition: src/base/args.h:86
#define GWEN_LOGDOMAIN
Definition: logger.h:35
#define GWEN_ARGS_FLAGS_HELP
Definition: src/base/args.h:52
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:38
int GWEN_Args_UsageHTML(GWEN_UNUSED const GWEN_ARGS *args, GWEN_UNUSED GWEN_BUFFER *ubuf)
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
Definition: buffer.c:684
#define GWEN_ARGS_RESULT_HELP
Definition: src/base/args.h:58
int GWEN_Args_UsageTXT(const GWEN_ARGS *args, GWEN_BUFFER *ubuf)
#define GWEN_ARGS_RESULT_ERROR
Definition: src/base/args.h:57
#define GWEN_ARGS_MODE_STOP_AT_FREEPARAM
Definition: src/base/args.h:55
const char * longDescription
Definition: src/base/args.h:88
int GWEN_Args_ShortUsage(GWEN_UNUSED const GWEN_ARGS *args, GWEN_UNUSED GWEN_BUFFER *ubuf, GWEN_UNUSED GWEN_ARGS_OUTTYPE ot)
unsigned int minNum
Definition: src/base/args.h:83
#define DBG_DEBUG(dbg_logger, format, args...)
Definition: debug.h:192
int GWEN_Args_Usage(const GWEN_ARGS *args, GWEN_BUFFER *ubuf, GWEN_ARGS_OUTTYPE ot)
#define GWEN_ARGS_MODE_ALLOW_FREEPARAM
Definition: src/base/args.h:54
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:380
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:83
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:41
#define GWEN_ARGS_FLAGS_LAST
Definition: src/base/args.h:51
GWEN_ARGS_TYPE type
Definition: src/base/args.h:81
GWEN_ARGS_OUTTYPE
Definition: src/base/args.h:67
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
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_DB_SetCharValue(GWEN_DB_NODE *n, uint32_t flags, const char *path, const char *val)
Definition: db.c:922
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:164
int GWEN_DB_GetIntValue(GWEN_DB_NODE *n, const char *path, int idx, int defVal)
Definition: db.c:1048
uint32_t flags
Definition: src/base/args.h:80
GWEN_DB_NODE * GWEN_DB_Group_new(const char *name)
Definition: db.c:131
const char * shortOption
Definition: src/base/args.h:85
int GWEN_DB_SetIntValue(GWEN_DB_NODE *n, uint32_t flags, const char *path, int val)
Definition: db.c:1086
int GWEN_Gui_ReadString(const char *text, GWEN_BUFFER *tbuf)
Definition: gui.c:306
#define GWEN_ARGS_FLAGS_HAS_ARGUMENT
Definition: src/base/args.h:50
#define GWEN_UNUSED
const char * name
Definition: src/base/args.h:82
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:1014
#define GWEN_DB_FLAGS_DEFAULT
Definition: db.h:168