30 # include <vcl_msvc_warnings.h> 48 {
return help_.c_str(); }
52 bool warn_about_unrecognized_arguments)
55 warn_about_unrecognized_arguments);
92 current_list().
add(a);
98 current_list().
parse(argc, argv, warn_about_unrecognized_arguments);
118 if (msg) std::cerr <<
"** WARNING ** " << msg << std::endl;
124 if (msg) std::cerr <<
"** ERROR ** " << msg << std::endl;
134 option_(option_string?option_string:
"\0"),
135 help_(helpstring?helpstring:
"\0")
143 option_(option_string?option_string:
"\0"),
144 help_(helpstring?helpstring:
"\0")
146 current_list().
add(
this);
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";
170 std::cerr <<
"vul_arg_info_list: WARNING: '-" <<
help_ 171 <<
"' option reserved and will be ignored\n";
173 args_.push_back(argmt);
181 for (
auto & arg : l.
args_)
190 std::cerr <<
"Usage: " << progname <<
' ';
192 std::cerr <<
"Usage: <prog_name> ";
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 <<
']';
207 std::cerr << arg->type_ <<
' ';
214 std::size_t maxl_option = std::max(std::size_t(8),
help_.size());
215 std::size_t maxl_type = 4;
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;
223 std::size_t l = std::strlen(arg->type_);
224 if (l > maxl_type) maxl_type = l;
228 std::string fmtbuf =
vul_sprintf(
"%%%ds %%-%ds %%s ", maxl_option, maxl_type);
232 for (
auto & arg :
args_)
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";
238 for (
auto & arg :
args_)
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());
245 std::cerr << std::endl;
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";
256 vul_printf(std::cerr, fmtbuf.c_str(),
help_.c_str(),
"bool",
"Print this message\n");
265 std::vector<bool> done_once(
args_.size(),
false);
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)
272 std::cerr <<
"vul_arg_info_list: WARNING: repeated switch [" 273 <<
args_[j]->option_ <<
"]\n";
276 for (
auto & arg :
args_)
280 char * cmdname = argv[0]+std::strlen(argv[0]);
281 while (cmdname > argv[0] && *cmdname !=
'/' && *cmdname !=
'\\') --cmdname ;
282 if (*cmdname ==
'\\' || *cmdname ==
'/') cmdname++;
289 char ** my_argv = argv + 1;
291 char* argmt = *my_argv;
293 for (
unsigned int i = 0; i <
args_.size(); ++i) {
294 if (!
args_[i]->option_.empty()) {
295 if (
help_ == argmt ) {
300 if (
args_[i]->option_==argmt) {
302 int advance =
args_[i]->parse(my_argv + 1);
303 args_[i]->set_ =
true;
306 for (
char ** av = my_argv; *(av + advance); ++av)
307 *av = *(av + advance + 1);
320 std::cerr <<
"args remaining:";
321 for (
char ** av = argv; *av; ++av)
322 std::cerr <<
" [" << *av <<
']';
323 std::cerr << std::endl;
329 int num_satisfied = 0;
330 for (
unsigned int i = 0; i <
args_.size(); ++i)
331 if (
args_[i]->option_.empty()) {
334 int advance =
args_[i]->parse(my_argv);
335 args_[i]->set_ =
true;
342 std::cerr <<
"\nargParse::ERROR: Required arg " << (num_satisfied+1)
343 <<
" not supplied\n\n";
351 for (
char ** av = my_argv; *av; ++av)
353 for (
int i = 1; i < argc; ++i)
354 argv[i] = my_argv[i-1];
355 argv[argc] =
nullptr;
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;
369 if (warn_about_unrecognized_arguments)
370 for (
char ** av = argv; *av; ++av)
373 std::cerr <<
"vul_arg_info_list: WARNING: Unparsed switch [" << *av <<
"]\n";
377 for (
auto & arg :
args_)
378 if (arg->required_ && ! (arg->set_) ) {
381 std::cerr <<
"\nargParse::ERROR: Required arg " << arg->option_
382 <<
" not supplied\n\n";
388 #ifdef DEBUG //fsm: do not print outcome - it looks like an error message. 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);
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;
406 std::cerr <<
"args remaining [argc = " << argc <<
"]:";
407 for (
char ** av = argv; *av; ++av)
408 std::cerr <<
' ' << *av;
409 std::cerr <<
"\n--------------\n";
429 static int list_parse(std::list<int> &out,
char ** argv)
434 if ( !argv[0] )
return 0;
436 std::string str(argv[0]);
438 #define REGEXP_INTEGER "\\-?[0123456789]+" 445 while (str.length() > 0 && range_regexp.find(str)) {
448 std::ptrdiff_t start= range_regexp.start(0);
449 std::ptrdiff_t endp = range_regexp.end(0);
451 std::cerr <<
"vul_arg<std::list<int> >: Bad argument [" << argv[0] <<
"]\n";
457 std::string token = str.substr(start, endp);
458 std::cerr <<
"token = " << token <<
'\n';
460 std::string match1 = range_regexp.match(1);
462 std::cerr <<
"match1 = " << match1 <<
'\n';
464 std::string match2 = range_regexp.match(2);
466 std::cerr <<
"match2 = " << match2 <<
'\n';
468 std::string match3 = range_regexp.match(3);
470 std::cerr <<
"match3 = " << match3 <<
'\n';
475 if (!str.empty() && str[0] ==
',') str.erase(0, 1);
478 std::cerr <<
"Range regexp matched [" << token <<
"]: parts [" 479 << match1<<
"] ["<<match2<<
"] ["<<match3<<
"]\n" 480 <<
" str->[" << str <<
"]\n";
483 bool matched2 = range_regexp.match(2).size() > 0;
484 bool matched3 = range_regexp.match(3).size() > 0;
498 std::cerr <<
" " << s <<
':' << d <<
':' << e <<
'\n';
502 std::cerr <<
"WARNING: d < 0\n";
505 for (
int i = s; i <= e; i += d)
510 std::cerr <<
"WARNING: d > 0\n";
513 for (
int i = s; i >= e; i += d)
521 std::cerr <<
"vul_arg<std::list<int> >: Bad argument fragment [" << str <<
"]\n";
532 # define VDS template <> 541 { s << (argmt() ?
"set" :
"not set"); }
559 if ( !argv || !argv[0] ) {
561 std::cerr <<
"vul_arg_parse: Expected integer, none is provided.\n";
565 char* endptr =
nullptr;
566 double v = std::strtod(argv[0], &endptr);
567 if (*endptr !=
'\0') {
569 std::cerr <<
"vul_arg_parse: WARNING: Attempt to parse \"" << *argv <<
"\" as int\n";
572 if (v != std::floor(v)) {
573 std::cerr <<
"vul_arg_parse: Expected integer: saw " << argv[0] << std::endl;
591 if ( !argv || !argv[0] )
594 std::cerr <<
"vul_arg_parse: Expected integer, none is provided.\n";
599 auto len = (
unsigned long)std::strlen(argv[0]);
600 for (
unsigned long i=0; i<len; ++i)
602 char tmp = argv[0][i];
603 if (tmp < '0' || tmp >
'9' ||
604 ((tmp ==
'l' || tmp ==
'L') && i+1 != len) ||
605 (tmp==
'-' && i != 0L && len <= 2L))
607 std::cerr <<
"vul_arg_parse: WARNING: Attempt to parse \"" << *argv <<
"\" as int64\n";
612 std::stringstream ss;
630 if ( !argv || !argv[0] ) {
632 std::cerr <<
"vul_arg_parse: Expected integer, none is provided.\n";
636 char* endptr =
nullptr;
637 double v = std::strtod(argv[0], &endptr);
638 if (*endptr !=
'\0') {
640 std::cerr <<
"vul_arg_parse: WARNING: Attempt to parse " << *argv <<
" as int\n";
643 if (v != std::floor(v)) {
644 std::cerr <<
"vul_arg_parse: Expected integer: saw " << argv[0] << std::endl;
647 argmt->
value_ = unsigned(v);
661 if ( !argv || !argv[0] ) {
663 std::cerr <<
"vul_arg_parse: Expected floating number, none is provided.\n";
667 char* endptr =
nullptr;
668 argmt->
value_ = (float)std::strtod(argv[0], &endptr);
672 std::cerr <<
"vul_arg_parse: WARNING: Attempt to parse " << *argv <<
" as float\n";
686 if ( !argv || !argv[0] ) {
688 std::cerr <<
"vul_arg_parse: Expected floating number, none is provided.\n";
692 char* endptr =
nullptr;
693 argmt->
value_ = std::strtod(argv[0], &endptr);
697 std::cerr <<
"vul_arg_parse: WARNING: Attempt to parse " << *argv <<
" as double\n";
707 { s <<
'\'' << (argmt()?argmt():
"(null)") <<
'\''; }
712 if (!argv || !argv[0]) {
714 std::cerr <<
"vul_arg_parse: Expected string, none is provided.\n";
728 { s <<
'\'' << (argmt()?argmt():
"(null)") <<
'\''; }
732 if ( !argv || !argv[0] ) {
734 std::cerr <<
"vul_arg_parse: Expected string, none is provided.\n";
748 { s <<
'\'' << argmt() <<
'\''; }
752 if ( !argv || !argv[0] ) {
754 std::cerr <<
"vul_arg_parse: Expected string, none is provided.\n";
763 std::cerr << __FILE__
": no argument to string option\n";
775 for (
const auto i : argmt())
781 return list_parse(argmt->
value_,argv);
791 for (
int i : argmt())
798 int retval = list_parse(tmp,argv);
801 for (
const auto & i : tmp)
802 argmt->
value_.push_back( i );
813 for (
unsigned int i : argmt())
820 int retval = list_parse(tmp,argv);
823 for (
const auto & i : tmp)
824 argmt->
value_.push_back(
unsigned(i) );
835 for (
double i : argmt())
841 if ( !argv || !argv[0] ) {
843 std::cerr <<
"vul_arg_parse: Expected a vector of floating number, none is provided.\n";
848 bool found_at_least_one_comma =
false;
853 char *current = argv[0];
855 char* endptr =
nullptr;
856 double tmp = std::strtod(current, &endptr);
858 if (*endptr ==
'\0') {
859 argmt->
value_.push_back(tmp);
862 if (found_at_least_one_comma)
return sucked;
865 else if (*endptr ==
',')
867 found_at_least_one_comma =
true;
868 argmt->
value_.push_back(tmp);
871 else if (endptr == current)
875 std::cerr <<
"vul_arg_parse: WARNING: Attempt to parse " << current <<
" as double\n";
Utility functions for C strings and std::strings.
Contains vul_printf function.
Pattern matching with regular expressions.
VDS int parse(vul_arg< bool > *argmt, char **)
static void set_help_precis(char const *str)
void set_help_description(char const *str)
Set the (possibly long) text used to document the command.
vul_arg_base(vul_arg_info_list &l, char const *option_string, char const *helpstring, bool required=false)
std::vector< vul_arg_base * > args_
static void display_usage(char const *msg=nullptr)
static void parse_deprecated(int &argc, char **&argv, bool warn_about_unrecognized_arguments=true)
The main static method.
void add(vul_arg_base *arg)
Add an argument to the list.
VDS void print_value(std::ostream &s, vul_arg< bool > const &argmt)
int vul_string_atoi(std::string const &s)
Reads an integer from a string.
void include(vul_arg_info_list &l)
Append another list. The other list is not copied, just pointed to.
char const * type_
Static text describing type of option (e.g. bool or double).
static void display_usage_and_exit(char const *msg=nullptr)
static void set_help_option(char const *str)
This is the base class for the templated vul_arg<T>s.
a helper for vul_arg::parse.
contains class for pattern matching with regular expressions
void vul_arg_display_usage_and_exit(char const *msg)
Print all args, and usage messages.
std::string help_
Description of argument.
static void add_to_current(vul_arg_base *a)
VDS void settype(vul_arg< bool > &argmt)
bool.
void set_help_option(char const *str)
Change the help operator (defaults to -?).
std::string option_
Option flag including "-" or "--".
void set_help_precis(char const *str)
Set the (short) text used to describe the command.
C++ conforming replacement to the ANSI C functions sprintf and printf.
std::string command_precis_
void vul_arg_parse(int &argc, char **&argv, bool warn_about_unrecognized_arguments)
Parse the list of arguments....
static void set_help_description(char const *str)
void parse(int &argc, char **&argv, bool warn_about_unrecognized_arguments)
Parse the command line, using the current list of args.
std::ostream & vul_printf(std::ostream &s, char const *fmt,...)
Print using printf format specifiers to an ostream.
void display_help(char const *progname=nullptr)
Display help about each option in the arg list.
static void include_deprecated(vul_arg_info_list &l)
Add another vul_arg_info_list to the current one.
bool set() const
Returns true if arg was set on the command line.
void vul_arg_include(vul_arg_info_list &l)
Add an externally supplied list of args to the global list.
bool set_
After parsing, true iff value was set on command line.
parse command-line arguments.
static VUL_EXPORT required_option_type is_required
creates a formatted ANSI C++ string