Chris@16: /*============================================================================= Chris@16: Boost.Wave: A Standard compliant C++ preprocessor library Chris@16: Chris@16: http://www.boost.org/ Chris@16: Chris@16: Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost Chris@16: Software License, Version 1.0. (See accompanying file Chris@16: LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: =============================================================================*/ Chris@16: Chris@16: #if !defined(INTERPRET_PRAGMA_HPP_B1F2315E_C5CE_4ED1_A343_0EF548B7942A_INCLUDED) Chris@16: #define INTERPRET_PRAGMA_HPP_B1F2315E_C5CE_4ED1_A343_0EF548B7942A_INCLUDED Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #if !defined(spirit_append_actor) Chris@16: #define spirit_append_actor(actor) boost::spirit::classic::push_back_a(actor) Chris@16: #define spirit_assign_actor(actor) boost::spirit::classic::assign_a(actor) Chris@16: #endif // !defined(spirit_append_actor) Chris@16: Chris@16: // this must occur after all of the includes and before any code appears Chris@16: #ifdef BOOST_HAS_ABI_HEADERS Chris@16: #include BOOST_ABI_PREFIX Chris@16: #endif Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: namespace boost { Chris@16: namespace wave { Chris@16: namespace util { Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // The function interpret_pragma interprets the given token sequence as the Chris@16: // body of a #pragma directive (or parameter to the _Pragma operator) and Chris@16: // executes the actions associated with recognized Wave specific options. Chris@16: // Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: inline bool Chris@16: interpret_pragma(ContextT &ctx, typename ContextT::token_type const &act_token, Chris@16: IteratorT it, IteratorT const &end, ContainerT &pending) Chris@16: { Chris@16: typedef typename ContextT::token_type token_type; Chris@16: typedef typename token_type::string_type string_type; Chris@16: Chris@16: using namespace cpplexer; Chris@16: if (T_IDENTIFIER == token_id(*it)) { Chris@16: // check for pragma wave ... Chris@16: if ((*it).get_value() == BOOST_WAVE_PRAGMA_KEYWORD) Chris@16: { Chris@16: // this is a wave specific option, it should have the form: Chris@16: // Chris@16: // #pragma command option(value) Chris@16: // Chris@16: // where Chris@16: // 'command' is the value of the preprocessor constant Chris@16: // BOOST_WAVE_PRAGMA_KEYWORD (defaults to "wave") and Chris@16: // '(value)' is required only for some pragma directives (this is Chris@16: // optional) Chris@16: // Chris@16: // All recognized #pragma operators are forwarded to the supplied Chris@16: // preprocessing hook. Chris@16: using namespace boost::spirit::classic; Chris@16: token_type option; Chris@16: ContainerT values; Chris@16: Chris@16: if (!parse (++it, end, Chris@16: ( ch_p(T_IDENTIFIER) Chris@16: [ Chris@16: spirit_assign_actor(option) Chris@16: ] Chris@16: | pattern_p(KeywordTokenType, Chris@16: TokenTypeMask|PPTokenFlag) Chris@16: [ Chris@16: spirit_assign_actor(option) Chris@16: ] Chris@16: | pattern_p(OperatorTokenType|AltExtTokenType, Chris@16: ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc. Chris@16: [ Chris@16: spirit_assign_actor(option) Chris@16: ] Chris@16: | pattern_p(BoolLiteralTokenType, Chris@16: TokenTypeMask|PPTokenFlag) Chris@16: [ Chris@16: spirit_assign_actor(option) Chris@16: ] Chris@16: ) Chris@16: >> !comment_nest_p( Chris@16: ch_p(T_LEFTPAREN), Chris@16: ch_p(T_RIGHTPAREN) Chris@16: )[spirit_assign_actor(values)], Chris@16: pattern_p(WhiteSpaceTokenType, TokenTypeMask|PPTokenFlag)).hit) Chris@16: { Chris@16: typename ContextT::string_type msg( Chris@16: impl::as_string(it, end)); Chris@16: BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, Chris@16: ill_formed_pragma_option, Chris@16: msg.c_str(), act_token.get_position()); Chris@16: return false; Chris@16: } Chris@16: Chris@16: // remove the falsely matched surrounding parenthesis's Chris@16: if (values.size() >= 2) { Chris@16: BOOST_ASSERT(T_LEFTPAREN == values.front() && T_RIGHTPAREN == values.back()); Chris@16: values.erase(values.begin()); Chris@16: typename ContainerT::reverse_iterator rit = values.rbegin(); Chris@16: values.erase((++rit).base()); Chris@16: } Chris@16: Chris@16: // decode the option (call the context_policy hook) Chris@16: if (!ctx.get_hooks().interpret_pragma( Chris@16: ctx.derived(), pending, option, values, act_token)) Chris@16: { Chris@16: // unknown #pragma option Chris@16: string_type option_str ((*it).get_value()); Chris@16: Chris@16: option_str += option.get_value(); Chris@16: if (values.size() > 0) { Chris@16: option_str += "("; Chris@16: option_str += impl::as_string(values); Chris@16: option_str += ")"; Chris@16: } Chris@16: BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, Chris@16: ill_formed_pragma_option, Chris@16: option_str.c_str(), act_token.get_position()); Chris@16: return false; Chris@16: } Chris@16: return true; Chris@16: } Chris@16: #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 Chris@16: else if ((*it).get_value() == "once") { Chris@16: // #pragma once Chris@16: return ctx.add_pragma_once_header(act_token, ctx.get_current_filename()); Chris@16: } Chris@16: #endif Chris@16: #if BOOST_WAVE_SUPPORT_PRAGMA_MESSAGE != 0 Chris@16: else if ((*it).get_value() == "message") { Chris@16: // #pragma message(...) or #pragma message ... Chris@16: using namespace boost::spirit::classic; Chris@16: ContainerT values; Chris@16: Chris@16: if (!parse (++it, end, Chris@16: ( ( ch_p(T_LEFTPAREN) Chris@16: >> lexeme_d[ Chris@16: *(anychar_p[spirit_append_actor(values)] - ch_p(T_RIGHTPAREN)) Chris@16: ] Chris@16: >> ch_p(T_RIGHTPAREN) Chris@16: ) Chris@16: | lexeme_d[ Chris@16: *(anychar_p[spirit_append_actor(values)] - ch_p(T_NEWLINE)) Chris@16: ] Chris@16: ), Chris@16: pattern_p(WhiteSpaceTokenType, TokenTypeMask|PPTokenFlag) Chris@16: ).hit Chris@16: ) Chris@16: { Chris@16: typename ContextT::string_type msg( Chris@16: impl::as_string(it, end)); Chris@16: BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, Chris@16: ill_formed_pragma_message, Chris@16: msg.c_str(), act_token.get_position()); Chris@16: return false; Chris@16: } Chris@16: Chris@16: // remove the falsely matched closing parenthesis/newline Chris@16: if (values.size() > 0) { Chris@16: BOOST_ASSERT(T_RIGHTPAREN == values.back() || T_NEWLINE == values.back()); Chris@16: typename ContainerT::reverse_iterator rit = values.rbegin(); Chris@16: values.erase((++rit).base()); Chris@16: } Chris@16: Chris@16: // output the message itself Chris@16: typename ContextT::string_type msg(impl::as_string(values)); Chris@16: BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, Chris@16: pragma_message_directive, Chris@16: msg.c_str(), act_token.get_position()); Chris@16: return false; Chris@16: } Chris@16: #endif Chris@16: } Chris@16: return false; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: } // namespace util Chris@16: } // namespace wave Chris@16: } // namespace boost Chris@16: Chris@16: // the suffix header occurs after all of the code Chris@16: #ifdef BOOST_HAS_ABI_HEADERS Chris@16: #include BOOST_ABI_SUFFIX Chris@16: #endif Chris@16: Chris@16: #endif // !defined(INTERPRET_PRAGMA_HPP_B1F2315E_C5CE_4ED1_A343_0EF548B7942A_INCLUDED)