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