123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494 |
- /*=============================================================================
- 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 ¯odef, std::vector<TokenT> const &formal_args,
- ContainerT const &definition,
- TokenT const ¯ocall, std::vector<ContainerT> const &arguments)
- {
- if (enabled_macro_counting())
- count_invocation(macrodef.get_value().c_str());
- if (!enabled_macro_tracing())
- return;
- #else
- // new signature
- template <typename ContextT, typename ContainerT, typename IteratorT>
- bool
- expanding_function_like_macro(ContextT const& ctx,
- TokenT const ¯odef, std::vector<TokenT> const &formal_args,
- ContainerT const &definition,
- TokenT const ¯ocall, 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 ¯odef,
- ContainerT const &definition, TokenT const ¯ocall)
- {
- 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 ¯odef, ContainerT const &definition,
- TokenT const ¯ocall)
- {
- 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)
|