]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Boost.Wave: A Standard compliant C++ preprocessor library | |
3 | Example demonstrating how to preprocess the token stream generated by a | |
4 | #pragma directive | |
5 | ||
6 | http://www.boost.org/ | |
7 | ||
8 | Copyright (c) 2001-2010 Hartmut Kaiser. Distributed under the Boost | |
9 | Software License, Version 1.0. (See accompanying file | |
10 | LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
11 | =============================================================================*/ | |
12 | ||
13 | #if !defined(BOOST_WAVE_SAMPLE_PREPROCESS_PRAGMA_OUTPUT_APR_03_2008_0813AM) | |
14 | #define BOOST_WAVE_SAMPLE_PREPROCESS_PRAGMA_OUTPUT_APR_03_2008_0813AM | |
15 | ||
16 | template <typename String, typename Iterator> | |
17 | inline String | |
18 | as_unescaped_string(Iterator it, Iterator const& end) | |
19 | { | |
20 | using namespace boost::wave; | |
21 | ||
22 | String result; | |
23 | for (/**/; it != end; ++it) | |
24 | { | |
25 | switch (token_id(*it)) { | |
26 | case T_STRINGLIT: | |
27 | { | |
f67539c2 | 28 | String val (util::impl::unescape_lit((*it).get_value()).c_str()); |
7c673cae FG |
29 | val.erase(val.size()-1); |
30 | val.erase(0, 1); | |
31 | result += val; | |
32 | } | |
33 | break; | |
34 | ||
35 | default: // just skip everything else (hey it's a sample) | |
36 | break; | |
37 | } | |
38 | } | |
39 | return result; | |
40 | } | |
41 | ||
42 | // return the string representation of a token sequence | |
43 | template <typename String, typename Container> | |
44 | inline String | |
45 | as_unescaped_string(Container const &token_sequence) | |
46 | { | |
47 | return as_unescaped_string<String>(token_sequence.begin(), | |
48 | token_sequence.end()); | |
49 | } | |
50 | ||
51 | /////////////////////////////////////////////////////////////////////////////// | |
52 | // | |
53 | // The preprocess_pragma_output_hooks policy class is used implement a special | |
54 | // #pragma wave pp("some C++ code") directive allowing to insert preprocessed | |
55 | // code into the output sequence generated by the tool. | |
56 | // | |
57 | // This policy type is used as a template parameter to the boost::wave::context<> | |
58 | // object. | |
59 | // | |
60 | /////////////////////////////////////////////////////////////////////////////// | |
61 | class preprocess_pragma_output_hooks | |
62 | : public boost::wave::context_policies::default_preprocessing_hooks | |
63 | { | |
64 | public: | |
65 | preprocess_pragma_output_hooks() {} | |
66 | ||
67 | template <typename Context> | |
68 | struct reset_language_support | |
69 | { | |
70 | reset_language_support(Context& ctx) | |
71 | : ctx_(ctx), lang_(ctx.get_language()) | |
72 | { | |
73 | ctx.set_language(boost::wave::enable_single_line(lang_), false); | |
74 | } | |
75 | ~reset_language_support() | |
76 | { | |
77 | ctx_.set_language(lang_, false); | |
78 | } | |
79 | ||
80 | Context& ctx_; | |
81 | boost::wave::language_support lang_; | |
82 | }; | |
83 | ||
84 | /////////////////////////////////////////////////////////////////////////// | |
85 | // | |
86 | // The function 'interpret_pragma' is called, whenever a #pragma command | |
87 | // directive is found which isn't known to the core Wave library, where | |
88 | // command is the value defined as the BOOST_WAVE_PRAGMA_KEYWORD constant | |
89 | // which defaults to "wave". | |
90 | // | |
91 | // The parameter 'ctx' is a reference to the context object used for | |
92 | // instantiating the preprocessing iterators by the user. | |
93 | // | |
94 | // The parameter 'pending' may be used to push tokens back into the input | |
95 | // stream, which are to be used as the replacement text for the whole | |
96 | // #pragma directive. | |
97 | // | |
98 | // The parameter 'option' contains the name of the interpreted pragma. | |
99 | // | |
100 | // The parameter 'values' holds the values of the parameter provided to | |
101 | // the pragma operator. | |
102 | // | |
103 | // The parameter 'act_token' contains the actual #pragma token, which may | |
104 | // be used for error output. | |
105 | // | |
106 | // If the return value is 'false', the whole #pragma directive is | |
107 | // interpreted as unknown and a corresponding error message is issued. A | |
108 | // return value of 'true' signs a successful interpretation of the given | |
109 | // #pragma. | |
110 | // | |
111 | /////////////////////////////////////////////////////////////////////////// | |
112 | template <typename Context, typename Container> | |
113 | bool | |
114 | interpret_pragma(Context& ctx, Container &pending, | |
115 | typename Context::token_type const& option, | |
116 | Container const& values, typename Context::token_type const& act_token) | |
117 | { | |
7c673cae FG |
118 | typedef typename Context::iterator_type iterator_type; |
119 | ||
120 | if (option.get_value() == "pp") { | |
121 | // Concatenate the string(s) passed as the options to this pragma, | |
122 | // preprocess the result using the current context and insert the | |
123 | // generated token sequence in place of the pragma directive into the | |
124 | // output stream. | |
125 | ||
126 | try { | |
127 | // We're explicitly using a std::string here since the type of the | |
128 | // iterators passed to the ctx.begin() below must match the types | |
129 | // of the iterator the original context instance has been created | |
130 | // with. | |
131 | std::string s (as_unescaped_string<std::string>(values)); | |
132 | reset_language_support<Context> lang(ctx); | |
133 | ||
134 | using namespace boost::wave; | |
135 | ||
136 | // The expanded token sequence is stored in the 'pragma' container | |
137 | // to ensure consistency in the output in the case of an error | |
138 | // while preprocessing the pragma option strings. | |
139 | Container pragma; | |
140 | iterator_type end = ctx.end(); | |
141 | for (iterator_type it = ctx.begin(s.begin(), s.end()); | |
20effc67 TL |
142 | it != end && token_id(*it) != T_EOF; |
143 | std::advance(it, 2)) // skip over whitespace | |
7c673cae FG |
144 | { |
145 | pragma.push_back(*it); | |
7c673cae FG |
146 | } |
147 | ||
148 | // prepend the newly generated token sequence to the 'pending' | |
149 | // container | |
150 | pending.splice(pending.begin(), pragma); | |
151 | } | |
152 | catch (boost::wave::preprocess_exception const& /*e*/) { | |
153 | // the library will report an 'ill_formed_pragma_option' for us | |
154 | return false; | |
155 | } | |
156 | return true; | |
157 | } | |
158 | ||
159 | // we don't know anything about this #pragma wave directive | |
160 | return false; | |
161 | } | |
162 | }; | |
163 | ||
164 | ||
165 | #endif | |
166 |