]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/wave/util/cpp_macromap_utils.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / wave / util / cpp_macromap_utils.hpp
CommitLineData
7c673cae
FG
1/*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
3
4 Token sequence analysis and transformation helper functions
5
6 http://www.boost.org/
7
8 Copyright (c) 2001-2012 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
20effc67
TL
13#if !defined(BOOST_CPP_MACROMAP_UTIL_HPP_HK041119)
14#define BOOST_CPP_MACROMAP_UTIL_HPP_HK041119
7c673cae
FG
15
16#include <boost/assert.hpp>
17
18#include <boost/wave/wave_config.hpp>
19#include <boost/wave/token_ids.hpp>
b32b8144 20#include <boost/wave/util/unput_queue_iterator.hpp>
20effc67 21#include <boost/wave/language_support.hpp>
7c673cae
FG
22
23// this must occur after all of the includes and before any code appears
24#ifdef BOOST_HAS_ABI_HEADERS
25#include BOOST_ABI_PREFIX
26#endif
27
28///////////////////////////////////////////////////////////////////////////////
29//
b32b8144 30// This file contains the definition of several token sequence analyze
7c673cae
FG
31// and transformation utility functions needed during macro handling.
32//
33///////////////////////////////////////////////////////////////////////////////
34
35///////////////////////////////////////////////////////////////////////////////
36namespace boost {
37namespace wave {
38namespace util {
39
40///////////////////////////////////////////////////////////////////////////////
41namespace on_exit {
42
43 ///////////////////////////////////////////////////////////////////////////
44 //
b32b8144 45 // On destruction pop the first element of the list given as the argument
7c673cae
FG
46 //
47 ///////////////////////////////////////////////////////////////////////////
48 template <typename ContainerT>
49 class pop_front {
50 public:
51 pop_front(ContainerT &list_) : list(list_) {}
52 ~pop_front() { list.pop_front(); }
53
54 private:
55 ContainerT &list;
56 };
57
58 ///////////////////////////////////////////////////////////////////////////
59 //
b32b8144
FG
60 // Append a given list to the list given as argument
61 // On destruction pop the first element of the list given as argument
7c673cae
FG
62 //
63 ///////////////////////////////////////////////////////////////////////////
64 template <typename ContainerT>
65 class splice_pop_front {
66 public:
b32b8144
FG
67 splice_pop_front(ContainerT &list_, ContainerT &queue)
68 : list(list_)
7c673cae
FG
69 {
70 list.splice(list.end(), queue);
71 }
72 ~splice_pop_front() { list.pop_front(); }
73
74 private:
75 ContainerT &list;
76 };
77
78 ///////////////////////////////////////////////////////////////////////////
79 //
80 // On destruction reset a referenced value to its initial state
81 //
82 ///////////////////////////////////////////////////////////////////////////
83 template <typename TypeT>
84 class reset {
85 public:
86 reset(TypeT &target_value_, TypeT new_value)
87 : target_value(target_value_), old_value(target_value_)
88 {
89 target_value_ = new_value;
90 }
91 ~reset() { target_value = old_value; }
92
93 private:
94 TypeT &target_value;
95 TypeT old_value;
96 };
97
98 ///////////////////////////////////////////////////////////////////////////
99 //
100 // On destruction assign the given iterator back
101 //
102 ///////////////////////////////////////////////////////////////////////////
103 template <typename IteratorT, typename UnputIteratorT>
104 class assign
105 {
106 public:
b32b8144 107 assign(IteratorT &it_, UnputIteratorT const &uit_)
7c673cae
FG
108 : it(it_), uit(uit_) {}
109 ~assign() { it = uit.base(); }
110
111 private:
112 IteratorT &it;
113 UnputIteratorT const &uit;
114 };
115
116 template <typename IteratorT>
117 class assign<IteratorT, IteratorT> {
118 public:
b32b8144 119 assign(IteratorT &it_, IteratorT const &uit_)
7c673cae
FG
120 : it(it_), uit(uit_) {}
121 ~assign() { it = uit; }
122
123 private:
124 IteratorT &it;
125 IteratorT const &uit;
126 };
127
128///////////////////////////////////////////////////////////////////////////////
129} // namespace on_exit
130
131///////////////////////////////////////////////////////////////////////////////
132namespace impl {
133
134///////////////////////////////////////////////////////////////////////////////
135//
136// Test, whether a given identifier resolves to a predefined name
137//
138///////////////////////////////////////////////////////////////////////////////
20effc67 139template <typename ContextT, typename StringT>
b32b8144 140inline bool
20effc67 141is_special_macroname (ContextT const & ctx, StringT const &name)
7c673cae
FG
142{
143 if (name.size() < 7)
144 return false;
145
146 if ("defined" == name)
147 return true;
148
20effc67
TL
149#if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
150 if (boost::wave::need_has_include(ctx.get_language()) &&
151 ("__has_include" == name))
152 return true;
153#endif
154
7c673cae 155 if ('_' == name[0] && '_' == name[1]) {
20effc67 156 StringT str = name.substr(2);
7c673cae 157
b32b8144 158 if (str == "cplusplus" || str == "STDC__" ||
7c673cae
FG
159 str == "TIME__" || str == "DATE__" ||
160 str == "LINE__" || str == "FILE__" ||
161 str == "INCLUDE_LEVEL__")
162 {
163 return true;
164 }
165 }
166 return false;
167}
168
169///////////////////////////////////////////////////////////////////////////////
170//
171// Test, whether two tokens are to be considered equal (different sequences
172// of whitespace are considered to be equal)
173//
174///////////////////////////////////////////////////////////////////////////////
175template <typename TokenT>
b32b8144 176inline bool
7c673cae
FG
177token_equals(TokenT const &left, TokenT const &right)
178{
179 using namespace boost::wave;
180
181 if (IS_CATEGORY(left, ParameterTokenType)) {
20effc67
TL
182 // if the existing token is of type T_PARAMETERBASE, then the right token
183 // must be of type T_IDENTIFIER or a keyword
184 token_id id = token_id(right);
7c673cae 185
b32b8144 186 return (T_IDENTIFIER == id ||
7c673cae
FG
187 IS_CATEGORY(id, KeywordTokenType) ||
188 IS_EXTCATEGORY(id, OperatorTokenType|AltExtTokenType) ||
b32b8144 189 IS_CATEGORY(id, BoolLiteralTokenType)) &&
7c673cae
FG
190 left.get_value() == right.get_value();
191 }
192
193 // if the left token has whitespace, the value is irrelevant
194 return token_id(left) == token_id(right) && (
195 IS_CATEGORY(left, WhiteSpaceTokenType) ||
196 left.get_value() == right.get_value()
197 );
198}
199
200///////////////////////////////////////////////////////////////////////////////
201//
202// Tests, whether two macro definitions are equal
203//
204///////////////////////////////////////////////////////////////////////////////
205template <typename ContainerT>
b32b8144
FG
206inline bool
207definition_equals(ContainerT const &definition,
7c673cae
FG
208 ContainerT const &new_definition)
209{
210 typedef typename ContainerT::const_iterator const_iterator_type;
211
20effc67
TL
212 const_iterator_type first1 = definition.begin();
213 const_iterator_type last1 = definition.end();
214 const_iterator_type first2 = new_definition.begin();
215 const_iterator_type last2 = new_definition.end();
7c673cae 216
b32b8144 217 while (first1 != last1 && first2 != last2 && token_equals(*first1, *first2))
7c673cae 218 {
20effc67
TL
219 // skip whitespace, if both sequences have a whitespace next
220 token_id id1 = next_token<const_iterator_type>::peek(first1, last1, false);
221 token_id id2 = next_token<const_iterator_type>::peek(first2, last2, false);
7c673cae 222
b32b8144
FG
223 if (IS_CATEGORY(id1, WhiteSpaceTokenType) &&
224 IS_CATEGORY(id2, WhiteSpaceTokenType))
7c673cae 225 {
20effc67
TL
226 // all consecutive whitespace tokens count as one whitespace
227 // adjust first1 and first2 accordingly
7c673cae
FG
228 skip_whitespace(first1, last1);
229 skip_whitespace(first2, last2);
230 }
b32b8144
FG
231 else if (!IS_CATEGORY(id1, WhiteSpaceTokenType) &&
232 !IS_CATEGORY(id2, WhiteSpaceTokenType))
7c673cae
FG
233 {
234 ++first1;
235 ++first2;
236 }
237 else {
20effc67 238 // the sequences differ
7c673cae
FG
239 break;
240 }
241 }
242 return (first1 == last1 && first2 == last2) ? true : false;
243}
244
245///////////////////////////////////////////////////////////////////////////////
246//
247// Tests, whether two given sets of macro parameters are equal
248//
249///////////////////////////////////////////////////////////////////////////////
250template <typename ContainerT>
b32b8144 251inline bool
7c673cae
FG
252parameters_equal(ContainerT const &parameters, ContainerT const &new_parameters)
253{
254 if (parameters.size() != new_parameters.size())
255 return false; // different parameter count
256
257 typedef typename ContainerT::const_iterator const_iterator_type;
258
20effc67
TL
259 const_iterator_type first1 = parameters.begin();
260 const_iterator_type last1 = parameters.end();
261 const_iterator_type first2 = new_parameters.begin();
262 const_iterator_type last2 = new_parameters.end();
7c673cae
FG
263
264 while (first1 != last1 && first2 != last2) {
20effc67 265 // parameters are different, if the corresponding tokens are different
7c673cae
FG
266 using namespace boost::wave;
267 if (token_id(*first1) != token_id(*first2) ||
268 (*first1).get_value() != (*first2).get_value())
269 {
270 break;
271 }
272 ++first1;
273 ++first2;
274 }
275 return (first1 == last1 && first2 == last2) ? true : false;
276}
277
278///////////////////////////////////////////////////////////////////////////////
279//
280// Strip leading and trailing whitespace from the given token sequence
281//
282///////////////////////////////////////////////////////////////////////////////
283template <typename ContainerT>
284inline void
285trim_replacement_list (ContainerT &replacement_list)
286{
287 using namespace boost::wave;
288
20effc67 289 // strip leading whitespace
7c673cae 290 if (replacement_list.size() > 0) {
20effc67
TL
291 typename ContainerT::iterator end = replacement_list.end();
292 typename ContainerT::iterator it = replacement_list.begin();
7c673cae 293
b32b8144 294 while (it != end && IS_CATEGORY(*it, WhiteSpaceTokenType)) {
7c673cae
FG
295 token_id id(*it);
296 if (T_PLACEHOLDER != id && T_PLACEMARKER != id) {
297 typename ContainerT::iterator next = it;
298 ++next;
299 replacement_list.erase(it);
300 it = next;
301 }
302 else {
303 ++it;
304 }
305 }
306 }
307
20effc67 308 // strip trailing whitespace
7c673cae 309 if (replacement_list.size() > 0) {
20effc67
TL
310 typename ContainerT::reverse_iterator rend = replacement_list.rend();
311 typename ContainerT::reverse_iterator rit = replacement_list.rbegin();
7c673cae 312
b32b8144 313 while (rit != rend && IS_CATEGORY(*rit, WhiteSpaceTokenType))
7c673cae
FG
314 ++rit;
315
20effc67
TL
316 typename ContainerT::iterator end = replacement_list.end();
317 typename ContainerT::iterator it = rit.base();
7c673cae 318
b32b8144 319 while (it != end && IS_CATEGORY(*it, WhiteSpaceTokenType)) {
7c673cae
FG
320 token_id id(*it);
321 if (T_PLACEHOLDER != id && T_PLACEMARKER != id) {
322 typename ContainerT::iterator next = it;
323 ++next;
324 replacement_list.erase(it);
325 it = next;
326 }
327 else {
328 ++it;
329 }
330 }
331 }
332}
333
334///////////////////////////////////////////////////////////////////////////////
335//
336// Tests, whether the given token sequence consists out of whitespace only
337//
338///////////////////////////////////////////////////////////////////////////////
339template <typename ContainerT>
340inline bool
341is_whitespace_only (ContainerT const &argument)
342{
343 typename ContainerT::const_iterator end = argument.end();
344 for (typename ContainerT::const_iterator it = argument.begin();
345 it != end; ++it)
346 {
347 if (!IS_CATEGORY(*it, WhiteSpaceTokenType))
348 return false;
349 }
350 return true;
351}
352
20effc67
TL
353///////////////////////////////////////////////////////////////////////////////
354//
355// Tests whether the given token sequence consists only of whitespace
356// and placemarkers
357//
358///////////////////////////////////////////////////////////////////////////////
359template <typename ContainerT>
360inline bool
361is_blank_only (ContainerT const &argument)
362{
363 typename ContainerT::const_iterator end = argument.end();
364 for (typename ContainerT::const_iterator it = argument.begin();
365 it != end; ++it)
366 {
367 if (!IS_CATEGORY(*it, WhiteSpaceTokenType) &&
368 (T_PLACEMARKER != token_id(*it)))
369 return false;
370 }
371 return true;
372}
373
7c673cae
FG
374///////////////////////////////////////////////////////////////////////////////
375//
376// Remove all placeholder tokens from the given token sequence
377//
378///////////////////////////////////////////////////////////////////////////////
379template <typename ContainerT>
380inline void
381remove_placeholders (ContainerT &replacement_list)
382{
383 using namespace boost::wave;
384
20effc67 385 // strip leading whitespace
7c673cae 386 if (replacement_list.size() > 0) {
20effc67
TL
387 typename ContainerT::iterator end = replacement_list.end();
388 typename ContainerT::iterator it = replacement_list.begin();
7c673cae
FG
389
390 while (it != end) {
391 token_id id(*it);
392 if (T_PLACEHOLDER == id || T_PLACEMARKER == id) {
393 typename ContainerT::iterator next = it;
394 ++next;
395 replacement_list.erase(it);
396 it = next;
397 }
398 else {
399 ++it;
400 }
401 }
402
20effc67 403 // remove all 'new' leading and trailing whitespace
7c673cae
FG
404 if (is_whitespace_only(replacement_list))
405 trim_replacement_list(replacement_list);
406 }
407}
408
409///////////////////////////////////////////////////////////////////////////////
410//
411// Remove all whitespace tokens on the left side of the given token sequence
412//
413///////////////////////////////////////////////////////////////////////////////
414template <typename ContainerT>
415inline void
416trim_sequence_left (ContainerT &argument)
417{
418 using namespace boost::wave;
419
20effc67 420 // strip leading whitespace (should be only one token)
7c673cae
FG
421 if (argument.size() > 0 &&
422 IS_CATEGORY(argument.front(), WhiteSpaceTokenType))
423 {
424 argument.pop_front();
425 }
426}
b32b8144 427
7c673cae
FG
428///////////////////////////////////////////////////////////////////////////////
429//
430// Remove all whitespace tokens on the right side of the given token sequence
431//
432///////////////////////////////////////////////////////////////////////////////
433template <typename ContainerT>
434inline void
435trim_sequence_right (ContainerT &argument)
436{
437 using namespace boost::wave;
438
20effc67 439 // strip trailing whitespace (should be only one token)
7c673cae
FG
440 if (argument.size() > 0 &&
441 IS_CATEGORY(argument.back(), WhiteSpaceTokenType))
442 {
443 argument.pop_back();
444 }
445}
446
447///////////////////////////////////////////////////////////////////////////////
448//
b32b8144 449// Remove all whitespace tokens on the left and right sides of the given token
7c673cae
FG
450// sequence
451//
452///////////////////////////////////////////////////////////////////////////////
453template <typename ContainerT>
454inline void
455trim_sequence (ContainerT &argument)
456{
457 trim_sequence_left(argument);
458 trim_sequence_right(argument);
459}
460
461///////////////////////////////////////////////////////////////////////////////
462// call 'skipped_token' preprocessing hook
463template <typename ContextT>
b32b8144 464void call_skipped_token_hook(ContextT& ctx,
7c673cae
FG
465 typename ContextT::token_type const& skipped)
466{
467#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
b32b8144 468 ctx.get_hooks().skipped_token(skipped);
7c673cae
FG
469#else
470 ctx.get_hooks().skipped_token(ctx.derived(), skipped);
471#endif
472}
473
474///////////////////////////////////////////////////////////////////////////////
475//
476// Skip forward to a given token
477//
478///////////////////////////////////////////////////////////////////////////////
479template <typename ContextT, typename IteratorT>
b32b8144
FG
480inline bool
481skip_to_token(ContextT& ctx, IteratorT &it, IteratorT const &end,
7c673cae
FG
482 token_id id, bool& seen_newline)
483{
484 using namespace boost::wave;
b32b8144 485 if (token_id(*it) == id)
7c673cae
FG
486 return true;
487
488// call_skipped_token_hook(ctx, *it);
b32b8144 489 if (++it == end)
7c673cae
FG
490 return false;
491
b32b8144
FG
492 while (IS_CATEGORY(*it, WhiteSpaceTokenType) ||
493 T_NEWLINE == token_id(*it))
7c673cae
FG
494 {
495 if (T_NEWLINE == token_id(*it))
496 seen_newline = true;
497
498// call_skipped_token_hook(ctx, *it);
499 if (++it == end)
500 return false;
501 }
502 return token_id(*it) == id;
503}
504
505///////////////////////////////////////////////////////////////////////////////
506//
b32b8144 507// Get the full name of a given macro name (concatenate the string
7c673cae
FG
508// representations of the single tokens).
509//
510///////////////////////////////////////////////////////////////////////////////
511template <typename IteratorT>
512inline std::string
513get_full_name(IteratorT const &begin, IteratorT const &end)
514{
515 std::string full_name;
b32b8144 516 for (IteratorT err_it = begin; err_it != end; ++err_it)
7c673cae
FG
517 full_name += (*err_it).get_value().c_str();
518
519 return full_name;
520}
521
522///////////////////////////////////////////////////////////////////////////////
523//
524// The following predicate is used in conjunction with the remove_copy_if
525// algorithm to allow the detection of an eventually copied operator ##.
526// No removal is performed in any case.
527//
528///////////////////////////////////////////////////////////////////////////////
529class find_concat_operator {
530public:
531 find_concat_operator(bool &found_) : found_concat(found_) {}
532
533 template <typename TokenT>
534 bool operator()(TokenT const &tok)
535 {
536 using namespace boost::wave;
537 if (T_POUND_POUND == BASE_TOKEN(token_id(tok)))
538 found_concat = true;
539 return false;
540 }
541
542private:
543 bool &found_concat;
544};
545
546///////////////////////////////////////////////////////////////////////////////
b32b8144 547// Convert a string of an arbitrary string compatible type to a internal
7c673cae
FG
548// string (BOOST_WAVE_STRING)
549template <typename Target, typename Src>
550struct to_string_helper
551{
552 typedef Target type;
553
554 static Target call(Src const& str)
555 {
556 return Target(str.c_str());
557 }
558};
559
560// do nothing if types are equal
561template <typename Src>
562struct to_string_helper<Src, Src>
563{
564 typedef Src const& type;
565
566 static Src const& call(Src const& str)
567 {
568 return str;
569 }
570};
571
572template <typename Target>
573struct to_string_helper<Target, char const*>
574{
575 typedef Target type;
576
577 static Target call(char const* str)
578 {
579 return Target(str);
580 }
581};
582
583///////////////////////////////////////////////////////////////////////////////
584} // namespace impl
585
586template <typename Target, typename Src>
587inline typename impl::to_string_helper<Target, Src>::type
588to_string(Src const& src)
589{
590 return impl::to_string_helper<Target, Src>::call(src);
591}
592
593///////////////////////////////////////////////////////////////////////////////
594} // namespace util
595} // namespace wave
596} // namespace boost
597
598// the suffix header occurs after all of the code
599#ifdef BOOST_HAS_ABI_HEADERS
600#include BOOST_ABI_SUFFIX
601#endif
602
20effc67 603#endif // !defined(BOOST_CPP_MACROMAP_UTIL_HPP_HK041119)