|
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 ¯ocall, 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 ¯ocall, 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 ¯odef,
ContainerT const &definition, TokenT const ¯ocall)
{
+ if (enabled_macro_counting())
+ count_invocation(macrodef.get_value().c_str());
+
if (!enabled_macro_tracing())
return;
#else
@@ -321,6 +339,9 @@
TokenT const ¯odef, ContainerT const &definition,
TokenT const ¯ocall)
{
+ 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