]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
dwarflint: Make it possible to define relevant options directly at checks
authorPetr Machata <pmachata@redhat.com>
Tue, 14 Sep 2010 21:05:58 +0000 (23:05 +0200)
committerPetr Machata <pmachata@redhat.com>
Tue, 14 Sep 2010 21:05:58 +0000 (23:05 +0200)
18 files changed:
dwarflint/Makefile.am
dwarflint/TODO
dwarflint/check_debug_info.cc
dwarflint/check_debug_loc_range.cc
dwarflint/check_matching_ranges.cc
dwarflint/check_nodebug.cc
dwarflint/checks.cc
dwarflint/dwarflint.cc
dwarflint/highlevel_check.hh
dwarflint/low.c
dwarflint/main.cc
dwarflint/main.hh [moved from dwarflint/options.h with 68% similarity]
dwarflint/option.cc [new file with mode: 0644]
dwarflint/option.hh [new file with mode: 0644]
dwarflint/options.cc [deleted file]
dwarflint/sections.cc
dwarflint/tests/run-nodebug.sh
dwarflint/where.c

index a44751f79690aef56a5c549f85a14fa5e5f8b450..faaedb629be5f703585696523d0e58c5a0f1b368 100644 (file)
@@ -49,7 +49,7 @@ dwarflint_SOURCES = \
        messages.cc messages.h \
        section_id.cc section_id.h \
        where.c where.h \
-       options.cc options.h \
+       option.cc option.hh \
        addr-record.cc addr-record.h \
        reloc.cc reloc.h \
        tables.cc tables.hh tables.h \
index e47c61220656ffd35eace4684fbe4a5df0caae37..99069b67690ab4d52a945cfc09cb211165e7d43d 100644 (file)
   there to be frequent additions to this "quirks table", so it should
   be fairly easy to extend this.
 
+  The current option --tolerant will go away when this is implemented.
+  I don't think it even works anyway.
+
 * multi-file mode
 
   While dwarflint manages checking several files (meaning you can put
index 8e8a36f0d9aae9b110203823587cee031bf5a600..d99fdadb29a0b3b43d55d4782e3d38c317f2f1ab 100644 (file)
@@ -1,6 +1,6 @@
 /* Routines related to .debug_info.
 
-   Copyright (C) 2009 Red Hat, Inc.
+   Copyright (C) 2009, 2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -34,7 +34,7 @@
 
 #include "messages.h"
 #include "pri.hh"
-#include "options.h"
+#include "option.hh"
 #include "sections.hh"
 #include "check_debug_loc_range.hh"
 #include "check_debug_abbrev.hh"
@@ -93,6 +93,10 @@ check_debug_info::descriptor ()
   return &cd;
 }
 
+static void_option
+  dump_die_offsets ("Dump DIE offsets to stderr as the tree is iterated.",
+                   "dump-offsets");
+
 namespace
 {
   bool
index d664122e60df62ff7099d895fb8dbf4d741d42dc..5a3f12689a5f0ae926c644f7f87ba00c4641553b 100644 (file)
@@ -1,6 +1,6 @@
 /* Routines related to .debug_loc and .debug_range.
 
-   Copyright (C) 2009 Red Hat, Inc.
+   Copyright (C) 2009, 2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
 #include "../libdw/dwarf.h"
 
 #include "low.h"
-#include "options.h"
 #include "check_debug_loc_range.hh"
 #include "check_debug_info.hh"
 #include "sections.hh"
 #include "../src/dwarf-opcodes.h"
 #include "pri.hh"
 
+bool do_range_coverage = false; // currently no option
+
 checkdescriptor const *
 check_debug_ranges::descriptor ()
 {
index 0afdc0788083116dfbfb8fc5b4d012bd31389e45..f9c0596206ea70c5188867783cc980506d1cee7c 100644 (file)
@@ -59,9 +59,6 @@ check_matching_ranges::check_matching_ranges (checkstack &stack,
                                              dwarflint &lint)
   : highlevel_check<check_matching_ranges> (stack, lint)
 {
-  if (be_tolerant || be_gnu)
-    throw check_base::unscheduled ();
-
   lint.check<check_debug_ranges> (stack);
   lint.check<check_debug_aranges> (stack);
 
index e26d3dfbf5dea7dac9b4a5881b23d67440f390d7..fe9fbb0e38094b36c577db837cda98ed993488f5 100644 (file)
@@ -24,9 +24,9 @@
    <http://www.openinventionnetwork.com>.  */
 
 #include "checks.hh"
-#include "options.h"
 #include "messages.h"
 #include "sections.hh"
+#include "option.hh"
 
 class check_nodebug
   : public check<check_nodebug>
@@ -62,10 +62,13 @@ 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)
 {
-  if (tolerate_nodebug)
+  if (ignore_missing)
     return;
 
   // We demand .debug_info and .debug_abbrev, the rest is optional.
index 16b7abe13f22b25a7dbcba5b8c8ddba2a19349c8..76ca27ae1f4ef38d5c684ea509b9c3b3d4a62e78 100644 (file)
    <http://www.openinventionnetwork.com>.  */
 
 #include "checks.hh"
-#include "options.h"
+#include "option.hh"
+
+static void_option show_progress
+  ("Print out checks as they are performed, their context and result.",
+   "show-progress");
 
 reporter::reporter (checkstack const &s, checkdescriptor const &a_cd)
   : stack (s)
@@ -36,7 +40,7 @@ reporter::reporter (checkstack const &s, checkdescriptor const &a_cd)
 void
 reporter::operator () (char const *what, bool ext)
 {
-  if (!be_verbose)
+  if (!show_progress)
     return;
 
   if (false)
index bbd17b5fae33bfb421de46e9c2112eb58d753841..9c21dbcc0a3a7c730f702e2c86bbec65d1c94ab6 100644 (file)
@@ -1,5 +1,5 @@
 /* Dwarflint check scheduler.
-   Copyright (C) 2008,2009 Red Hat, Inc.
+   Copyright (C) 2008,2009,2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -26,7 +26,7 @@
 #include "dwarflint.hh"
 #include "messages.h"
 #include "checks.hh"
-#include "options.h"
+#include "main.hh"
 
 #include <fcntl.h>
 #include <cstring>
@@ -122,6 +122,7 @@ namespace
 void
 dwarflint::check_registrar::list_checks () const
 {
+  bool be_verbose = opt_list_checks.value () == "full";
   typedef std::set<checkdescriptor const *> descset;
   descset descriptors;
   for (std::vector <item *>::const_iterator it = _m_items.begin ();
@@ -160,8 +161,9 @@ dwarflint::check_registrar::list_checks () const
        }
     }
   if (!be_verbose)
-    std::cout << "Use --list-checks --verbose "
-      "to get detailed description of each check." << std::endl;
+    std::cout
+      << "Use --list-checks=full to get more detailed description."
+      << std::endl;
 }
 
 namespace
index 5505ae1524a0487501c19cdd750699280cac2d91..7fb7b128afca4f56e36e3eedf60d0c3ce7e567a0 100644 (file)
@@ -1,5 +1,5 @@
 /* Pedantic checking of DWARF files.
-   Copyright (C) 2009 Red Hat, Inc.
+   Copyright (C) 2009, 2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -31,7 +31,6 @@
 #endif
 
 #include "checks.hh"
-#include "options.h"
 #include "c++/dwarf"
 #include "../libdwfl/libdwfl.h"
 
@@ -69,10 +68,7 @@ public:
   explicit highlevel_check (checkstack &stack, dwarflint &lint)
     : _m_loader (lint.check (stack, _m_loader))
     , dw (_m_loader->dw)
-  {
-    if (!do_high_level)
-      throw check_base::unscheduled ();
-  }
+  {}
 };
 
 template <class T>
index d5950e149e062e734806a9af8fdf913cd5d1678b..9872d4aeff0cca5b50d522e97ffcdbf7b9b3e143 100644 (file)
@@ -1,5 +1,5 @@
 /* Pedantic checking of DWARF files
-   Copyright (C) 2008,2009 Red Hat, Inc.
+   Copyright (C) 2008,2009,2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -46,7 +46,6 @@
 #include "../src/dwarfstrings.h"
 #include "low.h"
 #include "readctx.h"
-#include "options.h"
 #include "tables.h"
 
 #define PRI_CU "CU 0x%" PRIx64
@@ -331,8 +330,7 @@ check_aranges_structural (struct elf_file *file,
 
       inline void aranges_coverage_add (uint64_t begin, uint64_t length)
       {
-       if (coverage_is_overlap (aranges_coverage, begin, length)
-           && !be_gnu && !be_tolerant)
+       if (coverage_is_overlap (aranges_coverage, begin, length))
          {
            char buf[128];
            /* Not a show stopper, this shouldn't derail high-level.  */
index 05070d23ac046f627f949ec11ef46e2d3fa7c394..61a080bef574e7cf780044d91df780431ab9629c 100644 (file)
@@ -1,5 +1,5 @@
 /* Main entry point for dwarflint, a pedantic checker for DWARF files.
-   Copyright (C) 2008,2009 Red Hat, Inc.
+   Copyright (C) 2008,2009,2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -26,7 +26,6 @@
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
-#include <argp.h>
 #include <libintl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sstream>
 
 #include "low.h"
-#include "options.h"
 #include "dwarflint.hh"
 #include "readctx.h"
 #include "checks.hh"
-
-/* Bug report address.  */
-const char *argp_program_bug_address = PACKAGE_BUGREPORT;
-
-#define ARGP_strict    300
-#define ARGP_gnu       301
-#define ARGP_tolerant  302
-#define ARGP_ref        303
-#define ARGP_nohl       304
-#define ARGP_dump_off   305
-#define ARGP_check      306
-#define ARGP_list_checks 307
-
-/* Definitions of arguments for argp functions.  */
-static const struct argp_option options[] =
-{
-  { "strict", ARGP_strict, NULL, 0,
-    N_("Be extremely strict, flag level 2 features."), 0 },
-  { "quiet", 'q', NULL, 0, N_("Do not print anything if successful"), 0 },
-  { "ignore-missing", 'i', NULL, 0,
-    N_("Don't complain if files have no DWARF at all"), 0 },
-  { "gnu", ARGP_gnu, NULL, 0,
-    N_("Binary has been created with GNU toolchain and is therefore known to be \
-broken in certain ways"), 0 },
-  { "tolerant", ARGP_tolerant, NULL, 0,
-    N_("Don't output certain common error messages"), 0 },
-  { "ref", ARGP_ref, NULL, 0,
-    N_("When validating .debug_loc and .debug_ranges, display information about \
-the DIE referring to the entry in consideration"), 0 },
-  { "nohl", ARGP_nohl, NULL, 0,
-    N_("Don't run high-level tests"), 0 },
-  { "verbose", 'v', NULL, 0,
-    N_("Be verbose"), 0 },
-  { "dump-offsets", ARGP_dump_off, NULL, 0,
-    N_("Dump DIE offsets to stderr as the tree is iterated."), 0 },
-  { "check", ARGP_check, "[+-][@]name,...", 0,
-    N_("Only run selected checks."), 0 },
-  { "list-checks", ARGP_list_checks, NULL, 0,
-    N_("List all the available checks."), 0 },
-  { NULL, 0, NULL, 0, NULL, 0 }
-};
-
-/* Short description of program.  */
-static const char doc[] = N_("\
-Pedantic checking of DWARF stored in ELF files.");
-
-/* Strings for arguments in help texts.  */
-static const char args_doc[] = N_("FILE...");
+#include "option.hh"
 
 /* Messages that are accepted (and made into warning).  */
 struct message_criteria warning_criteria;
@@ -94,142 +45,94 @@ struct message_criteria warning_criteria;
 /* Accepted (warning) messages, that are turned into errors.  */
 struct message_criteria error_criteria;
 
-/* Whether to list available checks and exit.  */
-static bool just_list_checks = false;
-
-
-static error_t parse_opt (int key, char *arg, struct argp_state *state);
-
-/* Data structure to communicate with argp functions.  */
-static struct argp argp =
-{
-  options, parse_opt, args_doc, doc, NULL, NULL, NULL
-};
-
-struct initial_check_rules
-  : public check_rules
-{
-  initial_check_rules () {
-    push_back (check_rule ("@all", check_rule::request));
-    push_back (check_rule ("@nodefault", check_rule::forbid));
-  }
-} rules;
-
-/* Handle program arguments.  */
-static error_t
-parse_opt (int key, char *arg __attribute__ ((unused)),
-          struct argp_state *state __attribute__ ((unused)))
+struct check_option_t
+  : public option_common
 {
-  switch (key)
-    {
-    case ARGP_strict:
-      be_strict = true;
-      break;
-
-    case ARGP_gnu:
-      be_gnu = true;
-      break;
-
-    case ARGP_tolerant:
-      be_tolerant = true;
-      break;
-
-    case ARGP_ref:
-      show_refs = true;
-      break;
+  struct initial_check_rules
+    : public check_rules
+  {
+    initial_check_rules () {
+      push_back (check_rule ("@all", check_rule::request));
+      push_back (check_rule ("@nodefault", check_rule::forbid));
+    }
+  } rules;
 
-    case ARGP_nohl:
-      do_high_level = false;
-      break;
+  check_option_t ()
+    : option_common ("Only run selected checks.",
+                    "[+-][@]name,...", "check", 0)
+  {}
 
-    case ARGP_dump_off:
-      dump_die_offsets = true;
-      break;
+  error_t parse_opt (char *arg, __attribute__ ((unused)) argp_state *state)
+  {
+    static bool first = true;
+    std::stringstream ss (arg);
+    std::string item;
 
-    case ARGP_check:
+    while (std::getline (ss, item, ','))
       {
-       static bool first = true;
-       std::stringstream ss (arg);
-       std::string item;
+       if (item.empty ())
+         continue;
 
-       while (std::getline (ss, item, ','))
+       enum {
+         forbid,
+         request,
+         replace
+       } act;
+
+       // If the first rule has no operator, we assume the user
+       // wants to replace the implicit set of checks.
+       if (first)
          {
-           if (item.empty ())
-             continue;
-
-           enum {
-             forbid,
-             request,
-             replace
-           } act;
-
-           // If the first rule has no operator, we assume the user
-           // wants to replace the implicit set of checks.
-           if (first)
-             {
-               act = replace;
-               first = false;
-             }
-           else
-             // Otherwise the rules are implicitly requesting, even
-             // without the '+' operator.
-             act = request;
-
-           bool minus = item[0] == '-';
-           bool plus = item[0] == '+';
-           if (plus || minus)
-             item = item.substr (1);
-           if (plus)
-             act = request;
-           if (minus)
-             act = forbid;
-
-           if (act == replace)
-             {
-               rules.clear ();
-               act = request;
-             }
-
-           check_rule::action_t action
-             = act == request ? check_rule::request : check_rule::forbid;
-           rules.push_back (check_rule (item, action));
+           act = replace;
+           first = false;
+         }
+       else
+         // Otherwise the rules are implicitly requesting, even
+         // without the '+' operator.
+         act = request;
+
+       bool minus = item[0] == '-';
+       bool plus = item[0] == '+';
+       if (plus || minus)
+         item = item.substr (1);
+       if (plus)
+         act = request;
+       if (minus)
+         act = forbid;
+
+       if (act == replace)
+         {
+           rules.clear ();
+           act = request;
          }
-      }
-      break;
-
-    case ARGP_list_checks:
-      just_list_checks = true;
-      break;
 
-    case 'i':
-      tolerate_nodebug = true;
-      break;
+       check_rule::action_t action
+         = act == request ? check_rule::request : check_rule::forbid;
+       rules.push_back (check_rule (item, action));
+      }
+    return 0;
+  }
+} check_option;
 
-    case 'q':
-      be_quiet = true;
-      be_verbose = false;
-      break;
+void_option be_quiet ("Do not print anything if successful",
+                     "quiet", 'q');
 
-    case 'v':
-      be_quiet = false;
-      be_verbose = true;
-      break;
+string_option opt_list_checks ("List all the available checks.",
+                              "full", "list-checks", 0,
+                              OPTION_ARG_OPTIONAL);
 
-    case ARGP_KEY_NO_ARGS:
-      if (!just_list_checks)
-       {
-         fputs (gettext ("Missing file name.\n"), stderr);
-         argp_help (&argp, stderr, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
-                    program_invocation_short_name);
-         exit (1);
-       }
-      break;
+// 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");
 
-    default:
-      return ARGP_ERR_UNKNOWN;
-    }
-  return 0;
-}
+// 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 \
+the DIE referring to the entry in consideration", "ref");
+extern "C" bool show_refs () { return (bool)opt_show_refs; }
 
 int
 main (int argc, char *argv[])
@@ -241,14 +144,22 @@ main (int argc, char *argv[])
   textdomain (PACKAGE_TARNAME);
 
   /* Parse and process arguments.  */
+  struct argp argp = options::registered ().build_argp ();
   int remaining;
   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
 
-  if (just_list_checks)
+  if (opt_list_checks.seen ())
     {
       dwarflint::check_registrar::inst ()->list_checks ();
       std::exit (0);
     }
+  else if (remaining == argc)
+    {
+      fputs (gettext ("Missing file name.\n"), stderr);
+      argp_help (&argp, stderr, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
+                program_invocation_short_name);
+      std::exit (1);
+    }
 
   /* Initialize warning & error criteria.  */
   warning_criteria |= message_term (mc_none, mc_none);
@@ -257,10 +168,7 @@ main (int argc, char *argv[])
   error_criteria |= message_term (mc_error, mc_none);
 
   /* Configure warning & error criteria according to configuration.  */
-  if (tolerate_nodebug)
-    warning_criteria &= message_term (mc_none, mc_elf);
-
-  if (be_gnu)
+  if (ignore_bloat)
     warning_criteria &= message_term (mc_none, mc_acc_bloat);
 
   if (!be_strict)
@@ -277,7 +185,7 @@ main (int argc, char *argv[])
       warning_criteria &= message_term (mc_none, mc_ranges);
     }
 
-  if (be_verbose)
+  if (false) // for debugging
     {
       std::cout << "warning criteria: " << warning_criteria.str () << std::endl;
       std::cout << "error criteria:   " << error_criteria.str () << std::endl;
@@ -297,7 +205,7 @@ main (int argc, char *argv[])
          unsigned int prev_error_count = error_count;
          if (!only_one)
            std::cout << std::endl << fname << ":" << std::endl;
-         dwarflint lint (fname, rules);
+         dwarflint lint (fname, check_option.rules);
 
          if (prev_error_count == error_count && !be_quiet)
            puts (gettext ("No errors"));
similarity index 68%
rename from dwarflint/options.h
rename to dwarflint/main.hh
index 157d56f55e608a6771a92603ce8599e18ef779b8..0651895d7ae9248f59b33b12efc7c8c30cade75c 100644 (file)
@@ -1,5 +1,5 @@
-/*
-   Copyright (C) 2008,2009 Red Hat, Inc.
+/* Pedantic checker for DWARF files
+   Copyright (C) 2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
    Network licensing program, please visit www.openinventionnetwork.com
    <http://www.openinventionnetwork.com>.  */
 
-#ifdef __cplusplus
-extern "C"
-{
-#else
-#include <stdbool.h>
-#endif
+#ifndef DWARFLINT_MAIN_HH
+#define DWARFLINT_MAIN_HH
 
-  /* Whole-program options.  */
-  extern bool tolerate_nodebug;
-  extern bool be_quiet; /* -q */
-  extern bool be_verbose; /* -v */
-  extern bool be_strict; /* --strict */
-  extern bool be_gnu; /* --gnu */
-  extern bool be_tolerant; /* --tolerant */
-  extern bool show_refs; /* --ref */
-  extern bool do_high_level; /* ! --nohl */
-  extern bool dump_die_offsets; /* --dump-offsets */
+#include "option.hh"
+extern string_option opt_list_checks;
 
-  extern bool do_range_coverage;
-
-#ifdef __cplusplus
-}
-#endif
+#endif//DWARFLINT_MAIN_HH
diff --git a/dwarflint/option.cc b/dwarflint/option.cc
new file mode 100644 (file)
index 0000000..6fadf9a
--- /dev/null
@@ -0,0 +1,133 @@
+/* Pedantic checking of DWARF files
+   Copyright (C) 2009,2010 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+
+   Red Hat elfutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by the
+   Free Software Foundation; version 2 of the License.
+
+   Red Hat elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "option.hh"
+#include <cassert>
+#include <cstring>
+#include <iostream>
+
+option_common *
+options::opt (int key) const
+{
+  const_iterator it = find (key);
+  if (it == end ())
+    return NULL;
+  return it->second;
+}
+
+option_common const *
+options::getopt (int key) const
+{
+  return opt (key);
+}
+
+error_t
+options::parse_opt (int key, char *arg,
+                   __attribute__ ((unused)) argp_state *state)
+{
+  option_common *o = registered ().opt (key);
+  if (o == NULL)
+    return ARGP_ERR_UNKNOWN;
+  return o->parse_opt (arg, state);
+}
+
+struct last_option
+  : public argp_option
+{
+  last_option () {
+    std::memset (this, 0, sizeof (*this));
+  }
+};
+
+/* Bug report address.  */
+const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+
+argp
+options::build_argp ()
+{
+  _m_opts.clear ();
+  for (const_iterator it = begin (); it != end (); ++it)
+    _m_opts.push_back (it->second->build_option ());
+  _m_opts.push_back (last_option ());
+  argp a = {
+    &_m_opts.front (),
+    &options::parse_opt,
+    "FILE...",
+    "\
+Pedantic checking of DWARF stored in ELF files.",
+    NULL, NULL, NULL
+  };
+  return a;
+}
+
+
+int option_common::_m_last_opt = 300;
+
+options &
+options::registered ()
+{
+  static options opts;
+  return opts;
+}
+
+int
+option_common::get_short_option (char opt_short)
+{
+  if (opt_short)
+    return opt_short;
+  return _m_last_opt++;
+}
+
+namespace
+{
+  argp_option argp_option_ctor (char const *name, int key,
+                               char const *arg, int flags,
+                               char const *doc, int group)
+  {
+    assert (name != NULL);
+    assert (doc != NULL);
+    argp_option opt = {
+      name, key, arg, flags, doc, group
+    };
+    return opt;
+  }
+}
+
+option_common::option_common (char const *description,
+                             char const *arg_description,
+                             char const *opt_long, char opt_short,
+                             int flags)
+  : _m_opt (argp_option_ctor (opt_long, get_short_option (opt_short),
+                             arg_description, flags,
+                             description, 0))
+  , _m_seen (false)
+{
+  assert (options::registered ().getopt (_m_opt.key) == NULL);
+  options::registered ()[_m_opt.key] = this;
+}
diff --git a/dwarflint/option.hh b/dwarflint/option.hh
new file mode 100644 (file)
index 0000000..aa256d6
--- /dev/null
@@ -0,0 +1,147 @@
+/* Pedantic checker for DWARF files
+   Copyright (C) 2010 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+
+   Red Hat elfutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by the
+   Free Software Foundation; version 2 of the License.
+
+   Red Hat elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifndef DWARFLINT_OPTION_HH
+#define DWARFLINT_OPTION_HH
+
+#include <string>
+#include <argp.h>
+#include <map>
+#include <vector>
+#include <cassert>
+
+#include <iostream>
+
+class option_common;
+
+class options
+  : private std::map<int, option_common *>
+{
+  friend class option_common;
+  std::vector<argp_option> _m_opts;
+
+  option_common *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;
+  argp build_argp ();
+};
+
+class option_common
+{
+  argp_option _m_opt;
+
+  static int _m_last_opt;
+  static int get_short_option (char opt_short);
+
+protected:
+  bool _m_seen;
+
+  option_common (char const *description,
+                char const *arg_description,
+                char const *opt_long, char opt_short,
+                int flags = 0);
+
+public: // consumer interface
+  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;
+};
+
+template<class arg_type>
+class value_converter;
+
+template<class arg_type>
+class xoption
+  : public option_common
+{
+  arg_type _m_arg;
+
+public:
+  xoption (char const *description,
+          char const *arg_description,
+          char const *opt_long, char opt_short = 0,
+          int flags = 0)
+    : option_common (description, arg_description, opt_long, opt_short, flags)
+  {
+  }
+
+  arg_type const &value () const
+  {
+    return _m_arg;
+  }
+
+  error_t parse_opt (char *arg, __attribute__ ((unused)) argp_state *state)
+  {
+    _m_seen = true;
+    _m_arg = value_converter<arg_type>::convert (arg);
+    return 0;
+  }
+};
+
+template<>
+class xoption<void>
+  : public option_common
+{
+public:
+  xoption (char const *description,
+          char const *opt_long, char opt_short = 0, int flags = 0)
+    : option_common (description, NULL, opt_long, opt_short, flags)
+  {
+  }
+
+  error_t parse_opt (char *arg, __attribute__ ((unused)) argp_state *state)
+  {
+    assert (arg == NULL);
+    _m_seen = true;
+    return 0;
+  }
+
+  // This shouldn't be promoted to option_common, as
+  // e.g. xoption<bool> will naturally have a different
+  // implementation.
+  operator bool () { return seen (); }
+};
+
+template<>
+struct value_converter<std::string>
+{
+  static std::string convert (char const *arg)
+  {
+    if (arg == NULL)
+      return "";
+    else
+      return arg;
+  }
+};
+
+typedef xoption<void> void_option;
+typedef xoption<std::string> string_option;
+
+#endif//DWARFLINT_OPTION_HH
diff --git a/dwarflint/options.cc b/dwarflint/options.cc
deleted file mode 100644 (file)
index ff3b5e2..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-   Copyright (C) 2008,2009 Red Hat, Inc.
-   This file is part of Red Hat elfutils.
-
-   Red Hat elfutils is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by the
-   Free Software Foundation; version 2 of the License.
-
-   Red Hat elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License along
-   with Red Hat elfutils; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
-
-   Red Hat elfutils is an included package of the Open Invention Network.
-   An included package of the Open Invention Network is a package for which
-   Open Invention Network licensees cross-license their patents.  No patent
-   license is granted, either expressly or impliedly, by designation as an
-   included package.  Should you wish to participate in the Open Invention
-   Network licensing program, please visit www.openinventionnetwork.com
-   <http://www.openinventionnetwork.com>.  */
-
-#include "options.h"
-
-/* If true, we accept silently files without debuginfo.  */
-bool tolerate_nodebug = false;
-
-/* True if no message is to be printed if the run is succesful.  */
-bool be_quiet = false; /* -q */
-bool be_verbose = false; /* -v */
-bool be_strict = false; /* --strict */
-bool be_gnu = false; /* --gnu */
-bool be_tolerant = false; /* --tolerant */
-bool show_refs = false; /* --ref */
-bool do_high_level = true; /* ! --nohl */
-bool dump_die_offsets = false; /* --dump-offsets */
-
-/* True if coverage analysis of .debug_ranges vs. ELF sections should
-   be done.  */
-bool do_range_coverage = false; // currently no option
index a8932334a5be8f1b8621f462a81284f753e08403..1e07987eeafa6aa0068e106ef4d5086a8f3c9e77 100644 (file)
@@ -1,5 +1,5 @@
 /* Low-level section handling.
-   Copyright (C) 2009 Red Hat, Inc.
+   Copyright (C) 2009, 2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -34,7 +34,6 @@
 #include "sections.hh"
 #include "messages.h"
 #include "pri.hh"
-#include "options.h"
 
 checkdescriptor const *
 load_sections::descriptor ()
index f853e13c2fcf8f7711f74a216d0bb73ac2a8d475..a595433c0c2943378b975af058731d712ebfaa4c 100755 (executable)
@@ -33,3 +33,10 @@ testrun_compare ./dwarflint nodebug <<EOF
 error: .debug_abbrev: data not found.
 error: .debug_info: data not found.
 EOF
+
+testrun_compare ./dwarflint -i nodebug <<EOF
+No errors
+EOF
+
+testrun_compare ./dwarflint -q -i nodebug <<EOF
+EOF
index 3e28456561acf5f69897f0849bf7583907568749..ca9f0cd5694e4fda4216074ced94f9968afb314f 100644 (file)
@@ -24,7 +24,6 @@
    <http://www.openinventionnetwork.com>.  */
 
 #include "where.h"
-#include "options.h"
 
 #include <inttypes.h>
 #include <assert.h>
@@ -32,6 +31,8 @@
 #include <stdio.h>
 #include <string.h>
 
+extern bool show_refs (void);
+
 const char *
 where_fmt (const struct where *wh, char *ptr)
 {
@@ -189,7 +190,7 @@ where_fmt (const struct where *wh, char *ptr)
 void
 where_fmt_chain (const struct where *wh, const char *severity)
 {
-  if (wh != NULL && show_refs)
+  if (wh != NULL && show_refs ())
     for (struct where const *it = wh->next; it != NULL; it = it->next)
       printf ("%s: %s: caused by this reference.\n",
              severity, where_fmt (it, NULL));