textdomain (PACKAGE_TARNAME);
/* Parse and process arguments. */
- argp_full args (global_opts,
- dwarflint::check_registrar::inst ()->get_descriptors ());
-
+ argppp &argp = argppp::inst ();
int remaining;
- argp_parse (&args.get (), argc, argv, 0, &remaining, NULL);
+ argp.parse (argc, argv, 0, &remaining);
if (opt_list_checks.seen ())
{
else if (remaining == argc)
{
fputs (gettext ("Missing file name.\n"), stderr);
- argp_help (&args.get (), stderr, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
+ argp.help (stderr, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
program_invocation_short_name);
std::exit (1);
}
return find_opt (key);
}
-error_t
-options::parse_opt (int key, char *arg,
- __attribute__ ((unused)) argp_state *state)
-{
- option_i *o = global_opts.find_opt (key); // XXX temporary
- if (o == NULL)
- return ARGP_ERR_UNKNOWN;
- return o->parse_opt (arg, state);
-}
-
struct last_option
: public argp_option
{
_m_opts.push_back (last_option ());
argp a = {
&_m_opts.front (),
- &options::parse_opt,
+ NULL, // needs to be initialized later, in argppp
!toplev ? NULL : "FILE...",
!toplev ? NULL : "\
Pedantic checking of DWARF stored in ELF files.",
return a;
}
-argp_full::argp_full (options const &global,
- std::vector<checkdescriptor const *> checkdescriptors)
+argppp &
+argppp::inst ()
+{
+ static argppp my
+ (global_opts,
+ dwarflint::check_registrar::inst ()->get_descriptors ());
+ return my;
+}
+
+argppp::argppp (options const &global,
+ std::vector<checkdescriptor const *> checkdescriptors)
+ : _m_inited (false)
{
argp main = global.build_argp (true);
if (!(*it)->opts ().empty ())
{
_m_children_argps.push_back ((*it)->opts ().build_argp ());
+ _m_children_argps.back ().parser = &parse_opt;
_m_children_headers.push_back (std::string ("Options for ")
+ (*it)->name ()
+ ":");
+ _m_children_inputs.push_back (&(*it)->opts ());
}
unsigned pos = 0;
main.children = &_m_children.front ();
}
+ main.parser = &parse_opt;
_m_argp = main;
}
+error_t
+argppp::parse_opt (int key, char *arg, argp_state *state)
+{
+ if (key == ARGP_KEY_INIT && !inst ()._m_inited)
+ {
+ inst ()._m_inited = true;
+ unsigned i = 0;
+ for (std::vector<options const *>::const_iterator it
+ = inst ()._m_children_inputs.begin ();
+ it != inst ()._m_children_inputs.end (); ++it)
+ state->child_inputs[i++] = const_cast<options *> (*it);
+ return 0;
+ }
+ else
+ {
+ assert (state->input != NULL);
+ options const *opts = static_cast<options const *> (state->input);
+ option_i *o = opts->find_opt (key);
+ if (o == NULL)
+ return ARGP_ERR_UNKNOWN;
+ return o->parse_opt (arg, state);
+ }
+}
+
+void
+argppp::parse (int argc, char **argv, unsigned flags, int *remaining)
+{
+ assert (!_m_inited);
+ argp_parse (&_m_argp, argc, argv, flags, remaining, &global_opts);
+}
+
+void
+argppp::help (FILE *stream, unsigned flags, char *name)
+{
+ argp_help (&_m_argp, stream, flags, name);
+}
int option_i::_m_last_opt = 300;
class options
: private std::map<int, option_i *>
{
- friend class option_common;
+ friend class argppp;
mutable std::vector<argp_option> _m_opts;
option_i *find_opt (int key) const;
- static error_t parse_opt (int key, char *arg, argp_state *state);
public:
option_i const *getopt (int key) const;
}
};
-class argp_full
+// Wrapper of argp parsing. While in general argp does a decent job,
+// it's not possible to pass user arguments to the parser function
+// from the argp structure itself, and therefore share the same parser
+// for all the children. Since that's what we need to do, we need to
+// pass the "input" argument to argp_parse, and carefully setup the
+// child_inputs arguments. That means coordinating the whole parsing
+// process from one place. As a result this is hardly a nice,
+// reusable piece of code.
+class argppp
{
std::vector<argp> _m_children_argps;
std::vector<std::string> _m_children_headers;
std::vector<argp_child> _m_children;
+ std::vector<options const *> _m_children_inputs;
argp _m_argp;
+ bool _m_inited;
+ argppp (options const &global,
+ std::vector<checkdescriptor const *> checkdescriptors);
+
+ static error_t parse_opt (int key, char *arg, argp_state *state);
public:
- argp_full (options const &global,
- std::vector<checkdescriptor const *> checkdescriptors);
- argp const &get () const { return _m_argp; }
+ static argppp &inst ();
+ void parse (int argc, char **argv, unsigned flags, int *remaining);
+ void help (FILE *stream, unsigned flags, char *name);
};
class option_i // we cannot call it simply "option", this conflicts