Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r53586 - in trunk: boost/wave libs/wave tools/wave
From: hartmut.kaiser_at_[hidden]
Date: 2009-06-02 21:06:43


Author: hkaiser
Date: 2009-06-02 21:06:42 EDT (Tue, 02 Jun 2009)
New Revision: 53586
URL: http://svn.boost.org/trac/boost/changeset/53586

Log:
Wave: added --macrocounts/-c command line option to wave driver tool allowing to collect macro invocation counts
Text files modified:
   trunk/boost/wave/cpp_context.hpp | 1
   trunk/libs/wave/ChangeLog | 9 ++
   trunk/tools/wave/cpp.cpp | 75 +++++++++++++++++++----
   trunk/tools/wave/cpp_version.hpp | 8 +-
   trunk/tools/wave/trace_macro_expansion.hpp | 124 +++++++++++++++++++++++++++------------
   5 files changed, 158 insertions(+), 59 deletions(-)

Modified: trunk/boost/wave/cpp_context.hpp
==============================================================================
--- trunk/boost/wave/cpp_context.hpp (original)
+++ trunk/boost/wave/cpp_context.hpp 2009-06-02 21:06:42 EDT (Tue, 02 Jun 2009)
@@ -292,6 +292,7 @@
 
 // access the policies
     hook_policy_type &get_hooks() { return hooks; }
+ hook_policy_type const &get_hooks() const { return hooks; }
 
 // return type of actually used context type (might be the derived type)
     actual_context_type& derived()

Modified: trunk/libs/wave/ChangeLog
==============================================================================
--- trunk/libs/wave/ChangeLog (original)
+++ trunk/libs/wave/ChangeLog 2009-06-02 21:06:42 EDT (Tue, 02 Jun 2009)
@@ -32,10 +32,17 @@
   introduced in V2.0 broke this part.
 - Fixed a long standing race condition inhibiting to use Wave in multi threaded
   environments.
-- Removed old code related to pre Boost V1.31 (V1 of iterator library)
+- Removed old code related to pre Boost V1.31 (related to V1 of iterator
+ library).
 - Incorporated the changes from latest version of the flex_string class (#2946).
 - Fixed another race condition triggering problems using Wave in multi-threaded
   environments.
+- Added a new commandline option --macrocounts/-c to the Wave driver application
+ which lists all macro invocation counts an optionally specified file (default
+ is cout).
+
+- Implemented an additional command line option for the wave driver application
+ allowing to
 
 Boost V1.39.0
 - V2.0.1

Modified: trunk/tools/wave/cpp.cpp
==============================================================================
--- trunk/tools/wave/cpp.cpp (original)
+++ trunk/tools/wave/cpp.cpp 2009-06-02 21:06:42 EDT (Tue, 02 Jun 2009)
@@ -599,6 +599,42 @@
         return true;
     }
 
+ ///////////////////////////////////////////////////////////////////////////
+ // list macro invocation counts
+ bool list_macro_counts(context_type const& ctx, std::string filename)
+ {
+ // open file for macro invocation count listing
+ std::ofstream macrocounts_out;
+ fs::path macrocounts_file (boost::wave::util::create_path(filename));
+
+ if (macrocounts_file != "-") {
+ macrocounts_file = fs::complete(macrocounts_file);
+ fs::create_directories(boost::wave::util::branch_path(macrocounts_file));
+ macrocounts_out.open(macrocounts_file.string().c_str());
+ if (!macrocounts_out.is_open()) {
+ cerr << "wave: could not open file for macro invocation count listing: "
+ << macrocounts_file.string() << endl;
+ return false;
+ }
+ }
+ else {
+ macrocounts_out.copyfmt(cout);
+ macrocounts_out.clear(cout.rdstate());
+ static_cast<std::basic_ios<char> &>(macrocounts_out).rdbuf(cout.rdbuf());
+ }
+
+ // list all expanded macro names and their counts in alphabetical order
+ std::map<std::string, std::size_t> const& counts =
+ ctx.get_hooks().get_macro_counts();
+
+ typedef std::map<std::string, std::size_t>::const_iterator iterator;
+ iterator end = counts.end();
+ for (iterator it = counts.begin(); it != end; ++it)
+ macrocounts_out << (*it).first << "," << (*it).second << std::endl;
+
+ return true;
+ }
+
 ///////////////////////////////////////////////////////////////////////////////
 } // anonymous namespace
 
@@ -636,14 +672,14 @@
     std::ofstream output;
     std::ofstream traceout;
     std::ofstream includelistout;
-
+
     trace_flags enable_trace = trace_nothing;
-
+
         if (vm.count("traceto")) {
         // try to open the file, where to put the trace output
         fs::path trace_file (boost::wave::util::create_path(
             vm["traceto"].as<std::string>()));
-
+
             if (trace_file != "-") {
                 fs::create_directories(boost::wave::util::branch_path(trace_file));
                 traceout.open(trace_file.string().c_str());
@@ -667,7 +703,7 @@
         // try to open the file, where to put the include list
         fs::path includes_file(boost::wave::util::create_path(
             vm["listincludes"].as<std::string>()));
-
+
             if (includes_file != "-") {
                 fs::create_directories(boost::wave::util::branch_path(includes_file));
                 includelistout.open(includes_file.string().c_str());
@@ -677,7 +713,7 @@
                     return -1;
                 }
             }
- enable_trace = trace_includes;
+ enable_trace = trace_flags(enable_trace | trace_includes);
         }
         if ((enable_trace & trace_includes) && !includelistout.is_open()) {
         // by default list included names to std::cout
@@ -686,14 +722,14 @@
             static_cast<std::basic_ios<char> &>(includelistout).
                 rdbuf(cout.rdbuf());
         }
-
+
     // enable preserving comments mode
     bool preserve_comments = false;
     bool preserve_whitespace = false;
-
+
         if (vm.count("preserve")) {
         int preserve = vm["preserve"].as<int>();
-
+
             switch(preserve) {
             case 0: break;
             case 2:
@@ -702,7 +738,7 @@
             case 1:
                 preserve_comments = true;
                 break;
-
+
             default:
                 cerr << "wave: bogus preserve whitespace option value: "
                      << preserve << ", should be 0, 1, or 2" << endl;
@@ -713,7 +749,7 @@
     // Since the #pragma wave system() directive may cause a potential security
     // threat, it has to be enabled explicitly by --extended or -x
     bool enable_system_command = false;
-
+
         if (vm.count("extended"))
             enable_system_command = true;
 
@@ -725,6 +761,11 @@
     trace_macro_expansion<token_type> hooks(preserve_whitespace,
         output, traceout, includelistout, enable_trace, enable_system_command,
         allow_output, default_outfile);
+
+ // enable macro invocation count, if appropriate
+ if (vm.count("macrocounts"))
+ hooks.enable_macro_counting();
+
     context_type ctx (instring.begin(), instring.end(), file_name.c_str(), hooks);
 
 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
@@ -1046,6 +1087,10 @@
             if (!list_macro_names(ctx, vm["macronames"].as<std::string>()))
                 return -1;
         }
+ if (vm.count("macrocounts")) {
+ if (!list_macro_counts(ctx, vm["macrocounts"].as<std::string>()))
+ return -1;
+ }
     }
     catch (boost::wave::cpp_exception const &e) {
     // some preprocessing error
@@ -1096,7 +1141,7 @@
         desc_cmdline.add_options()
             ("help,h", "print out program usage (this message)")
             ("version,v", "print the version number")
- ("copyright,c", "print out the copyright statement")
+ ("copyright", "print out the copyright statement")
             ("config-file", po::value<vector<std::string> >()->composing(),
                 "specify a config file (alternatively: @filepath)")
         ;
@@ -1142,6 +1187,8 @@
                 "list names of included files to a file [arg] or to stdout [-]")
             ("macronames,m", po::value<std::string>(),
                 "list all defined macros to a file [arg] or to stdout [-]")
+ ("macrocounts,c", po::value<std::string>(),
+ "list macro invocation counts to a file [arg] or to stdout [-]")
             ("preserve,p", po::value<int>()->default_value(0),
                 "preserve whitespace\n"
                             "0: no whitespace is preserved (default),\n"
@@ -1194,10 +1241,10 @@
 
     // extract the arguments from the parsed command line
     vector<po::option> arguments;
-
+
         std::remove_copy_if(opts.options.begin(), opts.options.end(),
             back_inserter(arguments), cmd_line_utils::is_argument());
-
+
     // try to find a config file somewhere up the filesystem hierarchy
     // starting with the input file path. This allows to use a general wave.cfg
     // file for all files in a certain project.
@@ -1221,7 +1268,7 @@
                 input_dir = boost::wave::util::branch_path(input_dir);
             }
         }
-
+
     // if there is specified at least one config file, parse it and add the
     // options to the main variables_map
         if (vm.count("config-file")) {

Modified: trunk/tools/wave/cpp_version.hpp
==============================================================================
--- trunk/tools/wave/cpp_version.hpp (original)
+++ trunk/tools/wave/cpp_version.hpp 2009-06-02 21:06:42 EDT (Tue, 02 Jun 2009)
@@ -10,7 +10,7 @@
 #if !defined(CPP_VERSION_HPP_CE4FE67F_63F9_468D_8364_C855F89D3C5D_INCLUDED)
 #define CPP_VERSION_HPP_CE4FE67F_63F9_468D_8364_C855F89D3C5D_INCLUDED
 
-#include <boost/wave/wave_version.hpp>
+#include <boost/wave/wave_version.hpp>
 
 #define CPP_VERSION_MAJOR BOOST_WAVE_VERSION_MAJOR
 #define CPP_VERSION_MINOR BOOST_WAVE_VERSION_MINOR
@@ -18,8 +18,8 @@
 #define CPP_VERSION_FULL BOOST_WAVE_VERSION
 
 #define CPP_VERSION_FULL_STR BOOST_PP_STRINGIZE(CPP_VERSION_FULL)
-
-#define CPP_VERSION_DATE 20090522L
-#define CPP_VERSION_DATE_STR "20090522"
+
+#define CPP_VERSION_DATE 20090602L
+#define CPP_VERSION_DATE_STR "20090602"
 
 #endif // !defined(CPP_VERSION_HPP_CE4FE67F_63F9_468D_8364_C855F89D3C5D_INCLUDED)

Modified: trunk/tools/wave/trace_macro_expansion.hpp
==============================================================================
--- trunk/tools/wave/trace_macro_expansion.hpp (original)
+++ trunk/tools/wave/trace_macro_expansion.hpp 2009-06-02 21:06:42 EDT (Tue, 02 Jun 2009)
@@ -53,7 +53,8 @@
 enum trace_flags {
     trace_nothing = 0, // disable tracing
     trace_macros = 1, // enable macro tracing
- trace_includes = 2 // enable include file tracing
+ trace_macro_counts = 2, // enable invocation counting
+ trace_includes = 4 // enable include file tracing
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -70,7 +71,7 @@
         pragma_system_not_enabled = boost::wave::preprocess_exception::last_error_number + 1,
         pragma_mismatched_push_pop,
     };
-
+
     bad_pragma_exception(char const *what_, error_code code, int line_,
         int column_, char const *filename_) throw()
     : boost::wave::preprocess_exception(what_,
@@ -79,7 +80,7 @@
     {
     }
     ~bad_pragma_exception() throw() {}
-
+
     virtual char const *what() const throw()
     {
         return "boost::wave::bad_pragma_exception";
@@ -92,14 +93,14 @@
     {
         return boost::wave::util::severity_remark;
     }
-
+
     static char const *error_text(int code)
     {
         switch(code) {
         case pragma_system_not_enabled:
             return "the directive '#pragma wave system()' was not enabled, use the "
                    "-x command line argument to enable the execution of";
-
+
         case pragma_mismatched_push_pop:
             return "unbalanced #pragma push/pop in input file(s) for option";
         }
@@ -110,7 +111,7 @@
         switch(code) {
         case pragma_system_not_enabled:
             return boost::wave::util::severity_remark;
-
+
         case pragma_mismatched_push_pop:
             return boost::wave::util::severity_error;
         }
@@ -139,7 +140,7 @@
 : public boost::wave::context_policies::eat_whitespace<TokenT>
 {
     typedef boost::wave::context_policies::eat_whitespace<TokenT> base_type;
-
+
 public:
     trace_macro_expansion(bool preserve_whitespace_,
             std::ofstream &output_, std::ostream &tracestrm_,
@@ -159,7 +160,16 @@
     ~trace_macro_expansion()
     {
     }
-
+
+ void enable_macro_counting()
+ {
+ logging_flags = trace_flags(logging_flags | trace_macro_counts);
+ }
+ std::map<std::string, std::size_t> const& get_macro_counts() const
+ {
+ return counts;
+ }
+
     ///////////////////////////////////////////////////////////////////////////
     //
     // The function 'expanding_function_like_macro' is called whenever a
@@ -196,6 +206,9 @@
         ContainerT const &definition,
         TokenT const &macrocall, std::vector<ContainerT> const &arguments)
     {
+ if (enabled_macro_counting())
+ count_invocation(macrodef.get_value().c_str());
+
         if (!enabled_macro_tracing())
             return;
 #else
@@ -208,6 +221,9 @@
         TokenT const &macrocall, std::vector<ContainerT> const &arguments,
         IteratorT const& seqstart, IteratorT const& seqend)
     {
+ if (enabled_macro_counting())
+ count_invocation(macrodef.get_value().c_str());
+
         if (!enabled_macro_tracing())
             return false;
 #endif
@@ -228,8 +244,7 @@
             stream << ")" << std::endl;
             output(BOOST_WAVE_GETSTRING(stream));
             increment_level();
- }
-
+ }
     // output definition reference
         {
         BOOST_WAVE_OSSTREAM stream;
@@ -282,7 +297,7 @@
             close_trace_body();
         }
         open_trace_body();
-
+
 #if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS == 0
         return false;
 #endif
@@ -311,6 +326,9 @@
     void expanding_object_like_macro(TokenT const &macrodef,
         ContainerT const &definition, TokenT const &macrocall)
     {
+ if (enabled_macro_counting())
+ count_invocation(macrodef.get_value().c_str());
+
         if (!enabled_macro_tracing())
             return;
 #else
@@ -321,6 +339,9 @@
         TokenT const &macrodef, ContainerT const &definition,
         TokenT const &macrocall)
     {
+ if (enabled_macro_counting())
+ count_invocation(macrodef.get_value().c_str());
+
         if (!enabled_macro_tracing())
             return false;
 #endif
@@ -334,7 +355,7 @@
             output(BOOST_WAVE_GETSTRING(stream));
             increment_level();
         }
-
+
     // output definition reference
         {
         BOOST_WAVE_OSSTREAM stream;
@@ -350,7 +371,7 @@
         return false;
 #endif
     }
-
+
     ///////////////////////////////////////////////////////////////////////////
     //
     // The function 'expanded_macro' is called whenever the expansion of a
@@ -374,7 +395,7 @@
 #endif
     {
         if (!enabled_macro_tracing()) return;
-
+
         BOOST_WAVE_OSSTREAM stream;
         stream << boost::wave::util::impl::as_string(result) << std::endl;
         output(BOOST_WAVE_GETSTRING(stream));
@@ -412,7 +433,7 @@
         output(BOOST_WAVE_GETSTRING(stream));
         close_trace_body();
         close_trace_body();
-
+
         if (1 == get_level())
             decrement_level();
     }
@@ -482,7 +503,7 @@
                     act_token.get_position());
                 return false;
             }
-
+
         // try to spawn the given argument as a system command and return the
         // std::cout of this process as the replacement of this _Pragma
             return interpret_pragma_system(ctx, pending, values, act_token);
@@ -500,7 +521,7 @@
         }
         return false;
     }
-
+
     ///////////////////////////////////////////////////////////////////////////
     //
     // The function 'opened_include_file' is called whenever a file referred
@@ -539,7 +560,7 @@
             // print indented filename
             for (std::size_t i = 0; i < include_depth; ++i)
                 includestrm << " ";
-
+
             if (is_system_include)
                 includestrm << "<" << relname << "> (" << absname << ")";
             else
@@ -608,7 +629,7 @@
 #endif
     }
     using base_type::throw_exception;
-
+
 protected:
 #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0
     ///////////////////////////////////////////////////////////////////////////
@@ -640,7 +661,7 @@
 
         if (1 == values.size()) {
         token_type const &value = values.front();
-
+
             if (value.get_value() == "enable" ||
                 value.get_value() == "on" ||
                 value.get_value() == "1")
@@ -717,7 +738,7 @@
         token_id id = util::impl::skip_whitespace(it, end);
         if (T_COLON == id)
             id = util::impl::skip_whitespace(it, end);
-
+
         // implement push/pop
         if (T_IDENTIFIER == id) {
             if ((*it).get_value() == "push") {
@@ -752,12 +773,12 @@
 
         if (T_PP_NUMBER != id)
             return false;
-
+
         using namespace std; // some platforms have atoi in namespace std
         return interpret_pragma_option_preserve_set(
             atoi((*it).get_value().c_str()), preserve_whitespace, ctx);
     }
-
+
     // interpret the pragma wave option(line: [0|1|push|pop]) directive
     template <typename ContextT, typename IteratorT>
     bool
@@ -784,7 +805,7 @@
                         pragma_mismatched_push_pop, "line",
                         act_token.get_position());
                 }
-
+
             // pop output line from the internal option stack
                 ctx.set_language(
                     enable_emit_line_directives(ctx.get_language(), line_options.top()),
@@ -797,7 +818,7 @@
 
         if (T_PP_NUMBER != id)
             return false;
-
+
         using namespace std; // some platforms have atoi in namespace std
         int emit_lines = atoi((*it).get_value().c_str());
         if (0 == emit_lines || 1 == emit_lines) {
@@ -818,7 +839,7 @@
         ContextT& ctx, typename ContextT::token_type const &act_token)
     {
         namespace fs = boost::filesystem;
-
+
         // ensure all directories for this file do exist
         fs::create_directories(boost::wave::util::branch_path(fpath));
 
@@ -860,14 +881,14 @@
     {
         using namespace boost::wave;
         namespace fs = boost::filesystem;
-
+
         typedef typename ContextT::token_type token_type;
         typedef typename token_type::string_type string_type;
 
         token_id id = util::impl::skip_whitespace(it, end);
         if (T_COLON == id)
             id = util::impl::skip_whitespace(it, end);
-
+
         bool result = false;
         if (T_STRINGLIT == id) {
             namespace fs = boost::filesystem;
@@ -905,7 +926,7 @@
                         act_token.get_position());
                     return false;
                 }
-
+
             // pop output option from the internal option stack
                 output_option_type const& opts = output_options.top();
                 generate_output = opts.first;
@@ -941,7 +962,7 @@
                 result = interpret_pragma_option_output_close(true);
             }
         }
- return result;
+ return result;
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -952,15 +973,15 @@
         typename ContextT::token_type const &act_token)
     {
         using namespace boost::wave;
-
+
         typedef typename ContextT::token_type token_type;
         typedef typename token_type::string_type string_type;
         typedef typename ContainerT::const_iterator const_iterator;
-
+
         const_iterator end = values.end();
         for (const_iterator it = values.begin(); it != end; /**/) {
         bool valid_option = false;
-
+
             token_type const &value = *it;
             if (value.get_value() == "preserve") {
             // #pragma wave option(preserve: [0|1|2|push|pop])
@@ -1012,7 +1033,7 @@
         typedef typename token_type::string_type string_type;
 
         if (0 == values.size()) return false; // ill_formed_pragma_option
-
+
     string_type stdout_file(std::tmpnam(0));
     string_type stderr_file(std::tmpnam(0));
     string_type system_str(boost::wave::util::impl::as_string(values));
@@ -1022,14 +1043,14 @@
         if (0 != std::system(system_str.c_str())) {
         // unable to spawn the command
         string_type error_str("unable to spawn command: ");
-
+
             error_str += native_cmd;
             BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
                 ill_formed_pragma_option,
                 error_str.c_str(), act_token.get_position());
             return false;
         }
-
+
     // rescan the content of the stdout_file and insert it as the
     // _Pragma replacement
         typedef typename ContextT::lexer_type lexer_type;
@@ -1098,7 +1119,7 @@
     int increment_level() { return ++level; }
     int decrement_level() { BOOST_ASSERT(level > 0); return --level; }
     int get_level() const { return level; }
-
+
     bool enabled_macro_tracing() const
     {
         return (flags & trace_macros) && (logging_flags & trace_macros);
@@ -1107,7 +1128,28 @@
     {
         return (flags & trace_includes);
     }
-
+ bool enabled_macro_counting() const
+ {
+ return logging_flags & trace_macro_counts;
+ }
+
+ void count_invocation(std::string const& name)
+ {
+ typedef std::map<std::string, std::size_t>::iterator iterator;
+ typedef std::map<std::string, std::size_t>::value_type value_type;
+
+ iterator it = counts.find(name);
+ if (it == counts.end())
+ {
+ std::pair<iterator, bool> p = counts.insert(value_type(name, 0));
+ if (p.second)
+ it = p.first;
+ }
+
+ if (it != counts.end())
+ ++(*it).second;
+ }
+
     void timer(TokenT const &value)
     {
         if (value.get_value() == "0" || value.get_value() == "restart") {
@@ -1143,14 +1185,16 @@
     bool& generate_output; // allow generated tokens to be streamed to output
     std::string const& default_outfile; // name of the output file given on command line
     boost::filesystem::path current_outfile; // name of the current output file
-
+
     stop_watch elapsed_time; // trace timings
     std::time_t started_at; // time, this process was started at
-
+
     typedef std::pair<bool, boost::filesystem::path> output_option_type;
     std::stack<output_option_type> output_options; // output option stack
     std::stack<int> line_options; // line option stack
     std::stack<int> preserve_options; // preserve option stack
+
+ std::map<std::string, std::size_t> counts; // macro invocation counts
 };
 
 #undef BOOST_WAVE_GETSTRING


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk