gwenhywfar  4.8.0beta
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 <gwenhywfar/misc.h>
35 #include <gwenhywfar/debug.h>
36 #include <gwenhywfar/text.h>
37 #include <string.h>
38 
39 #define DISABLE_DEBUGLOG
40 
41 
42 
43 
44 int GWEN_Args_Check(int argc, char **argv,
45  int startAt,
46  uint32_t mode,
47  const GWEN_ARGS *args,
48  GWEN_DB_NODE *db){
49  int i;
50  const char *p;
51  const GWEN_ARGS *tmpArgs;
52  GWEN_DB_NODE *counts;
53  int stop;
54 
55  i=startAt;
56 
57  counts=GWEN_DB_Group_new("counts");
58 
59  stop=0;
60  while(i<argc && !stop) {
61  GWEN_ARGS_ELEMENT_TYPE t;
62  char *tmpBuf;
63  const char *v;
64  int value;
65 
66  DBG_INFO(GWEN_LOGDOMAIN, "Argument[%d] is \"%s\"", i, argv[i]);
67  p=argv[i];
68  if (*p=='-') {
69  p++;
70  if (*p=='-') {
71  p++;
72  t=GWEN_ArgsElementTypeLong;
73  }
74  else
75  t=GWEN_ArgsElementTypeShort;
76  }
77  else
78  t=GWEN_ArgsElementTypeFreeParam;
79 
80  switch(t) {
81  case GWEN_ArgsElementTypeFreeParam:
82  if (mode & GWEN_ARGS_MODE_ALLOW_FREEPARAM) {
85  "params", p);
86  i++;
87  }
88  else {
89  DBG_ERROR(GWEN_LOGDOMAIN, "Only options are allowed, but argument \"%s\" was not recognized as a known option.", p);
90  GWEN_DB_Group_free(counts);
92  }
94  DBG_DEBUG(GWEN_LOGDOMAIN, "Free parameter found, stopping as requested");
95  stop=1;
96  }
97  break;
98 
99  case GWEN_ArgsElementTypeShort:
100  for(tmpArgs=args;;tmpArgs++) {
101  if (tmpArgs->shortOption) {
102  if (strcmp(tmpArgs->shortOption, p)==0) {
103  /* found option */
105  tmpArgs->name,
106  GWEN_DB_GetIntValue(counts,
107  tmpArgs->name, 0, 0)+1);
108  break;
109  }
110  } /* if shortOption */
111 
112  if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST) {
113  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown short option \"%s\"", p);
114  GWEN_DB_Group_free(counts);
115  return GWEN_ARGS_RESULT_ERROR;
116  }
117  } /* for */
118  i++;
119 
120  if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT) {
121  /* argument needed */
122  if (i>=argc) {
123  DBG_ERROR(GWEN_LOGDOMAIN, "Argument needed for option \"%s\"", tmpArgs->name);
124  GWEN_DB_Group_free(counts);
125  return GWEN_ARGS_RESULT_ERROR;
126  }
127  switch(tmpArgs->type) {
128  case GWEN_ArgsType_Char:
131  tmpArgs->name, argv[i]);
132  break;
133 
134  case GWEN_ArgsType_Int:
135  if (sscanf(argv[i], "%i", &value)!=1) {
136  DBG_ERROR(GWEN_LOGDOMAIN, "Non-integer argument for short option \"%s\"", p);
137  GWEN_DB_Group_free(counts);
138  return GWEN_ARGS_RESULT_ERROR;
139  }
142  tmpArgs->name, value);
143  break;
144 
145  default:
146  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown option type \"%d\"",
147  tmpArgs->type);
148  GWEN_DB_Group_free(counts);
149  return GWEN_ARGS_RESULT_ERROR;
150  } /* switch */
151  i++;
152  }
153  else {
154  if (tmpArgs->flags & GWEN_ARGS_FLAGS_HELP) {
155  GWEN_DB_Group_free(counts);
156  return GWEN_ARGS_RESULT_HELP;
157  }
160  tmpArgs->name,
161  GWEN_DB_GetIntValue(counts, tmpArgs->name, 0, 0));
162  }
163  break;
164 
165  case GWEN_ArgsElementTypeLong:
166  /* copy option name up to (but excluding) the "=" if any,
167  * determine the start of possible argument */
168  v=p;
169  while(*v && *v!='=') v++;
170  tmpBuf=(char*)malloc(v-p+1);
171  assert(tmpBuf);
172  memmove(tmpBuf, p, v-p);
173  tmpBuf[v-p]=0;
174 
175  for(tmpArgs=args;;tmpArgs++) {
176  if (tmpArgs->longOption) {
177  if (strcmp(tmpArgs->longOption, tmpBuf)==0) {
178  /* found option */
180  tmpArgs->name,
181  GWEN_DB_GetIntValue(counts,
182  tmpArgs->name, 0, 0)+1);
183  break;
184  }
185  } /* if longOption */
186 
187  if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST) {
188  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown long option \"%s\"", tmpBuf);
189  free(tmpBuf);
190  GWEN_DB_Group_free(counts);
191  return GWEN_ARGS_RESULT_ERROR;
192  }
193  } /* for */
194  i++;
195 
196  if (*v=='=') {
197  if (!(tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT)) {
198  DBG_ERROR(GWEN_LOGDOMAIN, "No argument allowed for option \"%s\"",
199  tmpArgs->name);
200  free(tmpBuf);
201  GWEN_DB_Group_free(counts);
202  return GWEN_ARGS_RESULT_ERROR;
203  }
204  v++;
205  }
206 
207  if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT) {
208  /* argument needed */
209  if (*v==0) {
210  DBG_ERROR(GWEN_LOGDOMAIN, "Argument needed for option \"%s\"", tmpArgs->name);
211  free(tmpBuf);
212  GWEN_DB_Group_free(counts);
213  return GWEN_ARGS_RESULT_ERROR;
214  }
215  switch(tmpArgs->type) {
216  case GWEN_ArgsType_Char:
219  tmpArgs->name, v);
220  break;
221 
222  case GWEN_ArgsType_Int:
223  if (sscanf(v, "%i", &value)!=1) {
224  DBG_ERROR(GWEN_LOGDOMAIN, "Non-integer argument for long option \"%s\"",
225  tmpBuf);
226  free(tmpBuf);
227  GWEN_DB_Group_free(counts);
228  return GWEN_ARGS_RESULT_ERROR;
229  }
232  tmpArgs->name, value);
233  break;
234 
235  default:
236  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown option type \"%d\"", tmpArgs->type);
237  GWEN_DB_Group_free(counts);
238  return GWEN_ARGS_RESULT_ERROR;
239  } /* switch */
240  }
241  else {
242  if (tmpArgs->flags & GWEN_ARGS_FLAGS_HELP) {
243  GWEN_DB_Group_free(counts);
244  return GWEN_ARGS_RESULT_HELP;
245  }
248  tmpArgs->name,
249  GWEN_DB_GetIntValue(counts, tmpArgs->name, 0, 0));
250  }
251  free(tmpBuf);
252 
253  break;
254 
255  default:
256  DBG_ERROR(GWEN_LOGDOMAIN, "Internal error (unknown argv type \"%d\")",
257  t);
258  GWEN_DB_Group_free(counts);
259  return GWEN_ARGS_RESULT_ERROR;
260  break;
261  } /* switch */
262  } /* while */
263 
264  /* check argument counts */
265  for(tmpArgs=args;;tmpArgs++) {
266  const char *s;
267  int c;
268 
269  if (tmpArgs->longOption)
270  s=tmpArgs->longOption;
271  else
272  s=tmpArgs->shortOption;
273 
274  c=GWEN_DB_GetIntValue(counts, tmpArgs->name, 0, 0);
275 
276  /* check minnum */
277  if (tmpArgs->minNum && ((unsigned int)c<tmpArgs->minNum)) {
278  if (tmpArgs->minNum>1) {
279  DBG_ERROR(GWEN_LOGDOMAIN, "Option \"%s\" needed %d times (have %d)",
280  s, tmpArgs->minNum, c);
281  }
282  else {
283  DBG_ERROR(GWEN_LOGDOMAIN, "Option \"%s\" needed", s);
284  }
285  GWEN_DB_Group_free(counts);
286  return GWEN_ARGS_RESULT_ERROR;
287  }
288 
289  /* check maxnum */
290  if (tmpArgs->maxNum && ((unsigned int)c>tmpArgs->maxNum)) {
292  "Option \"%s\" needed at most %d times (have %d)",
293  s, tmpArgs->maxNum, c);
294  GWEN_DB_Group_free(counts);
295  return GWEN_ARGS_RESULT_ERROR;
296  }
297 
298  if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST)
299  break;
300  } /* for */
301  GWEN_DB_Group_free(counts);
302 
303  return i;
304 }
305 
306 
307 int GWEN_Args__AppendTXT(GWEN_BUFFER *ubuf, const char *s, unsigned int ins){
308  unsigned int i;
309 
310  while(*s) {
311  for (i=0; i<ins; i++) GWEN_Buffer_AppendByte(ubuf, ' ');
312  while(*s) {
313  char c;
314 
315  c=*s;
316  s++;
317  GWEN_Buffer_AppendByte(ubuf, c);
318  if (c=='\n')
319  break;
320  } /* while */
321  } /* while */
322 
323  return 0;
324 }
325 
326 
327 
328 int GWEN_Args_UsageTXT(const GWEN_ARGS *args, GWEN_BUFFER *ubuf){
329  const GWEN_ARGS *tmpArgs;
330 
331  for(tmpArgs=args;;tmpArgs++) {
332  const char *s;
333 
334  GWEN_Buffer_AppendString(ubuf, "\n");
335  if (tmpArgs->shortOption || tmpArgs->longOption) {
336  if (tmpArgs->shortOption) {
337  GWEN_Buffer_AppendString(ubuf, " ");
338  if (tmpArgs->minNum==0)
339  GWEN_Buffer_AppendString(ubuf, "[");
340  else
341  GWEN_Buffer_AppendString(ubuf, " ");
342  GWEN_Buffer_AppendString(ubuf, "-");
343  GWEN_Buffer_AppendString(ubuf, tmpArgs->shortOption);
344  if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT)
345  GWEN_Buffer_AppendString(ubuf, " PARAM");
346  if (tmpArgs->minNum==0)
347  GWEN_Buffer_AppendString(ubuf, "]");
348  GWEN_Buffer_AppendString(ubuf, "\n");
349  } /* if short option */
350 
351  if (tmpArgs->longOption) {
352  GWEN_Buffer_AppendString(ubuf, " ");
353  if (tmpArgs->minNum==0)
354  GWEN_Buffer_AppendString(ubuf, "[");
355  else
356  GWEN_Buffer_AppendString(ubuf, " ");
357  GWEN_Buffer_AppendString(ubuf, "--");
358  GWEN_Buffer_AppendString(ubuf, tmpArgs->longOption);
359  if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT)
360  GWEN_Buffer_AppendString(ubuf, "=PARAM");
361  if (tmpArgs->minNum==0)
362  GWEN_Buffer_AppendString(ubuf, "]");
363  GWEN_Buffer_AppendString(ubuf, "\n");
364  } /* if short option */
365 
366  s=tmpArgs->longDescription;
367  if (!s)
368  s=tmpArgs->shortDescription;
369 
370  if (s) {
371  GWEN_Args__AppendTXT(ubuf, s, 3);
372  GWEN_Buffer_AppendString(ubuf, "\n");
373  }
374  } /* if any option */
375  else {
377  "Option \"%s\" has neither a long nor a short name",
378  tmpArgs->name);
379  return -1;
380  }
381 
382  if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST)
383  break;
384  } /* for */
385 
386  return 0;
387 }
388 
389 
390 
392  GWEN_UNUSED GWEN_BUFFER *ubuf){
393  return 0;
394 }
395 
396 
397 
398 int GWEN_Args_Usage(const GWEN_ARGS *args, GWEN_BUFFER *ubuf,
399  GWEN_ARGS_OUTTYPE ot){
400  int rv;
401 
402  switch(ot) {
404  rv=GWEN_Args_UsageTXT(args, ubuf);
405  break;
407  rv=GWEN_Args_UsageHTML(args, ubuf);
408  break;
409  default:
410  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown output type %d", ot);
411  rv=-1;
412  } /* switch */
413 
414  return rv;
415 }
416 
417 
418 
420  GWEN_UNUSED GWEN_BUFFER *ubuf,
422  return 0;
423 }
424 
425 
426 
427 
428 
429 
430