15c01a454c
[SVN r78634]
874 lines
35 KiB
C++
874 lines
35 KiB
C++
/*=============================================================================
|
|
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(BOOST_WAVE_LIBS_WAVE_TEST_COLLECT_HOOKS_INFORMATION_HPP)
|
|
#define BOOST_WAVE_LIBS_WAVE_TEST_COLLECT_HOOKS_INFORMATION_HPP
|
|
|
|
#include <boost/config.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;
|
|
}
|
|
|
|
#if defined(BOOST_WINDOWS)
|
|
template <typename String>
|
|
inline String replace_slashes(String value, char const* lookfor = "\\",
|
|
char replace_with = '/')
|
|
{
|
|
typename String::size_type p = value.find_first_of(lookfor);
|
|
while (p != value.npos) {
|
|
value[p] = replace_with;
|
|
p = value.find_first_of(lookfor, p+1);
|
|
}
|
|
return value;
|
|
}
|
|
#endif
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
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 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 relname,
|
|
std::string absname, bool is_system_include)
|
|
{
|
|
using boost::wave::util::impl::escape_lit;
|
|
|
|
#if defined(BOOST_WINDOWS)
|
|
relname = replace_slashes(relname);
|
|
absname = replace_slashes(absname);
|
|
#endif
|
|
|
|
BOOST_WAVETEST_OSSTREAM strm;
|
|
strm << "05: " << escape_lit(relname)
|
|
<< " (" << escape_lit(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 filename,
|
|
std::string const& include_guard)
|
|
{
|
|
using boost::wave::util::impl::escape_lit;
|
|
|
|
#if defined(BOOST_WINDOWS)
|
|
filename = replace_slashes(filename);
|
|
#endif
|
|
|
|
BOOST_WAVETEST_OSSTREAM strm;
|
|
strm << "19: " << escape_lit(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 filename)
|
|
{
|
|
using boost::wave::util::impl::escape_lit;
|
|
|
|
#if defined(BOOST_WINDOWS)
|
|
filename = replace_slashes(filename);
|
|
#endif
|
|
|
|
BOOST_WAVETEST_OSSTREAM strm;
|
|
strm << "20: " << repr(pragma_token.get_position()) << ": "
|
|
<< pragma_token.get_value() << ": "
|
|
<< escape_lit(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
|
|
|
|
|
|
|