| /*============================================================================= |
| Boost.Wave: A Standard compliant C++ preprocessor library |
| 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) |
| =============================================================================*/ |
| |
| #if !defined(BOOST_WAVE_LIBS_WAVE_TEST_COLLECT_HOOKS_INFORMATION_HPP) |
| #define BOOST_WAVE_LIBS_WAVE_TEST_COLLECT_HOOKS_INFORMATION_HPP |
| |
| #include <boost/lexical_cast.hpp> |
| #include <boost/filesystem/path.hpp> |
| #include <boost/filesystem/operations.hpp> |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // workaround for missing ostringstream |
| #ifdef BOOST_NO_STRINGSTREAM |
| #include <strstream> |
| #define BOOST_WAVETEST_OSSTREAM std::ostrstream |
| std::string BOOST_WAVETEST_GETSTRING(std::ostrstream& ss) |
| { |
| ss << ends; |
| std::string rval = ss.str(); |
| ss.freeze(false); |
| return rval; |
| } |
| #else |
| #include <sstream> |
| #define BOOST_WAVETEST_GETSTRING(ss) ss.str() |
| #define BOOST_WAVETEST_OSSTREAM std::ostringstream |
| #endif |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| template <typename String> |
| String handle_filepath(String const &name) |
| { |
| using boost::wave::util::impl::unescape_lit; |
| |
| String unesc_name (unescape_lit(name)); |
| typename String::size_type p = unesc_name.find_last_of("/\\"); |
| if (p != unesc_name.npos) |
| unesc_name = unesc_name.substr(p+1); |
| return unesc_name; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| template <typename String> |
| inline String repr(boost::wave::util::file_position<String> const& pos) |
| { |
| std::string linenum = boost::lexical_cast<std::string>(pos.get_line()); |
| return handle_filepath(pos.get_file()) + String("(") + linenum.c_str() + ")"; |
| } |
| |
| template <typename String> |
| inline String repr(String const& value) |
| { |
| String result; |
| typename String::const_iterator end = value.end(); |
| for (typename String::const_iterator it = value.begin(); it != end; ++it) |
| { |
| typedef typename String::value_type char_type; |
| char_type c = *it; |
| if (c == static_cast<char_type>('\a')) |
| result.append("\\a"); |
| else if (c == static_cast<char_type>('\b')) |
| result.append("\\b"); |
| else if (c == static_cast<char_type>('\f')) |
| result.append("\\f"); |
| else if (c == static_cast<char_type>('\n')) |
| result.append("\\n"); |
| else if (c == static_cast<char_type>('\r')) |
| result.append("\\r"); |
| else if (c == static_cast<char_type>('\t')) |
| result.append("\\t"); |
| else if (c == static_cast<char_type>('\v')) |
| result.append("\\v"); |
| else |
| result += static_cast<char_type>(c); |
| } |
| return result; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| template <typename Token> |
| class collect_hooks_information |
| : public boost::wave::context_policies::eat_whitespace<Token> |
| { |
| typedef boost::wave::context_policies::eat_whitespace<Token> base_type; |
| |
| public: |
| collect_hooks_information(std::string& trace) |
| : hooks_trace(trace), skipped_token_hooks(false) |
| {} |
| |
| void set_skipped_token_hooks(bool flag) |
| { |
| skipped_token_hooks = flag; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // The function 'expanding_function_like_macro' is called, whenever a |
| // function-like macro is to be expanded. |
| // |
| // 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. |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| |
| template <typename Context, typename Container, typename Iterator> |
| bool |
| expanding_function_like_macro(Context const& ctx, |
| Token const& macro, std::vector<Token> const& formal_args, |
| Container const& definition, |
| Token const& macrocall, std::vector<Container> const& arguments, |
| Iterator const& seqstart, Iterator const& seqend) |
| { |
| BOOST_WAVETEST_OSSTREAM strm; |
| // trace real macro call |
| strm << "00: " << repr(macrocall.get_position()) << ": " |
| << macrocall.get_value() << "("; |
| for (typename std::vector<Token>::size_type i = 0; |
| i < arguments.size(); ++i) |
| { |
| strm << boost::wave::util::impl::as_string(arguments[i]); |
| if (i < arguments.size()-1) |
| strm << ","; |
| } |
| strm << "), "; |
| |
| // trace macro definition |
| strm << "[" << repr(macro.get_position()) << ": " |
| << macro.get_value() << "("; |
| for (typename std::vector<Token>::size_type i = 0; |
| i < formal_args.size(); ++i) |
| { |
| strm << formal_args[i].get_value(); |
| if (i < formal_args.size()-1) |
| strm << ", "; |
| } |
| strm << ")=" << boost::wave::util::impl::as_string(definition) << "]" |
| << std::endl; |
| |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| return false; // default is to normally expand the macro |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // 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 'macro' 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. |
| // |
| // The return value defines, whether the corresponding macro will be |
| // expanded (return false) or will be copied to the output (return true). |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Context, typename Container> |
| bool |
| expanding_object_like_macro(Context const& ctx, Token const& macro, |
| Container const& definition, Token const& macrocall) |
| { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "01: " << repr(macro.get_position()) << ": " |
| << macro.get_value() << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| return false; // default is to normally expand the macro |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // 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. |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Context, typename Container> |
| void expanded_macro(Context const& ctx, Container const& result) |
| { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "02: " << boost::wave::util::impl::as_string(result) << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // 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. |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Context, typename Container> |
| void rescanned_macro(Context const& ctx, Container const& result) |
| { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "03: " << boost::wave::util::impl::as_string(result) << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // The function 'found_include_directive' is called, whenever a #include |
| // directive was located. |
| // |
| // The parameter 'ctx' is a reference to the context object used for |
| // instantiating the preprocessing iterators by the user. |
| // |
| // The parameter 'filename' contains the (expanded) file name found after |
| // the #include directive. This has the format '<file>', '"file"' or |
| // 'file'. |
| // The formats '<file>' or '"file"' are used for #include directives found |
| // in the preprocessed token stream, the format 'file' is used for files |
| // specified through the --force_include command line argument. |
| // |
| // The parameter 'include_next' is set to true if the found directive was |
| // a #include_next directive and the BOOST_WAVE_SUPPORT_INCLUDE_NEXT |
| // preprocessing constant was defined to something != 0. |
| // |
| // The return value defines, whether the found file will be included |
| // (return false) or will be skipped (return true). |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Context> |
| bool |
| found_include_directive(Context const& ctx, std::string const& filename, |
| bool include_next) |
| { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "04: " << filename; |
| if (include_next) |
| strm << " (include_next)"; |
| strm << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| return false; // ok to include this file |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // 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. |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Context> |
| void |
| opened_include_file(Context const& ctx, std::string const& relname, |
| std::string const& absname, bool is_system_include) |
| { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "05: " << relname << " (" << absname << ")" << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // The function 'returning_from_include_file' is called, whenever an |
| // included file is about to be closed after it's processing is complete. |
| // |
| // The parameter 'ctx' is a reference to the context object used for |
| // instantiating the preprocessing iterators by the user. |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Context> |
| void |
| returning_from_include_file(Context const& ctx) |
| { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "06: " << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // 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 Context, typename Container> |
| bool |
| interpret_pragma(Context const& ctx, Container &pending, |
| Token const& option, Container const& values, Token const& act_token) |
| { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "07: " << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| return false; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // The function 'defined_macro' is called, whenever a macro was defined |
| // successfully. |
| // |
| // The parameter 'ctx' is a reference to the context object used for |
| // instantiating the preprocessing iterators by the user. |
| // |
| // The parameter 'name' is a reference to the token holding the macro name. |
| // |
| // The parameter 'is_functionlike' is set to true, whenever the newly |
| // defined macro is defined as a function like macro. |
| // |
| // The parameter 'parameters' holds the parameter tokens for the macro |
| // definition. If the macro has no parameters or if it is a object like |
| // macro, then this container is empty. |
| // |
| // The parameter 'definition' contains the token sequence given as the |
| // replacement sequence (definition part) of the newly defined macro. |
| // |
| // The parameter 'is_predefined' is set to true for all macros predefined |
| // during the initialization phase of the library. |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Context, typename Container> |
| void |
| defined_macro(Context const& ctx, Token const& macro, |
| bool is_functionlike, std::vector<Token> const& pars, |
| Container const& definition, bool is_predefined) |
| { |
| // do not trace the definition of the internal helper macros |
| if (!is_predefined) { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "08: " << repr(macro.get_position()) << ": " |
| << macro.get_value(); |
| if (is_functionlike) { |
| // list the parameter names for function style macros |
| strm << "("; |
| for (typename std::vector<Token>::size_type i = 0; |
| i < pars.size(); ++i) |
| { |
| strm << pars[i].get_value(); |
| if (i < pars.size()-1) |
| strm << ", "; |
| } |
| strm << ")"; |
| } |
| strm << "=" << boost::wave::util::impl::as_string(definition) |
| << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // The function 'undefined_macro' is called, whenever a macro definition |
| // was removed successfully. |
| // |
| // The parameter 'ctx' is a reference to the context object used for |
| // instantiating the preprocessing iterators by the user. |
| // |
| // The parameter 'name' holds the name of the macro, which definition was |
| // removed. |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Context> |
| void |
| undefined_macro(Context const& ctx, Token const& macro) |
| { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "09: " << repr(macro.get_position()) << ": " |
| << macro.get_value() << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // The function 'found_directive' is called, whenever a preprocessor |
| // directive was encountered, but before the corresponding action is |
| // executed. |
| // |
| // The parameter 'ctx' is a reference to the context object used for |
| // instantiating the preprocessing iterators by the user. |
| // |
| // The parameter 'directive' is a reference to the token holding the |
| // preprocessing directive. |
| // |
| // The return value defines, whether the given expression has to be |
| // to be executed in a normal way (return 'false'), or if it has to be |
| // skipped altogether (return 'true'), which means it gets replaced in the |
| // output by a single newline. |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Context> |
| bool |
| found_directive(Context const& ctx, Token const& directive) |
| { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "10: " << repr(directive.get_position()) << ": " |
| << directive.get_value() << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| return false; // by default we never skip any directives |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // The function 'evaluated_conditional_expression' is called, whenever a |
| // conditional preprocessing expression was evaluated (the expression |
| // given to a #if, #elif, #ifdef or #ifndef directive) |
| // |
| // The parameter 'ctx' is a reference to the context object used for |
| // instantiating the preprocessing iterators by the user. |
| // |
| // The parameter 'directive' is a reference to the token holding the |
| // corresponding preprocessing directive. |
| // |
| // The parameter 'expression' holds the non-expanded token sequence |
| // comprising the evaluated expression. |
| // |
| // The parameter expression_value contains the result of the evaluation of |
| // the expression in the current preprocessing context. |
| // |
| // The return value defines, whether the given expression has to be |
| // evaluated again, allowing to decide which of the conditional branches |
| // should be expanded. You need to return 'true' from this hook function |
| // to force the expression to be re-evaluated. |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Context, typename Container> |
| bool |
| evaluated_conditional_expression(Context const& ctx, |
| Token const& directive, Container const& expression, |
| bool expression_value) |
| { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "11: " << repr(directive.get_position()) << ": " |
| << directive.get_value() << " " |
| << boost::wave::util::impl::as_string(expression) << ": " |
| << expression_value << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| return false; // ok to continue, do not re-evaluate expression |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // The function 'skipped_token' is called, whenever a token is about to be |
| // skipped due to a false preprocessor condition (code fragments to be |
| // skipped inside the not evaluated conditional #if/#else/#endif branches). |
| // |
| // The parameter 'ctx' is a reference to the context object used for |
| // instantiating the preprocessing iterators by the user. |
| // |
| // The parameter 'token' refers to the token to be skipped. |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Context> |
| void |
| skipped_token(Context const& ctx, Token const& token) |
| { |
| // this normally generates a lot of noise |
| if (skipped_token_hooks) { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "12: " << repr(token.get_position()) << ": >" |
| << repr(token.get_value()) << "<" << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // The function 'generated_token' will be called by the library whenever a |
| // token is about to be returned from the library. |
| // |
| // The parameter 'ctx' is a reference to the context object used for |
| // instantiating the preprocessing iterators by the user. |
| // |
| // The parameter 't' is the token about to be returned from the library. |
| // This function may alter the token, but in this case it must be |
| // implemented with a corresponding signature: |
| // |
| // Token const& |
| // generated_token(Context const& ctx, Token& t); |
| // |
| // which makes it possible to modify the token in place. |
| // |
| // The default behavior is to return the token passed as the parameter |
| // without modification. |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Context> |
| Token const& |
| generated_token(Context const& ctx, Token const& t) |
| { |
| // this generates a lot of noise |
| // BOOST_WAVETEST_OSSTREAM strm; |
| // strm << "13: " << std::endl; |
| // hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| return t; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // The function 'may_skip_whitespace' will be called by the |
| // library, whenever it must be tested whether a specific token refers to |
| // whitespace and this whitespace has to be skipped. |
| // |
| // 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 Context> |
| bool |
| may_skip_whitespace(Context const& ctx, Token& token, bool& skipped_newline) |
| { |
| // this generates a lot of noise |
| // BOOST_WAVETEST_OSSTREAM strm; |
| // strm << "14: " << std::endl; |
| // hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| return this->base_type::may_skip_whitespace(ctx, token, skipped_newline); |
| } |
| |
| #if BOOST_WAVE_SUPPORT_WARNING_DIRECTIVE != 0 |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // The function 'found_warning_directive' will be called by the library |
| // whenever a #warning directive is found. |
| // |
| // The parameter 'ctx' is a reference to the context object used for |
| // instantiating the preprocessing iterators by the user. |
| // |
| // The parameter 'message' references the argument token sequence of the |
| // encountered #warning directive. |
| // |
| // If the return value is false, the library throws a preprocessor |
| // exception of the type 'warning_directive', if the return value is true |
| // the execution continues as if no #warning directive has been found. |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Context, typename Container> |
| bool |
| found_warning_directive(Context const& ctx, Container const& message) |
| { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "15: " << boost::wave::util::impl::as_string(message) |
| << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| return false; |
| } |
| #endif |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // The function 'found_error_directive' will be called by the library |
| // whenever a #error directive is found. |
| // |
| // The parameter 'ctx' is a reference to the context object used for |
| // instantiating the preprocessing iterators by the user. |
| // |
| // The parameter 'message' references the argument token sequence of the |
| // encountered #error directive. |
| // |
| // If the return value is false, the library throws a preprocessor |
| // exception of the type 'error_directive', if the return value is true |
| // the execution continues as if no #error directive has been found. |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Context, typename Container> |
| bool |
| found_error_directive(Context const& ctx, Container const& message) |
| { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "16: " << boost::wave::util::impl::as_string(message) |
| << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| return false; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // The function 'found_line_directive' will be called by the library |
| // whenever a #line directive is found. |
| // |
| // The parameter 'ctx' is a reference to the context object used for |
| // instantiating the preprocessing iterators by the user. |
| // |
| // The parameter 'arguments' references the argument token sequence of the |
| // encountered #line directive. |
| // |
| // The parameter 'line' contains the recognized line number from the #line |
| // directive. |
| // |
| // The parameter 'filename' references the recognized file name from the |
| // #line directive (if there was one given). |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Context, typename Container> |
| void |
| found_line_directive(Context const& ctx, Container const& arguments, |
| unsigned int line, std::string const& filename) |
| { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "17: " << boost::wave::util::impl::as_string(arguments) |
| << " (" << line << ", \"" << filename << "\")" << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // 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 Context, typename Exception> |
| void |
| throw_exception(Context const& ctx, Exception const& e) |
| { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "18: " << e.what() << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| return this->base_type::throw_exception(ctx, e); |
| } |
| |
| #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) |
| { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "19: " << filename << ": " << include_guard << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // The function 'detected_pragma_once' 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 directive |
| // #pragma once. |
| // |
| // The parameter 'ctx' is a reference to the context object used for |
| // instantiating the preprocessing iterators by the user. |
| // |
| // The parameter pragma_token refers to the token "#pragma" triggering |
| // this preprocessing hook. |
| // |
| // 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). |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename ContextT, typename TokenT> |
| void |
| detected_pragma_once(ContextT const& ctx, TokenT const& pragma_token, |
| std::string const& filename) |
| { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "20: " << repr(pragma_token.get_position()) << ": " |
| << pragma_token.get_value() << ": " << filename << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| } |
| #endif |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // The function 'found_unknown_directive' is called, whenever an unknown |
| // preprocessor directive was encountered. |
| // |
| // The parameter 'ctx' is a reference to the context object used for |
| // instantiating the preprocessing iterators by the user. |
| // |
| // The parameter 'line' holds the tokens of the entire source line |
| // containing the unknown directive. |
| // |
| // 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 |
| // line containing the unknown directive. |
| // |
| // The return value defines, whether the given expression has been |
| // properly interpreted by the hook function or not. If this function |
| // returns 'false', the library will raise an 'ill_formed_directive' |
| // preprocess_exception. Otherwise the tokens pushed back into 'pending' |
| // are passed on to the user program. |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename ContextT, typename ContainerT> |
| bool |
| found_unknown_directive(ContextT const& ctx, ContainerT const& line, |
| ContainerT& pending) |
| { |
| BOOST_WAVETEST_OSSTREAM strm; |
| strm << "21: " << repr((*line.begin()).get_position()) << ": " |
| << boost::wave::util::impl::as_string(line) << std::endl; |
| hooks_trace += BOOST_WAVETEST_GETSTRING(strm); |
| return false; |
| } |
| |
| private: |
| std::string& hooks_trace; |
| bool skipped_token_hooks; |
| }; |
| |
| #endif |
| |
| |
| |