]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
dwarflint: Recognize options local to check
authorPetr Machata <pmachata@redhat.com>
Fri, 24 Sep 2010 14:00:28 +0000 (16:00 +0200)
committerPetr Machata <pmachata@redhat.com>
Fri, 24 Sep 2010 14:00:28 +0000 (16:00 +0200)
dwarflint/main.cc
dwarflint/option.cc
dwarflint/option.hh

index 0c13bd0a42f81359d855f9227d6c17d9cf65bd74..c68e35da44fb783e00ebd922fd865de6a7648699 100644 (file)
@@ -152,12 +152,10 @@ main (int argc, char *argv[])
   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 ())
     {
@@ -167,7 +165,7 @@ main (int argc, char *argv[])
   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);
     }
index a42e05253bc0ee16a76a0c99cfeb120850d1aba8..99277270e94bfffacfb6c2d0a299919980887f24 100644 (file)
@@ -49,16 +49,6 @@ options::getopt (int key) const
   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
 {
@@ -88,7 +78,7 @@ options::build_argp (bool toplev) const
   _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.",
@@ -97,8 +87,18 @@ 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);
 
@@ -108,9 +108,11 @@ argp_full::argp_full (options const &global,
     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;
@@ -131,9 +133,46 @@ argp_full::argp_full (options const &global,
       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;
 
index 1b5172c25e3ace2592a64609300ab60b9a833ac7..6bde308c3eccb6dab8cc39ec24044972228fd67d 100644 (file)
 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;
@@ -55,17 +54,31 @@ public:
   }
 };
 
-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