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