Line data Source code
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 :
11 : #if !defined(MACRO_HELPERS_HPP_931BBC99_EBFA_4692_8FBE_B555998C2C39_INCLUDED)
12 : #define MACRO_HELPERS_HPP_931BBC99_EBFA_4692_8FBE_B555998C2C39_INCLUDED
13 :
14 : #include <vector>
15 :
16 : #include <boost/assert.hpp>
17 : #include <boost/wave/wave_config.hpp>
18 : #include <boost/wave/token_ids.hpp>
19 : #include <boost/wave/cpplexer/validate_universal_char.hpp>
20 : #include <boost/wave/util/unput_queue_iterator.hpp>
21 :
22 : // this must occur after all of the includes and before any code appears
23 : #ifdef BOOST_HAS_ABI_HEADERS
24 : #include BOOST_ABI_PREFIX
25 : #endif
26 :
27 : ///////////////////////////////////////////////////////////////////////////////
28 : namespace boost {
29 : namespace wave {
30 : namespace util {
31 :
32 : namespace impl {
33 :
34 : // escape a string literal (insert '\\' before every '\"', '?' and '\\')
35 : template <typename StringT>
36 : inline StringT
37 0 : escape_lit(StringT const &value)
38 : {
39 0 : StringT result;
40 0 : typename StringT::size_type pos = 0;
41 0 : typename StringT::size_type pos1 = value.find_first_of ("\"\\?", 0);
42 0 : if (StringT::npos != pos1) {
43 : do {
44 0 : result += value.substr(pos, pos1-pos)
45 : + StringT("\\")
46 0 : + StringT(1, value[pos1]);
47 0 : pos1 = value.find_first_of ("\"\\?", pos = pos1+1);
48 0 : } while (StringT::npos != pos1);
49 0 : result += value.substr(pos);
50 : }
51 : else {
52 0 : result = value;
53 : }
54 0 : return result;
55 : }
56 :
57 : // un-escape a string literal (remove '\\' just before '\\', '\"' or '?')
58 : template <typename StringT>
59 : inline StringT
60 0 : unescape_lit(StringT const &value)
61 : {
62 0 : StringT result;
63 0 : typename StringT::size_type pos = 0;
64 0 : typename StringT::size_type pos1 = value.find_first_of ("\\", 0);
65 0 : if (StringT::npos != pos1) {
66 : do {
67 0 : switch (value[pos1+1]) {
68 0 : case '\\':
69 : case '\"':
70 : case '?':
71 0 : result = result + value.substr(pos, pos1-pos);
72 0 : pos1 = value.find_first_of ("\\", (pos = pos1+1)+1);
73 0 : break;
74 :
75 0 : case 'n':
76 0 : result = result + value.substr(pos, pos1-pos) + "\n";
77 0 : pos1 = value.find_first_of ("\\", pos = pos1+1);
78 0 : ++pos;
79 0 : break;
80 :
81 0 : default:
82 0 : result = result + value.substr(pos, pos1-pos+1);
83 0 : pos1 = value.find_first_of ("\\", pos = pos1+1);
84 : }
85 :
86 0 : } while (pos1 != StringT::npos);
87 0 : result = result + value.substr(pos);
88 : }
89 : else {
90 : // the string doesn't contain any escaped character sequences
91 0 : result = value;
92 : }
93 0 : return result;
94 : }
95 :
96 : // return the string representation of a token sequence
97 : template <typename ContainerT, typename PositionT>
98 : inline typename ContainerT::value_type::string_type
99 0 : as_stringlit (ContainerT const &token_sequence, PositionT const &pos)
100 : {
101 : using namespace boost::wave;
102 : typedef typename ContainerT::value_type::string_type string_type;
103 :
104 0 : string_type result("\"");
105 0 : bool was_whitespace = false;
106 0 : typename ContainerT::const_iterator end = token_sequence.end();
107 0 : for (typename ContainerT::const_iterator it = token_sequence.begin();
108 0 : it != end; ++it)
109 : {
110 0 : token_id id = token_id(*it);
111 :
112 0 : if (IS_CATEGORY(*it, WhiteSpaceTokenType) || T_NEWLINE == id) {
113 0 : if (!was_whitespace) {
114 : // C++ standard 16.3.2.2 [cpp.stringize]
115 : // Each occurrence of white space between the argument's
116 : // preprocessing tokens becomes a single space character in the
117 : // character string literal.
118 0 : result += " ";
119 : was_whitespace = true;
120 : }
121 : }
122 0 : else if (T_STRINGLIT == id || T_CHARLIT == id) {
123 : // string literals and character literals have to be escaped
124 0 : result += impl::escape_lit((*it).get_value());
125 0 : was_whitespace = false;
126 : }
127 : else
128 : #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
129 0 : if (T_PLACEMARKER != id)
130 : #endif
131 : {
132 : // now append this token to the string
133 0 : result += (*it).get_value();
134 : was_whitespace = false;
135 : }
136 : }
137 0 : result += "\"";
138 :
139 : // validate the resulting literal to contain no invalid universal character
140 : // value (throws if invalid chars found)
141 0 : boost::wave::cpplexer::impl::validate_literal(result, pos.get_line(),
142 : pos.get_column(), pos.get_file());
143 0 : return result;
144 : }
145 :
146 : #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
147 : // return the string representation of a token sequence
148 : template <typename ContainerT, typename PositionT>
149 : inline typename ContainerT::value_type::string_type
150 0 : as_stringlit (std::vector<ContainerT> const &arguments,
151 : typename std::vector<ContainerT>::size_type i, PositionT const &pos)
152 : {
153 : using namespace boost::wave;
154 : typedef typename ContainerT::value_type::string_type string_type;
155 :
156 0 : BOOST_ASSERT(i < arguments.size());
157 :
158 0 : string_type result("\"");
159 0 : bool was_whitespace = false;
160 :
161 0 : for (/**/; i < arguments.size(); ++i) {
162 : // stringize all remaining arguments
163 0 : typename ContainerT::const_iterator end = arguments[i].end();
164 0 : for (typename ContainerT::const_iterator it = arguments[i].begin();
165 0 : it != end; ++it)
166 : {
167 0 : token_id id = token_id(*it);
168 :
169 0 : if (IS_CATEGORY(*it, WhiteSpaceTokenType) || T_NEWLINE == id) {
170 0 : if (!was_whitespace) {
171 : // C++ standard 16.3.2.2 [cpp.stringize]
172 : // Each occurrence of white space between the argument's
173 : // preprocessing tokens becomes a single space character in the
174 : // character string literal.
175 0 : result += " ";
176 : was_whitespace = true;
177 : }
178 : }
179 0 : else if (T_STRINGLIT == id || T_CHARLIT == id) {
180 : // string literals and character literals have to be escaped
181 0 : result += impl::escape_lit((*it).get_value());
182 0 : was_whitespace = false;
183 : }
184 0 : else if (T_PLACEMARKER != id) {
185 : // now append this token to the string
186 0 : result += (*it).get_value();
187 : was_whitespace = false;
188 : }
189 : }
190 :
191 : // append comma, if not last argument
192 0 : if (i < arguments.size()-1) {
193 0 : result += ",";
194 : was_whitespace = false;
195 : }
196 : }
197 0 : result += "\"";
198 :
199 : // validate the resulting literal to contain no invalid universal character
200 : // value (throws if invalid chars found)
201 0 : boost::wave::cpplexer::impl::validate_literal(result, pos.get_line(),
202 : pos.get_column(), pos.get_file());
203 0 : return result;
204 : }
205 : #endif // BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
206 :
207 : // return the string representation of a token sequence
208 : template <typename StringT, typename IteratorT>
209 : inline StringT
210 0 : as_string(IteratorT it, IteratorT const& end)
211 : {
212 0 : StringT result;
213 0 : for (/**/; it != end; ++it)
214 : {
215 0 : result += (*it).get_value();
216 : }
217 0 : return result;
218 : }
219 :
220 : // return the string representation of a token sequence
221 : template <typename ContainerT>
222 : inline typename ContainerT::value_type::string_type
223 0 : as_string (ContainerT const &token_sequence)
224 : {
225 : typedef typename ContainerT::value_type::string_type string_type;
226 0 : return as_string<string_type>(token_sequence.begin(),
227 0 : token_sequence.end());
228 : }
229 :
230 : #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
231 : ///////////////////////////////////////////////////////////////////////////
232 : //
233 : // Copies all arguments beginning with the given index to the output
234 : // sequence. The arguments are separated by commas.
235 : //
236 : template <typename ContainerT, typename PositionT>
237 0 : void replace_ellipsis (std::vector<ContainerT> const &arguments,
238 : typename ContainerT::size_type index,
239 : ContainerT &expanded, PositionT const &pos)
240 : {
241 : using namespace cpplexer;
242 : typedef typename ContainerT::value_type token_type;
243 :
244 0 : token_type comma(T_COMMA, ",", pos);
245 0 : for (/**/; index < arguments.size(); ++index) {
246 0 : ContainerT const &arg = arguments[index];
247 :
248 0 : std::copy(arg.begin(), arg.end(),
249 : std::inserter(expanded, expanded.end()));
250 :
251 0 : if (index < arguments.size()-1)
252 0 : expanded.push_back(comma);
253 : }
254 0 : }
255 : #endif
256 :
257 : // Skip all whitespace characters and queue the skipped characters into the
258 : // given container
259 : template <typename IteratorT>
260 : inline boost::wave::token_id
261 0 : skip_whitespace(IteratorT &first, IteratorT const &last)
262 : {
263 0 : token_id id = util::impl::next_token<IteratorT>::peek(first, last, false);
264 0 : if (IS_CATEGORY(id, WhiteSpaceTokenType)) {
265 0 : do {
266 0 : ++first;
267 0 : id = util::impl::next_token<IteratorT>::peek(first, last, false);
268 0 : } while (IS_CATEGORY(id, WhiteSpaceTokenType));
269 : }
270 0 : ++first;
271 0 : return id;
272 : }
273 :
274 : template <typename IteratorT, typename ContainerT>
275 : inline boost::wave::token_id
276 : skip_whitespace(IteratorT &first, IteratorT const &last, ContainerT &queue)
277 : {
278 : queue.push_back (*first); // queue up the current token
279 :
280 : token_id id = util::impl::next_token<IteratorT>::peek(first, last, false);
281 : if (IS_CATEGORY(id, WhiteSpaceTokenType)) {
282 : do {
283 : queue.push_back(*++first); // queue up the next whitespace
284 : id = util::impl::next_token<IteratorT>::peek(first, last, false);
285 : } while (IS_CATEGORY(id, WhiteSpaceTokenType));
286 : }
287 : ++first;
288 : return id;
289 : }
290 :
291 : } // namespace impl
292 :
293 : ///////////////////////////////////////////////////////////////////////////////
294 : } // namespace util
295 : } // namespace wave
296 : } // namespace boost
297 :
298 : // the suffix header occurs after all of the code
299 : #ifdef BOOST_HAS_ABI_HEADERS
300 : #include BOOST_ABI_SUFFIX
301 : #endif
302 :
303 : #endif // !defined(MACRO_HELPERS_HPP_931BBC99_EBFA_4692_8FBE_B555998C2C39_INCLUDED)
|