1 /*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
6 Copyright (c) 2001-2009 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 =============================================================================*/
11 #if !defined(MACRO_HELPERS_HPP_931BBC99_EBFA_4692_8FBE_B555998C2C39_INCLUDED)
12 #define MACRO_HELPERS_HPP_931BBC99_EBFA_4692_8FBE_B555998C2C39_INCLUDED
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>
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
27 ///////////////////////////////////////////////////////////////////////////////
34 // escape a string literal (insert '\\' before every '\"', '?' and '\\')
35 template <typename StringT
>
37 escape_lit(StringT
const &value
)
40 typename
StringT::size_type pos
= 0;
41 typename
StringT::size_type pos1
= value
.find_first_of ("\"\\?", 0);
42 if (StringT::npos
!= pos1
) {
44 result
+= value
.substr(pos
, pos1
-pos
)
46 + StringT(1, value
[pos1
]);
47 pos1
= value
.find_first_of ("\"\\?", pos
= pos1
+1);
48 } while (StringT::npos
!= pos1
);
49 result
+= value
.substr(pos
);
57 // un-escape a string literal (remove '\\' just before '\\', '\"' or '?')
58 template <typename StringT
>
60 unescape_lit(StringT
const &value
)
63 typename
StringT::size_type pos
= 0;
64 typename
StringT::size_type pos1
= value
.find_first_of ("\\", 0);
65 if (StringT::npos
!= pos1
) {
67 switch (value
[pos1
+1]) {
71 result
= result
+ value
.substr(pos
, pos1
-pos
);
72 pos1
= value
.find_first_of ("\\", (pos
= pos1
+1)+1);
76 result
= result
+ value
.substr(pos
, pos1
-pos
) + "\n";
77 pos1
= value
.find_first_of ("\\", pos
= pos1
+1);
82 result
= result
+ value
.substr(pos
, pos1
-pos
+1);
83 pos1
= value
.find_first_of ("\\", pos
= pos1
+1);
86 } while (pos1
!= StringT::npos
);
87 result
= result
+ value
.substr(pos
);
90 // the string doesn't contain any escaped character sequences
96 // return the string representation of a token sequence
97 template <typename ContainerT
, typename PositionT
>
98 inline typename
ContainerT::value_type::string_type
99 as_stringlit (ContainerT
const &token_sequence
, PositionT
const &pos
)
101 using namespace boost::wave
;
102 typedef typename
ContainerT::value_type::string_type string_type
;
104 string_type
result("\"");
105 bool was_whitespace
= false;
106 typename
ContainerT::const_iterator end
= token_sequence
.end();
107 for (typename
ContainerT::const_iterator it
= token_sequence
.begin();
110 token_id id
= token_id(*it
);
112 if (IS_CATEGORY(*it
, WhiteSpaceTokenType
) || T_NEWLINE
== id
) {
113 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.
119 was_whitespace
= true;
122 else if (T_STRINGLIT
== id
|| T_CHARLIT
== id
) {
123 // string literals and character literals have to be escaped
124 result
+= impl::escape_lit((*it
).get_value());
125 was_whitespace
= false;
128 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
129 if (T_PLACEMARKER
!= id
)
132 // now append this token to the string
133 result
+= (*it
).get_value();
134 was_whitespace
= false;
139 // validate the resulting literal to contain no invalid universal character
140 // value (throws if invalid chars found)
141 boost::wave::cpplexer::impl::validate_literal(result
, pos
.get_line(),
142 pos
.get_column(), pos
.get_file());
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 as_stringlit (std::vector
<ContainerT
> const &arguments
,
151 typename
std::vector
<ContainerT
>::size_type i
, PositionT
const &pos
)
153 using namespace boost::wave
;
154 typedef typename
ContainerT::value_type::string_type string_type
;
156 BOOST_ASSERT(i
< arguments
.size());
158 string_type
result("\"");
159 bool was_whitespace
= false;
161 for (/**/; i
< arguments
.size(); ++i
) {
162 // stringize all remaining arguments
163 typename
ContainerT::const_iterator end
= arguments
[i
].end();
164 for (typename
ContainerT::const_iterator it
= arguments
[i
].begin();
167 token_id id
= token_id(*it
);
169 if (IS_CATEGORY(*it
, WhiteSpaceTokenType
) || T_NEWLINE
== id
) {
170 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.
176 was_whitespace
= true;
179 else if (T_STRINGLIT
== id
|| T_CHARLIT
== id
) {
180 // string literals and character literals have to be escaped
181 result
+= impl::escape_lit((*it
).get_value());
182 was_whitespace
= false;
184 else if (T_PLACEMARKER
!= id
) {
185 // now append this token to the string
186 result
+= (*it
).get_value();
187 was_whitespace
= false;
191 // append comma, if not last argument
192 if (i
< arguments
.size()-1) {
194 was_whitespace
= false;
199 // validate the resulting literal to contain no invalid universal character
200 // value (throws if invalid chars found)
201 boost::wave::cpplexer::impl::validate_literal(result
, pos
.get_line(),
202 pos
.get_column(), pos
.get_file());
205 #endif // BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
207 // return the string representation of a token sequence
208 template <typename StringT
, typename IteratorT
>
210 as_string(IteratorT it
, IteratorT
const& end
)
213 for (/**/; it
!= end
; ++it
)
215 result
+= (*it
).get_value();
220 // return the string representation of a token sequence
221 template <typename ContainerT
>
222 inline typename
ContainerT::value_type::string_type
223 as_string (ContainerT
const &token_sequence
)
225 typedef typename
ContainerT::value_type::string_type string_type
;
226 return as_string
<string_type
>(token_sequence
.begin(),
227 token_sequence
.end());
230 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
231 ///////////////////////////////////////////////////////////////////////////
233 // Copies all arguments beginning with the given index to the output
234 // sequence. The arguments are separated by commas.
236 template <typename ContainerT
, typename PositionT
>
237 void replace_ellipsis (std::vector
<ContainerT
> const &arguments
,
238 typename
ContainerT::size_type index
,
239 ContainerT
&expanded
, PositionT
const &pos
)
241 using namespace cpplexer
;
242 typedef typename
ContainerT::value_type token_type
;
244 token_type
comma(T_COMMA
, ",", pos
);
245 for (/**/; index
< arguments
.size(); ++index
) {
246 ContainerT
const &arg
= arguments
[index
];
248 std::copy(arg
.begin(), arg
.end(),
249 std::inserter(expanded
, expanded
.end()));
251 if (index
< arguments
.size()-1)
252 expanded
.push_back(comma
);
257 // Skip all whitespace characters and queue the skipped characters into the
259 template <typename IteratorT
>
260 inline boost::wave::token_id
261 skip_whitespace(IteratorT
&first
, IteratorT
const &last
)
263 token_id id
= util::impl::next_token
<IteratorT
>::peek(first
, last
, false);
264 if (IS_CATEGORY(id
, WhiteSpaceTokenType
)) {
267 id
= util::impl::next_token
<IteratorT
>::peek(first
, last
, false);
268 } while (IS_CATEGORY(id
, WhiteSpaceTokenType
));
274 template <typename IteratorT
, typename ContainerT
>
275 inline boost::wave::token_id
276 skip_whitespace(IteratorT
&first
, IteratorT
const &last
, ContainerT
&queue
)
278 queue
.push_back (*first
); // queue up the current token
280 token_id id
= util::impl::next_token
<IteratorT
>::peek(first
, last
, false);
281 if (IS_CATEGORY(id
, WhiteSpaceTokenType
)) {
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
));
293 ///////////////////////////////////////////////////////////////////////////////
298 // the suffix header occurs after all of the code
299 #ifdef BOOST_HAS_ABI_HEADERS
300 #include BOOST_ABI_SUFFIX
303 #endif // !defined(MACRO_HELPERS_HPP_931BBC99_EBFA_4692_8FBE_B555998C2C39_INCLUDED)