27 #ifndef SCRIBO_DEBUG_OPTION_PARSER_HH
28 # define SCRIBO_DEBUG_OPTION_PARSER_HH
31 # include <scribo/debug/option_check.hh>
59 bool (*fcheck)(
const std::vector<const char *>&);
61 const char *by_default;
72 bool parse(
int argc,
char *argv[]);
74 void print_help()
const;
76 bool is_enabled(
const char *toggle_name)
const;
77 bool is_set(
const char *opt_name)
const;
79 std::vector<const char *> opt_values(
const char *opt_name)
const;
80 std::string opt_value(
const char *opt_name)
const;
82 const char* arg(
const char *)
const;
84 void set_verbose_enabled(
bool b);
88 typedef std::map<std::string, bool> toggles_t;
89 typedef std::vector<const char *> vector_t;
90 typedef std::map<std::string, vector_t> opts_t;
91 typedef std::map<std::string, const char *> args_t;
93 bool validate_toggle(
const char *name,
const char *fullname)
const;
94 bool validate_option(
const char *name,
const char *fullname,
int& opt_id)
const;
99 unsigned required_argc_;
110 # ifndef MLN_INCLUDE_ONLY
113 option_parser::option_parser(
const arg_data arg_desc[],
116 : arg_desc_(arg_desc), toggle_desc_(toggle_desc), opt_desc_(opt_desc),
119 for (required_argc_ = 0; arg_desc_[required_argc_].name; ++required_argc_)
123 for (
int i = 0; toggle_desc_[i].name; ++i)
124 toggles_[toggle_desc_[i].name] = toggle_desc_[i].enabled;
127 for (
int i = 0; opt_desc_[i].name; ++i)
128 if (opt_desc_[i].by_default)
129 opts_[opt_desc_[i].name].push_back(opt_desc_[i].by_default);
135 option_parser::validate_toggle(
const char *name,
const char *fullname)
const
137 if (toggles_.find(name) == toggles_.end())
139 std::cerr <<
"Error: invalid toggle " << fullname << std::endl;
149 option_parser::validate_option(
const char *name,
const char *fullname,
154 for (; opt_desc_[opt_id].name && strcmp(opt_desc_[opt_id].name, name); ++opt_id)
158 if (!opt_desc_[opt_id].name)
160 std::cerr <<
"Error: invalid option " << fullname << std::endl;
170 option_parser::parse(
int argc,
char *argv[])
172 bool no_error =
true;
173 unsigned nrequired_argc = 0;
177 char **arg_end = argv + argc;
180 while (argv < arg_end)
189 if (! strncmp(argv[0],
"--enable-", 9))
191 if (!validate_toggle(argv[0] + 9, argv[0]))
197 toggles_[argv[0] + 9] =
true;
199 std::cout <<
"> Toggle " << argv[0] + 9
200 <<
" enabled" << std::endl;
202 else if (! strncmp(argv[0],
"--disable-", 10))
204 if (!validate_toggle(argv[0] + 10, argv[0]))
210 toggles_[argv[0] + 10] =
false;
212 std::cout <<
"> Toggle " << argv[0] + 10
213 <<
" disabled" << std::endl;
217 char *opt = argv[0] + 2;
218 opts_[opt] = vector_t();
221 if (!strcmp(argv[0],
"--help"))
228 if (!validate_option(opt, argv[0], opt_id))
235 std::cout <<
" * Looking for arguments for option "
242 char **arg_lookup = argv + opt_desc_[opt_id].n_args;
246 while (argv < arg_end && argv <= arg_lookup)
248 opts_[opt].push_back(argv[0]);
253 if (argv <= arg_lookup)
255 std::cerr <<
"Error: missing arguments for option "
264 if (opt_desc_[opt_id].fcheck
265 && !opt_desc_[opt_id].fcheck(opts_[opt]))
275 std::cout <<
"> Set option " << opt <<
" to ";
276 for (vector_t::const_iterator it = opts_[opt].begin();
277 it != opts_[opt].end(); ++it)
278 std::cout << *it <<
" ";
279 std::cout << std::endl;
286 std::cerr <<
"Error: invalid option " << argv[0] << std::endl;
294 if (nrequired_argc == required_argc_)
296 std::cerr <<
"Error: wrong number of arguments! \""
297 << argv[0] <<
"\" was not expected!" << std::endl;
302 args_[arg_desc_[nrequired_argc].name] = argv[0];
310 if (nrequired_argc != required_argc_)
313 std::cerr <<
"Error: wrong number of arguments!" << std::endl;
319 std::cout << std::endl;
320 std::cout <<
"--------------" << std::endl;
327 std::string add_space(
const char* name)
331 int len = 20 - strlen(name);
332 for (
int i = 0; i < len; ++i)
341 option_parser::print_help()
const
343 std::cout <<
" Usage: " << name_;
344 for (
int i = 0; arg_desc_[i].name; ++i)
345 std::cout <<
" " << arg_desc_[i].name;
347 if (opt_desc_[0].name)
348 std::cout <<
" [OPTIONS]";
350 if (toggle_desc_[0].name)
351 std::cout <<
" [TOGGLES]" << std::endl;
353 std::cout << std::endl << std::endl;
355 std::cout <<
" List of the mandatory arguments:"
356 << std::endl << std::endl;
358 for (
int i = 0; arg_desc_[i].name; ++i)
359 std::cout <<
" " << arg_desc_[i].name << add_space(arg_desc_[i].name)
360 << arg_desc_[i].desc << std::endl;
362 std::cout << std::endl << std::endl;
365 if (opt_desc_[0].name)
367 std::cout <<
" [OPTIONS] can be replaced by one or several "
368 <<
"following options :" << std::endl << std::endl;
370 for (
int i = 0; opt_desc_[i].name; ++i)
372 std::cout <<
" " <<
"--" << opt_desc_[i].name <<
" ";
375 std::cout << opt_desc_[i].format << std::endl;
377 std::cout <<
"\t" << opt_desc_[i].desc << std::endl;
379 if (opt_desc_[i].by_default)
380 std::cout <<
"\tDefault value: " << opt_desc_[i].by_default << std::endl;
382 std::cout << std::endl;
385 std::cout <<
" --help" << std::endl;
386 std::cout <<
"\t Display this help." << std::endl << std::endl;
388 std::cout << std::endl << std::endl;
392 if (toggle_desc_[0].name)
394 std::cout <<
" [TOGGLES] can be replaced by one or several "
395 <<
"following toggle names prefixed by --enable- or --disable- :"
396 << std::endl << std::endl;
398 for (
int i = 0; toggle_desc_[i].name; ++i)
399 std::cout <<
" " << toggle_desc_[i].name << add_space(toggle_desc_[i].name)
400 << toggle_desc_[i].desc << std::endl;
402 std::cout << std::endl << std::endl;
405 std::cout <<
"------------" << std::endl;
406 std::cout <<
"EPITA/LRDE - Scribo 2008-2011" << std::endl;
412 option_parser::is_enabled(
const char *toggle_name)
const
414 toggles_t::const_iterator it = toggles_.find(toggle_name);
421 option_parser::is_set(
const char *opt_name)
const
423 return opts_.find(opt_name) != opts_.end();
428 std::vector<const char*>
429 option_parser::opt_values(
const char *opt_name)
const
431 opts_t::const_iterator it = opts_.find(opt_name);
432 mln_assertion(it != opts_.end());
439 option_parser::opt_value(
const char *opt_name)
const
441 opts_t::const_iterator it = opts_.find(opt_name);
442 mln_assertion(it != opts_.end());
443 return it->second[0];
449 option_parser::arg(
const char* name)
const
451 mln_assertion(args_.find(name) != args_.end());
452 return args_.find(name)->second;
458 option_parser::set_verbose_enabled(
bool b)
464 # endif // ! MLN_INCLUDE_ONLY
470 #endif // ! SCRIBO_DEBUG_OPTION_PARSER_HH