vul_arg.cxx
Go to the documentation of this file.
1 // This is core/vul/vul_arg.cxx
2 //:
3 // \file
4 // Note that even though this file defines instances of a templated
5 // class, it is a .cxx file and not a .hxx file because it does not
6 // supply a class definition for use by clients.
7 //
8 // If you need to define your own vul_arg<T>, you should #include vul_arg.h
9 // ONLY, in your source file (myarg.cxx, say), define these three global
10 // functions (which can by static if you like) in myarg.cxx
11 // \code
12 // void settype(vul_arg<T> &);
13 // void print_value(vul_arg<T> const &, std::ostream &);
14 // int parse(vul_arg<T>*, char**);
15 // \endcode
16 // and then instantiate the class vul_arg<T> as usual (in myarg.cxx).
17 
18 #include <algorithm>
19 #include <iostream>
20 #include <sstream>
21 #include <cstring>
22 #include <cstdlib>
23 #include <cmath>
24 #include <vector>
25 #include <list>
26 #include "vul_arg.h"
27 
28 #include <cassert>
29 #ifdef _MSC_VER
30 # include <vcl_msvc_warnings.h>
31 #endif
32 
33 #include <vul/vul_sprintf.h>
34 #include <vul/vul_string.h>
35 #include <vul/vul_reg_exp.h>
36 #include <vul/vul_printf.h>
37 
38 //------------------------------------------------------------------------------
39 
40 // definition: used in constructor of vul_arg for required flags
42 
43 
44 char const* vul_arg_base::option()
45 { return option_.c_str(); }
46 
47 char const* vul_arg_base::help()
48 { return help_.c_str(); }
49 
50 //: Parse the list of arguments....
51 void vul_arg_parse(int& argc, char **& argv,
52  bool warn_about_unrecognized_arguments)
53 {
55  warn_about_unrecognized_arguments);
56 }
57 
58 //: Add an externally supplied list of args to the global list.
60 {
62 }
63 
64 //: Print all args, and usage messages.
65 void vul_arg_display_usage_and_exit(char const* msg)
66 {
68 }
69 
70 
71 //: Returns true if arg was set on the command line.
72 bool vul_arg_base::set() const
73 { return set_; }
74 
75 static vul_arg_info_list& current_list() // instance "method"
76 {
77  static vul_arg_info_list list;
78  return list;
79 }
80 
81 //: Add another vul_arg_info_list to the current one.
82 // This allows for the inclusion of different sets of arguments into the
83 // main program, from different libraries.
85 {
86  current_list().include(l);
87 }
88 
89 //
91 {
92  current_list().add(a);
93 }
94 
95 //: The main static method.
96 void vul_arg_base::parse_deprecated(int& argc, char **& argv, bool warn_about_unrecognized_arguments)
97 {
98  current_list().parse(argc, argv, warn_about_unrecognized_arguments);
99 }
100 
101 void vul_arg_base::set_help_option(char const* str)
102 {
103  current_list().set_help_option( str);
104 }
105 
106 void vul_arg_base::set_help_precis(char const* str)
107 {
108  current_list().set_help_precis( str);
109 }
110 
112 {
113  current_list().set_help_description( str);
114 }
115 
116 void vul_arg_base::display_usage(char const* msg)
117 {
118  if (msg) std::cerr << "** WARNING ** " << msg << std::endl;
119  current_list().display_help("");
120 }
121 
123 {
124  if (msg) std::cerr << "** ERROR ** " << msg << std::endl;
125  current_list().display_help("");
126  std::exit(-1);
127 }
128 
129 // vul_arg_base constructors
130 
131 vul_arg_base::vul_arg_base(vul_arg_info_list& l, char const* option_string, char const* helpstring, bool required)
132 : set_(false),
133  required_(required),
134  option_(option_string?option_string:"\0"),
135  help_(helpstring?helpstring:"\0")
136 {
137  l.add(this);
138 }
139 
140 vul_arg_base::vul_arg_base(char const* option_string, char const* helpstring, bool required )
141  : set_(false),
142  required_(required),
143  option_(option_string?option_string:"\0"),
144  help_(helpstring?helpstring:"\0")
145 {
146  current_list().add(this);
147 }
148 
149 //------------------------------------------------------------------------------
150 
151 //: Change the help operator (defaults to -?)
153 {
154  // check that the operator isn't already being used
155  for (auto & arg : args_) {
156  if (std::strcmp(arg->option(),str) == 0) {
157  std::cerr << "vul_arg_info_list: WARNING: requested help operator already assigned\n";
158  return;
159  }
160  }
161 
162  help_ = str;
163 }
164 
165 
166 //: Add an argument to the list.
168 {
169  if ( argmt->option() && help_ == argmt->option() )
170  std::cerr << "vul_arg_info_list: WARNING: '-" << help_
171  << "' option reserved and will be ignored\n";
172  else
173  args_.push_back(argmt);
174 }
175 
176 //: Append another list. The other list is not copied, just pointed to.
178 {
179  assert(&l != this);
180 
181  for (auto & arg : l.args_)
182  add(arg);
183 }
184 
185 //: Display help about each option in the arg list.
186 // Note that this function does not exit at the end.
187 void vul_arg_info_list::display_help( char const*progname)
188 {
189  if (progname)
190  std::cerr << "Usage: " << progname << ' ';
191  else
192  std::cerr << "Usage: <prog_name> ";
193 
194  // Print "prog [-a int] string string"
195 
196  for (auto & arg : args_) {
197  if (! arg->option_.empty()) {
198  if (!arg->required_) std::cerr << '[';
199  std::cerr << arg->option();
200  if (std::strlen(arg->type_)> 0)
201  std::cerr << ' ' << arg->type_;
202  if (!arg->required_) std::cerr << ']';
203  std::cerr << ' ';
204  }
205  else {
206  // options without switches are required.
207  std::cerr << arg->type_ << ' ';
208  }
209  }
210 
211  std::cerr << std::endl << command_precis_ << std::endl;
212 
213  // Find longest option, type name, or default
214  std::size_t maxl_option = std::max(std::size_t(8), help_.size()); // Length of "REQUIRED" or help option
215  std::size_t maxl_type = 4; // Length of "Type", minimum "bool"
216  // int maxl_default = 0;
217  for (auto & arg : args_)
218  if (!arg->help_.empty()) {
219  if (!arg->option_.empty()) {
220  std::size_t l = std::strlen(arg->option());
221  if (l > maxl_option) maxl_option = l;
222  }
223  std::size_t l = std::strlen(arg->type_);
224  if (l > maxl_type) maxl_type = l;
225  }
226 
227  // Print long form of args
228  std::string fmtbuf = vul_sprintf("%%%ds %%-%ds %%s ", maxl_option, maxl_type);
229 
230  // Do required args first
231  vul_printf(std::cerr, "REQUIRED:\n");
232  for (auto & arg : args_) // First required without option string
233  if (!arg->help_.empty())
234  if (arg->option_.empty()&& !(arg->required_)) {
235  vul_printf(std::cerr, fmtbuf.c_str(), "", arg->type_, arg->help_.c_str());
236  std::cerr << " ["; arg->print_value(std::cerr); std::cerr << "]\n"; // default
237  }
238  for (auto & arg : args_) // Then required with option string
239  if (!arg->help_.empty())
240  if (arg->required_ && !arg->option_.empty()) {
241  vul_printf(std::cerr, fmtbuf.c_str(), arg->option(), arg->type_, arg->help_.c_str());
242  std::cerr << '\n'; // ["; args_[i]->print_value(std::cerr); std::cerr << "]\n"; // default
243  }
244 
245  std::cerr << std::endl;
246 
247  // Then others
248  vul_printf(std::cerr, "Optional:\n");
249  vul_printf(std::cerr, fmtbuf.c_str(), "Switch", "Type", "Help [default value]") << std::endl << std::endl;
250  for (auto & arg : args_)
251  if (!arg->help_.empty())
252  if (!arg->option_.empty() && !(arg->required_) ) {
253  vul_printf(std::cerr, fmtbuf.c_str(), arg->option(), arg->type_, arg->help_.c_str());
254  std::cerr << " ["; arg->print_value(std::cerr); std::cerr << "]\n"; // default
255  }
256  vul_printf(std::cerr, fmtbuf.c_str(), help_.c_str(), "bool", "Print this message\n");
257 
258  if (!description_.empty()) std::cerr << '\n' << description_;
259 }
260 
261 //: Parse the command line, using the current list of args.
262 // Remove all recognised arguments from the command line by modifying argc and argv.
263 void vul_arg_info_list::parse(int& argc, char **& argv, bool warn_about_unrecognized_arguments)
264 {
265  std::vector<bool> done_once(args_.size(), false);
266 
267  // 0. Check that there are no duplicate switches, O(n^2) as n is tiny.
268  for (unsigned int i = 0; i < args_.size(); ++i)
269  if (!args_[i]->option_.empty())
270  for (unsigned int j = i+1; j < args_.size(); ++j)
271  if (args_[i]->option_ == args_[j]->option_)
272  std::cerr << "vul_arg_info_list: WARNING: repeated switch ["
273  << args_[j]->option_ << "]\n";
274 
275  // 0a. Clear "set" flags on args
276  for (auto & arg : args_)
277  arg->set_ = false;
278 
279  // Generate shorter command name
280  char * cmdname = argv[0]+std::strlen(argv[0]);
281  while (cmdname > argv[0] && *cmdname != '/' && *cmdname != '\\') --cmdname ;
282  if (*cmdname == '\\' || *cmdname == '/') cmdname++;
283 
284 
285  // 1. Collect option arguments (i.e. ones with "-"),
286  // and squeeze them out of argv.
287  // Make sure to do things sequentially
288 
289  char ** my_argv = argv + 1; // Skip program name
290  while (*my_argv) {
291  char* argmt = *my_argv;
292  bool eaten = false;
293  for (unsigned int i = 0; i < args_.size(); ++i) {
294  if (!args_[i]->option_.empty()) {
295  if ( help_ == argmt ) { // look for the '-?' operator (i.e. HELP)
296  display_help(cmdname);
297  std::exit(1);
298  }
299 
300  if (args_[i]->option_==argmt) {
301  done_once[i] = true;
302  int advance = args_[i]->parse(my_argv + 1);
303  args_[i]->set_ = true;
304  if (advance >= 0) {
305  // Pull down remaining args
306  for (char ** av = my_argv; *(av + advance); ++av)
307  *av = *(av + advance + 1);
308 
309  eaten = true;
310  break;
311  }
312  }
313  }
314  }
315  if (!eaten)
316  ++my_argv;
317  }
318 
319  if (verbose_) {
320  std::cerr << "args remaining:";
321  for (char ** av = argv; *av; ++av)
322  std::cerr << " [" << *av << ']';
323  std::cerr << std::endl;
324  }
325 
326 
327  // 2. Just take from the list to fill the non-option arguments
328  my_argv = argv + 1;
329  int num_satisfied = 0;
330  for (unsigned int i = 0; i < args_.size(); ++i)
331  if (args_[i]->option_.empty()) {
332  if (*my_argv) {
333  done_once[i] = true;
334  int advance = args_[i]->parse(my_argv);
335  args_[i]->set_ = true;
336  my_argv += advance;
337  ++num_satisfied;
338  }
339  else {
340  display_help(cmdname);
341 
342  std::cerr << "\nargParse::ERROR: Required arg " << (num_satisfied+1)
343  << " not supplied\n\n";
344  std::exit(1);
345  }
346  }
347 
348 
349  // 3. Move my_argv down to first unused arg, and reset argc
350  argc = 1;
351  for (char ** av = my_argv; *av; ++av)
352  ++argc;
353  for (int i = 1; i < argc; ++i)
354  argv[i] = my_argv[i-1];
355  argv[argc] = nullptr;
356 
357  // 4. Error checking.
358  //
359  // 4.2 Sometimes it's bad if all args weren't used (i.e. trailing args)
360  if (autonomy_ == all) {
361  std::cerr << "vul_arg_info_list: Some arguments were unused: ";
362  for (char ** av = argv; *av; ++av)
363  std::cerr << ' ' << *av;
364  std::cerr << std::endl;
365  display_help(cmdname);
366  }
367 
368  // 4.3 It's often bad if a switch was not recognized.
369  if (warn_about_unrecognized_arguments)
370  for (char ** av = argv; *av; ++av)
371  if (**av == '-') {
372  display_help(cmdname);
373  std::cerr << "vul_arg_info_list: WARNING: Unparsed switch [" << *av << "]\n";
374  }
375 
376  // 4.3 This is required arguments (including option) have been set
377  for (auto & arg : args_)
378  if (arg->required_ && ! (arg->set_) ) {
379  display_help(cmdname);
380 
381  std::cerr << "\nargParse::ERROR: Required arg " << arg->option_
382  << " not supplied\n\n";
383  std::exit(1);
384  }
385 
386 
387  // 5. Some people like a chatty program.
388 #ifdef DEBUG //fsm: do not print outcome - it looks like an error message.
389  if (verbose_) {
390  // Print outcome
391  for (unsigned int i = 0; i < args_.size(); ++i)
392  if (args[i]->option_) {
393  std::cerr << "Switch " << args_[i]->option_ << ": "
394  << (!done_once[i] ? "not " : "") << "done, value [";
395  args[i]->print_value(std::cerr);
396  std::cerr << "]\n";
397  }
398 
399  for (unsigned int i = 0; i < args.size(); ++i)
400  if (!args[i]->option_) {
401  std::cerr << "Trailer: ";
402  args_[i]->print_value(std::cerr);
403  std::cerr << std::endl;
404  }
405 
406  std::cerr << "args remaining [argc = " << argc << "]:";
407  for (char ** av = argv; *av; ++av)
408  std::cerr << ' ' << *av;
409  std::cerr << "\n--------------\n";
410  }
411 #endif
412 }
413 
414 
415 //------------------------------------------------------------------------------
416 
417 //: function to parse matlab or UNIX style integer ranges.
418 // eg. 1:3 is matlab for 1,2,3 and 1-3 is UNIX for 1,2,3
419 //
420 // parsed as follows:
421 // any character other than '-' and ':' is considered a list separator
422 // simple ranges can be written as 1:3 or 1-3 (=1,2,3) or 3:1 (=3,2,1)
423 // complete ranges can be written as 1:2:5 or 1-2-5 (=1,3,5)
424 // negative numbers are handled 'transparently'
425 // (e.g. -1:-3 or -1--3 or even -1--1--3 ...:).
426 //
427 // Returns 1 on success and 0 on failure.
428 //
429 static int list_parse(std::list<int> &out, char ** argv)
430 {
431  out.clear();
432 
433  // Empty list specified as the last argument.
434  if ( !argv[0] ) return 0; // failure
435 
436  std::string str(argv[0]);
437 
438 #define REGEXP_INTEGER "\\-?[0123456789]+"
439 
440  vul_reg_exp range_regexp("(" REGEXP_INTEGER ")" // int
441  "([:-]" REGEXP_INTEGER ")?" // :int [optional]
442  "([:-]" REGEXP_INTEGER ")?" // :int [optional]
443  );
444 
445  while (str.length() > 0 && range_regexp.find(str)) {
446  // the start/end positions (ref from 0) of the
447  // current ',' separated token.
448  std::ptrdiff_t start= range_regexp.start(0);
449  std::ptrdiff_t endp = range_regexp.end(0);
450  if (start != 0) {
451  std::cerr << "vul_arg<std::list<int> >: Bad argument [" << argv[0] << "]\n";
452  return 0; // failure
453  }
454 
455 #ifdef DEBUG
456  // this is the current token.
457  std::string token = str.substr(start, endp);
458  std::cerr << "token = " << token << '\n';
459 #endif
460  std::string match1 = range_regexp.match(1);
461 #ifdef DEBUG
462  std::cerr << "match1 = " << match1 << '\n';
463 #endif
464  std::string match2 = range_regexp.match(2);
465 #ifdef DEBUG
466  std::cerr << "match2 = " << match2 << '\n';
467 #endif
468  std::string match3 = range_regexp.match(3);
469 #ifdef DEBUG
470  std::cerr << "match3 = " << match3 << '\n';
471 #endif
472 
473  // Remove this match from the front of string.
474  str.erase(0, endp);
475  if (!str.empty() && str[0] == ',') str.erase(0, 1);
476 
477 #if 0
478  std::cerr << "Range regexp matched [" << token << "]: parts ["
479  << match1<<"] ["<<match2<<"] ["<<match3<<"]\n"
480  << " str->[" << str << "]\n";
481 #endif
482 
483  bool matched2 = range_regexp.match(2).size() > 0;
484  bool matched3 = range_regexp.match(3).size() > 0;
485 
486  int s = vul_string_atoi(match1);
487  int d = 1;
488  int e = s;
489  if (matched3) {
490  // "1:2:10"
491  d = vul_string_atoi(match2.substr(1));
492  e = vul_string_atoi(match3.substr(1));
493  }
494  else if (matched2)
495  e = vul_string_atoi(match2.substr(1));
496 
497 #ifdef DEBUG
498  std::cerr << " " << s << ':' << d << ':' << e << '\n';
499 #endif
500  if (e >= s) {
501  if (d < 0) {
502  std::cerr << "WARNING: d < 0\n";
503  d = -d;
504  }
505  for (int i = s; i <= e; i += d)
506  out.push_back(i);
507  }
508  else {
509  if (d > 0) {
510  std::cerr << "WARNING: d > 0\n";
511  d = -d;
512  }
513  for (int i = s; i >= e; i += d)
514  out.push_back(i);
515  }
516  }
517 
518  if (str.empty())
519  return 1; // success
520 
521  std::cerr << "vul_arg<std::list<int> >: Bad argument fragment [" << str << "]\n";
522  return 0;
523 }
524 
525 //------------------------------------------------------------------------------
526 
527 // specializations for specific types.
528 // In emacs, C-s for "//: unsigned" to find the implementation for vul_arg<unsigned>
529 // In vi: "/^\/\/: unsigned"
530 
531 #if 1
532 # define VDS template <>
533 #else
534 # define VDS /* template <> */
535 #endif
536 
537 //: bool
538 VDS void settype(vul_arg<bool> &argmt) { argmt.type_ = "bool"; }
539 
540 VDS void print_value(std::ostream &s, vul_arg<bool> const &argmt)
541 { s << (argmt() ? "set" : "not set"); }
542 
543 VDS int parse(vul_arg<bool>* argmt, char ** /*argv*/)
544 {
545  argmt->value_ = true;
546  return 0; // bool sucks zero args, most others take one.
547 }
548 
549 template class vul_arg<bool>;
550 
551 //: int
552 VDS void settype(vul_arg<int> &argmt) { argmt.type_ = "integer"; }
553 
554 VDS void print_value(std::ostream &s, vul_arg<int> const &argmt)
555 { s << argmt(); }
556 
557 VDS int parse(vul_arg<int>* argmt, char ** argv)
558 {
559  if ( !argv || !argv[0] ) {
560  // no input
561  std::cerr << "vul_arg_parse: Expected integer, none is provided.\n";
562  return -1;
563  }
564 
565  char* endptr = nullptr;
566  double v = std::strtod(argv[0], &endptr);
567  if (*endptr != '\0') {
568  // There is junk after the number, or no number was found
569  std::cerr << "vul_arg_parse: WARNING: Attempt to parse \"" << *argv << "\" as int\n";
570  return -1;
571  }
572  if (v != std::floor(v)) {
573  std::cerr << "vul_arg_parse: Expected integer: saw " << argv[0] << std::endl;
574  return -1;
575  }
576  argmt->value_ = int(v);
577  return 1;
578 }
579 
580 template class vul_arg<int>;
581 
582 //: int64
583 #if VXL_HAS_INT_64
584 VDS void settype(vul_arg<vxl_int_64> &argmt) { argmt.type_ = "integer64"; }
585 
586 VDS void print_value(std::ostream &s, vul_arg<vxl_int_64> const &argmt)
587 { s << argmt(); }
588 
589 VDS int parse(vul_arg<vxl_int_64>* argmt, char ** argv)
590 {
591  if ( !argv || !argv[0] )
592  {
593  // no input
594  std::cerr << "vul_arg_parse: Expected integer, none is provided.\n";
595  return -1;
596  }
597 
598  // Ensure only digits are present allowing for the special case of an l or L suffix
599  auto len = (unsigned long)std::strlen(argv[0]);
600  for (unsigned long i=0; i<len; ++i)
601  {
602  char tmp = argv[0][i];
603  if (tmp < '0' || tmp > '9' || // Make sure the number only contains valid digits
604  ((tmp == 'l' || tmp == 'L') && i+1 != len) || // Or the trailing l or L suffix
605  (tmp=='-' && i != 0L && len <= 2L)) // Or a leading minus sign
606  {
607  std::cerr << "vul_arg_parse: WARNING: Attempt to parse \"" << *argv << "\" as int64\n";
608  return -1;
609  }
610  }
611 
612  std::stringstream ss;
613  ss << argv[0];
614  ss >> argmt->value_;
615 
616  return 1;
617 }
618 
619 template class vul_arg<vxl_int_64>;
620 #endif
621 
622 //: unsigned
623 VDS void settype(vul_arg<unsigned> &argmt) { argmt.type_ = "integer"; }
624 
625 VDS void print_value(std::ostream &s, vul_arg<unsigned> const &argmt)
626 { s << argmt(); }
627 
628 VDS int parse(vul_arg<unsigned>* argmt, char ** argv)
629 {
630  if ( !argv || !argv[0] ) {
631  // no input
632  std::cerr << "vul_arg_parse: Expected integer, none is provided.\n";
633  return -1;
634  }
635 
636  char* endptr = nullptr;
637  double v = std::strtod(argv[0], &endptr);
638  if (*endptr != '\0') {
639  // There is junk after the number, or no number was found
640  std::cerr << "vul_arg_parse: WARNING: Attempt to parse " << *argv << " as int\n";
641  return -1;
642  }
643  if (v != std::floor(v)) {
644  std::cerr << "vul_arg_parse: Expected integer: saw " << argv[0] << std::endl;
645  return -1;
646  }
647  argmt->value_ = unsigned(v);
648  return 1;
649 }
650 
651 template class vul_arg<unsigned>;
652 
653 //: float
654 VDS void settype(vul_arg<float> &argmt) { argmt.type_ = "float"; }
655 
656 VDS void print_value(std::ostream &s, vul_arg<float> const &argmt)
657 { s << argmt(); }
658 
659 VDS int parse(vul_arg<float>* argmt, char ** argv)
660 {
661  if ( !argv || !argv[0] ) {
662  // no input
663  std::cerr << "vul_arg_parse: Expected floating number, none is provided.\n";
664  return -1;
665  }
666 
667  char* endptr = nullptr;
668  argmt->value_ = (float)std::strtod(argv[0], &endptr);
669  if (*endptr == '\0')
670  return 1;
671  // There is junk after the number, or no number was found
672  std::cerr << "vul_arg_parse: WARNING: Attempt to parse " << *argv << " as float\n";
673  return -1;
674 }
675 
676 template class vul_arg<float>;
677 
678 //: double
679 VDS void settype(vul_arg<double> &argmt) { argmt.type_ = "float"; }
680 
681 VDS void print_value(std::ostream &s, vul_arg<double> const &argmt)
682 { s << argmt(); }
683 
684 VDS int parse(vul_arg<double>* argmt, char ** argv)
685 {
686  if ( !argv || !argv[0] ) {
687  // no input
688  std::cerr << "vul_arg_parse: Expected floating number, none is provided.\n";
689  return -1;
690  }
691 
692  char* endptr = nullptr;
693  argmt->value_ = std::strtod(argv[0], &endptr);
694  if (*endptr == '\0')
695  return 1;
696  // There is junk after the number, or no number was found
697  std::cerr << "vul_arg_parse: WARNING: Attempt to parse " << *argv << " as double\n";
698  return -1;
699 }
700 
701 template class vul_arg<double>;
702 
703 //: char *
704 VDS void settype(vul_arg<char *> &argmt) { argmt.type_ = "string"; }
705 
706 VDS void print_value(std::ostream &s, vul_arg<char *> const &argmt)
707 { s << '\'' << (argmt()?argmt():"(null)") << '\''; }
708 
709 VDS int parse(vul_arg<char*>* argmt, char ** argv)
710 {
711  // Reached the end?
712  if (!argv || !argv[0]) {
713  // no input
714  std::cerr << "vul_arg_parse: Expected string, none is provided.\n";
715  return -1;
716  }
717 
718  argmt->value_ = argv[0]; // argv is valid till the end of the program so
719  return 1; // it's ok to just grab the pointer.
720 }
721 
722 template class vul_arg<char*>;
723 
724 //: char const *
725 VDS void settype(vul_arg<char const *> &argmt) { argmt.type_ = "string"; }
726 
727 VDS void print_value(std::ostream &s, vul_arg<char const *> const &argmt)
728 { s << '\'' << (argmt()?argmt():"(null)") << '\''; }
729 
730 VDS int parse(vul_arg<char const *>* argmt, char ** argv)
731 {
732  if ( !argv || !argv[0] ) {
733  // no input
734  std::cerr << "vul_arg_parse: Expected string, none is provided.\n";
735  return -1;
736  }
737 
738  argmt->value_ = argv[0]; // argv is valid till the end of the program so
739  return 1; // it's ok to just grab the pointer.
740 }
741 
742 template class vul_arg<char const*>;
743 
744 //: std::string
745 VDS void settype(vul_arg<std::string> &argmt) { argmt.type_ = "string"; }
746 
747 VDS void print_value(std::ostream &s, vul_arg<std::string> const &argmt)
748 { s << '\'' << argmt() << '\''; }
749 
750 VDS int parse(vul_arg<std::string>* argmt, char ** argv)
751 {
752  if ( !argv || !argv[0] ) {
753  // no input
754  std::cerr << "vul_arg_parse: Expected string, none is provided.\n";
755  return -1;
756  }
757 
758  if (argv[0]) {
759  argmt->value_ = argv[0];
760  return 1;
761  }
762  else {
763  std::cerr << __FILE__ ": no argument to string option\n";
764  return 0;
765  }
766 }
767 
768 template class vul_arg<std::string>;
769 
770 //: std::list<int>
771 VDS void settype(vul_arg<std::list<int> > &argmt) { argmt.type_ = "integer list"; }
772 
773 VDS void print_value(std::ostream &s, vul_arg<std::list<int> > const &argmt)
774 {
775  for (const auto i : argmt())
776  s << ' ' << i;
777 }
778 
779 VDS int parse(vul_arg<std::list<int> >* argmt, char ** argv)
780 {
781  return list_parse(argmt->value_,argv);
782 }
783 
784 template class vul_arg<std::list<int> >;
785 
786 //: std::vector<int>
787 VDS void settype(vul_arg<std::vector<int> > &argmt) { argmt.type_ = "integer list"; }
788 
789 VDS void print_value(std::ostream &s, vul_arg<std::vector<int> > const &argmt)
790 {
791  for (int i : argmt())
792  s << ' ' << i;
793 }
794 
795 VDS int parse(vul_arg<std::vector<int> >* argmt, char ** argv)
796 {
797  std::list<int> tmp;
798  int retval = list_parse(tmp,argv);
799  // Defaults should be cleared when the user supplies a value
800  argmt->value_.clear();
801  for (const auto & i : tmp)
802  argmt->value_.push_back( i );
803  return retval;
804 }
805 
806 template class vul_arg<std::vector<int> >;
807 
808 //: std::vector<unsigned>
809 VDS void settype(vul_arg<std::vector<unsigned> > &argmt) { argmt.type_="integer list"; }
810 
811 VDS void print_value(std::ostream &s, vul_arg<std::vector<unsigned> > const &argmt)
812 {
813  for (unsigned int i : argmt())
814  s << ' ' << i;
815 }
816 
817 VDS int parse(vul_arg<std::vector<unsigned> >* argmt, char ** argv)
818 {
819  std::list<int> tmp;
820  int retval = list_parse(tmp,argv);
821  // Defaults should be cleared when the user supplies a value
822  argmt->value_.clear();
823  for (const auto & i : tmp)
824  argmt->value_.push_back( unsigned(i) );
825  return retval;
826 }
827 
828 template class vul_arg<std::vector<unsigned> >;
829 
830 //: std::vector<double>
831 VDS void settype(vul_arg<std::vector<double> > &argmt) {argmt.type_ = "double list";}
832 
833 VDS void print_value(std::ostream &s, vul_arg<std::vector<double> > const &argmt)
834 {
835  for (double i : argmt())
836  s << ' ' << i;
837 }
838 
839 VDS int parse(vul_arg<std::vector<double> >* argmt, char ** argv)
840 {
841  if ( !argv || !argv[0] ) {
842  // no input
843  std::cerr << "vul_arg_parse: Expected a vector of floating number, none is provided.\n";
844  return -1;
845  }
846 
847  // if true don't treat space separator as leading to another double.
848  bool found_at_least_one_comma = false;
849 
850  int sucked = 0;
851  // Defaults should be cleared when the user supplies a value
852  argmt->value_.clear();
853  char *current = argv[0];
854  while (current) {
855  char* endptr = nullptr;
856  double tmp = std::strtod(current, &endptr);
857  //argmt->value_
858  if (*endptr == '\0') {
859  argmt->value_.push_back(tmp);
860  ++ sucked;
861  ++ argv;
862  if (found_at_least_one_comma) return sucked;
863  current = argv[0];
864  }
865  else if (*endptr == ',')
866  {
867  found_at_least_one_comma = true;
868  argmt->value_.push_back(tmp);
869  current = endptr+1;
870  }
871  else if (endptr == current)
872  break; // OK. end of list of doubles.
873  else {
874  // There is junk after the number, or no number was found
875  std::cerr << "vul_arg_parse: WARNING: Attempt to parse " << current << " as double\n";
876  return -1;
877  }
878  }
879  return sucked;
880 }
881 
882 template class vul_arg<std::vector<double> >;
std::string help_
Definition: vul_arg.h:238
Utility functions for C strings and std::strings.
Contains vul_printf function.
Pattern matching with regular expressions.
Definition: vul_reg_exp.h:82
VDS int parse(vul_arg< bool > *argmt, char **)
Definition: vul_arg.cxx:543
#define VDS
Definition: vul_arg.cxx:532
static void set_help_precis(char const *str)
Definition: vul_arg.cxx:106
void set_help_description(char const *str)
Set the (possibly long) text used to document the command.
Definition: vul_arg.h:234
vul_arg_base(vul_arg_info_list &l, char const *option_string, char const *helpstring, bool required=false)
Definition: vul_arg.cxx:131
std::vector< vul_arg_base * > args_
Definition: vul_arg.h:237
static void display_usage(char const *msg=nullptr)
Definition: vul_arg.cxx:116
#define REGEXP_INTEGER
static void parse_deprecated(int &argc, char **&argv, bool warn_about_unrecognized_arguments=true)
The main static method.
Definition: vul_arg.cxx:96
void add(vul_arg_base *arg)
Add an argument to the list.
Definition: vul_arg.cxx:167
VDS void print_value(std::ostream &s, vul_arg< bool > const &argmt)
Definition: vul_arg.cxx:540
int vul_string_atoi(std::string const &s)
Reads an integer from a string.
Definition: vul_string.cxx:217
char const * help()
Definition: vul_arg.cxx:47
void include(vul_arg_info_list &l)
Append another list. The other list is not copied, just pointed to.
Definition: vul_arg.cxx:177
T value_
Definition: vul_arg.h:136
char const * type_
Static text describing type of option (e.g. bool or double).
Definition: vul_arg.h:68
char const * option()
Definition: vul_arg.cxx:44
static void display_usage_and_exit(char const *msg=nullptr)
Definition: vul_arg.cxx:122
static void set_help_option(char const *str)
Definition: vul_arg.cxx:101
std::string description_
Definition: vul_arg.h:239
This is the base class for the templated vul_arg<T>s.
Definition: vul_arg.h:35
a helper for vul_arg::parse.
Definition: vul_arg.h:208
contains class for pattern matching with regular expressions
void vul_arg_display_usage_and_exit(char const *msg)
Print all args, and usage messages.
Definition: vul_arg.cxx:65
std::string help_
Description of argument.
Definition: vul_arg.h:77
autonomy autonomy_
Definition: vul_arg.h:242
static void add_to_current(vul_arg_base *a)
Definition: vul_arg.cxx:90
VDS void settype(vul_arg< bool > &argmt)
bool.
Definition: vul_arg.cxx:538
void set_help_option(char const *str)
Change the help operator (defaults to -?).
Definition: vul_arg.cxx:152
std::string option_
Option flag including "-" or "--".
Definition: vul_arg.h:75
void set_help_precis(char const *str)
Set the (short) text used to describe the command.
Definition: vul_arg.h:230
C++ conforming replacement to the ANSI C functions sprintf and printf.
Definition: vul_sprintf.h:31
std::string command_precis_
Definition: vul_arg.h:240
void vul_arg_parse(int &argc, char **&argv, bool warn_about_unrecognized_arguments)
Parse the list of arguments....
Definition: vul_arg.cxx:51
static void set_help_description(char const *str)
Definition: vul_arg.cxx:111
void parse(int &argc, char **&argv, bool warn_about_unrecognized_arguments)
Parse the command line, using the current list of args.
Definition: vul_arg.cxx:263
std::ostream & vul_printf(std::ostream &s, char const *fmt,...)
Print using printf format specifiers to an ostream.
Definition: vul_printf.cxx:17
void display_help(char const *progname=nullptr)
Display help about each option in the arg list.
Definition: vul_arg.cxx:187
static void include_deprecated(vul_arg_info_list &l)
Add another vul_arg_info_list to the current one.
Definition: vul_arg.cxx:84
bool set() const
Returns true if arg was set on the command line.
Definition: vul_arg.cxx:72
void vul_arg_include(vul_arg_info_list &l)
Add an externally supplied list of args to the global list.
Definition: vul_arg.cxx:59
bool set_
After parsing, true iff value was set on command line.
Definition: vul_arg.h:71
parse command-line arguments.
Definition: vul_arg.h:29
static VUL_EXPORT required_option_type is_required
Definition: vul_arg.h:41
creates a formatted ANSI C++ string
Command-line arguments.