9fd423ca58
[SVN r58724]
168 lines
6.1 KiB
C++
168 lines
6.1 KiB
C++
/*=============================================================================
|
|
Boost.Wave: A Standard compliant C++ preprocessor library
|
|
Example demonstrating how to preprocess the token stream generated by a
|
|
#pragma directive
|
|
|
|
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_SAMPLE_PREPROCESS_PRAGMA_OUTPUT_APR_03_2008_0813AM)
|
|
#define BOOST_WAVE_SAMPLE_PREPROCESS_PRAGMA_OUTPUT_APR_03_2008_0813AM
|
|
|
|
template <typename String, typename Iterator>
|
|
inline String
|
|
as_unescaped_string(Iterator it, Iterator const& end)
|
|
{
|
|
using namespace boost::wave;
|
|
|
|
String result;
|
|
for (/**/; it != end; ++it)
|
|
{
|
|
switch (token_id(*it)) {
|
|
case T_STRINGLIT:
|
|
{
|
|
string val (util::impl::unescape_lit((*it).get_value()).c_str());
|
|
val.erase(val.size()-1);
|
|
val.erase(0, 1);
|
|
result += val;
|
|
}
|
|
break;
|
|
|
|
default: // just skip everything else (hey it's a sample)
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// return the string representation of a token sequence
|
|
template <typename String, typename Container>
|
|
inline String
|
|
as_unescaped_string(Container const &token_sequence)
|
|
{
|
|
return as_unescaped_string<String>(token_sequence.begin(),
|
|
token_sequence.end());
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// The preprocess_pragma_output_hooks policy class is used implement a special
|
|
// #pragma wave pp("some C++ code") directive allowing to insert preprocessed
|
|
// code into the output sequence generated by the tool.
|
|
//
|
|
// This policy type is used as a template parameter to the boost::wave::context<>
|
|
// object.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
class preprocess_pragma_output_hooks
|
|
: public boost::wave::context_policies::default_preprocessing_hooks
|
|
{
|
|
public:
|
|
preprocess_pragma_output_hooks() {}
|
|
|
|
template <typename Context>
|
|
struct reset_language_support
|
|
{
|
|
reset_language_support(Context& ctx)
|
|
: ctx_(ctx), lang_(ctx.get_language())
|
|
{
|
|
ctx.set_language(boost::wave::enable_single_line(lang_), false);
|
|
}
|
|
~reset_language_support()
|
|
{
|
|
ctx_.set_language(lang_, false);
|
|
}
|
|
|
|
Context& ctx_;
|
|
boost::wave::language_support lang_;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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& ctx, Container &pending,
|
|
typename Context::token_type const& option,
|
|
Container const& values, typename Context::token_type const& act_token)
|
|
{
|
|
typedef typename Context::token_type token_type;
|
|
typedef typename Context::iterator_type iterator_type;
|
|
|
|
if (option.get_value() == "pp") {
|
|
// Concatenate the string(s) passed as the options to this pragma,
|
|
// preprocess the result using the current context and insert the
|
|
// generated token sequence in place of the pragma directive into the
|
|
// output stream.
|
|
|
|
try {
|
|
// We're explicitly using a std::string here since the type of the
|
|
// iterators passed to the ctx.begin() below must match the types
|
|
// of the iterator the original context instance has been created
|
|
// with.
|
|
std::string s (as_unescaped_string<std::string>(values));
|
|
reset_language_support<Context> lang(ctx);
|
|
|
|
using namespace boost::wave;
|
|
|
|
// The expanded token sequence is stored in the 'pragma' container
|
|
// to ensure consistency in the output in the case of an error
|
|
// while preprocessing the pragma option strings.
|
|
Container pragma;
|
|
iterator_type end = ctx.end();
|
|
for (iterator_type it = ctx.begin(s.begin(), s.end());
|
|
it != end && token_id(*it) != T_EOF; ++it)
|
|
{
|
|
pragma.push_back(*it);
|
|
it++;
|
|
}
|
|
|
|
// prepend the newly generated token sequence to the 'pending'
|
|
// container
|
|
pending.splice(pending.begin(), pragma);
|
|
}
|
|
catch (boost::wave::preprocess_exception const& /*e*/) {
|
|
// the library will report an 'ill_formed_pragma_option' for us
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// we don't know anything about this #pragma wave directive
|
|
return false;
|
|
}
|
|
};
|
|
|
|
|
|
#endif
|
|
|