]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
dwarflint: Don't assume all options are global
authorPetr Machata <pmachata@redhat.com>
Thu, 23 Sep 2010 16:00:36 +0000 (18:00 +0200)
committerPetr Machata <pmachata@redhat.com>
Thu, 23 Sep 2010 16:00:36 +0000 (18:00 +0200)
- currently this breaks dwarflint, because per-check options are not yet
  processed.  Options that belonged to global group before still work and
  are correctly registered as globals, but e.g. -i or the suite of options
  at locstats aren't recognized.

dwarflint/check_nodebug.cc
dwarflint/checkdescriptor.hh
dwarflint/checks.cc
dwarflint/locstats.cc
dwarflint/main.cc
dwarflint/option.cc
dwarflint/option.hh
dwarflint/option.ii [new file with mode: 0644]

index 543daf5b1400f255e8352db473ef9edec7ce974f..03df1122724bf405885ef6b26c5162687550b090 100644 (file)
 #include "sections.hh"
 #include "option.hh"
 
+static void_option ignore_missing
+  ("Don't complain if files have no DWARF at all",
+   "ignore", 'i');
+
 class check_nodebug
   : public check<check_nodebug>
 {
@@ -37,6 +41,7 @@ public:
     static checkdescriptor cd
       (checkdescriptor::create ("check_nodebug")
        .groups ("@low")
+       .option (ignore_missing)
        .description (
 "Checks that there are at least essential debuginfo sections present\n"
 "in the ELF file.\n"));
@@ -62,9 +67,6 @@ private:
 };
 
 static reg<check_nodebug> reg_nodebug;
-static void_option ignore_missing
-  ("Don't complain if files have no DWARF at all",
-   "ignore-missing", 'i');
 
 check_nodebug::check_nodebug (checkstack &stack, dwarflint &lint)
 {
index f5131b2a1ec2d7dcc767a4ec0c3a18662fab7c8a..8845e162b5a4c5da6bd97a92fa321e66abf2fe2a 100644 (file)
@@ -29,6 +29,9 @@
 #include <set>
 #include <string>
 #include <iosfwd>
+#include <vector>
+
+#include "option.ii"
 
 struct checkgroups
   : public std::set<std::string>
@@ -52,6 +55,7 @@ struct checkdescriptor
     char const *const _m_name;
     char const *_m_description;
     bool _m_hidden;
+    std::vector<option_i *> _m_opts;
 
   public:
     create (char const *name = NULL);
@@ -72,6 +76,12 @@ struct checkdescriptor
       _m_hidden = true;
       return *this;
     }
+
+    create option (option_i &opt)
+    {
+      _m_opts.push_back (&opt);
+      return *this;
+    }
   };
 
   checkdescriptor (create const &c);
index 76ca27ae1f4ef38d5c684ea509b9c3b3d4a62e78..4561f8c8765f580bef3d5b7be334c812fb9b16e2 100644 (file)
@@ -26,7 +26,7 @@
 #include "checks.hh"
 #include "option.hh"
 
-static void_option show_progress
+static global_opt<void_option> show_progress
   ("Print out checks as they are performed, their context and result.",
    "show-progress");
 
index 83dafbb05c6a4faadc8defbb1fe80bf676ac2f25..5b054d44cba9f3ac0a5a2146e1b09322f905fe5d 100644 (file)
@@ -36,6 +36,24 @@ using elfutils::dwarf;
 
 namespace
 {
+
+#define DIE_OPTSTRING                                  \
+  "{single-addr|artificial|inlined|inlined_subroutine\
+|no-coverage|mutable|immutable}[,...]"
+
+  string_option opt_ignore
+  ("Skip certain DIEs.", DIE_OPTSTRING, "ignore");
+
+  string_option opt_dump
+  ("Dump certain DIEs.", DIE_OPTSTRING, "dump");
+
+  string_option opt_tabulation_rule
+  ("Rule for sorting results into buckets. start is either integer 0..100, \
+or special value 0.0 indicating cases with no coverage whatsoever \
+(i.e. not those that happen to round to 0%).",
+   "start[:step][,...]",
+   "tabulate");
+
   class locstats
     : public highlevel_check<locstats>
   {
@@ -44,6 +62,9 @@ namespace
       static checkdescriptor cd
        (checkdescriptor::create ("locstats")
         .groups ("@nodefault")
+        .option (opt_ignore)
+        .option (opt_dump)
+        .option (opt_tabulation_rule)
         .description (
 "Computes a location info coverage statistics.  Goes through the whole\n"
 "DIE graph, looking at each variable and formal parameter, and\n"
@@ -69,25 +90,6 @@ namespace
   TYPE(mutable)                        \
   TYPE(immutable)
 
-  string_option opt_ignore
-    ("Skip certain DIEs.",
-     "{single-addr|artificial|inlined|inlined_subroutine\
-|no-coverage|mutable|immutable}[,...]",
-     "locstats:ignore");
-
-  string_option opt_dump
-    ("Dump certain DIEs.",
-     "{single-addr|artificial|inlined|inlined_subroutine\
-|no-coverage|mutable|immutable}[,...]",
-     "locstats:dump");
-
-  string_option opt_tabulation_rule
-    ("Rule for sorting results into buckets. start is either integer 0..100, \
-or special value 0.0 indicating cases with no coverage whatsoever \
-(i.e. not those that happen to round to 0%).",
-     "start[:step][,...]",
-     "locstats:tabulate");
-
   struct tabrule
   {
     int start;
@@ -325,10 +327,10 @@ locstats::locstats (checkstack &stack, dwarflint &lint)
   for (int i = 0; i <= 100; ++i)
     tally[i] = 0;
 
-  tabrules_t tabrules (opt_tabulation_rule.seen ()
-                      ? opt_tabulation_rule.value () : "10:10");
-  die_type_matcher ignore (opt_ignore.seen () ? opt_ignore.value () : "");
-  die_type_matcher dump (opt_dump.seen () ? opt_dump.value () : "");
+  tabrules_t tabrules (/*opt_tabulation_rule.seen ()
+                        ? opt_tabulation_rule.value () :*/ "10:10");
+  die_type_matcher ignore (/*opt_ignore.seen () ? opt_ignore.value () :*/ "");
+  die_type_matcher dump (/*opt_dump.seen () ? opt_dump.value () :*/ "");
   std::bitset<dt__count> interested = ignore | dump;
   bool interested_mutability
     = interested.test (dt_mutable) || interested.test (dt_immutable);
index c2670c5332fe5751d2a2450ce2ceb58beb46495d..268b66f8d60ab9fd5fa5456840bb76e2184f6a7a 100644 (file)
@@ -46,7 +46,7 @@ struct message_criteria warning_criteria;
 struct message_criteria error_criteria;
 
 struct check_option_t
-  : public option_common
+  : public global_opt<option_common>
 {
   struct initial_checkrules
     : public checkrules
@@ -59,8 +59,8 @@ struct check_option_t
   } rules;
 
   check_option_t ()
-    : option_common ("Only run selected checks.",
-                    "[+-][@]name,...", "check", 0)
+    : global_opt<option_common> ("Only run selected checks.",
+                                "[+-][@]name,...", "check", 0)
   {}
 
   error_t parse_opt (char *arg, __attribute__ ((unused)) argp_state *state)
@@ -116,23 +116,29 @@ struct check_option_t
   }
 } check_option;
 
-void_option be_quiet ("Do not print anything if successful",
-                     "quiet", 'q');
+global_opt<void_option>
+  be_quiet ("Do not print anything if successful",
+           "quiet", 'q');
 
-string_option opt_list_checks ("List all the available checks.",
-                              "full", "list-checks", 0,
-                              OPTION_ARG_OPTIONAL);
+global_opt<string_option>
+  opt_list_checks ("List all the available checks.",
+                  "full", "list-checks", 0,
+                  OPTION_ARG_OPTIONAL);
 
 // xxx The following three should go away when we introduce the
 // message filtering.  Or should be preserved, but in a way that makes
 // more sense, right now they are simply a misnomer.
-void_option ignore_bloat ("Ignore messages related to bloat.", "ignore-bloat");
-void_option be_strict ("Be somewhat stricter.", "strict");
-void_option be_tolerant ("Be somewhat more tolerant.", "tolerant");
+global_opt<void_option>
+  ignore_bloat ("Ignore messages related to bloat.", "ignore-bloat");
+global_opt<void_option>
+  be_strict ("Be somewhat stricter.", "strict");
+global_opt<void_option>
+  be_tolerant ("Be somewhat more tolerant.", "tolerant");
 
 // xxx as soon as where is in c++, this can move there
-void_option opt_show_refs = void_option (
-"When validating .debug_loc and .debug_ranges, display information about \
+global_opt<void_option>
+  opt_show_refs("\
+When validating .debug_loc and .debug_ranges, display information about \
 the DIE referring to the entry in consideration", "ref");
 extern "C" bool show_refs () { return (bool)opt_show_refs; }
 
@@ -146,7 +152,7 @@ main (int argc, char *argv[])
   textdomain (PACKAGE_TARNAME);
 
   /* Parse and process arguments.  */
-  struct argp argp = options::registered ().build_argp ();
+  struct argp argp = global_opts.build_argp ();
   int remaining;
   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
 
index 6fadf9ab738ff471e97d771464220c67dd8432e5..8a127efa8a3800e595ffc7b218ca3224f7cafcf6 100644 (file)
@@ -32,8 +32,8 @@
 #include <cstring>
 #include <iostream>
 
-option_common *
-options::opt (int key) const
+option_i *
+options::find_opt (int key) const
 {
   const_iterator it = find (key);
   if (it == end ())
@@ -41,17 +41,17 @@ options::opt (int key) const
   return it->second;
 }
 
-option_common const *
+option_i const *
 options::getopt (int key) const
 {
-  return opt (key);
+  return find_opt (key);
 }
 
 error_t
 options::parse_opt (int key, char *arg,
                    __attribute__ ((unused)) argp_state *state)
 {
-  option_common *o = registered ().opt (key);
+  option_i *o = global_opts.find_opt (key); // XXX temporary
   if (o == NULL)
     return ARGP_ERR_UNKNOWN;
   return o->parse_opt (arg, state);
@@ -60,11 +60,20 @@ options::parse_opt (int key, char *arg,
 struct last_option
   : public argp_option
 {
-  last_option () {
+  last_option ()
+  {
     std::memset (this, 0, sizeof (*this));
   }
 };
 
+void
+options::add (option_i *opt)
+{
+  int key = opt->key ();
+  assert (getopt (key) == NULL);
+  (*this)[key] = opt;
+}
+
 /* Bug report address.  */
 const char *argp_program_bug_address = PACKAGE_BUGREPORT;
 
@@ -87,17 +96,10 @@ Pedantic checking of DWARF stored in ELF files.",
 }
 
 
-int option_common::_m_last_opt = 300;
-
-options &
-options::registered ()
-{
-  static options opts;
-  return opts;
-}
+int option_i::_m_last_opt = 300;
 
 int
-option_common::get_short_option (char opt_short)
+option_i::get_short_option (char opt_short)
 {
   if (opt_short)
     return opt_short;
@@ -127,7 +129,6 @@ option_common::option_common (char const *description,
                              arg_description, flags,
                              description, 0))
   , _m_seen (false)
-{
-  assert (options::registered ().getopt (_m_opt.key) == NULL);
-  options::registered ()[_m_opt.key] = this;
-}
+{}
+
+options global_opts;
index aa256d62e478d2fe1854a808582953efd7319fd5..4c79b58ba57bdd2a8e095872558ec084c86f2026 100644 (file)
 #include <map>
 #include <vector>
 #include <cassert>
-
 #include <iostream>
 
-class option_common;
+#include "option.ii"
 
 class options
-  : private std::map<int, option_common *>
+  : private std::map<int, option_i *>
 {
   friend class option_common;
   std::vector<argp_option> _m_opts;
 
-  option_common *opt (int key) const;
+  option_i *find_opt (int key) const;
   static error_t parse_opt (int key, char *arg, argp_state *state);
 
 public:
-  static options &registered ();
-  option_common const *getopt (int key) const;
+  option_i const *getopt (int key) const;
   argp build_argp ();
+  void add (option_i *opt);
 };
 
-class option_common
+class option_i // we cannot call it simply "option", this conflicts
+              // with another global declaration
 {
-  argp_option _m_opt;
-
+  // last allocated option unique identifier
   static int _m_last_opt;
+
+protected:
+  // Answer either opt_short argument if it's non-0.  Otherwise create
+  // new unique identifier.
   static int get_short_option (char opt_short);
 
+public:
+  virtual bool seen () const = 0;
+  virtual argp_option const &build_option () const = 0;
+  virtual error_t parse_opt (char *arg, argp_state *state) = 0;
+  virtual int key () const = 0;
+  virtual ~option_i () {}
+};
+
+class option_common
+  : public option_i
+{
+  argp_option _m_opt;
+
 protected:
   bool _m_seen;
 
@@ -66,12 +82,24 @@ protected:
                 char const *opt_long, char opt_short,
                 int flags = 0);
 
-public: // consumer interface
-  bool seen () const { return _m_seen; }
+public:
+  bool
+  seen () const
+  {
+    return _m_seen;
+  }
 
-public: // option handler interface
-  argp_option const &build_option () const { return _m_opt; }
-  virtual error_t parse_opt (char *arg, argp_state *state) = 0;
+  argp_option const &
+  build_option () const
+  {
+    return _m_opt;
+  }
+
+  int
+  key () const
+  {
+    return _m_opt.key;
+  }
 };
 
 template<class arg_type>
@@ -144,4 +172,18 @@ struct value_converter<std::string>
 typedef xoption<void> void_option;
 typedef xoption<std::string> string_option;
 
+extern options global_opts;
+
+template<class OPT>
+struct global_opt
+  : public OPT
+{
+  template<typename... Args>
+  global_opt (Args const&... args)
+    : OPT (args...)
+  {
+    global_opts.add (this);
+  }
+};
+
 #endif//DWARFLINT_OPTION_HH
diff --git a/dwarflint/option.ii b/dwarflint/option.ii
new file mode 100644 (file)
index 0000000..473d62a
--- /dev/null
@@ -0,0 +1 @@
+class option_i;