| /*============================================================================= |
| 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 |
| |