]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Boost.Wave: A Standard compliant C++ preprocessor library | |
3 | ||
4 | http://www.boost.org/ | |
5 | ||
6 | Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost | |
7 | Software License, Version 1.0. (See accompanying file | |
8 | LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | =============================================================================*/ | |
10 | ||
20effc67 TL |
11 | #if !defined(BOOST_INTERPRET_PRAGMA_HPP_B1F2315E_C5CE_4ED1_A343_0EF548B7942A_INCLUDED) |
12 | #define BOOST_INTERPRET_PRAGMA_HPP_B1F2315E_C5CE_4ED1_A343_0EF548B7942A_INCLUDED | |
7c673cae FG |
13 | |
14 | #include <string> | |
15 | #include <list> | |
16 | ||
17 | #include <boost/spirit/include/classic_core.hpp> | |
18 | #include <boost/spirit/include/classic_assign_actor.hpp> | |
19 | #include <boost/spirit/include/classic_push_back_actor.hpp> | |
20 | #include <boost/spirit/include/classic_confix.hpp> | |
21 | ||
22 | #include <boost/wave/wave_config.hpp> | |
23 | ||
24 | #include <boost/wave/util/pattern_parser.hpp> | |
25 | #include <boost/wave/util/macro_helpers.hpp> | |
26 | ||
27 | #include <boost/wave/token_ids.hpp> | |
28 | #include <boost/wave/cpp_exceptions.hpp> | |
29 | #include <boost/wave/cpp_iteration_context.hpp> | |
30 | #include <boost/wave/language_support.hpp> | |
31 | ||
32 | #if !defined(spirit_append_actor) | |
33 | #define spirit_append_actor(actor) boost::spirit::classic::push_back_a(actor) | |
34 | #define spirit_assign_actor(actor) boost::spirit::classic::assign_a(actor) | |
35 | #endif // !defined(spirit_append_actor) | |
36 | ||
37 | // this must occur after all of the includes and before any code appears | |
38 | #ifdef BOOST_HAS_ABI_HEADERS | |
39 | #include BOOST_ABI_PREFIX | |
40 | #endif | |
41 | ||
42 | /////////////////////////////////////////////////////////////////////////////// | |
43 | namespace boost { | |
44 | namespace wave { | |
45 | namespace util { | |
46 | ||
47 | /////////////////////////////////////////////////////////////////////////////// | |
48 | // | |
49 | // The function interpret_pragma interprets the given token sequence as the | |
b32b8144 | 50 | // body of a #pragma directive (or parameter to the _Pragma operator) and |
7c673cae FG |
51 | // executes the actions associated with recognized Wave specific options. |
52 | // | |
53 | /////////////////////////////////////////////////////////////////////////////// | |
54 | template <typename ContextT, typename IteratorT, typename ContainerT> | |
b32b8144 | 55 | inline bool |
7c673cae FG |
56 | interpret_pragma(ContextT &ctx, typename ContextT::token_type const &act_token, |
57 | IteratorT it, IteratorT const &end, ContainerT &pending) | |
58 | { | |
59 | typedef typename ContextT::token_type token_type; | |
60 | typedef typename token_type::string_type string_type; | |
61 | ||
62 | using namespace cpplexer; | |
63 | if (T_IDENTIFIER == token_id(*it)) { | |
64 | // check for pragma wave ... | |
b32b8144 | 65 | if ((*it).get_value() == BOOST_WAVE_PRAGMA_KEYWORD) |
7c673cae FG |
66 | { |
67 | // this is a wave specific option, it should have the form: | |
68 | // | |
69 | // #pragma command option(value) | |
70 | // | |
b32b8144 | 71 | // where |
7c673cae FG |
72 | // 'command' is the value of the preprocessor constant |
73 | // BOOST_WAVE_PRAGMA_KEYWORD (defaults to "wave") and | |
b32b8144 | 74 | // '(value)' is required only for some pragma directives (this is |
7c673cae FG |
75 | // optional) |
76 | // | |
b32b8144 | 77 | // All recognized #pragma operators are forwarded to the supplied |
7c673cae FG |
78 | // preprocessing hook. |
79 | using namespace boost::spirit::classic; | |
80 | token_type option; | |
81 | ContainerT values; | |
b32b8144 FG |
82 | |
83 | if (!parse (++it, end, | |
7c673cae FG |
84 | ( ch_p(T_IDENTIFIER) |
85 | [ | |
86 | spirit_assign_actor(option) | |
b32b8144 FG |
87 | ] |
88 | | pattern_p(KeywordTokenType, | |
7c673cae FG |
89 | TokenTypeMask|PPTokenFlag) |
90 | [ | |
91 | spirit_assign_actor(option) | |
b32b8144 FG |
92 | ] |
93 | | pattern_p(OperatorTokenType|AltExtTokenType, | |
7c673cae FG |
94 | ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc. |
95 | [ | |
96 | spirit_assign_actor(option) | |
b32b8144 FG |
97 | ] |
98 | | pattern_p(BoolLiteralTokenType, | |
7c673cae FG |
99 | TokenTypeMask|PPTokenFlag) |
100 | [ | |
101 | spirit_assign_actor(option) | |
b32b8144 | 102 | ] |
7c673cae FG |
103 | ) |
104 | >> !comment_nest_p( | |
105 | ch_p(T_LEFTPAREN), | |
106 | ch_p(T_RIGHTPAREN) | |
107 | )[spirit_assign_actor(values)], | |
108 | pattern_p(WhiteSpaceTokenType, TokenTypeMask|PPTokenFlag)).hit) | |
109 | { | |
110 | typename ContextT::string_type msg( | |
111 | impl::as_string<string_type>(it, end)); | |
b32b8144 | 112 | BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, |
7c673cae FG |
113 | ill_formed_pragma_option, |
114 | msg.c_str(), act_token.get_position()); | |
115 | return false; | |
116 | } | |
117 | ||
20effc67 | 118 | // remove the falsely matched surrounding parenthesis's |
7c673cae FG |
119 | if (values.size() >= 2) { |
120 | BOOST_ASSERT(T_LEFTPAREN == values.front() && T_RIGHTPAREN == values.back()); | |
121 | values.erase(values.begin()); | |
122 | typename ContainerT::reverse_iterator rit = values.rbegin(); | |
123 | values.erase((++rit).base()); | |
124 | } | |
125 | ||
20effc67 | 126 | // decode the option (call the context_policy hook) |
7c673cae | 127 | if (!ctx.get_hooks().interpret_pragma( |
b32b8144 | 128 | ctx.derived(), pending, option, values, act_token)) |
7c673cae | 129 | { |
20effc67 TL |
130 | // unknown #pragma option |
131 | string_type option_str((*it).get_value()); | |
7c673cae FG |
132 | |
133 | option_str += option.get_value(); | |
134 | if (values.size() > 0) { | |
135 | option_str += "("; | |
136 | option_str += impl::as_string(values); | |
137 | option_str += ")"; | |
138 | } | |
b32b8144 | 139 | BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, |
7c673cae FG |
140 | ill_formed_pragma_option, |
141 | option_str.c_str(), act_token.get_position()); | |
142 | return false; | |
143 | } | |
144 | return true; | |
145 | } | |
146 | #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 | |
147 | else if ((*it).get_value() == "once") { | |
20effc67 | 148 | // #pragma once |
7c673cae FG |
149 | return ctx.add_pragma_once_header(act_token, ctx.get_current_filename()); |
150 | } | |
b32b8144 | 151 | #endif |
7c673cae FG |
152 | #if BOOST_WAVE_SUPPORT_PRAGMA_MESSAGE != 0 |
153 | else if ((*it).get_value() == "message") { | |
20effc67 | 154 | // #pragma message(...) or #pragma message ... |
7c673cae FG |
155 | using namespace boost::spirit::classic; |
156 | ContainerT values; | |
157 | ||
b32b8144 FG |
158 | if (!parse (++it, end, |
159 | ( ( ch_p(T_LEFTPAREN) | |
7c673cae FG |
160 | >> lexeme_d[ |
161 | *(anychar_p[spirit_append_actor(values)] - ch_p(T_RIGHTPAREN)) | |
162 | ] | |
163 | >> ch_p(T_RIGHTPAREN) | |
164 | ) | |
165 | | lexeme_d[ | |
166 | *(anychar_p[spirit_append_actor(values)] - ch_p(T_NEWLINE)) | |
167 | ] | |
168 | ), | |
169 | pattern_p(WhiteSpaceTokenType, TokenTypeMask|PPTokenFlag) | |
170 | ).hit | |
171 | ) | |
172 | { | |
173 | typename ContextT::string_type msg( | |
174 | impl::as_string<string_type>(it, end)); | |
b32b8144 | 175 | BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, |
7c673cae FG |
176 | ill_formed_pragma_message, |
177 | msg.c_str(), act_token.get_position()); | |
178 | return false; | |
179 | } | |
180 | ||
20effc67 | 181 | // remove the falsely matched closing parenthesis/newline |
7c673cae FG |
182 | if (values.size() > 0) { |
183 | BOOST_ASSERT(T_RIGHTPAREN == values.back() || T_NEWLINE == values.back()); | |
184 | typename ContainerT::reverse_iterator rit = values.rbegin(); | |
185 | values.erase((++rit).base()); | |
186 | } | |
187 | ||
20effc67 | 188 | // output the message itself |
7c673cae | 189 | typename ContextT::string_type msg(impl::as_string(values)); |
b32b8144 FG |
190 | BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, |
191 | pragma_message_directive, | |
7c673cae FG |
192 | msg.c_str(), act_token.get_position()); |
193 | return false; | |
194 | } | |
195 | #endif | |
196 | } | |
197 | return false; | |
198 | } | |
199 | ||
200 | /////////////////////////////////////////////////////////////////////////////// | |
201 | } // namespace util | |
202 | } // namespace wave | |
203 | } // namespace boost | |
204 | ||
205 | // the suffix header occurs after all of the code | |
206 | #ifdef BOOST_HAS_ABI_HEADERS | |
207 | #include BOOST_ABI_SUFFIX | |
208 | #endif | |
209 | ||
20effc67 | 210 | #endif // !defined(BOOST_INTERPRET_PRAGMA_HPP_B1F2315E_C5CE_4ED1_A343_0EF548B7942A_INCLUDED) |