ViSP  2.9.0
vpParseArgv.cpp
1 /****************************************************************************
2  *
3  * $Id: vpParseArgv.cpp 3789 2012-06-13 21:01:08Z fspindle $
4  *
5  * This file contains a procedure that handles table-based
6  * argv-argc parsing.
7  *
8  * Copyright 1990 Regents of the University of California
9  * Permission to use, copy, modify, and distribute this
10  * software and its documentation for any purpose and without
11  * fee is hereby granted, provided that the above copyright
12  * notice appear in all copies. The University of California
13  * makes no representations about the suitability of this
14  * software for any purpose. It is provided "as is" without
15  * express or implied warranty.
16  *
17  *
18  * This file has been modified to not rely on tcl, tk or X11.
19  * Based on tkArgv.c from tk2.3 :
20  *
21  *
22  * Modifications by Peter Neelin (November 27, 1992)
23  * Modifications by Fabien Spindler (June 20, 2006)
24  */
25 
33 #include <visp/vpParseArgv.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <math.h>
38 #include <ctype.h>
39 
40 /*
41  * Default table of argument descriptors. These are normally available
42  * in every application.
43  */
44 
45 vpParseArgv::vpArgvInfo vpParseArgv::defaultTable[2] = {
46  {"-help", ARGV_HELP, (char *) NULL, (char *) NULL,
47  "Print summary of command-line options and abort.\n"},
48  {NULL, ARGV_END, (char *) NULL, (char *) NULL,
49  (char *) NULL}
50 };
51 
52 int (*handlerProc1)(const char *dst, const char *key, const char *argument);
53 int (*handlerProc2)(const char *dst, const char *key, int valargc, const char **argument);
54 
55 
78 bool
79 vpParseArgv::parse(int *argcPtr, const char **argv, vpArgvInfo *argTable,
80  int flags)
81 
82 {
83  register vpArgvInfo *infoPtr; /* Pointer to the current entry in the
84  * table of argument descriptions. */
85  vpArgvInfo *matchPtr; /* Descriptor that matches current argument. */
86  const char *curArg; /* Current argument */
87  register char c; /* Second character of current arg (used for
88  * quick check for matching; use 2nd char.
89  * because first char. will almost always
90  * be '-'). */
91  int srcIndex; /* Location from which to read next argument
92  * from argv. */
93  int dstIndex; /* Index into argv to which next unused
94  * argument should be copied (never greater
95  * than srcIndex). */
96  int argc; /* # arguments in argv still to process. */
97  size_t length; /* Number of characters in current argument. */
98  unsigned long nargs; /* Number of following arguments to get. */
99 
100 /* Macro to optionally print errors */
101 #define FPRINTF if (!(flags&ARGV_NO_PRINT)) (void) fprintf
102 
103  if (flags & ARGV_DONT_SKIP_FIRST_ARG) {
104  srcIndex = dstIndex = 0;
105  argc = *argcPtr;
106  } else {
107  srcIndex = dstIndex = 1;
108  argc = *argcPtr-1;
109  }
110 
111  while (argc > 0) {
112  curArg = argv[srcIndex];
113  srcIndex++;
114  argc--;
115  c = curArg[1];
116  length = strlen(curArg);
117 
118  /*
119  * Loop throught the argument descriptors searching for one with
120  * the matching key string. If found, leave a pointer to it in
121  * matchPtr.
122  */
123 
124  matchPtr = NULL;
125  for (unsigned int i = 0; i < 2; i++) {
126  if (i == 0) {
127  infoPtr = argTable;
128  } else {
129  infoPtr = defaultTable;
130  }
131  for (; infoPtr->type != ARGV_END; infoPtr++) {
132  if (infoPtr->key == NULL) {
133  continue;
134  }
135  if ((infoPtr->key[1] != c)
136  || (strncmp(infoPtr->key, curArg, length) != 0)) {
137  continue;
138  }
139  if (infoPtr->key[length] == 0) {
140  matchPtr = infoPtr;
141  goto gotMatch;
142  }
143  if (flags & ARGV_NO_ABBREV) {
144  continue;
145  }
146  if (matchPtr != NULL) {
147  FPRINTF(stderr, "ambiguous option \"%s\"\n", curArg);
148  return true;
149  }
150  matchPtr = infoPtr;
151  }
152  }
153  if (matchPtr == NULL) {
154 
155  /*
156  * Unrecognized argument. Just copy it down, unless the caller
157  * prefers an error to be registered.
158  */
159 
160  if (flags & ARGV_NO_LEFTOVERS) {
161  FPRINTF(stderr, "unrecognized argument \"%s\"\n", curArg);
162  }
163  argv[dstIndex] = curArg;
164  dstIndex++;
165  continue;
166  }
167 
168  /*
169  * Take the appropriate action based on the option type
170  */
171  gotMatch:
172  infoPtr = matchPtr;
173  switch (infoPtr->type) {
174  case ARGV_CONSTANT:
175  *((int *) infoPtr->dst) = (long) infoPtr->src;
176  break;
177  case ARGV_INT:
178  nargs = (unsigned long) infoPtr->src;
179  if (nargs<1) nargs=1;
180  for (unsigned long i=0; i<nargs; i++) {
181  if (argc == 0) {
182  goto missingArg;
183  } else {
184  char *endPtr=NULL;
185 
186  *(((int *) infoPtr->dst)+i) =
187  strtol(argv[srcIndex], &endPtr, 0);
188  if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) {
189  FPRINTF(stderr,
190  "expected integer argument for \"%s\" but got \"%s\"\n",
191  infoPtr->key, argv[srcIndex]);
192  return true;
193  }
194  srcIndex++;
195  argc--;
196  }
197  }
198  break;
199  case ARGV_LONG:
200  nargs = (unsigned long) infoPtr->src;
201  if (nargs<1) nargs=1;
202  for (unsigned long i=0; i<nargs; i++) {
203  if (argc == 0) {
204  goto missingArg;
205  } else {
206  char *endPtr=NULL;
207 
208  *(((long *) infoPtr->dst)+i) =
209  strtol(argv[srcIndex], &endPtr, 0);
210  if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) {
211  FPRINTF(stderr,
212  "expected long argument for \"%s\" but got \"%s\"\n",
213  infoPtr->key, argv[srcIndex]);
214  return true;
215  }
216  srcIndex++;
217  argc--;
218  }
219  }
220  break;
221  case ARGV_STRING:
222  nargs = (unsigned long) infoPtr->src;
223  if (nargs<1) nargs=1;
224  for (unsigned long i=0; i<nargs; i++) {
225  if (argc == 0) {
226  goto missingArg;
227  } else {
228  *(((const char **)infoPtr->dst)+i) = argv[srcIndex];
229  srcIndex++;
230  argc--;
231  }
232  }
233  break;
234  case ARGV_REST:
235  *((int *) infoPtr->dst) = dstIndex;
236  goto argsDone;
237  case ARGV_FLOAT:
238  nargs = (unsigned long) infoPtr->src;
239  if (nargs<1) nargs=1;
240  for (unsigned long i=0; i<nargs; i++) {
241  if (argc == 0) {
242  goto missingArg;
243  } else {
244  char *endPtr;
245 
246  *(((float *) infoPtr->dst)+i) =
247  (float)strtod(argv[srcIndex], &endPtr); // Here we use strtod
248  if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) {
249  FPRINTF(stderr,
250  "expected floating-point argument for \"%s\" but got\"%s\"\n",
251  infoPtr->key, argv[srcIndex]);
252  return true;
253  }
254  srcIndex++;
255  argc--;
256  }
257  }
258  break;
259  case ARGV_DOUBLE:
260  nargs = (unsigned long) infoPtr->src;
261  if (nargs<1) nargs=1;
262  for (unsigned long i=0; i<nargs; i++) {
263  if (argc == 0) {
264  goto missingArg;
265  } else {
266  char *endPtr;
267 
268  *(((double *) infoPtr->dst)+i) =
269  strtod(argv[srcIndex], &endPtr);
270  if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) {
271  FPRINTF(stderr,
272  "expected double-point argument for \"%s\" but got\"%s\"\n",
273  infoPtr->key, argv[srcIndex]);
274  return true;
275  }
276  srcIndex++;
277  argc--;
278  }
279  }
280  break;
281 
282  case ARGV_FUNC: {
283  handlerProc1 = (int (*)(const char *dst, const char *key, const char *argument))infoPtr->src;
284 
285  if ((*handlerProc1)(infoPtr->dst, infoPtr->key, argv[srcIndex]))
286  {
287  srcIndex += 1;
288  argc -= 1;
289  }
290  break;
291  }
292  case ARGV_GENFUNC: {
293  handlerProc2 = (int (*)(const char *dst, const char *key, int valargc, const char **argument))infoPtr->src;
294 
295  argc = (*handlerProc2)(infoPtr->dst, infoPtr->key, argc, argv+srcIndex);
296  if (argc < 0) {
297  return true;
298  }
299  break;
300  }
301 
302  case ARGV_HELP:
303  printUsage (argTable, flags);
304  return true;
305  case ARGV_END:
306  default:
307  FPRINTF(stderr, "bad argument type %d in vpArgvInfo",
308  infoPtr->type);
309  return true;
310  }
311  }
312 
313  /*
314  * If we broke out of the loop because of an OPT_REST argument,
315  * copy the remaining arguments down.
316  */
317 
318  argsDone:
319  while (argc) {
320  argv[dstIndex] = argv[srcIndex];
321  srcIndex++;
322  dstIndex++;
323  argc--;
324  }
325  argv[dstIndex] = (char *) NULL;
326  *argcPtr = dstIndex;
327  return false;
328 
329  missingArg:
330  FPRINTF(stderr, "\"%s\" option requires an additional argument\n", curArg);
331  return true;
332 
333 #undef FPRINTF
334 }
335 
350 void
351 vpParseArgv::printUsage(vpArgvInfo * argTable, int flags)
352 {
353  register vpArgvInfo *infoPtr;
354  int width;
355  int numSpaces;
356 #define NUM_SPACES 20
357  static char spaces[] = " ";
358 /* char tmp[30]; */
359  unsigned long nargs;
360 
361 /* Macro to optionally print errors */
362 #define FPRINTF if (!(flags&ARGV_NO_PRINT)) (void) fprintf
363 
364  /*
365  * First, compute the width of the widest option key, so that we
366  * can make everything line up.
367  */
368 
369  width = 4;
370  for (unsigned int i = 0; i < 2; i++) {
371  for (infoPtr = i ? defaultTable : argTable;
372  infoPtr->type != ARGV_END; infoPtr++) {
373  int length;
374  if (infoPtr->key == NULL) {
375  continue;
376  }
377  length = (int)strlen(infoPtr->key);
378  if (length > width) {
379  width = length;
380  }
381  }
382  }
383 
384  FPRINTF(stderr, "Command-specific options:");
385  for (unsigned int i = 0; ; i++) {
386  for (infoPtr = i ? defaultTable : argTable;
387  infoPtr->type != ARGV_END; infoPtr++) {
388  if ((infoPtr->type == ARGV_HELP) && (infoPtr->key == NULL)) {
389  FPRINTF(stderr, "\n%s", infoPtr->help);
390  continue;
391  }
392  FPRINTF(stderr, "\n %s:", infoPtr->key);
393  numSpaces = width + 1 - (int)strlen(infoPtr->key);
394  while (numSpaces > 0) {
395  if (numSpaces >= NUM_SPACES) {
396  FPRINTF(stderr, "%s",spaces);
397  } else {
398  FPRINTF(stderr, "%s",spaces+NUM_SPACES-numSpaces);
399  }
400  numSpaces -= NUM_SPACES;
401  }
402  FPRINTF(stderr, "%s",infoPtr->help);
403  switch (infoPtr->type) {
404  case ARGV_INT: {
405  FPRINTF(stderr, "\n\t\tDefault value:");
406  nargs = (unsigned long) infoPtr->src;
407  if (nargs<1) nargs=1;
408  for (unsigned long j=0; j<nargs; j++) {
409  FPRINTF(stderr, " %d", *(((int *) infoPtr->dst)+j));
410  }
411  break;
412  }
413  case ARGV_LONG: {
414  FPRINTF(stderr, "\n\t\tDefault value:");
415  nargs = (unsigned long) infoPtr->src;
416  if (nargs<1) nargs=1;
417  for (unsigned long j=0; j<nargs; j++) {
418  FPRINTF(stderr, " %ld", *(((long *) infoPtr->dst)+j));
419  }
420  break;
421  }
422  case ARGV_FLOAT: {
423  FPRINTF(stderr, "\n\t\tDefault value:");
424  nargs = (unsigned long) infoPtr->src;
425  if (nargs<1) nargs=1;
426  for (unsigned long j=0; j<nargs; j++) {
427  FPRINTF(stderr, " %f", *(((float *) infoPtr->dst)+j));
428  }
429  break;
430  }
431  case ARGV_DOUBLE: {
432  FPRINTF(stderr, "\n\t\tDefault value:");
433  nargs = (unsigned long) infoPtr->src;
434  if (nargs<1) nargs=1;
435  for (unsigned long j=0; j<nargs; j++) {
436  FPRINTF(stderr, " %g", *(((double *) infoPtr->dst)+j));
437  }
438  break;
439  }
440  case ARGV_STRING: {
441  const char *string;
442 
443  nargs = (unsigned long) infoPtr->src;
444  if (nargs<1) nargs=1;
445  string = *((const char **) infoPtr->dst);
446  if ((nargs==1) && (string == NULL)) break;
447  for (unsigned long j=0; j<nargs; j++) {
448  string = *(((const char **) infoPtr->dst)+j);
449  if (string != NULL) {
450  FPRINTF(stderr, " \"%s\"", string);
451  }
452  else {
453  FPRINTF(stderr, " \"%s\"", string);
454  }
455  }
456 
457  break;
458  }
459  case ARGV_END:
460  case ARGV_HELP:
461  case ARGV_GENFUNC:
462  case ARGV_FUNC:
463  case ARGV_REST:
464  case ARGV_CONSTANT:
465  default: {
466  break;
467  }
468  }
469  }
470 
471  if ((flags & ARGV_NO_DEFAULTS) || (i > 0)) {
472  break;
473  }
474  FPRINTF(stderr, "\nGeneric options for all commands:");
475  }
476 
477  FPRINTF(stderr, "\n");
478 #undef FPRINTF
479 }
480 
508 int
509 vpParseArgv::parse(int argc, const char** argv, const char* validOpts,
510  const char** param)
511 {
512  static int iArg = 1;
513  int chOpt;
514  const char* psz = NULL;
515  const char* pszParam = NULL;
516 
517  if (iArg < argc) {
518  psz = &(argv[iArg][0]);
519  if (*psz == '-') { // || *psz == '/') {
520  // we have an option specifier
521  chOpt = argv[iArg][1];
522  if (isalnum(chOpt) || ispunct(chOpt)) {
523  // we have an option character
524  psz = strchr(validOpts, chOpt);
525  if (psz != NULL) {
526  // option is valid, we want to return chOpt
527  if (psz[1] == ':') {
528  // option can have a parameter
529  psz = &(argv[iArg][2]);
530  if (*psz == '\0') {
531  // must look at next argv for param
532  if (iArg+1 < argc) {
533  psz = &(argv[iArg+1][0]);
534  // next argv is the param
535  iArg++;
536  pszParam = psz;
537  }
538  else {
539  // reached end of args looking for param
540  // option specified without parameter
541  chOpt = -1;
542  pszParam = &(argv[iArg][0]);
543  }
544 
545  }
546  else {
547  // param is attached to option
548  pszParam = psz;
549  }
550  }
551  else {
552  // option is alone, has no parameter
553  }
554  }
555  else {
556  // option specified is not in list of valid options
557  chOpt = -1;
558  pszParam = &(argv[iArg][0]);
559  }
560  }
561  else {
562  // though option specifier was given, option character
563  // is not alpha or was was not specified
564  chOpt = -1;
565  pszParam = &(argv[iArg][0]);
566  }
567  }
568  else {
569  // standalone arg given with no option specifier
570  chOpt = 1;
571  pszParam = &(argv[iArg][0]);
572  }
573  }
574  else {
575  // end of argument list
576  chOpt = 0;
577  }
578 
579  iArg++;
580  *param = pszParam;
581  return (chOpt);
582 }
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:79
static vpArgvInfo defaultTable[2]
Definition: vpParseArgv.h:183