summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/wave/tool
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/wave/tool')
-rw-r--r--src/boost/libs/wave/tool/build/Jamfile.v273
-rw-r--r--src/boost/libs/wave/tool/cpp.cpp1508
-rw-r--r--src/boost/libs/wave/tool/cpp.hpp42
-rw-r--r--src/boost/libs/wave/tool/cpp_config.hpp63
-rw-r--r--src/boost/libs/wave/tool/cpp_version.hpp25
-rw-r--r--src/boost/libs/wave/tool/stop_watch.hpp84
-rw-r--r--src/boost/libs/wave/tool/trace_macro_expansion.hpp1494
7 files changed, 3289 insertions, 0 deletions
diff --git a/src/boost/libs/wave/tool/build/Jamfile.v2 b/src/boost/libs/wave/tool/build/Jamfile.v2
new file mode 100644
index 00000000..e7d91114
--- /dev/null
+++ b/src/boost/libs/wave/tool/build/Jamfile.v2
@@ -0,0 +1,73 @@
+# Wave: A Standard compliant C++ preprocessor
+#
+# Boost Wave Library Build Jamfile
+#
+# http://www.boost.org/
+#
+# Copyright (c) 2001-2010 Hartmut Kaiser. Distributed under the Boost
+# Software License, Version 1.0. (See accompanying file
+# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+# Make sure all of Wave is compiled with threading disabled. We still need
+# to link with Boost.Thread, but no multi-threaded features are being used
+# in the Wave tool anyway.
+
+import feature ;
+import option ;
+
+feature.feature wavetool
+ : on
+ : optional composite propagated
+ ;
+
+feature.compose <wavetool>on
+ : <define>BOOST_WAVE_SUPPORT_THREADING=0
+ ;
+
+###############################################################################
+project
+ : requirements
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ ;
+
+exe wave
+ :
+ ../cpp.cpp
+ /boost//wave
+ /boost//program_options
+ /boost//filesystem
+ /boost//serialization
+ /boost//system
+ /boost//thread
+ /boost//date_time
+ :
+ <threading>multi
+# <debug-symbols>on
+ <wavetool>on
+ :
+ release
+ ;
+
+local bindir = [ option.get bindir : ../../../dist/bin ] ;
+local libdir = [ option.get libdir : ../../../dist/lib ] ;
+
+install dist-bin
+ :
+ wave
+ :
+ <install-type>EXE
+ <location>$(bindir)
+ :
+ release
+ ;
+
+install dist-lib
+ :
+ wave
+ :
+ <install-type>LIB
+ <location>$(libdir)
+ :
+ release
+ ;
diff --git a/src/boost/libs/wave/tool/cpp.cpp b/src/boost/libs/wave/tool/cpp.cpp
new file mode 100644
index 00000000..36988a6b
--- /dev/null
+++ b/src/boost/libs/wave/tool/cpp.cpp
@@ -0,0 +1,1508 @@
+/*=============================================================================
+ Boost.Wave: A Standard compliant C++ preprocessor library
+
+ http://www.boost.org/
+
+ Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
+ Software License, Version 1.0. (See accompanying file
+ LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#define BOOST_WAVE_SERIALIZATION 0 // enable serialization
+#define BOOST_WAVE_BINARY_SERIALIZATION 0 // use binary archives
+#define BOOST_WAVE_XML_SERIALIZATION 1 // use XML archives
+
+#include "cpp.hpp" // global configuration
+
+///////////////////////////////////////////////////////////////////////////////
+// Include additional Boost libraries
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/convenience.hpp>
+#include <boost/filesystem/fstream.hpp>
+#include <boost/timer.hpp>
+#include <boost/any.hpp>
+#include <boost/algorithm/cxx11/any_of.hpp>
+#include <boost/algorithm/string/join.hpp>
+#include <boost/range/algorithm/find.hpp>
+#include <boost/range/end.hpp>
+#include <boost/foreach.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// Include Wave itself
+#include <boost/wave.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// Include the lexer related stuff
+#include <boost/wave/cpplexer/cpp_lex_token.hpp> // token type
+#include <boost/wave/cpplexer/cpp_lex_iterator.hpp> // lexer type
+
+///////////////////////////////////////////////////////////////////////////////
+// Include serialization support, if requested
+#if BOOST_WAVE_SERIALIZATION != 0
+#include <boost/serialization/serialization.hpp>
+#if BOOST_WAVE_BINARY_SERIALIZATION != 0
+#include <boost/archive/binary_iarchive.hpp>
+#include <boost/archive/binary_oarchive.hpp>
+typedef boost::archive::binary_iarchive iarchive;
+typedef boost::archive::binary_oarchive oarchive;
+#elif BOOST_WAVE_XML_SERIALIZATION != 0
+#include <boost/archive/xml_iarchive.hpp>
+#include <boost/archive/xml_oarchive.hpp>
+typedef boost::archive::xml_iarchive iarchive;
+typedef boost::archive::xml_oarchive oarchive;
+#else
+#include <boost/archive/text_iarchive.hpp>
+#include <boost/archive/text_oarchive.hpp>
+typedef boost::archive::text_iarchive iarchive;
+typedef boost::archive::text_oarchive oarchive;
+#endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Include the context policies to use
+#include "trace_macro_expansion.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// Include lexer specifics, import lexer names
+#if BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION == 0
+#include <boost/wave/cpplexer/re2clex/cpp_re2c_lexer.hpp>
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Include the grammar definitions, if these shouldn't be compiled separately
+// (ATTENTION: _very_ large compilation times!)
+#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION == 0
+#include <boost/wave/grammars/cpp_intlit_grammar.hpp>
+#include <boost/wave/grammars/cpp_chlit_grammar.hpp>
+#include <boost/wave/grammars/cpp_grammar.hpp>
+#include <boost/wave/grammars/cpp_expression_grammar.hpp>
+#include <boost/wave/grammars/cpp_predef_macros_grammar.hpp>
+#include <boost/wave/grammars/cpp_defined_grammar.hpp>
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Import required names
+using namespace boost::spirit::classic;
+
+using std::pair;
+using std::vector;
+using std::getline;
+using boost::filesystem::ofstream;
+using boost::filesystem::ifstream;
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::ostream;
+using std::istreambuf_iterator;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// This application uses the lex_iterator and lex_token types predefined
+// with the Wave library, but it is possible to use your own types.
+//
+// You may want to have a look at the other samples to see how this is
+// possible to achieve.
+ typedef boost::wave::cpplexer::lex_token<> token_type;
+ typedef boost::wave::cpplexer::lex_iterator<token_type>
+ lex_iterator_type;
+
+// The C++ preprocessor iterators shouldn't be constructed directly. They
+// are to be generated through a boost::wave::context<> object. This
+// boost::wave::context object is additionally to be used to initialize and
+// define different parameters of the actual preprocessing.
+ typedef boost::wave::context<
+ std::string::iterator, lex_iterator_type,
+ boost::wave::iteration_context_policies::load_file_to_string,
+ trace_macro_expansion<token_type> >
+ context_type;
+
+///////////////////////////////////////////////////////////////////////////////
+// print the current version
+std::string get_version()
+{
+ std::string version (context_type::get_version_string());
+ version = version.substr(1, version.size()-2); // strip quotes
+ version += std::string(" (" CPP_VERSION_DATE_STR ")"); // add date
+ return version;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// print the current version for interactive sessions
+int print_interactive_version()
+{
+ cout << "Wave: A Standard conformant C++ preprocessor based on the Boost.Wave library" << endl;
+ cout << "Version: " << get_version() << endl;
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// print the copyright statement
+int print_copyright()
+{
+ char const *copyright[] = {
+ "",
+ "Wave: A Standard conformant C++ preprocessor based on the Boost.Wave library",
+ "http://www.boost.org/",
+ "",
+ "Copyright (c) 2001-2012 Hartmut Kaiser, Distributed under the Boost",
+ "Software License, Version 1.0. (See accompanying file",
+ "LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)",
+ 0
+ };
+
+ for (int i = 0; 0 != copyright[i]; ++i)
+ cout << copyright[i] << endl;
+
+ return 0; // exit app
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// forward declarations only
+namespace cmd_line_utils
+{
+ class include_paths;
+}
+
+namespace boost { namespace program_options {
+
+ void validate(boost::any &v, std::vector<std::string> const &s,
+ cmd_line_utils::include_paths *, long);
+
+}} // boost::program_options
+
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/program_options.hpp>
+
+namespace po = boost::program_options;
+namespace fs = boost::filesystem;
+
+///////////////////////////////////////////////////////////////////////////////
+namespace cmd_line_utils {
+ // Additional command line parser which interprets '@something' as an
+ // option "config-file" with the value "something".
+ inline pair<std::string, std::string>
+ at_option_parser(std::string const&s)
+ {
+ if ('@' == s[0])
+ return std::make_pair(std::string("config-file"), s.substr(1));
+ else
+ return pair<std::string, std::string>();
+ }
+
+ // class, which keeps include file information read from the command line
+ class include_paths {
+ public:
+ include_paths() : seen_separator(false) {}
+
+ vector<std::string> paths; // stores user paths
+ vector<std::string> syspaths; // stores system paths
+ bool seen_separator; // command line contains a '-I-' option
+
+ // Function which validates additional tokens from command line.
+ static void
+ validate(boost::any &v, vector<std::string> const &tokens)
+ {
+ if (v.empty())
+ v = boost::any(include_paths());
+
+ include_paths *p = boost::any_cast<include_paths>(&v);
+
+ BOOST_ASSERT(p);
+ // Assume only one path per '-I' occurrence.
+ std::string const& t = po::validators::get_single_string(tokens);
+ if (t == "-") {
+ // found -I- option, so switch behaviour
+ p->seen_separator = true;
+ }
+ else if (p->seen_separator) {
+ // store this path as a system path
+ p->syspaths.push_back(t);
+ }
+ else {
+ // store this path as an user path
+ p->paths.push_back(t);
+ }
+ }
+ };
+
+ // Read all options from a given config file, parse and add them to the
+ // given variables_map
+ bool read_config_file_options(std::string const &filename,
+ po::options_description const &desc, po::variables_map &vm,
+ bool may_fail = false)
+ {
+ ifstream ifs(filename.c_str());
+
+ if (!ifs.is_open()) {
+ if (!may_fail) {
+ cerr << filename
+ << ": command line warning: config file not found"
+ << endl;
+ }
+ return false;
+ }
+
+ vector<std::string> options;
+ std::string line;
+
+ while (std::getline(ifs, line)) {
+ // skip empty lines
+ std::string::size_type pos = line.find_first_not_of(" \t");
+ if (pos == std::string::npos)
+ continue;
+
+ // skip comment lines
+ if ('#' != line[pos]) {
+ // strip leading and trailing whitespace
+ std::string::size_type endpos = line.find_last_not_of(" \t");
+ BOOST_ASSERT(endpos != std::string::npos);
+ options.push_back(line.substr(pos, endpos-pos+1));
+ }
+ }
+
+ if (options.size() > 0) {
+ using namespace boost::program_options::command_line_style;
+ po::store(po::command_line_parser(options)
+ .options(desc).style(unix_style).run(), vm);
+ po::notify(vm);
+ }
+ return true;
+ }
+
+ // predicate to extract all positional arguments from the command line
+ struct is_argument {
+ bool operator()(po::option const &opt)
+ {
+ return (opt.position_key == -1) ? true : false;
+ }
+ };
+
+ // trim quotes from path names, if any
+ std::string trim_quotes(std::string const& file)
+ {
+ if (('"' == file[0] || '\'' == file[0]) && file[0] == file[file.size()-1])
+ {
+ return file.substr(1, file.size()-2);
+ }
+ return file;
+ }
+
+///////////////////////////////////////////////////////////////////////////////
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Special validator overload, which allows to handle the -I- syntax for
+// switching the semantics of an -I option.
+//
+///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace program_options {
+
+ void validate(boost::any &v, std::vector<std::string> const &s,
+ cmd_line_utils::include_paths *, long)
+ {
+ cmd_line_utils::include_paths::validate(v, s);
+ }
+
+}} // namespace boost::program_options
+
+///////////////////////////////////////////////////////////////////////////////
+namespace {
+
+ class auto_stop_watch : public stop_watch
+ {
+ public:
+ auto_stop_watch(std::ostream &outstrm_)
+ : print_time(false), outstrm(outstrm_)
+ {
+ }
+
+ ~auto_stop_watch()
+ {
+ if (print_time) {
+ outstrm << "Elapsed time: "
+ << this->format_elapsed_time()
+ << std::endl;
+ }
+ }
+
+ void set_print_time(bool print_time_)
+ {
+ print_time = print_time_;
+ }
+
+ private:
+ bool print_time;
+ std::ostream &outstrm;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ inline std::string
+ report_iostate_error(std::ios::iostate state)
+ {
+ BOOST_ASSERT(state & (std::ios::badbit | std::ios::failbit | std::ios::eofbit));
+ std::string result;
+ if (state & std::ios::badbit) {
+ result += " the reported problem was: "
+ "loss of integrity of the stream buffer\n";
+ }
+ if (state & std::ios::failbit) {
+ result += " the reported problem was: "
+ "an operation was not processed correctly\n";
+ }
+ if (state & std::ios::eofbit) {
+ result += " the reported problem was: "
+ "end-of-file while writing to the stream\n";
+ }
+ return result;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Retrieve the position of a macro definition
+ template <typename Context>
+ inline bool
+ get_macro_position(Context &ctx,
+ typename Context::token_type::string_type const& name,
+ typename Context::position_type &pos)
+ {
+ bool has_parameters = false;
+ bool is_predefined = false;
+ std::vector<typename Context::token_type> parameters;
+ typename Context::token_sequence_type definition;
+
+ return ctx.get_macro_definition(name, has_parameters, is_predefined,
+ pos, parameters, definition);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Generate some meaningful error messages
+ template <typename Exception>
+ inline int
+ report_error_message(Exception const &e, bool treat_warnings_as_error)
+ {
+ // default error reporting
+ cerr
+ << e.file_name() << ":" << e.line_no() << ":" << e.column_no()
+ << ": " << e.description() << endl;
+
+ // errors count as one
+ return (treat_warnings_as_error ||
+ e.get_severity() == boost::wave::util::severity_error ||
+ e.get_severity() == boost::wave::util::severity_fatal) ? 1 : 0;
+ }
+
+ template <typename Context>
+ inline int
+ report_error_message(Context &ctx, boost::wave::cpp_exception const &e,
+ bool treat_warnings_as_error)
+ {
+ // default error reporting
+ int result = report_error_message(e, treat_warnings_as_error);
+
+ using boost::wave::preprocess_exception;
+ switch(e.get_errorcode()) {
+ case preprocess_exception::macro_redefinition:
+ {
+ // report the point of the initial macro definition
+ typename Context::position_type pos;
+ if (get_macro_position(ctx, e.get_related_name(), pos)) {
+ cerr
+ << pos << ": "
+ << preprocess_exception::severity_text(e.get_severity())
+ << ": this is the location of the previous definition."
+ << endl;
+ }
+ else {
+ cerr
+ << e.file_name() << ":" << e.line_no() << ":"
+ << e.column_no() << ": "
+ << preprocess_exception::severity_text(e.get_severity())
+ << ": not able to retrieve the location of the previous "
+ << "definition." << endl;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return result;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Read one logical line of text
+ inline bool
+ read_a_line (std::istream &instream, std::string &instring)
+ {
+ bool eol = true;
+ do {
+ std::string line;
+ std::getline(instream, line);
+ if (instream.rdstate() & std::ios::failbit)
+ return false; // nothing to do
+
+ eol = true;
+ if (line.find_last_of('\\') == line.size()-1)
+ eol = false;
+
+ instring += line + '\n';
+ } while (!eol);
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Load and save the internal tables of the wave::context object
+ template <typename Context>
+ inline void
+ load_state(po::variables_map const &vm, Context &ctx)
+ {
+#if BOOST_WAVE_SERIALIZATION != 0
+ try {
+ if (vm.count("state") > 0) {
+ fs::path state_file (
+ boost::wave::util::create_path(vm["state"].as<std::string>()));
+ if (state_file == "-")
+ state_file = boost::wave::util::create_path("wave.state");
+
+ std::ios::openmode mode = std::ios::in;
+
+#if BOOST_WAVE_BINARY_SERIALIZATION != 0
+ mode = (std::ios::openmode)(mode | std::ios::binary);
+#endif
+ ifstream ifs (state_file.string().c_str(), mode);
+ if (ifs.is_open()) {
+ using namespace boost::serialization;
+ iarchive ia(ifs);
+ std::string version;
+
+ ia >> make_nvp("version", version); // load version
+ if (version == CPP_VERSION_FULL_STR)
+ ia >> make_nvp("state", ctx); // load the internal tables from disc
+ else {
+ cerr << "wave: detected version mismatch while loading state, state was not loaded." << endl;
+ cerr << " loaded version: " << version << endl;
+ cerr << " expected version: " << CPP_VERSION_FULL_STR << endl;
+ }
+ }
+ }
+ }
+ catch (boost::archive::archive_exception const& e) {
+ cerr << "wave: error while loading state: "
+ << e.what() << endl;
+ }
+ catch (boost::wave::preprocess_exception const& e) {
+ cerr << "wave: error while loading state: "
+ << e.description() << endl;
+ }
+#endif
+ }
+
+ template <typename Context>
+ inline void
+ save_state(po::variables_map const &vm, Context const &ctx)
+ {
+#if BOOST_WAVE_SERIALIZATION != 0
+ try {
+ if (vm.count("state") > 0) {
+ fs::path state_file (boost::wave::util::create_path(
+ vm["state"].as<std::string>()));
+ if (state_file == "-")
+ state_file = boost::wave::util::create_path("wave.state");
+
+ std::ios::openmode mode = std::ios::out;
+
+#if BOOST_WAVE_BINARY_SERIALIZATION != 0
+ mode = (std::ios::openmode)(mode | std::ios::binary);
+#endif
+ ofstream ofs(state_file.string().c_str(), mode);
+ if (!ofs.is_open()) {
+ cerr << "wave: could not open state file for writing: "
+ << state_file.string() << endl;
+ // this is non-fatal
+ }
+ else {
+ using namespace boost::serialization;
+ oarchive oa(ofs);
+ std::string version(CPP_VERSION_FULL_STR);
+ oa << make_nvp("version", version); // write version
+ oa << make_nvp("state", ctx); // write the internal tables to disc
+ }
+ }
+ }
+ catch (boost::archive::archive_exception const& e) {
+ cerr << "wave: error while writing state: "
+ << e.what() << endl;
+ }
+#endif
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // list all defined macros
+ bool list_macro_names(context_type const& ctx, std::string filename)
+ {
+ // open file for macro names listing
+ ofstream macronames_out;
+ fs::path macronames_file (boost::wave::util::create_path(filename));
+
+ if (macronames_file != "-") {
+ macronames_file = boost::wave::util::complete_path(macronames_file);
+ boost::wave::util::create_directories(
+ boost::wave::util::branch_path(macronames_file));
+ macronames_out.open(macronames_file.string().c_str());
+ if (!macronames_out.is_open()) {
+ cerr << "wave: could not open file for macro name listing: "
+ << macronames_file.string() << endl;
+ return false;
+ }
+ }
+ else {
+ macronames_out.copyfmt(cout);
+ macronames_out.clear(cout.rdstate());
+ static_cast<std::basic_ios<char> &>(macronames_out).rdbuf(cout.rdbuf());
+ }
+
+ // simply list all defined macros and its definitions
+ typedef context_type::const_name_iterator name_iterator;
+ name_iterator end = ctx.macro_names_end();
+ for (name_iterator it = ctx.macro_names_begin(); it != end; ++it)
+ {
+ typedef std::vector<context_type::token_type> parameters_type;
+
+ bool has_pars = false;
+ bool predef = false;
+ context_type::position_type pos;
+ parameters_type pars;
+ context_type::token_sequence_type def;
+
+ if (ctx.get_macro_definition(*it, has_pars, predef, pos, pars, def))
+ {
+ macronames_out << (predef ? "-P" : "-D") << *it;
+ if (has_pars) {
+ // list the parameter names for function style macros
+ macronames_out << "(";
+ parameters_type::const_iterator pend = pars.end();
+ for (parameters_type::const_iterator pit = pars.begin();
+ pit != pend; /**/)
+ {
+ macronames_out << (*pit).get_value();
+ if (++pit != pend)
+ macronames_out << ", ";
+ }
+ macronames_out << ")";
+ }
+ macronames_out << "=";
+
+ // print the macro definition
+ context_type::token_sequence_type::const_iterator dend = def.end();
+ for (context_type::token_sequence_type::const_iterator dit = def.begin();
+ dit != dend; ++dit)
+ {
+ macronames_out << (*dit).get_value();
+ }
+
+ macronames_out << std::endl;
+ }
+ }
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // list macro invocation counts
+ bool list_macro_counts(context_type const& ctx, std::string filename)
+ {
+ // open file for macro invocation count listing
+ ofstream macrocounts_out;
+ fs::path macrocounts_file (boost::wave::util::create_path(filename));
+
+ if (macrocounts_file != "-") {
+ macrocounts_file = boost::wave::util::complete_path(macrocounts_file);
+ boost::wave::util::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;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // read all of a file into a string
+ std::string read_entire_file(std::istream& instream)
+ {
+ std::string content;
+
+ instream.unsetf(std::ios::skipws);
+
+#if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
+ // this is known to be very slow for large files on some systems
+ copy (std::istream_iterator<char>(instream),
+ std::istream_iterator<char>(),
+ std::inserter(content, content.end()));
+#else
+ content = std::string(std::istreambuf_iterator<char>(instream.rdbuf()),
+ std::istreambuf_iterator<char>());
+#endif
+ return content;
+ }
+} // anonymous namespace
+
+///////////////////////////////////////////////////////////////////////////////
+// do the actual preprocessing
+int
+do_actual_work (std::string file_name, std::istream &instream,
+ po::variables_map const &vm, bool input_is_stdin)
+{
+// current file position is saved for exception handling
+boost::wave::util::file_position_type current_position;
+auto_stop_watch elapsed_time(cerr);
+int error_count = 0;
+const bool treat_warnings_as_error = vm.count("warning") &&
+ boost::algorithm::any_of_equal(
+ vm["warning"].as<std::vector<std::string> >(), "error");
+
+ try {
+ // process the given file
+ std::string instring;
+
+ instream.unsetf(std::ios::skipws);
+ if (!input_is_stdin)
+ instring = read_entire_file(instream);
+
+ // The preprocessing of the input stream is done on the fly behind the
+ // scenes during iteration over the context_type::iterator_type stream.
+ ofstream output;
+ ofstream traceout;
+ ofstream includelistout;
+ ofstream listguardsout;
+
+ 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 != "-") {
+ boost::wave::util::create_directories(
+ boost::wave::util::branch_path(trace_file));
+ traceout.open(trace_file.string().c_str());
+ if (!traceout.is_open()) {
+ cerr << "wave: could not open trace file: " << trace_file
+ << endl;
+ return -1;
+ }
+ }
+ enable_trace = trace_macros;
+ }
+ if ((enable_trace & trace_macros) && !traceout.is_open()) {
+ // by default trace to std::cerr
+ traceout.copyfmt(cerr);
+ traceout.clear(cerr.rdstate());
+ static_cast<std::basic_ios<char> &>(traceout).rdbuf(cerr.rdbuf());
+ }
+
+ // Open the stream where to output the list of included file names
+ if (vm.count("listincludes")) {
+ // 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 != "-") {
+ boost::wave::util::create_directories(
+ boost::wave::util::branch_path(includes_file));
+ includelistout.open(includes_file.string().c_str());
+ if (!includelistout.is_open()) {
+ cerr << "wave: could not open include list file: "
+ << includes_file.string() << endl;
+ return -1;
+ }
+ }
+ enable_trace = trace_flags(enable_trace | trace_includes);
+ }
+ if ((enable_trace & trace_includes) && !includelistout.is_open()) {
+ // by default list included names to std::cout
+ includelistout.copyfmt(cout);
+ includelistout.clear(cout.rdstate());
+ static_cast<std::basic_ios<char> &>(includelistout).
+ rdbuf(cout.rdbuf());
+ }
+
+ // Open the stream where to output the list of included file names
+ if (vm.count("listguards")) {
+ // try to open the file, where to put the include list
+ fs::path listguards_file(boost::wave::util::create_path(
+ vm["listguards"].as<std::string>()));
+
+ if (listguards_file != "-") {
+ boost::wave::util::create_directories(
+ boost::wave::util::branch_path(listguards_file));
+ listguardsout.open(listguards_file.string().c_str());
+ if (!listguardsout.is_open()) {
+ cerr << "wave: could not open include guard list file: "
+ << listguards_file.string() << endl;
+ return -1;
+ }
+ }
+ enable_trace = trace_flags(enable_trace | trace_guards);
+ }
+ if ((enable_trace & trace_guards) && !listguardsout.is_open()) {
+ // by default list included names to std::cout
+ listguardsout.copyfmt(cout);
+ listguardsout.clear(cout.rdstate());
+ static_cast<std::basic_ios<char> &>(listguardsout).
+ rdbuf(cout.rdbuf());
+ }
+
+ // enable preserving comments mode
+ bool preserve_comments = false;
+ bool preserve_whitespace = false;
+ bool preserve_bol_whitespace = false;
+
+ if (vm.count("preserve")) {
+ int preserve = vm["preserve"].as<int>();
+
+ switch(preserve) {
+ case 0: break; // preserve no whitespace
+ case 3: // preserve all whitespace
+ preserve_whitespace = true;
+ preserve_comments = true;
+ preserve_bol_whitespace = true;
+ break;
+
+ case 2: // preserve comments and BOL whitespace only
+ preserve_comments = true;
+ preserve_bol_whitespace = true;
+ break;
+
+ case 1: // preserve BOL whitespace only
+ preserve_bol_whitespace = true;
+ break;
+
+ default:
+ cerr << "wave: bogus preserve whitespace option value: "
+ << preserve << ", should be 0, 1, 2, or 3" << endl;
+ return -1;
+ }
+ }
+
+ // 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;
+
+ // This this the central piece of the Wave library, it provides you with
+ // the iterators to get the preprocessed tokens and allows to configure
+ // the preprocessing stage in advance.
+ bool allow_output = true; // will be manipulated from inside the hooks object
+ std::string default_outfile; // will be used from inside the hooks object
+ trace_macro_expansion<token_type> hooks(preserve_whitespace,
+ preserve_bol_whitespace, output, traceout, includelistout,
+ listguardsout, enable_trace, enable_system_command, allow_output,
+ default_outfile);
+
+ // enable macro invocation count, if appropriate
+ if (vm.count("macrocounts"))
+ hooks.enable_macro_counting();
+
+ // check, if we have a license file to prepend
+ std::string license;
+
+ if (vm.count ("license")) {
+ // try to open the file, where to put the preprocessed output
+ std::string license_file(vm["license"].as<std::string>());
+ ifstream license_stream(license_file.c_str());
+
+ if (!license_stream.is_open()) {
+ cerr << "wave: could not open specified license file: "
+ << license_file << endl;
+ return -1;
+ }
+ license = read_entire_file(license_stream);
+ hooks.set_license_info(license);
+ }
+
+ context_type ctx (instring.begin(), instring.end(), file_name.c_str(), hooks);
+
+#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
+ // enable C99 mode, if appropriate (implies variadics)
+ if (vm.count("c99")) {
+#if BOOST_WAVE_SUPPORT_CPP0X != 0
+ if (vm.count("c++11")) {
+ cerr << "wave: multiple language options specified: --c99 "
+ "and --c++11" << endl;
+ return -1;
+ }
+#endif
+ ctx.set_language(
+ boost::wave::language_support(
+ boost::wave::support_c99
+ | boost::wave::support_option_convert_trigraphs
+ | boost::wave::support_option_emit_line_directives
+#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
+ | boost::wave::support_option_include_guard_detection
+#endif
+#if BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES != 0
+ | boost::wave::support_option_emit_pragma_directives
+#endif
+ | boost::wave::support_option_insert_whitespace
+ ));
+ }
+ else if (vm.count("variadics")) {
+ // enable variadics and placemarkers, if appropriate
+ ctx.set_language(boost::wave::enable_variadics(ctx.get_language()));
+ }
+#endif // BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
+#if BOOST_WAVE_SUPPORT_CPP0X != 0
+ if (vm.count("c++11")) {
+ if (vm.count("c99")) {
+ cerr << "wave: multiple language options specified: --c99 "
+ "and --c++11" << endl;
+ return -1;
+ }
+ ctx.set_language(
+ boost::wave::language_support(
+ boost::wave::support_cpp0x
+ | boost::wave::support_option_convert_trigraphs
+ | boost::wave::support_option_long_long
+ | boost::wave::support_option_emit_line_directives
+#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
+ | boost::wave::support_option_include_guard_detection
+#endif
+#if BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES != 0
+ | boost::wave::support_option_emit_pragma_directives
+#endif
+ | boost::wave::support_option_insert_whitespace
+ ));
+ }
+#endif // BOOST_WAVE_SUPPORT_CPP0X != 0
+
+ // enable long long support, if appropriate
+ if (vm.count("long_long")) {
+ ctx.set_language(
+ boost::wave::enable_long_long(ctx.get_language()));
+ }
+
+#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
+// disable include guard detection
+ if (vm.count("noguard")) {
+ ctx.set_language(
+ boost::wave::enable_include_guard_detection(
+ ctx.get_language(), false));
+ }
+#endif
+
+ // enable preserving comments mode
+ if (preserve_comments) {
+ ctx.set_language(
+ boost::wave::enable_preserve_comments(ctx.get_language()));
+ }
+
+ // control the generation of #line directives
+ if (vm.count("line")) {
+ int lineopt = vm["line"].as<int>();
+ if (0 != lineopt && 1 != lineopt && 2 != lineopt) {
+ cerr << "wave: bogus value for --line command line option: "
+ << lineopt << endl;
+ return -1;
+ }
+ ctx.set_language(
+ boost::wave::enable_emit_line_directives(ctx.get_language(),
+ lineopt != 0));
+
+ if (2 == lineopt)
+ ctx.get_hooks().enable_relative_names_in_line_directives(true);
+ }
+
+ // control whether whitespace should be inserted to disambiguate output
+ if (vm.count("disambiguate")) {
+ int disambiguateopt = vm["disambiguate"].as<int>();
+ if (0 != disambiguateopt && 1 != disambiguateopt) {
+ cerr << "wave: bogus value for --disambiguate command line option: "
+ << disambiguateopt << endl;
+ return -1;
+ }
+ ctx.set_language(
+ boost::wave::enable_insert_whitespace(ctx.get_language(),
+ disambiguateopt != 0));
+ }
+
+ // add include directories to the system include search paths
+ if (vm.count("sysinclude")) {
+ vector<std::string> syspaths = vm["sysinclude"].as<vector<std::string> >();
+
+ vector<std::string>::const_iterator end = syspaths.end();
+ for (vector<std::string>::const_iterator cit = syspaths.begin();
+ cit != end; ++cit)
+ {
+ ctx.add_sysinclude_path(cmd_line_utils::trim_quotes(*cit).c_str());
+ }
+ }
+
+ // add include directories to the include search paths
+ if (vm.count("include")) {
+ cmd_line_utils::include_paths const &ip =
+ vm["include"].as<cmd_line_utils::include_paths>();
+ vector<std::string>::const_iterator end = ip.paths.end();
+
+ for (vector<std::string>::const_iterator cit = ip.paths.begin();
+ cit != end; ++cit)
+ {
+ ctx.add_include_path(cmd_line_utils::trim_quotes(*cit).c_str());
+ }
+
+ // if -I- was given on the command line, this has to be propagated
+ if (ip.seen_separator)
+ ctx.set_sysinclude_delimiter();
+
+ // add system include directories to the include path
+ vector<std::string>::const_iterator sysend = ip.syspaths.end();
+ for (vector<std::string>::const_iterator syscit = ip.syspaths.begin();
+ syscit != sysend; ++syscit)
+ {
+ ctx.add_sysinclude_path(cmd_line_utils::trim_quotes(*syscit).c_str());
+ }
+ }
+
+ // add additional defined macros
+ if (vm.count("define")) {
+ vector<std::string> const &macros = vm["define"].as<vector<std::string> >();
+ vector<std::string>::const_iterator end = macros.end();
+ for (vector<std::string>::const_iterator cit = macros.begin();
+ cit != end; ++cit)
+ {
+ ctx.add_macro_definition(*cit);
+ }
+ }
+
+ // add additional predefined macros
+ if (vm.count("predefine")) {
+ vector<std::string> const &predefmacros =
+ vm["predefine"].as<vector<std::string> >();
+ vector<std::string>::const_iterator end = predefmacros.end();
+ for (vector<std::string>::const_iterator cit = predefmacros.begin();
+ cit != end; ++cit)
+ {
+ ctx.add_macro_definition(*cit, true);
+ }
+ }
+
+ // undefine specified macros
+ if (vm.count("undefine")) {
+ vector<std::string> const &undefmacros =
+ vm["undefine"].as<vector<std::string> >();
+ vector<std::string>::const_iterator end = undefmacros.end();
+ for (vector<std::string>::const_iterator cit = undefmacros.begin();
+ cit != end; ++cit)
+ {
+ ctx.remove_macro_definition(*cit, true);
+ }
+ }
+
+#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS == 0
+ // suppress expansion of specified macros
+ if (vm.count("noexpand")) {
+ vector<std::string> const &noexpandmacros =
+ vm["noexpand"].as<vector<std::string> >();
+ vector<std::string>::const_iterator end = noexpandmacros.end();
+ for (vector<std::string>::const_iterator cit = noexpandmacros.begin();
+ cit != end; ++cit)
+ {
+ ctx.get_hooks().add_noexpandmacro(*cit);
+ }
+ }
+#endif
+
+ // maximal include nesting depth
+ if (vm.count("nesting")) {
+ int max_depth = vm["nesting"].as<int>();
+ if (max_depth < 1 || max_depth > 100000) {
+ cerr << "wave: bogus maximal include nesting depth: "
+ << max_depth << endl;
+ return -1;
+ }
+ ctx.set_max_include_nesting_depth(max_depth);
+ }
+
+ // open the output file
+ if (vm.count("output")) {
+ // try to open the file, where to put the preprocessed output
+ fs::path out_file (boost::wave::util::create_path(
+ vm["output"].as<std::string>()));
+
+ if (out_file == "-") {
+ allow_output = false; // inhibit output initially
+ default_outfile = "-";
+ }
+ else {
+ out_file = boost::wave::util::complete_path(out_file);
+ boost::wave::util::create_directories(
+ boost::wave::util::branch_path(out_file));
+ output.open(out_file.string().c_str());
+ if (!output.is_open()) {
+ cerr << "wave: could not open output file: "
+ << out_file.string() << endl;
+ return -1;
+ }
+ if (!license.empty())
+ output << license;
+ default_outfile = out_file.string();
+ }
+ }
+ else if (!input_is_stdin && vm.count("autooutput")) {
+ // generate output in the file <input_base_name>.i
+ fs::path out_file (boost::wave::util::create_path(file_name));
+ std::string basename (boost::wave::util::leaf(out_file));
+ std::string::size_type pos = basename.find_last_of(".");
+
+ if (std::string::npos != pos)
+ basename = basename.substr(0, pos);
+ out_file = boost::wave::util::branch_path(out_file) / (basename + ".i");
+
+ boost::wave::util::create_directories(
+ boost::wave::util::branch_path(out_file));
+ output.open(out_file.string().c_str());
+ if (!output.is_open()) {
+ cerr << "wave: could not open output file: "
+ << out_file.string() << endl;
+ return -1;
+ }
+ if (!license.empty())
+ output << license;
+ default_outfile = out_file.string();
+ }
+
+ // we assume the session to be interactive if input is stdin and output is
+ // stdout and the output is not inhibited
+ bool is_interactive = input_is_stdin && !output.is_open() && allow_output;
+
+ if (is_interactive) {
+ // if interactive we don't warn for missing endif's etc.
+ ctx.set_language(
+ boost::wave::enable_single_line(ctx.get_language()), false);
+ }
+
+ // analyze the input file
+ context_type::iterator_type first = ctx.begin();
+ context_type::iterator_type last = ctx.end();
+
+ // preprocess the required include files
+ if (vm.count("forceinclude")) {
+ // add the filenames to force as include files in _reverse_ order
+ // the second parameter 'is_last' of the force_include function should
+ // be set to true for the last (first given) file.
+ std::vector<std::string> const &force =
+ vm["forceinclude"].as<std::vector<std::string> >();
+ std::vector<std::string>::const_reverse_iterator rend = force.rend();
+ for (std::vector<std::string>::const_reverse_iterator cit = force.rbegin();
+ cit != rend; /**/)
+ {
+ std::string filename(*cit);
+ first.force_include(filename.c_str(), ++cit == rend);
+ }
+ }
+
+ elapsed_time.set_print_time(!input_is_stdin && vm.count("timer") > 0);
+ if (is_interactive) {
+ print_interactive_version(); // print welcome message
+ load_state(vm, ctx); // load the internal tables from disc
+ }
+ else if (vm.count("state")) {
+ // the option "state" is usable in interactive mode only
+ cerr << "wave: ignoring the command line option 'state', "
+ << "use it in interactive mode only." << endl;
+ }
+
+ // >>>>>>>>>>>>> The actual preprocessing happens here. <<<<<<<<<<<<<<<<<<<
+ // loop over the input lines if reading from stdin, otherwise this loop
+ // will be executed once
+ do {
+ // loop over all generated tokens outputting the generated text
+ bool finished = false;
+
+ if (input_is_stdin) {
+ if (is_interactive)
+ cout << ">>> "; // prompt if is interactive
+
+ // read next line and continue
+ instring.clear();
+ if (!read_a_line(instream, instring))
+ break; // end of input reached
+ first = ctx.begin(instring.begin(), instring.end());
+ }
+
+ bool need_to_advanve = false;
+
+ do {
+ try {
+ if (need_to_advanve) {
+ ++first;
+ need_to_advanve = false;
+ }
+
+ while (first != last) {
+ // store the last known good token position
+ current_position = (*first).get_position();
+
+ // print out the current token value
+ if (allow_output) {
+ if (!output.good()) {
+ cerr << "wave: problem writing to the current "
+ << "output file" << endl;
+ cerr << report_iostate_error(output.rdstate());
+ break;
+ }
+ if (output.is_open())
+ output << (*first).get_value();
+ else
+ cout << (*first).get_value();
+ }
+
+ // advance to the next token
+ ++first;
+ }
+ finished = true;
+ }
+ catch (boost::wave::cpp_exception const &e) {
+ // some preprocessing error
+ if (is_interactive || boost::wave::is_recoverable(e)) {
+ error_count += report_error_message(ctx, e,
+ treat_warnings_as_error);
+ need_to_advanve = true; // advance to the next token
+ }
+ else {
+ throw; // re-throw for non-recoverable errors
+ }
+ }
+ catch (boost::wave::cpplexer::lexing_exception const &e) {
+ // some preprocessing error
+ if (is_interactive ||
+ boost::wave::cpplexer::is_recoverable(e))
+ {
+ error_count +=
+ report_error_message(e, treat_warnings_as_error);
+ need_to_advanve = true; // advance to the next token
+ }
+ else {
+ throw; // re-throw for non-recoverable errors
+ }
+ }
+ } while (!finished);
+ } while (input_is_stdin);
+
+ if (is_interactive)
+ save_state(vm, ctx); // write the internal tables to disc
+
+ // list all defined macros at the end of the preprocessing
+ if (vm.count("macronames")) {
+ 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
+ report_error_message(e, treat_warnings_as_error);
+ return 1;
+ }
+ catch (boost::wave::cpplexer::lexing_exception const &e) {
+ // some lexing error
+ report_error_message(e, treat_warnings_as_error);
+ return 2;
+ }
+ catch (std::exception const &e) {
+ // use last recognized token to retrieve the error position
+ cerr
+ << current_position << ": "
+ << "exception caught: " << e.what()
+ << endl;
+ return 3;
+ }
+ catch (...) {
+ // use last recognized token to retrieve the error position
+ cerr
+ << current_position << ": "
+ << "unexpected exception caught." << endl;
+ return 4;
+ }
+ return -error_count; // returns the number of errors as a negative integer
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// main entry point
+int
+main (int argc, char *argv[])
+{
+ const std::string accepted_w_args[] = {"error"};
+
+ // test Wave compilation configuration
+ if (!BOOST_WAVE_TEST_CONFIGURATION()) {
+ cout << "wave: warning: the library this application was linked against was compiled "
+ << endl
+ << " using a different configuration (see wave_config.hpp)."
+ << endl;
+ }
+
+ // analyze the command line options and arguments
+ try {
+ // declare the options allowed on the command line only
+ po::options_description desc_cmdline ("Options allowed on the command line only");
+
+ desc_cmdline.add_options()
+ ("help,h", "print out program usage (this message)")
+ ("version,v", "print the version number")
+ ("copyright", "print out the copyright statement")
+ ("config-file", po::value<vector<std::string> >()->composing(),
+ "specify a config file (alternatively: @filepath)")
+ ;
+
+ const std::string w_arg_desc = "Warning settings. Currently supported: -W" +
+ boost::algorithm::join(accepted_w_args, ", -W");
+
+ // declare the options allowed on command line and in config files
+ po::options_description desc_generic ("Options allowed additionally in a config file");
+
+ desc_generic.add_options()
+ ("output,o", po::value<std::string>(),
+ "specify a file [arg] to use for output instead of stdout or "
+ "disable output [-]")
+ ("autooutput,E",
+ "output goes into a file named <input_basename>.i")
+ ("license", po::value<std::string>(),
+ "prepend the content of the specified file to each created file")
+ ("include,I", po::value<cmd_line_utils::include_paths>()->composing(),
+ "specify an additional include directory")
+ ("sysinclude,S", po::value<vector<std::string> >()->composing(),
+ "specify an additional system include directory")
+ ("forceinclude,F", po::value<std::vector<std::string> >()->composing(),
+ "force inclusion of the given file")
+ ("define,D", po::value<std::vector<std::string> >()->composing(),
+ "specify a macro to define (as macro[=[value]])")
+ ("predefine,P", po::value<std::vector<std::string> >()->composing(),
+ "specify a macro to predefine (as macro[=[value]])")
+ ("undefine,U", po::value<std::vector<std::string> >()->composing(),
+ "specify a macro to undefine")
+#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS == 0
+ ("noexpand,N", po::value<std::vector<std::string> >()->composing(),
+ "specify a macro name, which should not be expanded")
+#endif
+ ("nesting,n", po::value<int>(),
+ "specify a new maximal include nesting depth")
+ ("warning,W", po::value<std::vector<std::string> >()->composing(),
+ w_arg_desc.c_str())
+ ;
+
+ po::options_description desc_ext ("Extended options (allowed everywhere)");
+
+ desc_ext.add_options()
+ ("traceto,t", po::value<std::string>(),
+ "output macro expansion tracing information to a file [arg] "
+ "or to stderr [-]")
+ ("timer", "output overall elapsed computing time to stderr")
+ ("long_long", "enable long long support in C++ mode")
+#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
+ ("variadics", "enable certain C99 extensions in C++ mode")
+ ("c99", "enable C99 mode (implies --variadics)")
+#endif
+#if BOOST_WAVE_SUPPORT_CPP0X != 0
+ ("c++11", "enable C++11 mode (implies --variadics and --long_long)")
+#endif
+ ("listincludes,l", po::value<std::string>(),
+ "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"
+ "1: begin of line whitespace is preserved,\n"
+ "2: comments and begin of line whitespace is preserved,\n"
+ "3: all whitespace is preserved")
+ ("line,L", po::value<int>()->default_value(1),
+ "control the generation of #line directives\n"
+ "0: no #line directives are generated,\n"
+ "1: #line directives will be emitted (default),\n"
+ "2: #line directives will be emitted using relative\n"
+ " filenames")
+ ("disambiguate", po::value<int>()->default_value(1),
+ "control whitespace insertion to disambiguate\n"
+ "consecutive tokens\n"
+ "0: no additional whitespace is generated,\n"
+ "1: whitespace is used to disambiguate output (default)")
+ ("extended,x", "enable the #pragma wave system() directive")
+#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
+ ("noguard,G", "disable include guard detection")
+ ("listguards,g", po::value<std::string>(),
+ "list names of files flagged as 'include once' to a file [arg] "
+ "or to stdout [-]")
+#endif
+#if BOOST_WAVE_SERIALIZATION != 0
+ ("state,s", po::value<std::string>(),
+ "load and save state information from/to the given file [arg] "
+ "or 'wave.state' [-] (interactive mode only)")
+#endif
+ ;
+
+ // combine the options for the different usage schemes
+ po::options_description desc_overall_cmdline;
+ po::options_description desc_overall_cfgfile;
+
+ desc_overall_cmdline.add(desc_cmdline).add(desc_generic).add(desc_ext);
+ desc_overall_cfgfile.add(desc_generic).add(desc_ext);
+
+ // parse command line and store results
+ using namespace boost::program_options::command_line_style;
+
+ po::parsed_options opts(po::parse_command_line(argc, argv,
+ desc_overall_cmdline, unix_style, cmd_line_utils::at_option_parser));
+ po::variables_map vm;
+
+ po::store(opts, vm);
+ po::notify(vm);
+
+// // Try to find a wave.cfg in the same directory as the executable was
+// // started from. If this exists, treat it as a wave config file
+// fs::path filename(argv[0]);
+//
+// filename = filename.branch_path() / "wave.cfg";
+// cmd_line_utils::read_config_file_options(filename.string(),
+// desc_overall_cfgfile, vm, true);
+
+ // 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.
+ if (arguments.size() > 0 && arguments[0].value[0] != "-") {
+ // construct full path of input file
+ fs::path input_dir (boost::wave::util::complete_path(
+ boost::wave::util::create_path(arguments[0].value[0])));
+
+ // chop of file name
+ input_dir = boost::wave::util::branch_path(
+ boost::wave::util::normalize(input_dir));
+
+ // walk up the hierarchy, trying to find a file wave.cfg
+ while (!input_dir.empty()) {
+ fs::path filename = input_dir / "wave.cfg";
+ if (cmd_line_utils::read_config_file_options(filename.string(),
+ desc_overall_cfgfile, vm, true))
+ {
+ break; // break on the first cfg file found
+ }
+ 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")) {
+ vector<std::string> const &cfg_files =
+ vm["config-file"].as<vector<std::string> >();
+ vector<std::string>::const_iterator end = cfg_files.end();
+ for (vector<std::string>::const_iterator cit = cfg_files.begin();
+ cit != end; ++cit)
+ {
+ // parse a single config file and store the results
+ cmd_line_utils::read_config_file_options(*cit,
+ desc_overall_cfgfile, vm);
+ }
+ }
+
+ // validate warning settings
+ if (vm.count("warning"))
+ {
+ BOOST_FOREACH(const std::string& arg,
+ vm["warning"].as<std::vector<std::string> >())
+ {
+ if (boost::range::find(accepted_w_args, arg) ==
+ boost::end(accepted_w_args))
+ {
+ cerr << "wave: Invalid warning setting: " << arg << endl;
+ return -1;
+ }
+ }
+ }
+
+ // ... act as required
+ if (vm.count("help")) {
+ po::options_description desc_help (
+ "Usage: wave [options] [@config-file(s)] [file]");
+
+ desc_help.add(desc_cmdline).add(desc_generic).add(desc_ext);
+ cout << desc_help << endl;
+ return 1;
+ }
+
+ if (vm.count("version")) {
+ cout << get_version() << endl;
+ return 0;
+ }
+
+ if (vm.count("copyright")) {
+ return print_copyright();
+ }
+
+ // if there is no input file given, then take input from stdin
+ if (0 == arguments.size() || 0 == arguments[0].value.size() ||
+ arguments[0].value[0] == "-")
+ {
+ // preprocess the given input from stdin
+ return do_actual_work("<stdin>", std::cin, vm, true);
+ }
+ else {
+ if (arguments.size() > 1) {
+ // this driver understands to parse one input file only
+ cerr << "wave: more than one input file specified, "
+ << "ignoring all but the first!" << endl;
+ }
+
+ std::string file_name(arguments[0].value[0]);
+ ifstream instream(file_name.c_str());
+
+ // preprocess the given input file
+ if (!instream.is_open()) {
+ cerr << "wave: could not open input file: " << file_name << endl;
+ return -1;
+ }
+ return do_actual_work(file_name, instream, vm, false);
+ }
+ }
+ catch (std::exception const &e) {
+ cout << "wave: exception caught: " << e.what() << endl;
+ return 6;
+ }
+ catch (...) {
+ cerr << "wave: unexpected exception caught." << endl;
+ return 7;
+ }
+}
+
diff --git a/src/boost/libs/wave/tool/cpp.hpp b/src/boost/libs/wave/tool/cpp.hpp
new file mode 100644
index 00000000..2c795d2b
--- /dev/null
+++ b/src/boost/libs/wave/tool/cpp.hpp
@@ -0,0 +1,42 @@
+/*=============================================================================
+ Boost.Wave: A Standard compliant C++ preprocessor library
+
+ http://www.boost.org/
+
+ Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
+ Software License, Version 1.0. (See accompanying file
+ LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(CPP_HPP_920D0370_741F_44AF_BF86_F6104BDACF75_INCLUDED)
+#define CPP_HPP_920D0370_741F_44AF_BF86_F6104BDACF75_INCLUDED
+
+///////////////////////////////////////////////////////////////////////////////
+// This file may be used as a precompiled header (if applicable)
+
+///////////////////////////////////////////////////////////////////////////////
+// include often used files from the stdlib
+#include <iostream>
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <iterator>
+
+///////////////////////////////////////////////////////////////////////////////
+// include boost config
+#include <boost/config.hpp> // global configuration information
+
+///////////////////////////////////////////////////////////////////////////////
+// build version
+#include "cpp_version.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// configure this app here (global configuration constants)
+#include "cpp_config.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// include required boost libraries
+#include <boost/assert.hpp>
+#include <boost/pool/pool_alloc.hpp>
+
+#endif // !defined(CPP_HPP_920D0370_741F_44AF_BF86_F6104BDACF75_INCLUDED)
diff --git a/src/boost/libs/wave/tool/cpp_config.hpp b/src/boost/libs/wave/tool/cpp_config.hpp
new file mode 100644
index 00000000..e6e4f63e
--- /dev/null
+++ b/src/boost/libs/wave/tool/cpp_config.hpp
@@ -0,0 +1,63 @@
+/*=============================================================================
+ Boost.Wave: A Standard compliant C++ preprocessor library
+ Global application configuration of the Wave driver command
+
+ http://www.boost.org/
+
+ Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
+ Software License, Version 1.0. (See accompanying file
+ LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(CPP_CONFIG_HPP_F143F90A_A63F_4B27_AC41_9CA4F14F538D_INCLUDED)
+#define CPP_CONFIG_HPP_F143F90A_A63F_4B27_AC41_9CA4F14F538D_INCLUDED
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment the following, if you need debug output, the
+// BOOST_SPIRIT_DEBUG_FLAGS constants below helps to fine control the amount of
+// the generated debug output
+//#define BOOST_SPIRIT_DEBUG
+
+///////////////////////////////////////////////////////////////////////////////
+// debug rules, subrules and grammars only, for possible flags see
+// spirit/include/classic_debug.hpp
+#if defined(BOOST_SPIRIT_DEBUG)
+
+#define BOOST_SPIRIT_DEBUG_FLAGS ( \
+ BOOST_SPIRIT_DEBUG_FLAGS_NODES | \
+ BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES \
+ ) \
+ /**/
+
+///////////////////////////////////////////////////////////////////////////////
+// Debug flags for the Wave library, possible flags (defined in
+// wave_config.hpp):
+//
+// #define BOOST_SPIRIT_DEBUG_FLAGS_CPP_GRAMMAR 0x0001
+// #define BOOST_SPIRIT_DEBUG_FLAGS_TIME_CONVERSION 0x0002
+// #define BOOST_SPIRIT_DEBUG_FLAGS_CPP_EXPR_GRAMMAR 0x0004
+// #define BOOST_SPIRIT_DEBUG_FLAGS_INTLIT_GRAMMAR 0x0008
+// #define BOOST_SPIRIT_DEBUG_FLAGS_CHLIT_GRAMMAR 0x0010
+// #define BOOST_SPIRIT_DEBUG_FLAGS_DEFINED_GRAMMAR 0x0020
+// #define BOOST_SPIRIT_DEBUG_FLAGS_PREDEF_MACROS_GRAMMAR 0x0040
+
+#define BOOST_SPIRIT_DEBUG_FLAGS_CPP ( 0 \
+ /* insert the required flags from above */ \
+ ) \
+ /**/
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Include the configuration stuff for the Wave library itself
+#include <boost/wave/wave_config.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// MSVC specific #pragma's
+#if defined(BOOST_MSVC)
+#pragma warning (disable: 4355) // 'this' used in base member initializer list
+#pragma warning (disable: 4800) // forcing value to bool 'true' or 'false'
+#pragma inline_depth(255)
+#pragma inline_recursion(on)
+#endif // defined(BOOST_MSVC)
+
+#endif // !defined(CPP_CONFIG_HPP_F143F90A_A63F_4B27_AC41_9CA4F14F538D_INCLUDED)
diff --git a/src/boost/libs/wave/tool/cpp_version.hpp b/src/boost/libs/wave/tool/cpp_version.hpp
new file mode 100644
index 00000000..43330c2c
--- /dev/null
+++ b/src/boost/libs/wave/tool/cpp_version.hpp
@@ -0,0 +1,25 @@
+/*=============================================================================
+ Boost.Wave: A Standard compliant C++ preprocessor library
+ http://www.boost.org/
+
+ Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
+ Software License, Version 1.0. (See accompanying file
+ LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#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>
+
+#define CPP_VERSION_MAJOR BOOST_WAVE_VERSION_MAJOR
+#define CPP_VERSION_MINOR BOOST_WAVE_VERSION_MINOR
+#define CPP_VERSION_SUBMINOR BOOST_WAVE_VERSION_SUBMINOR
+#define CPP_VERSION_FULL BOOST_WAVE_VERSION
+
+#define CPP_VERSION_FULL_STR BOOST_PP_STRINGIZE(CPP_VERSION_FULL)
+
+#define CPP_VERSION_DATE 20120523L
+#define CPP_VERSION_DATE_STR "20120523"
+
+#endif // !defined(CPP_VERSION_HPP_CE4FE67F_63F9_468D_8364_C855F89D3C5D_INCLUDED)
diff --git a/src/boost/libs/wave/tool/stop_watch.hpp b/src/boost/libs/wave/tool/stop_watch.hpp
new file mode 100644
index 00000000..e3285466
--- /dev/null
+++ b/src/boost/libs/wave/tool/stop_watch.hpp
@@ -0,0 +1,84 @@
+/*=============================================================================
+ Boost.Wave: A Standard compliant C++ preprocessor library
+ http://www.boost.org/
+
+ Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
+ Software License, Version 1.0. (See accompanying file
+ LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(STOP_WATCH_HPP_HK040911_INCLUDED)
+#define STOP_WATCH_HPP_HK040911_INCLUDED
+
+#include <boost/config.hpp>
+#include <boost/timer.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+//
+class stop_watch : public boost::timer {
+
+ typedef boost::timer base_t;
+
+public:
+ stop_watch() : is_suspended_since(0), suspended_overall(0) {}
+
+ void suspend()
+ {
+ if (0 == is_suspended_since) {
+ // if not already suspended
+ is_suspended_since = this->base_t::elapsed();
+ }
+ }
+ void resume()
+ {
+ if (0 != is_suspended_since) {
+ // if really suspended
+ suspended_overall += this->base_t::elapsed() - is_suspended_since;
+ is_suspended_since = 0;
+ }
+ }
+ double elapsed() const
+ {
+ if (0 == is_suspended_since) {
+ // currently running
+ return this->base_t::elapsed() - suspended_overall;
+ }
+
+ // currently suspended
+ BOOST_ASSERT(is_suspended_since >= suspended_overall);
+ return is_suspended_since - suspended_overall;
+ }
+
+ std::string format_elapsed_time() const
+ {
+ double current = elapsed();
+ char time_buffer[sizeof("1234:56:78.90 abcd.")+1];
+
+ using namespace std;
+ if (current >= 3600) {
+ // show hours
+ sprintf (time_buffer, "%d:%02d:%02d.%03d hrs.",
+ (int)(current) / 3600, ((int)(current) % 3600) / 60,
+ ((int)(current) % 3600) % 60,
+ (int)(current * 1000) % 1000);
+ }
+ else if (current >= 60) {
+ // show minutes
+ sprintf (time_buffer, "%d:%02d.%03d min.",
+ (int)(current) / 60, (int)(current) % 60,
+ (int)(current * 1000) % 1000);
+ }
+ else {
+ // show seconds
+ sprintf(time_buffer, "%d.%03d sec.", (int)current,
+ (int)(current * 1000) % 1000);
+ }
+ return time_buffer;
+ }
+
+private:
+ double is_suspended_since;
+ double suspended_overall;
+};
+
+#endif // !defined(STOP_WATCH_HPP_HK040911_INCLUDED)
diff --git a/src/boost/libs/wave/tool/trace_macro_expansion.hpp b/src/boost/libs/wave/tool/trace_macro_expansion.hpp
new file mode 100644
index 00000000..99a3647e
--- /dev/null
+++ b/src/boost/libs/wave/tool/trace_macro_expansion.hpp
@@ -0,0 +1,1494 @@
+/*=============================================================================
+ Boost.Wave: A Standard compliant C++ preprocessor library
+ http://www.boost.org/
+
+ Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
+ Software License, Version 1.0. (See accompanying file
+ LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if !defined(TRACE_MACRO_EXPANSION_HPP_D8469318_8407_4B9D_A19F_13CA60C1661F_INCLUDED)
+#define TRACE_MACRO_EXPANSION_HPP_D8469318_8407_4B9D_A19F_13CA60C1661F_INCLUDED
+
+#include <cstdio>
+#include <cstdlib>
+#include <ctime>
+
+#include <ostream>
+#include <string>
+#include <stack>
+#include <set>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/convenience.hpp>
+
+#include <boost/wave/token_ids.hpp>
+#include <boost/wave/util/macro_helpers.hpp>
+#include <boost/wave/util/filesystem_compatibility.hpp>
+#include <boost/wave/preprocessing_hooks.hpp>
+#include <boost/wave/whitespace_handling.hpp>
+#include <boost/wave/language_support.hpp>
+#include <boost/wave/cpp_exceptions.hpp>
+
+#include "stop_watch.hpp"
+
+#ifdef BOOST_NO_STRINGSTREAM
+#include <strstream>
+#define BOOST_WAVE_OSSTREAM std::ostrstream
+std::string BOOST_WAVE_GETSTRING(std::ostrstream& ss)
+{
+ ss << std::ends;
+ std::string rval = ss.str();
+ ss.freeze(false);
+ return rval;
+}
+#else
+#include <sstream>
+#define BOOST_WAVE_GETSTRING(ss) ss.str()
+#define BOOST_WAVE_OSSTREAM std::ostringstream
+#endif
+
+// trace_flags: enable single tracing functionality
+enum trace_flags {
+ trace_nothing = 0, // disable tracing
+ trace_macros = 1, // enable macro tracing
+ trace_macro_counts = 2, // enable invocation counting
+ trace_includes = 4, // enable include file tracing
+ trace_guards = 8 // enable include guard tracing
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Special error thrown whenever the #pragma wave system() directive is
+// disabled
+//
+///////////////////////////////////////////////////////////////////////////////
+class bad_pragma_exception :
+ public boost::wave::preprocess_exception
+{
+public:
+ enum error_code {
+ 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, std::size_t line_,
+ std::size_t column_, char const *filename_) throw()
+ : boost::wave::preprocess_exception(what_,
+ (boost::wave::preprocess_exception::error_code)code, line_,
+ column_, filename_)
+ {
+ }
+ ~bad_pragma_exception() throw() {}
+
+ virtual char const *what() const throw()
+ {
+ return "boost::wave::bad_pragma_exception";
+ }
+ virtual bool is_recoverable() const throw()
+ {
+ return true;
+ }
+ virtual int get_severity() const throw()
+ {
+ 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";
+ }
+ return "Unknown exception";
+ }
+ static boost::wave::util::severity severity_level(int code)
+ {
+ switch(code) {
+ case pragma_system_not_enabled:
+ return boost::wave::util::severity_remark;
+
+ case pragma_mismatched_push_pop:
+ return boost::wave::util::severity_error;
+ }
+ return boost::wave::util::severity_fatal;
+ }
+ static char const *severity_text(int code)
+ {
+ return boost::wave::util::get_severity(boost::wave::util::severity_remark);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// The trace_macro_expansion policy is used to trace the macro expansion of
+// macros whenever it is requested from inside the input stream to preprocess
+// through the '#pragma wave_option(trace: enable)' directive. The macro
+// tracing is disabled with the help of a '#pragma wave_option(trace: disable)'
+// directive.
+//
+// This policy type is used as a template parameter to the boost::wave::context<>
+// object.
+//
+///////////////////////////////////////////////////////////////////////////////
+template <typename TokenT>
+class trace_macro_expansion
+: 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_, bool preserve_bol_whitespace_,
+ std::ofstream &output_, std::ostream &tracestrm_,
+ std::ostream &includestrm_, std::ostream &guardstrm_,
+ trace_flags flags_, bool enable_system_command_,
+ bool& generate_output_, std::string const& default_outfile_)
+ : outputstrm(output_), tracestrm(tracestrm_),
+ includestrm(includestrm_), guardstrm(guardstrm_),
+ level(0), flags(flags_), logging_flags(trace_nothing),
+ enable_system_command(enable_system_command_),
+ preserve_whitespace(preserve_whitespace_),
+ preserve_bol_whitespace(preserve_bol_whitespace_),
+ generate_output(generate_output_),
+ default_outfile(default_outfile_),
+ emit_relative_filenames(false)
+ {
+ }
+ ~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;
+ }
+
+ void enable_relative_names_in_line_directives(bool flag)
+ {
+ emit_relative_filenames = flag;
+ }
+ bool enable_relative_names_in_line_directives() const
+ {
+ return emit_relative_filenames;
+ }
+
+ // add a macro name, which should not be expanded at all (left untouched)
+ void add_noexpandmacro(std::string const& name)
+ {
+ noexpandmacros.insert(name);
+ }
+
+ void set_license_info(std::string const& info)
+ {
+ license_info = info;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'expanding_function_like_macro' is called whenever a
+ // function-like macro is to be expanded.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'macrodef' marks the position, where the macro to expand
+ // is defined.
+ //
+ // The parameter 'formal_args' holds the formal arguments used during the
+ // definition of the macro.
+ //
+ // The parameter 'definition' holds the macro definition for the macro to
+ // trace.
+ //
+ // The parameter 'macro_call' marks the position, where this macro invoked.
+ //
+ // The parameter 'arguments' holds the macro arguments used during the
+ // invocation of the macro
+ //
+ // The parameters 'seqstart' and 'seqend' point into the input token
+ // stream allowing to access the whole token sequence comprising the macro
+ // invocation (starting with the opening parenthesis and ending after the
+ // closing one).
+ //
+ // The return value defines whether the corresponding macro will be
+ // expanded (return false) or will be copied to the output (return true).
+ // Note: the whole argument list is copied unchanged to the output as well
+ // without any further processing.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
+ // old signature
+ template <typename ContainerT>
+ void expanding_function_like_macro(
+ TokenT const &macrodef, std::vector<TokenT> const &formal_args,
+ 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
+ // new signature
+ template <typename ContextT, typename ContainerT, typename IteratorT>
+ bool
+ expanding_function_like_macro(ContextT const& ctx,
+ TokenT const &macrodef, std::vector<TokenT> const &formal_args,
+ ContainerT const &definition,
+ TokenT const &macrocall, std::vector<ContainerT> const &arguments,
+ IteratorT const& seqstart, IteratorT const& seqend)
+ {
+ if (enabled_macro_counting() || !noexpandmacros.empty()) {
+ std::string name (macrodef.get_value().c_str());
+
+ if (noexpandmacros.find(name.c_str()) != noexpandmacros.end())
+ return true; // do not expand this macro
+
+ if (enabled_macro_counting())
+ count_invocation(name.c_str());
+ }
+
+ if (!enabled_macro_tracing())
+ return false;
+#endif
+ if (0 == get_level()) {
+ // output header line
+ BOOST_WAVE_OSSTREAM stream;
+
+ stream
+ << macrocall.get_position() << ": "
+ << macrocall.get_value() << "(";
+
+ // argument list
+ for (typename ContainerT::size_type i = 0; i < arguments.size(); ++i) {
+ stream << boost::wave::util::impl::as_string(arguments[i]);
+ if (i < arguments.size()-1)
+ stream << ", ";
+ }
+ stream << ")" << std::endl;
+ output(BOOST_WAVE_GETSTRING(stream));
+ increment_level();
+ }
+
+ // output definition reference
+ {
+ BOOST_WAVE_OSSTREAM stream;
+
+ stream
+ << macrodef.get_position() << ": see macro definition: "
+ << macrodef.get_value() << "(";
+
+ // formal argument list
+ for (typename std::vector<TokenT>::size_type i = 0;
+ i < formal_args.size(); ++i)
+ {
+ stream << formal_args[i].get_value();
+ if (i < formal_args.size()-1)
+ stream << ", ";
+ }
+ stream << ")" << std::endl;
+ output(BOOST_WAVE_GETSTRING(stream));
+ }
+
+ if (formal_args.size() > 0) {
+ // map formal and real arguments
+ open_trace_body("invoked with\n");
+ for (typename std::vector<TokenT>::size_type j = 0;
+ j < formal_args.size(); ++j)
+ {
+ using namespace boost::wave;
+
+ BOOST_WAVE_OSSTREAM stream;
+ stream << formal_args[j].get_value() << " = ";
+#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
+ if (T_ELLIPSIS == token_id(formal_args[j])) {
+ // ellipsis
+ for (typename ContainerT::size_type k = j;
+ k < arguments.size(); ++k)
+ {
+ stream << boost::wave::util::impl::as_string(arguments[k]);
+ if (k < arguments.size()-1)
+ stream << ", ";
+ }
+ }
+ else
+#endif
+ {
+ stream << boost::wave::util::impl::as_string(arguments[j]);
+ }
+ stream << std::endl;
+ output(BOOST_WAVE_GETSTRING(stream));
+ }
+ close_trace_body();
+ }
+ open_trace_body();
+
+#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS == 0
+ return false;
+#endif
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'expanding_object_like_macro' is called whenever a
+ // object-like macro is to be expanded .
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'macrodef' marks the position, where the macro to expand
+ // is defined.
+ //
+ // The definition 'definition' holds the macro definition for the macro to
+ // trace.
+ //
+ // The parameter 'macrocall' marks the position, where this macro invoked.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
+ // old signature
+ template <typename ContainerT>
+ 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
+ // new signature
+ template <typename ContextT, typename ContainerT>
+ bool
+ expanding_object_like_macro(ContextT const& ctx,
+ TokenT const &macrodef, ContainerT const &definition,
+ TokenT const &macrocall)
+ {
+ if (enabled_macro_counting() || !noexpandmacros.empty()) {
+ std::string name (macrodef.get_value().c_str());
+
+ if (noexpandmacros.find(name.c_str()) != noexpandmacros.end())
+ return true; // do not expand this macro
+
+ if (enabled_macro_counting())
+ count_invocation(name.c_str());
+ }
+
+ if (!enabled_macro_tracing())
+ return false;
+#endif
+ if (0 == get_level()) {
+ // output header line
+ BOOST_WAVE_OSSTREAM stream;
+
+ stream
+ << macrocall.get_position() << ": "
+ << macrocall.get_value() << std::endl;
+ output(BOOST_WAVE_GETSTRING(stream));
+ increment_level();
+ }
+
+ // output definition reference
+ {
+ BOOST_WAVE_OSSTREAM stream;
+
+ stream
+ << macrodef.get_position() << ": see macro definition: "
+ << macrodef.get_value() << std::endl;
+ output(BOOST_WAVE_GETSTRING(stream));
+ }
+ open_trace_body();
+
+#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS == 0
+ return false;
+#endif
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'expanded_macro' is called whenever the expansion of a
+ // macro is finished but before the rescanning process starts.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'result' contains the token sequence generated as the
+ // result of the macro expansion.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
+ // old signature
+ template <typename ContainerT>
+ void expanded_macro(ContainerT const &result)
+#else
+ // new signature
+ template <typename ContextT, typename ContainerT>
+ void expanded_macro(ContextT const& ctx,ContainerT const &result)
+#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));
+
+ open_trace_body("rescanning\n");
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'rescanned_macro' is called whenever the rescanning of a
+ // macro is finished.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'result' contains the token sequence generated as the
+ // result of the rescanning.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
+ // old signature
+ template <typename ContainerT>
+ void rescanned_macro(ContainerT const &result)
+#else
+ // new signature
+ template <typename ContextT, typename ContainerT>
+ void rescanned_macro(ContextT const& ctx,ContainerT const &result)
+#endif
+ {
+ if (!enabled_macro_tracing() || get_level() == 0)
+ return;
+
+ BOOST_WAVE_OSSTREAM stream;
+ stream << boost::wave::util::impl::as_string(result) << std::endl;
+ output(BOOST_WAVE_GETSTRING(stream));
+ close_trace_body();
+ close_trace_body();
+
+ if (1 == get_level())
+ decrement_level();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'interpret_pragma' is called whenever a #pragma command
+ // directive is found which isn't known to the core Wave library, where
+ // command is the value defined as the BOOST_WAVE_PRAGMA_KEYWORD constant
+ // which defaults to "wave".
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'pending' may be used to push tokens back into the input
+ // stream, which are to be used as the replacement text for the whole
+ // #pragma directive.
+ //
+ // The parameter 'option' contains the name of the interpreted pragma.
+ //
+ // The parameter 'values' holds the values of the parameter provided to
+ // the pragma operator.
+ //
+ // The parameter 'act_token' contains the actual #pragma token, which may
+ // be used for error output.
+ //
+ // If the return value is 'false', the whole #pragma directive is
+ // interpreted as unknown and a corresponding error message is issued. A
+ // return value of 'true' signs a successful interpretation of the given
+ // #pragma.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename ContextT, typename ContainerT>
+ bool
+ interpret_pragma(ContextT &ctx, ContainerT &pending,
+ typename ContextT::token_type const &option, ContainerT const &valuetokens,
+ typename ContextT::token_type const &act_token)
+ {
+ typedef typename ContextT::token_type token_type;
+
+ ContainerT values(valuetokens);
+ boost::wave::util::impl::trim_sequence(values); // trim whitespace
+
+ if (option.get_value() == "timer") {
+ // #pragma wave timer(value)
+ if (0 == values.size()) {
+ // no value means '1'
+ using namespace boost::wave;
+ timer(token_type(T_INTLIT, "1", act_token.get_position()));
+ }
+ else {
+ timer(values.front());
+ }
+ return true;
+ }
+ if (option.get_value() == "trace") {
+ // enable/disable tracing option
+ return interpret_pragma_trace(ctx, values, act_token);
+ }
+ if (option.get_value() == "system") {
+ if (!enable_system_command) {
+ // if the #pragma wave system() directive is not enabled, throw
+ // a corresponding error (actually its a remark),
+ typename ContextT::string_type msg(
+ boost::wave::util::impl::as_string(values));
+ BOOST_WAVE_THROW_CTX(ctx, bad_pragma_exception,
+ pragma_system_not_enabled,
+ msg.c_str(), 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);
+ }
+ if (option.get_value() == "stop") {
+ // stop the execution and output the argument
+ typename ContextT::string_type msg(
+ boost::wave::util::impl::as_string(values));
+ BOOST_WAVE_THROW_CTX(ctx, boost::wave::preprocess_exception,
+ error_directive, msg.c_str(), act_token.get_position());
+ return false;
+ }
+ if (option.get_value() == "option") {
+ // handle different options
+ return interpret_pragma_option(ctx, values, act_token);
+ }
+ return false;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'emit_line_directive' is called whenever a #line directive
+ // has to be emitted into the generated output.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'pending' may be used to push tokens back into the input
+ // stream, which are to be used instead of the default output generated
+ // for the #line directive.
+ //
+ // The parameter 'act_token' contains the actual #pragma token, which may
+ // be used for error output. The line number stored in this token can be
+ // used as the line number emitted as part of the #line directive.
+ //
+ // If the return value is 'false', a default #line directive is emitted
+ // by the library. A return value of 'true' will inhibit any further
+ // actions, the tokens contained in 'pending' will be copied verbatim
+ // to the output.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename ContextT, typename ContainerT>
+ bool
+ emit_line_directive(ContextT const& ctx, ContainerT &pending,
+ typename ContextT::token_type const& act_token)
+ {
+ if (!need_emit_line_directives(ctx.get_language()) ||
+ !enable_relative_names_in_line_directives())
+ {
+ return false;
+ }
+
+ // emit a #line directive showing the relative filename instead
+ typename ContextT::position_type pos = act_token.get_position();
+ unsigned int column = 6;
+
+ typedef typename ContextT::token_type result_type;
+ using namespace boost::wave;
+
+ pos.set_column(1);
+ pending.push_back(result_type(T_PP_LINE, "#line", pos));
+
+ pos.set_column(column); // account for '#line'
+ pending.push_back(result_type(T_SPACE, " ", pos));
+
+ // 21 is the max required size for a 64 bit integer represented as a
+ // string
+ char buffer[22];
+
+ using namespace std; // for some systems sprintf is in namespace std
+ sprintf (buffer, "%zd", pos.get_line());
+
+ pos.set_column(++column); // account for ' '
+ pending.push_back(result_type(T_INTLIT, buffer, pos));
+ pos.set_column(column += (unsigned int)strlen(buffer)); // account for <number>
+ pending.push_back(result_type(T_SPACE, " ", pos));
+ pos.set_column(++column); // account for ' '
+
+ std::string file("\"");
+ boost::filesystem::path filename(
+ boost::wave::util::create_path(ctx.get_current_relative_filename().c_str()));
+
+ using boost::wave::util::impl::escape_lit;
+ file += escape_lit(boost::wave::util::native_file_string(filename)) + "\"";
+
+ pending.push_back(result_type(T_STRINGLIT, file.c_str(), pos));
+ pos.set_column(column += (unsigned int)file.size()); // account for filename
+ pending.push_back(result_type(T_GENERATEDNEWLINE, "\n", pos));
+
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'opened_include_file' is called whenever a file referred
+ // by an #include directive was successfully located and opened.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'filename' contains the file system path of the
+ // opened file (this is relative to the directory of the currently
+ // processed file or a absolute path depending on the paths given as the
+ // include search paths).
+ //
+ // The include_depth parameter contains the current include file depth.
+ //
+ // The is_system_include parameter denotes, whether the given file was
+ // found as a result of a #include <...> directive.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
+ // old signature
+ void
+ opened_include_file(std::string const &relname, std::string const &absname,
+ std::size_t include_depth, bool is_system_include)
+ {
+#else
+ // new signature
+ template <typename ContextT>
+ void
+ opened_include_file(ContextT const& ctx, std::string const &relname,
+ std::string const &absname, bool is_system_include)
+ {
+ std::size_t include_depth = ctx.get_iteration_depth();
+#endif
+ if (enabled_include_tracing()) {
+ // print indented filename
+ for (std::size_t i = 0; i < include_depth; ++i)
+ includestrm << " ";
+
+ if (is_system_include)
+ includestrm << "<" << relname << "> (" << absname << ")";
+ else
+ includestrm << "\"" << relname << "\" (" << absname << ")";
+
+ includestrm << std::endl;
+ }
+ }
+
+#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'detected_include_guard' is called whenever either a
+ // include file is about to be added to the list of #pragma once headers.
+ // That means this header file will not be opened and parsed again even
+ // if it is specified in a later #include directive.
+ // This function is called as the result of a detected include guard
+ // scheme.
+ //
+ // The implemented heuristics for include guards detects two forms of
+ // include guards:
+ //
+ // #ifndef INCLUDE_GUARD_MACRO
+ // #define INCLUDE_GUARD_MACRO
+ // ...
+ // #endif
+ //
+ // or
+ //
+ // if !defined(INCLUDE_GUARD_MACRO)
+ // #define INCLUDE_GUARD_MACRO
+ // ...
+ // #endif
+ //
+ // note, that the parenthesis are optional (i.e. !defined INCLUDE_GUARD_MACRO
+ // will work as well). The code allows for any whitespace, newline and single
+ // '#' tokens before the #if/#ifndef and after the final #endif.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'filename' contains the file system path of the
+ // opened file (this is relative to the directory of the currently
+ // processed file or a absolute path depending on the paths given as the
+ // include search paths).
+ //
+ // The parameter contains the name of the detected include guard.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename ContextT>
+ void
+ detected_include_guard(ContextT const& ctx, std::string const& filename,
+ std::string const& include_guard)
+ {
+ if (enabled_guard_tracing()) {
+ guardstrm << include_guard << ":" << std::endl
+ << " " << filename << std::endl;
+ }
+ }
+#endif
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'may_skip_whitespace' will be called by the
+ // library whenever a token is about to be returned to the calling
+ // application.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The 'token' parameter holds a reference to the current token. The policy
+ // is free to change this token if needed.
+ //
+ // The 'skipped_newline' parameter holds a reference to a boolean value
+ // which should be set to true by the policy function whenever a newline
+ // is going to be skipped.
+ //
+ // If the return value is true, the given token is skipped and the
+ // preprocessing continues to the next token. If the return value is
+ // false, the given token is returned to the calling application.
+ //
+ // ATTENTION!
+ // Caution has to be used, because by returning true the policy function
+ // is able to force skipping even significant tokens, not only whitespace.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename ContextT>
+ bool may_skip_whitespace(ContextT const &ctx, TokenT &token,
+ bool &skipped_newline)
+ {
+ return this->base_type::may_skip_whitespace(
+ ctx, token, need_preserve_comments(ctx.get_language()),
+ preserve_bol_whitespace, skipped_newline) ?
+ !preserve_whitespace : false;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // The function 'throw_exception' will be called by the library whenever a
+ // preprocessing exception occurs.
+ //
+ // The parameter 'ctx' is a reference to the context object used for
+ // instantiating the preprocessing iterators by the user.
+ //
+ // The parameter 'e' is the exception object containing detailed error
+ // information.
+ //
+ // The default behavior is to call the function boost::throw_exception.
+ //
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename ContextT>
+ void
+ throw_exception(ContextT const& ctx, boost::wave::preprocess_exception const& e)
+ {
+#if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0
+ if (!is_import_directive_error(e))
+ boost::throw_exception(e);
+#else
+ boost::throw_exception(e);
+#endif
+ }
+ using base_type::throw_exception;
+
+protected:
+#if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0
+ ///////////////////////////////////////////////////////////////////////////
+ // Avoid throwing an error from a #import directive
+ bool is_import_directive_error(boost::wave::preprocess_exception const& e)
+ {
+ using namespace boost::wave;
+ if (e.get_errorcode() != preprocess_exception::ill_formed_directive)
+ return false;
+
+ // the error string is formatted as 'severity: error: directive'
+ std::string error(e.description());
+ std::string::size_type p = error.find_last_of(":");
+ return p != std::string::npos && error.substr(p+2) == "import";
+ }
+#endif
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Interpret the different Wave specific pragma directives/operators
+ template <typename ContextT, typename ContainerT>
+ bool
+ interpret_pragma_trace(ContextT& ctx, ContainerT const &values,
+ typename ContextT::token_type const &act_token)
+ {
+ typedef typename ContextT::token_type token_type;
+ typedef typename token_type::string_type string_type;
+
+ bool valid_option = false;
+
+ if (1 == values.size()) {
+ token_type const &value = values.front();
+
+ if (value.get_value() == "enable" ||
+ value.get_value() == "on" ||
+ value.get_value() == "1")
+ {
+ // #pragma wave trace(enable)
+ enable_tracing(static_cast<trace_flags>(
+ tracing_enabled() | trace_macros));
+ valid_option = true;
+ }
+ else if (value.get_value() == "disable" ||
+ value.get_value() == "off" ||
+ value.get_value() == "0")
+ {
+ // #pragma wave trace(disable)
+ enable_tracing(static_cast<trace_flags>(
+ tracing_enabled() & ~trace_macros));
+ valid_option = true;
+ }
+ }
+ if (!valid_option) {
+ // unknown option value
+ string_type option_str ("trace");
+
+ if (values.size() > 0) {
+ option_str += "(";
+ option_str += boost::wave::util::impl::as_string(values);
+ option_str += ")";
+ }
+ BOOST_WAVE_THROW_CTX(ctx, boost::wave::preprocess_exception,
+ ill_formed_pragma_option, option_str.c_str(),
+ act_token.get_position());
+ return false;
+ }
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // interpret the pragma wave option(preserve: [0|1|2|3|push|pop]) directive
+ template <typename ContextT>
+ static bool
+ interpret_pragma_option_preserve_set(int mode, bool &preserve_whitespace,
+ bool& preserve_bol_whitespace, ContextT &ctx)
+ {
+ switch(mode) {
+ // preserve no whitespace
+ case 0:
+ preserve_whitespace = false;
+ preserve_bol_whitespace = false;
+ ctx.set_language(
+ enable_preserve_comments(ctx.get_language(), false),
+ false);
+ break;
+
+ // preserve BOL whitespace only
+ case 1:
+ preserve_whitespace = false;
+ preserve_bol_whitespace = true;
+ ctx.set_language(
+ enable_preserve_comments(ctx.get_language(), false),
+ false);
+ break;
+
+ // preserve comments and BOL whitespace only
+ case 2:
+ preserve_whitespace = false;
+ preserve_bol_whitespace = true;
+ ctx.set_language(
+ enable_preserve_comments(ctx.get_language()),
+ false);
+ break;
+
+ // preserve all whitespace
+ case 3:
+ preserve_whitespace = true;
+ preserve_bol_whitespace = true;
+ ctx.set_language(
+ enable_preserve_comments(ctx.get_language()),
+ false);
+ break;
+
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ template <typename ContextT, typename IteratorT>
+ bool
+ interpret_pragma_option_preserve(ContextT &ctx, IteratorT &it,
+ IteratorT end, typename ContextT::token_type const &act_token)
+ {
+ using namespace boost::wave;
+
+ 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") {
+ // push current preserve option onto the internal option stack
+ if (need_preserve_comments(ctx.get_language())) {
+ if (preserve_whitespace)
+ preserve_options.push(3);
+ else
+ preserve_options.push(2);
+ }
+ else if (preserve_bol_whitespace) {
+ preserve_options.push(1);
+ }
+ else {
+ preserve_options.push(0);
+ }
+ return true;
+ }
+ else if ((*it).get_value() == "pop") {
+ // test for mismatched push/pop #pragmas
+ if (preserve_options.empty()) {
+ BOOST_WAVE_THROW_CTX(ctx, bad_pragma_exception,
+ pragma_mismatched_push_pop, "preserve",
+ act_token.get_position());
+ }
+
+ // pop output preserve from the internal option stack
+ bool result = interpret_pragma_option_preserve_set(
+ preserve_options.top(), preserve_whitespace,
+ preserve_bol_whitespace, ctx);
+ preserve_options.pop();
+ return result;
+ }
+ return false;
+ }
+
+ 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,
+ preserve_bol_whitespace, ctx);
+ }
+
+ // interpret the pragma wave option(line: [0|1|2|push|pop]) directive
+ template <typename ContextT, typename IteratorT>
+ bool
+ interpret_pragma_option_line(ContextT &ctx, IteratorT &it,
+ IteratorT end, typename ContextT::token_type const &act_token)
+ {
+ using namespace boost::wave;
+
+ 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") {
+ // push current line option onto the internal option stack
+ int mode = 0;
+ if (need_emit_line_directives(ctx.get_language())) {
+ mode = 1;
+ if (enable_relative_names_in_line_directives())
+ mode = 2;
+ }
+ line_options.push(mode);
+ return true;
+ }
+ else if ((*it).get_value() == "pop") {
+ // test for mismatched push/pop #pragmas
+ if (line_options.empty()) {
+ BOOST_WAVE_THROW_CTX(ctx, bad_pragma_exception,
+ 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(), 0 != line_options.top()),
+ false);
+ enable_relative_names_in_line_directives(2 == line_options.top());
+ line_options.pop();
+ return true;
+ }
+ return false;
+ }
+
+ 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 || 2 == emit_lines) {
+ // set the new emit #line directive mode
+ ctx.set_language(
+ enable_emit_line_directives(ctx.get_language(), emit_lines),
+ false);
+ return true;
+ }
+ return false;
+ }
+
+ // interpret the pragma wave option(output: ["filename"|null|default|push|pop])
+ // directive
+ template <typename ContextT>
+ bool
+ interpret_pragma_option_output_open(boost::filesystem::path &fpath,
+ ContextT& ctx, typename ContextT::token_type const &act_token)
+ {
+ namespace fs = boost::filesystem;
+
+ // ensure all directories for this file do exist
+ boost::wave::util::create_directories(
+ boost::wave::util::branch_path(fpath));
+
+ // figure out, whether the file has been written to by us, if yes, we
+ // append any output to this file, otherwise we overwrite it
+ std::ios::openmode mode = std::ios::out;
+ if (fs::exists(fpath) && written_by_us.find(fpath) != written_by_us.end())
+ mode = (std::ios::openmode)(std::ios::out | std::ios::app);
+
+ written_by_us.insert(fpath);
+
+ // close the current file
+ if (outputstrm.is_open())
+ outputstrm.close();
+
+ // open the new file
+ outputstrm.open(fpath.string().c_str(), mode);
+ if (!outputstrm.is_open()) {
+ BOOST_WAVE_THROW_CTX(ctx, boost::wave::preprocess_exception,
+ could_not_open_output_file,
+ fpath.string().c_str(), act_token.get_position());
+ return false;
+ }
+
+ // write license text, if file was created and if requested
+ if (mode == std::ios::out && !license_info.empty())
+ outputstrm << license_info;
+
+ generate_output = true;
+ current_outfile = fpath;
+ return true;
+ }
+
+ bool interpret_pragma_option_output_close(bool generate)
+ {
+ if (outputstrm.is_open())
+ outputstrm.close();
+ current_outfile = boost::filesystem::path();
+ generate_output = generate;
+ return true;
+ }
+
+ template <typename ContextT, typename IteratorT>
+ bool
+ interpret_pragma_option_output(ContextT &ctx, IteratorT &it,
+ IteratorT end, typename ContextT::token_type const &act_token)
+ {
+ 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;
+
+ string_type fname ((*it).get_value());
+ fs::path fpath (boost::wave::util::create_path(
+ util::impl::unescape_lit(fname.substr(1, fname.size()-2)).c_str()));
+ fpath = boost::wave::util::complete_path(fpath, ctx.get_current_directory());
+ result = interpret_pragma_option_output_open(fpath, ctx, act_token);
+ }
+ else if (T_IDENTIFIER == id) {
+ if ((*it).get_value() == "null") {
+ // suppress all output from this point on
+ result = interpret_pragma_option_output_close(false);
+ }
+ else if ((*it).get_value() == "push") {
+ // initialize the current_outfile, if appropriate
+ if (output_options.empty() && current_outfile.empty() &&
+ !default_outfile.empty() && default_outfile != "-")
+ {
+ current_outfile = boost::wave::util::complete_path(
+ default_outfile, ctx.get_current_directory());
+ }
+
+ // push current output option onto the internal option stack
+ output_options.push(
+ output_option_type(generate_output, current_outfile));
+ result = true;
+ }
+ else if ((*it).get_value() == "pop") {
+ // test for mismatched push/pop #pragmas
+ if (output_options.empty()) {
+ BOOST_WAVE_THROW_CTX(ctx, bad_pragma_exception,
+ pragma_mismatched_push_pop, "output",
+ 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;
+ current_outfile = opts.second;
+ if (!current_outfile.empty()) {
+ // re-open the last file
+ result = interpret_pragma_option_output_open(current_outfile,
+ ctx, act_token);
+ }
+ else {
+ // either no output or generate to std::cout
+ result = interpret_pragma_option_output_close(generate_output);
+ }
+ output_options.pop();
+ }
+ }
+ else if (T_DEFAULT == id) {
+ // re-open the default output given on command line
+ if (!default_outfile.empty()) {
+ if (default_outfile == "-") {
+ // the output was suppressed on the command line
+ result = interpret_pragma_option_output_close(false);
+ }
+ else {
+ // there was a file name on the command line
+ fs::path fpath(boost::wave::util::create_path(default_outfile));
+ result = interpret_pragma_option_output_open(fpath, ctx,
+ act_token);
+ }
+ }
+ else {
+ // generate the output to std::cout
+ result = interpret_pragma_option_output_close(true);
+ }
+ }
+ return result;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // join all adjacent string tokens into the first one
+ template <typename StringT>
+ StringT unlit(StringT const& str)
+ {
+ return str.substr(1, str.size()-2);
+ }
+
+ template <typename StringT>
+ StringT merge_string_lits(StringT const& lhs, StringT const& rhs)
+ {
+ StringT result ("\"");
+
+ result += unlit(lhs);
+ result += unlit(rhs);
+ result += "\"";
+ return result;
+ }
+
+ template <typename ContextT, typename ContainerT>
+ void join_adjacent_string_tokens(ContextT &ctx, ContainerT const& values,
+ ContainerT& joined_values)
+ {
+ 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;
+ typedef typename ContainerT::iterator iterator;
+
+ token_type* current = 0;
+
+ const_iterator end = values.end();
+ for (const_iterator it = values.begin(); it != end; ++it) {
+ token_id id(*it);
+
+ if (id == T_STRINGLIT) {
+ if (!current) {
+ joined_values.push_back(*it);
+ current = &joined_values.back();
+ }
+ else {
+ current->set_value(merge_string_lits(
+ current->get_value(), (*it).get_value()));
+ }
+ }
+ else if (current) {
+ typedef util::impl::next_token<const_iterator> next_token_type;
+ token_id next_id (next_token_type::peek(it, end, true));
+
+ if (next_id != T_STRINGLIT) {
+ current = 0;
+ joined_values.push_back(*it);
+ }
+ }
+ else {
+ joined_values.push_back(*it);
+ }
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // interpret the pragma wave option() directives
+ template <typename ContextT, typename ContainerT>
+ bool
+ interpret_pragma_option(ContextT &ctx, ContainerT const &cvalues,
+ 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;
+
+ ContainerT values;
+ join_adjacent_string_tokens(ctx, cvalues, values);
+
+ 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|3|push|pop])
+ valid_option = interpret_pragma_option_preserve(ctx, it, end,
+ act_token);
+ }
+ else if (value.get_value() == "line") {
+ // #pragma wave option(line: [0|1|2|push|pop])
+ valid_option = interpret_pragma_option_line(ctx, it, end,
+ act_token);
+ }
+ else if (value.get_value() == "output") {
+ // #pragma wave option(output: ["filename"|null|default|push|pop])
+ valid_option = interpret_pragma_option_output(ctx, it, end,
+ act_token);
+ }
+
+ if (!valid_option) {
+ // unknown option value
+ string_type option_str ("option");
+
+ if (values.size() > 0) {
+ option_str += "(";
+ option_str += util::impl::as_string(values);
+ option_str += ")";
+ }
+ BOOST_WAVE_THROW_CTX(ctx, boost::wave::preprocess_exception,
+ ill_formed_pragma_option,
+ option_str.c_str(), act_token.get_position());
+ return false;
+ }
+
+ token_id id = util::impl::skip_whitespace(it, end);
+ if (id == T_COMMA)
+ util::impl::skip_whitespace(it, end);
+ }
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // interpret the #pragma wave system() directive
+ template <typename ContextT, typename ContainerT>
+ bool
+ interpret_pragma_system(ContextT& ctx, ContainerT &pending,
+ ContainerT const &values,
+ typename ContextT::token_type const &act_token)
+ {
+ typedef typename ContextT::token_type token_type;
+ 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));
+ string_type native_cmd(system_str);
+
+ system_str += " >" + stdout_file + " 2>" + stderr_file;
+ 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, boost::wave::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;
+ typedef typename ContextT::input_policy_type input_policy_type;
+ typedef boost::wave::iteration_context<
+ ContextT, lexer_type, input_policy_type>
+ iteration_context_type;
+
+ iteration_context_type iter_ctx(ctx, stdout_file.c_str(),
+ act_token.get_position(), ctx.get_language());
+ ContainerT pragma;
+
+ for (/**/; iter_ctx.first != iter_ctx.last; ++iter_ctx.first)
+ pragma.push_back(*iter_ctx.first);
+
+ // prepend the newly generated token sequence to the 'pending' container
+ pending.splice(pending.begin(), pragma);
+
+ // erase the created tempfiles
+ std::remove(stdout_file.c_str());
+ std::remove(stderr_file.c_str());
+ return true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The function enable_tracing is called, whenever the status of the
+ // tracing was changed.
+ // The parameter 'enable' is to be used as the new tracing status.
+ void enable_tracing(trace_flags flags)
+ { logging_flags = flags; }
+
+ // The function tracing_enabled should return the current tracing status.
+ trace_flags tracing_enabled()
+ { return logging_flags; }
+
+ // Helper functions for generating the trace output
+ void open_trace_body(char const *label = 0)
+ {
+ if (label)
+ output(label);
+ output("[\n");
+ increment_level();
+ }
+ void close_trace_body()
+ {
+ if (get_level() > 0) {
+ decrement_level();
+ output("]\n");
+ tracestrm << std::flush; // flush the stream buffer
+ }
+ }
+
+ template <typename StringT>
+ void output(StringT const &outstr) const
+ {
+ indent(get_level());
+ tracestrm << outstr; // output the given string
+ }
+
+ void indent(int level) const
+ {
+ for (int i = 0; i < level; ++i)
+ tracestrm << " "; // indent
+ }
+
+ 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);
+ }
+ bool enabled_include_tracing() const
+ {
+ return (flags & trace_includes);
+ }
+ bool enabled_guard_tracing() const
+ {
+ return (flags & trace_guards);
+ }
+ 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") {
+ // restart the timer
+ elapsed_time.restart();
+ }
+ else if (value.get_value() == "1") {
+ // print out the current elapsed time
+ std::cerr
+ << value.get_position() << ": "
+ << elapsed_time.format_elapsed_time()
+ << std::endl;
+ }
+ else if (value.get_value() == "suspend") {
+ // suspend the timer
+ elapsed_time.suspend();
+ }
+ else if (value.get_value() == "resume") {
+ // resume the timer
+ elapsed_time.resume();
+ }
+ }
+
+private:
+ std::ofstream &outputstrm; // main output stream
+ std::ostream &tracestrm; // trace output stream
+ std::ostream &includestrm; // included list output stream
+ std::ostream &guardstrm; // include guard output stream
+ int level; // indentation level
+ trace_flags flags; // enabled globally
+ trace_flags logging_flags; // enabled by a #pragma
+ bool enable_system_command; // enable #pragma wave system() command
+ bool preserve_whitespace; // enable whitespace preservation
+ bool preserve_bol_whitespace; // enable begin of line whitespace preservation
+ 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::set<boost::filesystem::path> written_by_us; // all files we have written to
+
+ 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
+ bool emit_relative_filenames; // emit relative names in #line directives
+
+ std::set<std::string> noexpandmacros; // list of macros not to expand
+
+ std::string license_info; // text to pre-pend to all generated output files
+};
+
+#undef BOOST_WAVE_GETSTRING
+#undef BOOST_WAVE_OSSTREAM
+
+#endif // !defined(TRACE_MACRO_EXPANSION_HPP_D8469318_8407_4B9D_A19F_13CA60C1661F_INCLUDED)