From: Petr Machata Date: Thu, 23 Sep 2010 16:00:36 +0000 (+0200) Subject: dwarflint: Don't assume all options are global X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=75c18f5e549e400cafca2b9137c83f7c6460cf02;p=thirdparty%2Felfutils.git dwarflint: Don't assume all options are global - 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. --- diff --git a/dwarflint/check_nodebug.cc b/dwarflint/check_nodebug.cc index 543daf5b1..03df11227 100644 --- a/dwarflint/check_nodebug.cc +++ b/dwarflint/check_nodebug.cc @@ -28,6 +28,10 @@ #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 { @@ -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 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) { diff --git a/dwarflint/checkdescriptor.hh b/dwarflint/checkdescriptor.hh index f5131b2a1..8845e162b 100644 --- a/dwarflint/checkdescriptor.hh +++ b/dwarflint/checkdescriptor.hh @@ -29,6 +29,9 @@ #include #include #include +#include + +#include "option.ii" struct checkgroups : public std::set @@ -52,6 +55,7 @@ struct checkdescriptor char const *const _m_name; char const *_m_description; bool _m_hidden; + std::vector _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); diff --git a/dwarflint/checks.cc b/dwarflint/checks.cc index 76ca27ae1..4561f8c87 100644 --- a/dwarflint/checks.cc +++ b/dwarflint/checks.cc @@ -26,7 +26,7 @@ #include "checks.hh" #include "option.hh" -static void_option show_progress +static global_opt show_progress ("Print out checks as they are performed, their context and result.", "show-progress"); diff --git a/dwarflint/locstats.cc b/dwarflint/locstats.cc index 83dafbb05..5b054d44c 100644 --- a/dwarflint/locstats.cc +++ b/dwarflint/locstats.cc @@ -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 { @@ -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 interested = ignore | dump; bool interested_mutability = interested.test (dt_mutable) || interested.test (dt_immutable); diff --git a/dwarflint/main.cc b/dwarflint/main.cc index c2670c533..268b66f8d 100644 --- a/dwarflint/main.cc +++ b/dwarflint/main.cc @@ -46,7 +46,7 @@ struct message_criteria warning_criteria; struct message_criteria error_criteria; struct check_option_t - : public option_common + : public global_opt { 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 ("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 + 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 + 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 + ignore_bloat ("Ignore messages related to bloat.", "ignore-bloat"); +global_opt + be_strict ("Be somewhat stricter.", "strict"); +global_opt + 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 + 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); diff --git a/dwarflint/option.cc b/dwarflint/option.cc index 6fadf9ab7..8a127efa8 100644 --- a/dwarflint/option.cc +++ b/dwarflint/option.cc @@ -32,8 +32,8 @@ #include #include -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; diff --git a/dwarflint/option.hh b/dwarflint/option.hh index aa256d62e..4c79b58ba 100644 --- a/dwarflint/option.hh +++ b/dwarflint/option.hh @@ -31,33 +31,49 @@ #include #include #include - #include -class option_common; +#include "option.ii" class options - : private std::map + : private std::map { friend class option_common; std::vector _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 ®istered (); - 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 @@ -144,4 +172,18 @@ struct value_converter typedef xoption void_option; typedef xoption string_option; +extern options global_opts; + +template +struct global_opt + : public OPT +{ + template + 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 index 000000000..473d62a84 --- /dev/null +++ b/dwarflint/option.ii @@ -0,0 +1 @@ +class option_i;