Line data Source code
1 : /*=============================================================================
2 : Boost.Wave: A Standard compliant C++ preprocessor library
3 :
4 : Macro expansion engine
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 :
13 : #if !defined(CPP_MACROMAP_HPP_CB8F51B0_A3F0_411C_AEF4_6FF631B8B414_INCLUDED)
14 : #define CPP_MACROMAP_HPP_CB8F51B0_A3F0_411C_AEF4_6FF631B8B414_INCLUDED
15 :
16 : #include <cstdlib>
17 : #include <cstdio>
18 : #include <ctime>
19 :
20 : #include <list>
21 : #include <map>
22 : #include <set>
23 : #include <vector>
24 : #include <iterator>
25 : #include <algorithm>
26 :
27 : #include <boost/assert.hpp>
28 : #include <boost/wave/wave_config.hpp>
29 : #if BOOST_WAVE_SERIALIZATION != 0
30 : #include <boost/serialization/serialization.hpp>
31 : #include <boost/serialization/shared_ptr.hpp>
32 : #endif
33 :
34 : #include <boost/filesystem/path.hpp>
35 : #include <boost/lexical_cast.hpp>
36 :
37 : #include <boost/wave/util/time_conversion_helper.hpp>
38 : #include <boost/wave/util/unput_queue_iterator.hpp>
39 : #include <boost/wave/util/macro_helpers.hpp>
40 : #include <boost/wave/util/macro_definition.hpp>
41 : #include <boost/wave/util/symbol_table.hpp>
42 : #include <boost/wave/util/cpp_macromap_utils.hpp>
43 : #include <boost/wave/util/cpp_macromap_predef.hpp>
44 : #include <boost/wave/util/filesystem_compatibility.hpp>
45 : #include <boost/wave/grammars/cpp_defined_grammar_gen.hpp>
46 :
47 : #include <boost/wave/wave_version.hpp>
48 : #include <boost/wave/cpp_exceptions.hpp>
49 : #include <boost/wave/language_support.hpp>
50 :
51 : // this must occur after all of the includes and before any code appears
52 : #ifdef BOOST_HAS_ABI_HEADERS
53 : #include BOOST_ABI_PREFIX
54 : #endif
55 :
56 : ///////////////////////////////////////////////////////////////////////////////
57 : namespace boost { namespace wave { namespace util {
58 :
59 : ///////////////////////////////////////////////////////////////////////////////
60 : //
61 : // macromap
62 : //
63 : // This class holds all currently defined macros and on demand expands
64 : // those macro definitions
65 : //
66 : ///////////////////////////////////////////////////////////////////////////////
67 : template <typename ContextT>
68 : class macromap {
69 :
70 : typedef macromap<ContextT> self_type;
71 : typedef typename ContextT::token_type token_type;
72 : typedef typename token_type::string_type string_type;
73 : typedef typename token_type::position_type position_type;
74 :
75 : typedef typename ContextT::token_sequence_type definition_container_type;
76 : typedef std::vector<token_type> parameter_container_type;
77 :
78 : typedef macro_definition<token_type, definition_container_type>
79 : macro_definition_type;
80 : typedef symbol_table<string_type, macro_definition_type>
81 : defined_macros_type;
82 : typedef typename defined_macros_type::value_type::second_type
83 : macro_ref_type;
84 :
85 : public:
86 0 : macromap(ContextT &ctx_)
87 0 : : current_macros(0), defined_macros(new defined_macros_type(1)),
88 0 : main_pos("", 0), ctx(ctx_), macro_uid(1)
89 : {
90 0 : current_macros = defined_macros.get();
91 0 : }
92 0 : ~macromap() {}
93 :
94 : // Add a new macro to the given macro scope
95 : bool add_macro(token_type const &name, bool has_parameters,
96 : parameter_container_type ¶meters,
97 : definition_container_type &definition, bool is_predefined = false,
98 : defined_macros_type *scope = 0);
99 :
100 : // Tests, whether the given macro name is defined in the given macro scope
101 : bool is_defined(string_type const &name,
102 : typename defined_macros_type::iterator &it,
103 : defined_macros_type *scope = 0) const;
104 :
105 : // expects a token sequence as its parameters
106 : template <typename IteratorT>
107 : bool is_defined(IteratorT const &begin, IteratorT const &end) const;
108 :
109 : // expects an arbitrary string as its parameter
110 : bool is_defined(string_type const &str) const;
111 :
112 : // Get the macro definition for the given macro scope
113 : bool get_macro(string_type const &name, bool &has_parameters,
114 : bool &is_predefined, position_type &pos,
115 : parameter_container_type ¶meters,
116 : definition_container_type &definition,
117 : defined_macros_type *scope = 0) const;
118 :
119 : // Remove a macro name from the given macro scope
120 : bool remove_macro(string_type const &name, position_type const& pos,
121 : bool even_predefined = false);
122 :
123 : template <typename IteratorT, typename ContainerT>
124 : token_type const &expand_tokensequence(IteratorT &first,
125 : IteratorT const &last, ContainerT &pending, ContainerT &expanded,
126 : bool& seen_newline, bool expand_operator_defined);
127 :
128 : // Expand all macros inside the given token sequence
129 : template <typename IteratorT, typename ContainerT>
130 : void expand_whole_tokensequence(ContainerT &expanded,
131 : IteratorT &first, IteratorT const &last,
132 : bool expand_operator_defined);
133 :
134 : // Init the predefined macros (add them to the given scope)
135 : void init_predefined_macros(char const *fname = "<Unknown>",
136 : defined_macros_type *scope = 0, bool at_global_scope = true);
137 : void predefine_macro(defined_macros_type *scope, string_type const &name,
138 : token_type const &t);
139 :
140 : // Init the internal macro symbol namespace
141 : void reset_macromap();
142 :
143 0 : position_type &get_main_pos() { return main_pos; }
144 : position_type const& get_main_pos() const { return main_pos; }
145 :
146 : // interface for macro name introspection
147 : typedef typename defined_macros_type::name_iterator name_iterator;
148 : typedef typename defined_macros_type::const_name_iterator const_name_iterator;
149 :
150 : name_iterator begin()
151 : { return defined_macros_type::make_iterator(current_macros->begin()); }
152 : name_iterator end()
153 : { return defined_macros_type::make_iterator(current_macros->end()); }
154 : const_name_iterator begin() const
155 : { return defined_macros_type::make_iterator(current_macros->begin()); }
156 : const_name_iterator end() const
157 : { return defined_macros_type::make_iterator(current_macros->end()); }
158 :
159 : protected:
160 : // Helper functions for expanding all macros in token sequences
161 : template <typename IteratorT, typename ContainerT>
162 : token_type const &expand_tokensequence_worker(ContainerT &pending,
163 : unput_queue_iterator<IteratorT, token_type, ContainerT> &first,
164 : unput_queue_iterator<IteratorT, token_type, ContainerT> const &last,
165 : bool& seen_newline, bool expand_operator_defined);
166 :
167 : // Collect all arguments supplied to a macro invocation
168 : #if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
169 : template <typename IteratorT, typename ContainerT, typename SizeT>
170 : typename std::vector<ContainerT>::size_type collect_arguments (
171 : token_type const curr_token, std::vector<ContainerT> &arguments,
172 : IteratorT &next, IteratorT const &end, SizeT const ¶meter_count,
173 : bool& seen_newline);
174 : #else
175 : template <typename IteratorT, typename ContainerT, typename SizeT>
176 : typename std::vector<ContainerT>::size_type collect_arguments (
177 : token_type const curr_token, std::vector<ContainerT> &arguments,
178 : IteratorT &next, IteratorT &endparen, IteratorT const &end,
179 : SizeT const ¶meter_count, bool& seen_newline);
180 : #endif
181 :
182 : // Expand a single macro name
183 : template <typename IteratorT, typename ContainerT>
184 : bool expand_macro(ContainerT &pending, token_type const &name,
185 : typename defined_macros_type::iterator it,
186 : IteratorT &first, IteratorT const &last,
187 : bool& seen_newline, bool expand_operator_defined,
188 : defined_macros_type *scope = 0, ContainerT *queue_symbol = 0);
189 :
190 : // Expand a predefined macro (__LINE__, __FILE__ and __INCLUDE_LEVEL__)
191 : template <typename ContainerT>
192 : bool expand_predefined_macro(token_type const &curr_token,
193 : ContainerT &expanded);
194 :
195 : // Expand a single macro argument
196 : template <typename ContainerT>
197 : void expand_argument (typename std::vector<ContainerT>::size_type arg,
198 : std::vector<ContainerT> &arguments,
199 : std::vector<ContainerT> &expanded_args, bool expand_operator_defined,
200 : std::vector<bool> &has_expanded_args);
201 :
202 : // Expand the replacement list (replaces parameters with arguments)
203 : template <typename ContainerT>
204 : void expand_replacement_list(
205 : macro_definition_type const ¯odefinition,
206 : std::vector<ContainerT> &arguments,
207 : bool expand_operator_defined, ContainerT &expanded);
208 :
209 : // Rescans the replacement list for macro expansion
210 : template <typename IteratorT, typename ContainerT>
211 : void rescan_replacement_list(token_type const &curr_token,
212 : macro_definition_type ¯odef, ContainerT &replacement_list,
213 : ContainerT &expanded, bool expand_operator_defined,
214 : IteratorT &nfirst, IteratorT const &nlast);
215 :
216 : // Resolves the operator defined() and replces the token with "0" or "1"
217 : template <typename IteratorT, typename ContainerT>
218 : token_type const &resolve_defined(IteratorT &first, IteratorT const &last,
219 : ContainerT &expanded);
220 :
221 : // Resolve operator _Pragma or the #pragma directive
222 : template <typename IteratorT, typename ContainerT>
223 : bool resolve_operator_pragma(IteratorT &first,
224 : IteratorT const &last, ContainerT &expanded, bool& seen_newline);
225 :
226 : // Handle the concatenation operator '##'
227 : template <typename ContainerT>
228 : bool concat_tokensequence(ContainerT &expanded);
229 :
230 : template <typename ContainerT>
231 : bool is_valid_concat(string_type new_value,
232 : position_type const &pos, ContainerT &rescanned);
233 :
234 : #if BOOST_WAVE_SERIALIZATION != 0
235 : public:
236 : BOOST_STATIC_CONSTANT(unsigned int, version = 0x10);
237 : BOOST_STATIC_CONSTANT(unsigned int, version_mask = 0x0f);
238 :
239 : private:
240 : friend class boost::serialization::access;
241 : template<typename Archive>
242 : void save(Archive &ar, const unsigned int version) const
243 : {
244 : using namespace boost::serialization;
245 : ar & make_nvp("defined_macros", defined_macros);
246 : }
247 : template<typename Archive>
248 : void load(Archive &ar, const unsigned int loaded_version)
249 : {
250 : using namespace boost::serialization;
251 : if (version != (loaded_version & ~version_mask)) {
252 : BOOST_WAVE_THROW(preprocess_exception, incompatible_config,
253 : "cpp_context state version", get_main_pos());
254 : }
255 : ar & make_nvp("defined_macros", defined_macros);
256 : current_macros = defined_macros.get();
257 : }
258 : BOOST_SERIALIZATION_SPLIT_MEMBER()
259 : #endif
260 :
261 : private:
262 : defined_macros_type *current_macros; // current symbol table
263 : boost::shared_ptr<defined_macros_type> defined_macros; // global symbol table
264 :
265 : token_type act_token; // current token
266 : position_type main_pos; // last token position in the pp_iterator
267 : string_type base_name; // the name to be expanded by __BASE_FILE__
268 : ContextT &ctx; // context object associated with the macromap
269 : long macro_uid;
270 : predefined_macros predef; // predefined macro support
271 : };
272 : ///////////////////////////////////////////////////////////////////////////////
273 :
274 : ///////////////////////////////////////////////////////////////////////////////
275 : //
276 : // add_macro(): adds a new macro to the macromap
277 : //
278 : ///////////////////////////////////////////////////////////////////////////////
279 : template <typename ContextT>
280 : inline bool
281 0 : macromap<ContextT>::add_macro(token_type const &name, bool has_parameters,
282 : parameter_container_type ¶meters, definition_container_type &definition,
283 : bool is_predefined, defined_macros_type *scope)
284 : {
285 0 : if (!is_predefined && impl::is_special_macroname (name.get_value())) {
286 : // exclude special macro names
287 0 : BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
288 : illegal_redefinition, name.get_value().c_str(), main_pos,
289 : name.get_value().c_str());
290 : return false;
291 : }
292 0 : if (boost::wave::need_variadics(ctx.get_language()) &&
293 0 : "__VA_ARGS__" == name.get_value())
294 : {
295 : // can't use __VA_ARGS__ as a macro name
296 0 : BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
297 : bad_define_statement_va_args, name.get_value().c_str(), main_pos,
298 : name.get_value().c_str());
299 : return false;
300 : }
301 0 : if (AltExtTokenType == (token_id(name) & ExtTokenOnlyMask)) {
302 : // exclude special operator names
303 0 : BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
304 : illegal_operator_redefinition, name.get_value().c_str(), main_pos,
305 : name.get_value().c_str());
306 : return false;
307 : }
308 :
309 : // try to define the new macro
310 0 : defined_macros_type *current_scope = scope ? scope : current_macros;
311 0 : typename defined_macros_type::iterator it = current_scope->find(name.get_value());
312 :
313 0 : if (it != current_scope->end()) {
314 : // redefinition, should not be different
315 0 : macro_definition_type* macrodef = (*it).second.get();
316 0 : if (macrodef->is_functionlike != has_parameters ||
317 0 : !impl::parameters_equal(macrodef->macroparameters, parameters) ||
318 0 : !impl::definition_equals(macrodef->macrodefinition, definition))
319 : {
320 0 : BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
321 : macro_redefinition, name.get_value().c_str(), main_pos,
322 : name.get_value().c_str());
323 : }
324 : return false;
325 : }
326 :
327 : // test the validity of the parameter names
328 0 : if (has_parameters) {
329 0 : std::set<typename token_type::string_type> names;
330 :
331 : typedef typename parameter_container_type::iterator
332 : parameter_iterator_type;
333 : typedef typename std::set<typename token_type::string_type>::iterator
334 : name_iterator_type;
335 :
336 0 : parameter_iterator_type end = parameters.end();
337 0 : for (parameter_iterator_type itp = parameters.begin(); itp != end; ++itp)
338 : {
339 0 : name_iterator_type pit = names.find((*itp).get_value());
340 :
341 0 : if (pit != names.end()) {
342 : // duplicate parameter name
343 0 : BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
344 : duplicate_parameter_name, (*pit).c_str(), main_pos,
345 : name.get_value().c_str());
346 : return false;
347 : }
348 0 : names.insert((*itp).get_value());
349 : }
350 : }
351 :
352 : // insert a new macro node
353 0 : std::pair<typename defined_macros_type::iterator, bool> p =
354 : current_scope->insert(
355 0 : typename defined_macros_type::value_type(
356 : name.get_value(),
357 0 : macro_ref_type(new macro_definition_type(name,
358 0 : has_parameters, is_predefined, ++macro_uid)
359 : )
360 : )
361 : );
362 :
363 0 : if (!p.second) {
364 0 : BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
365 : macro_insertion_error, name.get_value().c_str(), main_pos,
366 : name.get_value().c_str());
367 : return false;
368 : }
369 :
370 : // add the parameters and the definition
371 0 : std::swap((*p.first).second->macroparameters, parameters);
372 0 : std::swap((*p.first).second->macrodefinition, definition);
373 :
374 : // call the context supplied preprocessing hook
375 : #if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
376 : ctx.get_hooks().defined_macro(name, has_parameters,
377 : (*p.first).second->macroparameters,
378 : (*p.first).second->macrodefinition, is_predefined);
379 : #else
380 0 : ctx.get_hooks().defined_macro(ctx.derived(), name, has_parameters,
381 0 : (*p.first).second->macroparameters,
382 0 : (*p.first).second->macrodefinition, is_predefined);
383 : #endif
384 : return true;
385 : }
386 :
387 : ///////////////////////////////////////////////////////////////////////////////
388 : //
389 : // is_defined(): returns, whether a given macro is already defined
390 : //
391 : ///////////////////////////////////////////////////////////////////////////////
392 : template <typename ContextT>
393 : inline bool
394 0 : macromap<ContextT>::is_defined(typename token_type::string_type const &name,
395 : typename defined_macros_type::iterator &it,
396 : defined_macros_type *scope) const
397 : {
398 0 : if (0 == scope) scope = current_macros;
399 :
400 0 : if ((it = scope->find(name)) != scope->end())
401 : return true; // found in symbol table
402 :
403 : // quick pre-check
404 0 : if (name.size() < 8 || '_' != name[0] || '_' != name[1])
405 : return false; // quick check failed
406 :
407 0 : return name == "__LINE__" || name == "__FILE__" ||
408 0 : name == "__INCLUDE_LEVEL__";
409 : }
410 :
411 : template <typename ContextT>
412 : template <typename IteratorT>
413 : inline bool
414 0 : macromap<ContextT>::is_defined(IteratorT const &begin,
415 : IteratorT const &end) const
416 : {
417 : // in normal mode the name under inspection should consist of an identifier
418 : // only
419 0 : token_id id = token_id(*begin);
420 :
421 0 : if (T_IDENTIFIER != id &&
422 0 : !IS_CATEGORY(id, KeywordTokenType) &&
423 0 : !IS_EXTCATEGORY(id, OperatorTokenType|AltExtTokenType) &&
424 : !IS_CATEGORY(id, BoolLiteralTokenType))
425 : {
426 0 : std::string msg(impl::get_full_name(begin, end));
427 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, invalid_macroname,
428 : msg.c_str(), main_pos);
429 0 : return false;
430 : }
431 :
432 0 : IteratorT it = begin;
433 0 : string_type name ((*it).get_value());
434 0 : typename defined_macros_type::iterator cit;
435 :
436 0 : if (++it != end) {
437 : // there should be only one token as the inspected name
438 0 : std::string msg(impl::get_full_name(begin, end));
439 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, invalid_macroname,
440 : msg.c_str(), main_pos);
441 0 : return false;
442 : }
443 0 : return is_defined(name, cit, 0);
444 : }
445 :
446 : ///////////////////////////////////////////////////////////////////////////////
447 : // same as above, only takes an arbitrary string type as its parameter
448 : template <typename ContextT>
449 : inline bool
450 0 : macromap<ContextT>::is_defined(string_type const &str) const
451 : {
452 0 : typename defined_macros_type::iterator cit;
453 0 : return is_defined(str, cit, 0);
454 : }
455 :
456 : ///////////////////////////////////////////////////////////////////////////////
457 : //
458 : // Get the macro definition for the given macro scope
459 : //
460 : ///////////////////////////////////////////////////////////////////////////////
461 : template <typename ContextT>
462 : inline bool
463 : macromap<ContextT>::get_macro(string_type const &name, bool &has_parameters,
464 : bool &is_predefined, position_type &pos,
465 : parameter_container_type ¶meters,
466 : definition_container_type &definition,
467 : defined_macros_type *scope) const
468 : {
469 : typename defined_macros_type::iterator it;
470 : if (!is_defined(name, it, scope))
471 : return false;
472 :
473 : macro_definition_type ¯o_def = *(*it).second.get();
474 :
475 : has_parameters = macro_def.is_functionlike;
476 : is_predefined = macro_def.is_predefined;
477 : pos = macro_def.macroname.get_position();
478 : parameters = macro_def.macroparameters;
479 : definition = macro_def.macrodefinition;
480 : return true;
481 : }
482 :
483 : ///////////////////////////////////////////////////////////////////////////////
484 : //
485 : // remove_macro(): remove a macro from the macromap
486 : //
487 : ///////////////////////////////////////////////////////////////////////////////
488 : template <typename ContextT>
489 : inline bool
490 0 : macromap<ContextT>::remove_macro(string_type const &name,
491 : position_type const& pos, bool even_predefined)
492 : {
493 0 : typename defined_macros_type::iterator it = current_macros->find(name);
494 :
495 0 : if (it != current_macros->end()) {
496 0 : if ((*it).second->is_predefined) {
497 0 : if (!even_predefined || impl::is_special_macroname(name)) {
498 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
499 : bad_undefine_statement, name.c_str(), main_pos);
500 0 : return false;
501 : }
502 : }
503 0 : current_macros->erase(it);
504 :
505 : // call the context supplied preprocessing hook function
506 0 : token_type tok(T_IDENTIFIER, name, pos);
507 :
508 : #if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
509 : ctx.get_hooks().undefined_macro(tok);
510 : #else
511 0 : ctx.get_hooks().undefined_macro(ctx.derived(), tok);
512 : #endif
513 : return true;
514 : }
515 0 : else if (impl::is_special_macroname(name)) {
516 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_undefine_statement,
517 : name.c_str(), pos);
518 : }
519 : return false; // macro was not defined
520 : }
521 :
522 : ///////////////////////////////////////////////////////////////////////////////
523 : //
524 : // expand_tokensequence
525 : //
526 : // This function is a helper function which wraps the given iterator
527 : // range into corresponding unput_iterator's and calls the main workhorse
528 : // of the macro expansion engine (the function expand_tokensequence_worker)
529 : //
530 : // This is the top level macro expansion function called from the
531 : // preprocessing iterator component only.
532 : //
533 : ///////////////////////////////////////////////////////////////////////////////
534 : template <typename ContextT>
535 : template <typename IteratorT, typename ContainerT>
536 : inline typename ContextT::token_type const &
537 0 : macromap<ContextT>::expand_tokensequence(IteratorT &first,
538 : IteratorT const &last, ContainerT &pending, ContainerT &expanded,
539 : bool& seen_newline, bool expand_operator_defined)
540 : {
541 : typedef impl::gen_unput_queue_iterator<IteratorT, token_type, ContainerT>
542 : gen_type;
543 : typedef typename gen_type::return_type iterator_type;
544 :
545 0 : iterator_type first_it = gen_type::generate(expanded, first);
546 0 : iterator_type last_it = gen_type::generate(last);
547 :
548 0 : on_exit::assign<IteratorT, iterator_type> on_exit(first, first_it);
549 :
550 : return expand_tokensequence_worker(pending, first_it, last_it,
551 0 : seen_newline, expand_operator_defined);
552 : }
553 :
554 : ///////////////////////////////////////////////////////////////////////////////
555 : //
556 : // expand_tokensequence_worker
557 : //
558 : // This function is the main workhorse of the macro expansion engine. It
559 : // expands as much tokens as needed to identify the next preprocessed
560 : // token to return to the caller.
561 : // It returns the next preprocessed token.
562 : //
563 : // The iterator 'first' is adjusted accordingly.
564 : //
565 : ///////////////////////////////////////////////////////////////////////////////
566 : template <typename ContextT>
567 : template <typename IteratorT, typename ContainerT>
568 : inline typename ContextT::token_type const &
569 0 : macromap<ContextT>::expand_tokensequence_worker(
570 : ContainerT &pending,
571 : unput_queue_iterator<IteratorT, token_type, ContainerT> &first,
572 : unput_queue_iterator<IteratorT, token_type, ContainerT> const &last,
573 : bool& seen_newline, bool expand_operator_defined)
574 : {
575 : // if there exist pending tokens (tokens, which are already preprocessed), then
576 : // return the next one from there
577 0 : if (!pending.empty()) {
578 0 : on_exit::pop_front<definition_container_type> pop_front_token(pending);
579 :
580 0 : return act_token = pending.front();
581 : }
582 :
583 : // analyze the next element of the given sequence, if it is an
584 : // T_IDENTIFIER token, try to replace this as a macro etc.
585 : using namespace boost::wave;
586 :
587 0 : if (first != last) {
588 0 : token_id id = token_id(*first);
589 :
590 : // ignore placeholder tokens
591 0 : if (T_PLACEHOLDER == id) {
592 0 : token_type placeholder = *first;
593 :
594 0 : ++first;
595 0 : if (first == last)
596 0 : return act_token = placeholder;
597 0 : id = token_id(*first);
598 : }
599 :
600 0 : if (T_IDENTIFIER == id || IS_CATEGORY(id, KeywordTokenType) ||
601 0 : IS_EXTCATEGORY(id, OperatorTokenType|AltExtTokenType) ||
602 : IS_CATEGORY(id, BoolLiteralTokenType))
603 : {
604 : // try to replace this identifier as a macro
605 0 : if (expand_operator_defined && (*first).get_value() == "defined") {
606 : // resolve operator defined()
607 0 : return resolve_defined(first, last, pending);
608 : }
609 0 : else if (boost::wave::need_variadics(ctx.get_language()) &&
610 0 : (*first).get_value() == "_Pragma")
611 : {
612 : // in C99 mode only: resolve the operator _Pragma
613 0 : token_type curr_token = *first;
614 :
615 0 : if (!resolve_operator_pragma(first, last, pending, seen_newline) ||
616 0 : pending.size() > 0)
617 : {
618 : // unknown to us pragma or supplied replacement, return the
619 : // next token
620 0 : on_exit::pop_front<definition_container_type> pop_token(pending);
621 :
622 0 : return act_token = pending.front();
623 : }
624 :
625 : // the operator _Pragma() was eaten completely, continue
626 0 : return act_token = token_type(T_PLACEHOLDER, "_",
627 : curr_token.get_position());
628 : }
629 :
630 0 : token_type name_token (*first);
631 0 : typename defined_macros_type::iterator it;
632 :
633 0 : if (is_defined(name_token.get_value(), it)) {
634 : // the current token contains an identifier, which is currently
635 : // defined as a macro
636 0 : if (expand_macro(pending, name_token, it, first, last,
637 : seen_newline, expand_operator_defined))
638 : {
639 : // the tokens returned by expand_macro should be rescanned
640 : // beginning at the last token of the returned replacement list
641 0 : if (first != last) {
642 : // splice the last token back into the input queue
643 0 : typename ContainerT::reverse_iterator rit = pending.rbegin();
644 :
645 0 : first.get_unput_queue().splice(
646 0 : first.get_unput_queue().begin(), pending,
647 0 : (++rit).base(), pending.end());
648 : }
649 :
650 : // fall through ...
651 : }
652 0 : else if (!pending.empty()) {
653 : // return the first token from the pending queue
654 0 : on_exit::pop_front<definition_container_type> pop_queue (pending);
655 :
656 0 : return act_token = pending.front();
657 : }
658 : else {
659 : // macro expansion reached the eoi
660 0 : return act_token = token_type();
661 : }
662 :
663 : // return the next preprocessed token
664 : return expand_tokensequence_worker(pending, first, last,
665 0 : seen_newline, expand_operator_defined);
666 : }
667 : // else if (expand_operator_defined) {
668 : // // in preprocessing conditionals undefined identifiers and keywords
669 : // // are to be replaced with '0' (see. C++ standard 16.1.4, [cpp.cond])
670 : // return act_token =
671 : // token_type(T_INTLIT, "0", (*first++).get_position());
672 : // }
673 : else {
674 0 : act_token = name_token;
675 0 : ++first;
676 0 : return act_token;
677 : }
678 : }
679 0 : else if (expand_operator_defined && IS_CATEGORY(*first, BoolLiteralTokenType)) {
680 : // expanding a constant expression inside #if/#elif, special handling
681 : // of 'true' and 'false'
682 :
683 : // all remaining identifiers and keywords, except for true and false,
684 : // are replaced with the pp-number 0 (C++ standard 16.1.4, [cpp.cond])
685 0 : return act_token = token_type(T_INTLIT, T_TRUE != id ? "0" : "1",
686 0 : (*first++).get_position());
687 : }
688 : else {
689 0 : act_token = *first;
690 0 : ++first;
691 0 : return act_token;
692 : }
693 : }
694 0 : return act_token = token_type(); // eoi
695 : }
696 :
697 : ///////////////////////////////////////////////////////////////////////////////
698 : //
699 : // collect_arguments(): collect the actual arguments of a macro invocation
700 : //
701 : // return the number of successfully detected non-empty arguments
702 : //
703 : ///////////////////////////////////////////////////////////////////////////////
704 : #if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
705 : template <typename ContextT>
706 : template <typename IteratorT, typename ContainerT, typename SizeT>
707 : inline typename std::vector<ContainerT>::size_type
708 : macromap<ContextT>::collect_arguments (token_type const curr_token,
709 : std::vector<ContainerT> &arguments, IteratorT &next,
710 : IteratorT const &end, SizeT const ¶meter_count, bool& seen_newline)
711 : #else
712 : template <typename ContextT>
713 : template <typename IteratorT, typename ContainerT, typename SizeT>
714 : inline typename std::vector<ContainerT>::size_type
715 0 : macromap<ContextT>::collect_arguments (token_type const curr_token,
716 : std::vector<ContainerT> &arguments, IteratorT &next, IteratorT &endparen,
717 : IteratorT const &end, SizeT const ¶meter_count, bool& seen_newline)
718 : #endif
719 : {
720 : using namespace boost::wave;
721 :
722 0 : arguments.push_back(ContainerT());
723 :
724 : // collect the actual arguments
725 0 : typename std::vector<ContainerT>::size_type count_arguments = 0;
726 0 : int nested_parenthesis_level = 1;
727 0 : ContainerT *argument = &arguments[0];
728 0 : bool was_whitespace = false;
729 0 : token_type startof_argument_list = *next;
730 :
731 0 : while (++next != end && nested_parenthesis_level) {
732 0 : token_id id = token_id(*next);
733 :
734 0 : if (0 == parameter_count &&
735 0 : !IS_CATEGORY((*next), WhiteSpaceTokenType) && id != T_NEWLINE &&
736 0 : id != T_RIGHTPAREN && id != T_LEFTPAREN)
737 : {
738 : // there shouldn't be any arguments
739 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
740 : too_many_macroarguments, curr_token.get_value().c_str(),
741 : main_pos);
742 : return 0;
743 : }
744 :
745 0 : switch (id) {
746 0 : case T_LEFTPAREN:
747 0 : ++nested_parenthesis_level;
748 0 : argument->push_back(*next);
749 : was_whitespace = false;
750 : break;
751 :
752 0 : case T_RIGHTPAREN:
753 : {
754 0 : if (--nested_parenthesis_level >= 1)
755 0 : argument->push_back(*next);
756 : else {
757 : // found closing parenthesis
758 : // trim_sequence(argument);
759 : #if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS == 0
760 0 : endparen = next;
761 : #endif
762 0 : if (parameter_count > 0) {
763 0 : if (argument->empty() ||
764 0 : impl::is_whitespace_only(*argument))
765 : {
766 : #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
767 0 : if (boost::wave::need_variadics(ctx.get_language())) {
768 : // store a placemarker as the argument
769 0 : argument->push_back(token_type(T_PLACEMARKER, "\xA7",
770 0 : (*next).get_position()));
771 0 : ++count_arguments;
772 : }
773 : #endif
774 : }
775 : else {
776 0 : ++count_arguments;
777 : }
778 : }
779 : }
780 : was_whitespace = false;
781 : }
782 : break;
783 :
784 0 : case T_COMMA:
785 0 : if (1 == nested_parenthesis_level) {
786 : // next parameter
787 : // trim_sequence(argument);
788 0 : if (argument->empty() ||
789 0 : impl::is_whitespace_only(*argument))
790 : {
791 : #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
792 0 : if (boost::wave::need_variadics(ctx.get_language())) {
793 : // store a placemarker as the argument
794 0 : argument->push_back(token_type(T_PLACEMARKER, "\xA7",
795 0 : (*next).get_position()));
796 0 : ++count_arguments;
797 : }
798 : #endif
799 : }
800 : else {
801 0 : ++count_arguments;
802 : }
803 0 : arguments.push_back(ContainerT()); // add new arg
804 0 : argument = &arguments[arguments.size()-1];
805 : }
806 : else {
807 : // surrounded by parenthesises, so store to current argument
808 0 : argument->push_back(*next);
809 : }
810 : was_whitespace = false;
811 : break;
812 :
813 0 : case T_NEWLINE:
814 0 : seen_newline = true;
815 : /* fall through */
816 0 : case T_SPACE:
817 : case T_SPACE2:
818 : case T_CCOMMENT:
819 0 : if (!was_whitespace)
820 0 : argument->push_back(token_type(T_SPACE, " ", (*next).get_position()));
821 0 : was_whitespace = true;
822 : break; // skip whitespace
823 :
824 : case T_PLACEHOLDER:
825 : break; // ignore placeholder
826 :
827 0 : default:
828 0 : argument->push_back(*next);
829 : was_whitespace = false;
830 : break;
831 : }
832 : }
833 :
834 0 : if (nested_parenthesis_level >= 1) {
835 : // missing ')': improperly terminated macro invocation
836 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
837 : improperly_terminated_macro, "missing ')'", main_pos);
838 : return 0;
839 : }
840 :
841 : // if no argument was expected and we didn't find any, than remove the empty
842 : // element
843 0 : if (0 == parameter_count && 0 == count_arguments) {
844 0 : BOOST_ASSERT(1 == arguments.size());
845 0 : arguments.clear();
846 : }
847 : return count_arguments;
848 : }
849 :
850 : ///////////////////////////////////////////////////////////////////////////////
851 : //
852 : // expand_whole_tokensequence
853 : //
854 : // fully expands a given token sequence
855 : //
856 : ///////////////////////////////////////////////////////////////////////////////
857 : template <typename ContextT>
858 : template <typename IteratorT, typename ContainerT>
859 : inline void
860 0 : macromap<ContextT>::expand_whole_tokensequence(ContainerT &expanded,
861 : IteratorT &first, IteratorT const &last,
862 : bool expand_operator_defined)
863 : {
864 : typedef impl::gen_unput_queue_iterator<IteratorT, token_type, ContainerT>
865 : gen_type;
866 : typedef typename gen_type::return_type iterator_type;
867 :
868 0 : ContainerT empty;
869 0 : iterator_type first_it = gen_type::generate(empty, first);
870 0 : iterator_type last_it = gen_type::generate(last);
871 :
872 0 : on_exit::assign<IteratorT, iterator_type> on_exit(first, first_it);
873 0 : ContainerT pending_queue;
874 : bool seen_newline;
875 :
876 0 : while (!pending_queue.empty() || first_it != last_it) {
877 0 : expanded.push_back(
878 : expand_tokensequence_worker(pending_queue, first_it,
879 : last_it, seen_newline, expand_operator_defined)
880 : );
881 : }
882 :
883 : // should have returned all expanded tokens
884 0 : BOOST_ASSERT(pending_queue.empty()/* && unput_queue.empty()*/);
885 0 : }
886 :
887 : ///////////////////////////////////////////////////////////////////////////////
888 : //
889 : // expand_argument
890 : //
891 : // fully expands the given argument of a macro call
892 : //
893 : ///////////////////////////////////////////////////////////////////////////////
894 : template <typename ContextT>
895 : template <typename ContainerT>
896 : inline void
897 0 : macromap<ContextT>::expand_argument (
898 : typename std::vector<ContainerT>::size_type arg,
899 : std::vector<ContainerT> &arguments, std::vector<ContainerT> &expanded_args,
900 : bool expand_operator_defined, std::vector<bool> &has_expanded_args)
901 : {
902 0 : if (!has_expanded_args[arg]) {
903 : // expand the argument only once
904 : typedef typename std::vector<ContainerT>::value_type::iterator
905 : argument_iterator_type;
906 :
907 0 : argument_iterator_type begin_it = arguments[arg].begin();
908 0 : argument_iterator_type end_it = arguments[arg].end();
909 :
910 0 : expand_whole_tokensequence(expanded_args[arg], begin_it, end_it,
911 : expand_operator_defined);
912 0 : impl::remove_placeholders(expanded_args[arg]);
913 0 : has_expanded_args[arg] = true;
914 : }
915 0 : }
916 :
917 : ///////////////////////////////////////////////////////////////////////////////
918 : //
919 : // expand_replacement_list
920 : //
921 : // fully expands the replacement list of a given macro with the
922 : // actual arguments/expanded arguments
923 : // handles the '#' [cpp.stringize] and the '##' [cpp.concat] operator
924 : //
925 : ///////////////////////////////////////////////////////////////////////////////
926 : template <typename ContextT>
927 : template <typename ContainerT>
928 : inline void
929 0 : macromap<ContextT>::expand_replacement_list(
930 : macro_definition_type const ¯odef,
931 : std::vector<ContainerT> &arguments, bool expand_operator_defined,
932 : ContainerT &expanded)
933 : {
934 : using namespace boost::wave;
935 : typedef typename macro_definition_type::const_definition_iterator_t
936 : macro_definition_iter_t;
937 :
938 0 : std::vector<ContainerT> expanded_args(arguments.size());
939 0 : std::vector<bool> has_expanded_args(arguments.size());
940 0 : bool seen_concat = false;
941 0 : bool adjacent_concat = false;
942 0 : bool adjacent_stringize = false;
943 :
944 0 : macro_definition_iter_t cend = macrodef.macrodefinition.end();
945 0 : for (macro_definition_iter_t cit = macrodef.macrodefinition.begin();
946 0 : cit != cend; ++cit)
947 : {
948 0 : bool use_replaced_arg = true;
949 0 : token_id base_id = BASE_TOKEN(token_id(*cit));
950 :
951 0 : if (T_POUND_POUND == base_id) {
952 : // concatenation operator
953 : adjacent_concat = true;
954 : seen_concat = true;
955 : }
956 0 : else if (T_POUND == base_id) {
957 : // stringize operator
958 : adjacent_stringize = true;
959 : }
960 : else {
961 0 : if (adjacent_stringize || adjacent_concat ||
962 : T_POUND_POUND == impl::next_token<macro_definition_iter_t>
963 0 : ::peek(cit, cend))
964 : {
965 : use_replaced_arg = false;
966 : }
967 0 : if (adjacent_concat) // spaces after '##' ?
968 0 : adjacent_concat = IS_CATEGORY(*cit, WhiteSpaceTokenType);
969 : }
970 :
971 0 : if (IS_CATEGORY((*cit), ParameterTokenType)) {
972 : // copy argument 'i' instead of the parameter token i
973 : typename ContainerT::size_type i;
974 : #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
975 0 : bool is_ellipsis = false;
976 :
977 0 : if (IS_EXTCATEGORY((*cit), ExtParameterTokenType)) {
978 0 : BOOST_ASSERT(boost::wave::need_variadics(ctx.get_language()));
979 0 : i = token_id(*cit) - T_EXTPARAMETERBASE;
980 0 : is_ellipsis = true;
981 : }
982 : else
983 : #endif
984 : {
985 0 : i = token_id(*cit) - T_PARAMETERBASE;
986 : }
987 :
988 0 : BOOST_ASSERT(i < arguments.size());
989 0 : if (use_replaced_arg) {
990 :
991 : #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
992 0 : if (is_ellipsis) {
993 0 : position_type const &pos = (*cit).get_position();
994 :
995 0 : BOOST_ASSERT(boost::wave::need_variadics(ctx.get_language()));
996 :
997 : // ensure all variadic arguments to be expanded
998 0 : for (typename vector<ContainerT>::size_type arg = i;
999 0 : arg < expanded_args.size(); ++arg)
1000 : {
1001 0 : expand_argument(arg, arguments, expanded_args,
1002 : expand_operator_defined, has_expanded_args);
1003 : }
1004 0 : impl::replace_ellipsis(expanded_args, i, expanded, pos);
1005 : }
1006 : else
1007 : #endif
1008 : {
1009 : // ensure argument i to be expanded
1010 0 : expand_argument(i, arguments, expanded_args,
1011 : expand_operator_defined, has_expanded_args);
1012 :
1013 : // replace argument
1014 0 : ContainerT const &arg = expanded_args[i];
1015 :
1016 0 : std::copy(arg.begin(), arg.end(),
1017 : std::inserter(expanded, expanded.end()));
1018 : }
1019 : }
1020 0 : else if (adjacent_stringize &&
1021 0 : !IS_CATEGORY(*cit, WhiteSpaceTokenType))
1022 : {
1023 : // stringize the current argument
1024 0 : BOOST_ASSERT(!arguments[i].empty());
1025 :
1026 : // safe a copy of the first tokens position (not a reference!)
1027 0 : position_type pos ((*arguments[i].begin()).get_position());
1028 :
1029 : #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1030 0 : if (is_ellipsis && boost::wave::need_variadics(ctx.get_language())) {
1031 0 : impl::trim_sequence_left(arguments[i]);
1032 0 : impl::trim_sequence_right(arguments.back());
1033 0 : expanded.push_back(token_type(T_STRINGLIT,
1034 : impl::as_stringlit(arguments, i, pos), pos));
1035 : }
1036 : else
1037 : #endif
1038 : {
1039 0 : impl::trim_sequence(arguments[i]);
1040 0 : expanded.push_back(token_type(T_STRINGLIT,
1041 0 : impl::as_stringlit(arguments[i], pos), pos));
1042 : }
1043 0 : adjacent_stringize = false;
1044 : }
1045 : else {
1046 : // simply copy the original argument (adjacent '##' or '#')
1047 : #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1048 0 : if (is_ellipsis) {
1049 0 : position_type const &pos = (*cit).get_position();
1050 :
1051 0 : impl::trim_sequence_left(arguments[i]);
1052 0 : impl::trim_sequence_right(arguments.back());
1053 0 : BOOST_ASSERT(boost::wave::need_variadics(ctx.get_language()));
1054 0 : impl::replace_ellipsis(arguments, i, expanded, pos);
1055 : }
1056 : else
1057 : #endif
1058 : {
1059 0 : ContainerT &arg = arguments[i];
1060 :
1061 0 : impl::trim_sequence(arg);
1062 0 : std::copy(arg.begin(), arg.end(),
1063 : std::inserter(expanded, expanded.end()));
1064 : }
1065 : }
1066 : }
1067 0 : else if (!adjacent_stringize || T_POUND != base_id) {
1068 : // insert the actual replacement token (if it is not the '#' operator)
1069 0 : expanded.push_back(*cit);
1070 : }
1071 : }
1072 :
1073 0 : if (adjacent_stringize) {
1074 : // error, '#' should not be the last token
1075 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_operator,
1076 : "stringize ('#')", main_pos);
1077 0 : return;
1078 : }
1079 :
1080 : // handle the cpp.concat operator
1081 0 : if (seen_concat)
1082 0 : concat_tokensequence(expanded);
1083 : }
1084 :
1085 : ///////////////////////////////////////////////////////////////////////////////
1086 : //
1087 : // rescan_replacement_list
1088 : //
1089 : // As the name implies, this function is used to rescan the replacement list
1090 : // after the first macro substitution phase.
1091 : //
1092 : ///////////////////////////////////////////////////////////////////////////////
1093 : template <typename ContextT>
1094 : template <typename IteratorT, typename ContainerT>
1095 : inline void
1096 0 : macromap<ContextT>::rescan_replacement_list(token_type const &curr_token,
1097 : macro_definition_type ¯o_def, ContainerT &replacement_list,
1098 : ContainerT &expanded, bool expand_operator_defined,
1099 : IteratorT &nfirst, IteratorT const &nlast)
1100 : {
1101 0 : if (!replacement_list.empty()) {
1102 : #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1103 : // remove the placemarkers
1104 0 : if (boost::wave::need_variadics(ctx.get_language())) {
1105 0 : typename ContainerT::iterator end = replacement_list.end();
1106 : typename ContainerT::iterator it = replacement_list.begin();
1107 :
1108 0 : while (it != end) {
1109 : using namespace boost::wave;
1110 0 : if (T_PLACEMARKER == token_id(*it)) {
1111 0 : typename ContainerT::iterator placemarker = it;
1112 :
1113 0 : ++it;
1114 0 : replacement_list.erase(placemarker);
1115 : }
1116 : else {
1117 0 : ++it;
1118 : }
1119 : }
1120 : }
1121 : #endif
1122 :
1123 : // rescan the replacement list, during this rescan the current macro under
1124 : // expansion isn't available as an expandable macro
1125 0 : on_exit::reset<bool> on_exit(macro_def.is_available_for_replacement, false);
1126 0 : typename ContainerT::iterator begin_it = replacement_list.begin();
1127 0 : typename ContainerT::iterator end_it = replacement_list.end();
1128 :
1129 0 : expand_whole_tokensequence(expanded, begin_it, end_it,
1130 : expand_operator_defined);
1131 :
1132 : // trim replacement list, leave placeholder tokens untouched
1133 0 : impl::trim_replacement_list(expanded);
1134 : }
1135 :
1136 0 : if (expanded.empty()) {
1137 : // the resulting replacement list should contain at least a placeholder
1138 : // token
1139 0 : expanded.push_back(token_type(T_PLACEHOLDER, "_", curr_token.get_position()));
1140 : }
1141 0 : }
1142 :
1143 : ///////////////////////////////////////////////////////////////////////////////
1144 : //
1145 : // expand_macro(): expands a defined macro
1146 : //
1147 : // This functions tries to expand the macro, to which points the 'first'
1148 : // iterator. The functions eats up more tokens, if the macro to expand is
1149 : // a function-like macro.
1150 : //
1151 : ///////////////////////////////////////////////////////////////////////////////
1152 : template <typename ContextT>
1153 : template <typename IteratorT, typename ContainerT>
1154 : inline bool
1155 0 : macromap<ContextT>::expand_macro(ContainerT &expanded,
1156 : token_type const &curr_token, typename defined_macros_type::iterator it,
1157 : IteratorT &first, IteratorT const &last,
1158 : bool& seen_newline, bool expand_operator_defined,
1159 : defined_macros_type *scope, ContainerT *queue_symbol)
1160 : {
1161 : using namespace boost::wave;
1162 :
1163 0 : if (0 == scope) scope = current_macros;
1164 :
1165 0 : BOOST_ASSERT(T_IDENTIFIER == token_id(curr_token) ||
1166 : IS_CATEGORY(token_id(curr_token), KeywordTokenType) ||
1167 : IS_EXTCATEGORY(token_id(curr_token), OperatorTokenType|AltExtTokenType) ||
1168 : IS_CATEGORY(token_id(curr_token), BoolLiteralTokenType));
1169 :
1170 0 : if (it == scope->end()) {
1171 0 : ++first; // advance
1172 :
1173 : // try to expand a predefined macro (__FILE__, __LINE__ or __INCLUDE_LEVEL__)
1174 0 : if (expand_predefined_macro(curr_token, expanded))
1175 : return false;
1176 :
1177 : // not defined as a macro
1178 0 : if (0 != queue_symbol) {
1179 0 : expanded.splice(expanded.end(), *queue_symbol);
1180 : }
1181 : else {
1182 0 : expanded.push_back(curr_token);
1183 : }
1184 0 : return false;
1185 : }
1186 :
1187 : // ensure the parameters to be replaced with special parameter tokens
1188 0 : macro_definition_type ¯o_def = *(*it).second.get();
1189 :
1190 0 : macro_def.replace_parameters();
1191 :
1192 : // test if this macro is currently available for replacement
1193 0 : if (!macro_def.is_available_for_replacement) {
1194 : // this macro is marked as non-replaceable
1195 : // copy the macro name itself
1196 0 : if (0 != queue_symbol) {
1197 0 : queue_symbol->push_back(token_type(T_NONREPLACABLE_IDENTIFIER,
1198 : curr_token.get_value(), curr_token.get_position()));
1199 0 : expanded.splice(expanded.end(), *queue_symbol);
1200 : }
1201 : else {
1202 0 : expanded.push_back(token_type(T_NONREPLACABLE_IDENTIFIER,
1203 : curr_token.get_value(), curr_token.get_position()));
1204 : }
1205 0 : ++first;
1206 0 : return false;
1207 : }
1208 :
1209 : // try to replace the current identifier as a function-like macro
1210 0 : ContainerT replacement_list;
1211 :
1212 0 : if (T_LEFTPAREN == impl::next_token<IteratorT>::peek(first, last)) {
1213 : // called as a function-like macro
1214 0 : impl::skip_to_token(ctx, first, last, T_LEFTPAREN, seen_newline);
1215 :
1216 : #if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS == 0
1217 0 : IteratorT seqstart = first;
1218 0 : IteratorT seqend = first;
1219 : #endif
1220 :
1221 0 : if (macro_def.is_functionlike) {
1222 : // defined as a function-like macro
1223 :
1224 : // collect the arguments
1225 0 : std::vector<ContainerT> arguments;
1226 : #if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
1227 : typename std::vector<ContainerT>::size_type count_args =
1228 : collect_arguments (curr_token, arguments, first, last,
1229 : macro_def.macroparameters.size(), seen_newline);
1230 : #else
1231 0 : typename std::vector<ContainerT>::size_type count_args =
1232 : collect_arguments (curr_token, arguments, first, seqend, last,
1233 : macro_def.macroparameters.size(), seen_newline);
1234 : #endif
1235 :
1236 : // verify the parameter count
1237 0 : if (count_args < macro_def.macroparameters.size() ||
1238 0 : arguments.size() < macro_def.macroparameters.size())
1239 : {
1240 0 : if (count_args != arguments.size()) {
1241 : // must been at least one empty argument in C++ mode
1242 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1243 : empty_macroarguments, curr_token.get_value().c_str(),
1244 : main_pos);
1245 : }
1246 : else {
1247 : // too few macro arguments
1248 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1249 : too_few_macroarguments, curr_token.get_value().c_str(),
1250 : main_pos);
1251 : }
1252 0 : return false;
1253 : }
1254 :
1255 0 : if (count_args > macro_def.macroparameters.size() ||
1256 0 : arguments.size() > macro_def.macroparameters.size())
1257 : {
1258 : #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1259 0 : if (!macro_def.has_ellipsis)
1260 : #endif
1261 : {
1262 : // too many macro arguments
1263 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1264 : too_many_macroarguments,
1265 : curr_token.get_value().c_str(), main_pos);
1266 : return false;
1267 : }
1268 : }
1269 :
1270 : // inject tracing support
1271 : #if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
1272 : ctx.get_hooks().expanding_function_like_macro(
1273 : macro_def.macroname, macro_def.macroparameters,
1274 : macro_def.macrodefinition, curr_token, arguments);
1275 : #else
1276 0 : if (ctx.get_hooks().expanding_function_like_macro(ctx.derived(),
1277 0 : macro_def.macroname, macro_def.macroparameters,
1278 0 : macro_def.macrodefinition, curr_token, arguments,
1279 : seqstart, seqend))
1280 : {
1281 : // // do not expand this macro, just copy the whole sequence
1282 : // expanded.push_back(curr_token);
1283 : // std::copy(seqstart, first,
1284 : // std::inserter(expanded, expanded.end()));
1285 : // do not expand macro, just copy macro name and parenthesis
1286 : expanded.push_back(curr_token);
1287 : expanded.push_back(*seqstart);
1288 : first = ++seqstart;
1289 : return false; // no further preprocessing required
1290 : }
1291 : #endif
1292 :
1293 : // expand the replacement list of this macro
1294 0 : expand_replacement_list(macro_def, arguments, expand_operator_defined,
1295 : replacement_list);
1296 : }
1297 : else {
1298 : // defined as an object-like macro
1299 : #if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
1300 : ctx.get_hooks().expanding_object_like_macro(
1301 : macro_def.macroname, macro_def.macrodefinition, curr_token);
1302 : #else
1303 0 : if (ctx.get_hooks().expanding_object_like_macro(ctx.derived(),
1304 0 : macro_def.macroname, macro_def.macrodefinition, curr_token))
1305 : {
1306 : // do not expand this macro, just copy the whole sequence
1307 : expanded.push_back(curr_token);
1308 0 : return false; // no further preprocessing required
1309 : }
1310 : #endif
1311 :
1312 0 : bool found = false;
1313 0 : impl::find_concat_operator concat_tag(found);
1314 :
1315 0 : std::remove_copy_if(macro_def.macrodefinition.begin(),
1316 : macro_def.macrodefinition.end(),
1317 : std::inserter(replacement_list, replacement_list.end()),
1318 : concat_tag);
1319 :
1320 : // handle concatenation operators
1321 0 : if (found && !concat_tokensequence(replacement_list))
1322 : return false;
1323 : }
1324 : }
1325 : else {
1326 : // called as an object like macro
1327 0 : if ((*it).second->is_functionlike) {
1328 : // defined as a function-like macro
1329 0 : if (0 != queue_symbol) {
1330 0 : queue_symbol->push_back(curr_token);
1331 0 : expanded.splice(expanded.end(), *queue_symbol);
1332 : }
1333 : else {
1334 0 : expanded.push_back(curr_token);
1335 : }
1336 0 : ++first; // skip macro name
1337 0 : return false; // no further preprocessing required
1338 : }
1339 : else {
1340 : // defined as an object-like macro (expand it)
1341 : #if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
1342 : ctx.get_hooks().expanding_object_like_macro(
1343 : macro_def.macroname, macro_def.macrodefinition, curr_token);
1344 : #else
1345 0 : if (ctx.get_hooks().expanding_object_like_macro(ctx.derived(),
1346 0 : macro_def.macroname, macro_def.macrodefinition, curr_token))
1347 : {
1348 : // do not expand this macro, just copy the whole sequence
1349 : expanded.push_back(curr_token);
1350 : ++first; // skip macro name
1351 0 : return false; // no further preprocessing required
1352 : }
1353 : #endif
1354 :
1355 0 : bool found = false;
1356 0 : impl::find_concat_operator concat_tag(found);
1357 :
1358 0 : std::remove_copy_if(macro_def.macrodefinition.begin(),
1359 : macro_def.macrodefinition.end(),
1360 : std::inserter(replacement_list, replacement_list.end()),
1361 : concat_tag);
1362 :
1363 : // handle concatenation operators
1364 0 : if (found && !concat_tokensequence(replacement_list))
1365 : return false;
1366 :
1367 0 : ++first; // skip macro name
1368 : }
1369 : }
1370 :
1371 : // rescan the replacement list
1372 0 : ContainerT expanded_list;
1373 :
1374 : #if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
1375 : ctx.get_hooks().expanded_macro(replacement_list);
1376 : #else
1377 0 : ctx.get_hooks().expanded_macro(ctx.derived(), replacement_list);
1378 : #endif
1379 :
1380 0 : rescan_replacement_list(curr_token, macro_def, replacement_list,
1381 : expanded_list, expand_operator_defined, first, last);
1382 :
1383 : #if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
1384 : ctx.get_hooks().rescanned_macro(expanded_list);
1385 : #else
1386 0 : ctx.get_hooks().rescanned_macro(ctx.derived(), expanded_list);
1387 : #endif
1388 0 : expanded.splice(expanded.end(), expanded_list);
1389 0 : return true; // rescan is required
1390 : }
1391 :
1392 : ///////////////////////////////////////////////////////////////////////////////
1393 : //
1394 : // If the token under inspection points to a certain predefined macro it will
1395 : // be expanded, otherwise false is returned.
1396 : // (only __FILE__, __LINE__ and __INCLUDE_LEVEL__ macros are expanded here)
1397 : //
1398 : ///////////////////////////////////////////////////////////////////////////////
1399 : template <typename ContextT>
1400 : template <typename ContainerT>
1401 : inline bool
1402 0 : macromap<ContextT>::expand_predefined_macro(token_type const &curr_token,
1403 : ContainerT &expanded)
1404 : {
1405 : using namespace boost::wave;
1406 :
1407 0 : string_type const &value = curr_token.get_value();
1408 :
1409 0 : if (value.size() < 8 || '_' != value[0] || '_' != value[1])
1410 : return false; // quick check failed
1411 :
1412 0 : if (value == "__LINE__") {
1413 : // expand the __LINE__ macro
1414 0 : std::string buffer = lexical_cast<std::string>(main_pos.get_line());
1415 :
1416 0 : expanded.push_back(token_type(T_INTLIT, buffer.c_str(), curr_token.get_position()));
1417 0 : return true;
1418 : }
1419 0 : else if (value == "__FILE__") {
1420 : // expand the __FILE__ macro
1421 : namespace fs = boost::filesystem;
1422 :
1423 0 : std::string file("\"");
1424 0 : fs::path filename(wave::util::create_path(main_pos.get_file().c_str()));
1425 :
1426 : using boost::wave::util::impl::escape_lit;
1427 0 : file += escape_lit(wave::util::native_file_string(filename)) + "\"";
1428 0 : expanded.push_back(token_type(T_STRINGLIT, file.c_str(),
1429 : curr_token.get_position()));
1430 0 : return true;
1431 : }
1432 0 : else if (value == "__INCLUDE_LEVEL__") {
1433 : // expand the __INCLUDE_LEVEL__ macro
1434 : char buffer[22]; // 21 bytes holds all NUL-terminated unsigned 64-bit numbers
1435 :
1436 : using namespace std; // for some systems sprintf is in namespace std
1437 0 : sprintf(buffer, "%d", (int)ctx.get_iteration_depth());
1438 0 : expanded.push_back(token_type(T_INTLIT, buffer, curr_token.get_position()));
1439 : return true;
1440 : }
1441 : return false; // no predefined token
1442 : }
1443 :
1444 : ///////////////////////////////////////////////////////////////////////////////
1445 : //
1446 : // resolve_defined(): resolve the operator defined() and replace it with the
1447 : // correct T_INTLIT token
1448 : //
1449 : ///////////////////////////////////////////////////////////////////////////////
1450 : template <typename ContextT>
1451 : template <typename IteratorT, typename ContainerT>
1452 : inline typename ContextT::token_type const &
1453 0 : macromap<ContextT>::resolve_defined(IteratorT &first,
1454 : IteratorT const &last, ContainerT &pending)
1455 : {
1456 : using namespace boost::wave;
1457 : using namespace boost::wave::grammars;
1458 :
1459 0 : ContainerT result;
1460 0 : IteratorT start = first;
1461 0 : boost::spirit::classic::parse_info<IteratorT> hit =
1462 : defined_grammar_gen<typename ContextT::lexer_type>::
1463 0 : parse_operator_defined(start, last, result);
1464 :
1465 0 : if (!hit.hit) {
1466 0 : string_type msg ("defined(): ");
1467 0 : msg = msg + util::impl::as_string<string_type>(first, last);
1468 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_expression,
1469 : msg.c_str(), main_pos);
1470 :
1471 : // insert a dummy token
1472 0 : pending.push_back(token_type(T_INTLIT, "0", main_pos));
1473 : }
1474 : else {
1475 0 : impl::assign_iterator<IteratorT>::do_(first, hit.stop);
1476 :
1477 : // insert a token, which reflects the outcome
1478 0 : pending.push_back(token_type(T_INTLIT,
1479 0 : is_defined(result.begin(), result.end()) ? "1" : "0",
1480 0 : main_pos));
1481 : }
1482 :
1483 0 : on_exit::pop_front<definition_container_type> pop_front_token(pending);
1484 :
1485 0 : return act_token = pending.front();
1486 : }
1487 :
1488 : ///////////////////////////////////////////////////////////////////////////////
1489 : //
1490 : // resolve_operator_pragma(): resolve the operator _Pragma() and dispatch to
1491 : // the associated action
1492 : //
1493 : // This function returns true, if the pragma was correctly interpreted.
1494 : // The iterator 'first' is positioned behind the closing ')'.
1495 : // This function returns false, if the _Pragma was not known, the
1496 : // preprocessed token sequence is pushed back to the 'pending' sequence.
1497 : //
1498 : ///////////////////////////////////////////////////////////////////////////////
1499 : template <typename ContextT>
1500 : template <typename IteratorT, typename ContainerT>
1501 : inline bool
1502 0 : macromap<ContextT>::resolve_operator_pragma(IteratorT &first,
1503 : IteratorT const &last, ContainerT &pending, bool& seen_newline)
1504 : {
1505 : // isolate the parameter of the operator _Pragma
1506 0 : token_type pragma_token = *first;
1507 :
1508 0 : if (!impl::skip_to_token(ctx, first, last, T_LEFTPAREN, seen_newline)) {
1509 : // illformed operator _Pragma
1510 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_expression,
1511 : "operator _Pragma()", pragma_token.get_position());
1512 : return false;
1513 : }
1514 :
1515 0 : std::vector<ContainerT> arguments;
1516 : #if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
1517 : typename std::vector<ContainerT>::size_type count_args =
1518 : collect_arguments (pragma_token, arguments, first, last, 1, seen_newline);
1519 : #else
1520 0 : IteratorT endparen = first;
1521 0 : typename std::vector<ContainerT>::size_type count_args =
1522 0 : collect_arguments (pragma_token, arguments, first, endparen, last, 1,
1523 : seen_newline);
1524 : #endif
1525 :
1526 : // verify the parameter count
1527 0 : if (pragma_token.get_position().get_file().empty())
1528 0 : pragma_token.set_position(act_token.get_position());
1529 :
1530 0 : if (count_args < 1 || arguments.size() < 1) {
1531 : // too few macro arguments
1532 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, too_few_macroarguments,
1533 : pragma_token.get_value().c_str(), pragma_token.get_position());
1534 : return false;
1535 : }
1536 0 : if (count_args > 1 || arguments.size() > 1) {
1537 : // too many macro arguments
1538 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, too_many_macroarguments,
1539 : pragma_token.get_value().c_str(), pragma_token.get_position());
1540 : return false;
1541 : }
1542 :
1543 : // preprocess the pragma token body
1544 : typedef typename std::vector<ContainerT>::value_type::iterator
1545 : argument_iterator_type;
1546 :
1547 0 : ContainerT expanded;
1548 0 : argument_iterator_type begin_it = arguments[0].begin();
1549 0 : argument_iterator_type end_it = arguments[0].end();
1550 0 : expand_whole_tokensequence(expanded, begin_it, end_it, false);
1551 :
1552 : // un-escape the parameter of the operator _Pragma
1553 : typedef typename token_type::string_type string_type;
1554 :
1555 0 : string_type pragma_cmd;
1556 0 : typename ContainerT::const_iterator end_exp = expanded.end();
1557 0 : for (typename ContainerT::const_iterator it_exp = expanded.begin();
1558 0 : it_exp != end_exp; ++it_exp)
1559 : {
1560 0 : if (T_EOF == token_id(*it_exp))
1561 : break;
1562 0 : if (IS_CATEGORY(*it_exp, WhiteSpaceTokenType))
1563 0 : continue;
1564 :
1565 0 : if (T_STRINGLIT != token_id(*it_exp)) {
1566 : // ill formed operator _Pragma
1567 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1568 : ill_formed_pragma_option, "_Pragma",
1569 : pragma_token.get_position());
1570 0 : return false;
1571 : }
1572 0 : if (pragma_cmd.size() > 0) {
1573 : // there should be exactly one string literal (string literals are to
1574 : // be concatenated at translation phase 6, but _Pragma operators are
1575 : // to be executed at translation phase 4)
1576 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1577 : ill_formed_pragma_option, "_Pragma",
1578 : pragma_token.get_position());
1579 : return false;
1580 : }
1581 :
1582 : // remove the '\"' and concat all given string literal-values
1583 0 : string_type token_str = (*it_exp).get_value();
1584 0 : pragma_cmd += token_str.substr(1, token_str.size() - 2);
1585 : }
1586 0 : string_type pragma_cmd_unesc = impl::unescape_lit(pragma_cmd);
1587 :
1588 : // tokenize the pragma body
1589 : typedef typename ContextT::lexer_type lexer_type;
1590 :
1591 0 : ContainerT pragma;
1592 0 : std::string pragma_cmd_str(pragma_cmd_unesc.c_str());
1593 0 : lexer_type it = lexer_type(pragma_cmd_str.begin(), pragma_cmd_str.end(),
1594 0 : pragma_token.get_position(), ctx.get_language());
1595 0 : lexer_type end = lexer_type();
1596 0 : for (/**/; it != end; ++it)
1597 0 : pragma.push_back(*it);
1598 :
1599 : // analyze the preprocessed token sequence and eventually dispatch to the
1600 : // associated action
1601 0 : if (interpret_pragma(ctx, pragma_token, pragma.begin(), pragma.end(),
1602 : pending))
1603 : {
1604 : return true; // successfully recognized a wave specific pragma
1605 : }
1606 :
1607 : // unknown pragma token sequence, push it back and return to the caller
1608 0 : pending.push_front(token_type(T_SPACE, " ", pragma_token.get_position()));
1609 0 : pending.push_front(token_type(T_RIGHTPAREN, ")", pragma_token.get_position()));
1610 0 : pending.push_front(token_type(T_STRINGLIT, string_type("\"") + pragma_cmd + "\"",
1611 : pragma_token.get_position()));
1612 0 : pending.push_front(token_type(T_LEFTPAREN, "(", pragma_token.get_position()));
1613 0 : pending.push_front(pragma_token);
1614 : return false;
1615 : }
1616 :
1617 : ///////////////////////////////////////////////////////////////////////////////
1618 : //
1619 : // Test, whether the result of a concat operator is well formed or not.
1620 : //
1621 : // This is done by re-scanning (re-tokenizing) the resulting token sequence,
1622 : // which should give back exactly one token.
1623 : //
1624 : ///////////////////////////////////////////////////////////////////////////////
1625 : template <typename ContextT>
1626 : template <typename ContainerT>
1627 : inline bool
1628 0 : macromap<ContextT>::is_valid_concat(string_type new_value,
1629 : position_type const &pos, ContainerT &rescanned)
1630 : {
1631 : // re-tokenize the newly generated string
1632 : typedef typename ContextT::lexer_type lexer_type;
1633 :
1634 0 : std::string value_to_test(new_value.c_str());
1635 :
1636 : boost::wave::language_support lang =
1637 0 : boost::wave::enable_prefer_pp_numbers(ctx.get_language());
1638 0 : lang = boost::wave::enable_single_line(lang);
1639 :
1640 0 : lexer_type it = lexer_type(value_to_test.begin(), value_to_test.end(), pos,
1641 : lang);
1642 0 : lexer_type end = lexer_type();
1643 0 : for (/**/; it != end && T_EOF != token_id(*it); ++it)
1644 : {
1645 : // as of Wave V2.0.7 pasting of tokens is valid only if the resulting
1646 : // tokens are pp_tokens (as mandated by C++11)
1647 0 : if (!is_pp_token(*it))
1648 : return false;
1649 0 : rescanned.push_back(*it);
1650 : }
1651 :
1652 : #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1653 0 : if (boost::wave::need_variadics(ctx.get_language()))
1654 : return true; // in variadics mode token pasting is well defined
1655 : #endif
1656 :
1657 : // test if the newly generated token sequence contains more than 1 token
1658 0 : return 1 == rescanned.size();
1659 : }
1660 :
1661 : ///////////////////////////////////////////////////////////////////////////////
1662 : //
1663 : // Handle all occurrences of the concatenation operator '##' inside the given
1664 : // token sequence.
1665 : //
1666 : ///////////////////////////////////////////////////////////////////////////////
1667 : template <typename Context>
1668 0 : inline void report_invalid_concatenation(Context& ctx,
1669 : typename Context::token_type const& prev,
1670 : typename Context::token_type const& next,
1671 : typename Context::position_type const& main_pos)
1672 : {
1673 0 : typename Context::string_type error_string("\"");
1674 :
1675 0 : error_string += prev.get_value();
1676 0 : error_string += "\" and \"";
1677 0 : error_string += next.get_value();
1678 0 : error_string += "\"";
1679 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, invalid_concat,
1680 : error_string.c_str(), main_pos);
1681 0 : }
1682 :
1683 : template <typename ContextT>
1684 : template <typename ContainerT>
1685 : inline bool
1686 0 : macromap<ContextT>::concat_tokensequence(ContainerT &expanded)
1687 : {
1688 : using namespace boost::wave;
1689 : typedef typename ContainerT::iterator iterator_type;
1690 :
1691 0 : iterator_type end = expanded.end();
1692 0 : iterator_type prev = end;
1693 0 : for (iterator_type it = expanded.begin(); it != end; /**/)
1694 : {
1695 0 : if (T_POUND_POUND == BASE_TOKEN(token_id(*it))) {
1696 0 : iterator_type next = it;
1697 :
1698 0 : ++next;
1699 0 : if (prev == end || next == end) {
1700 : // error, '##' should be in between two tokens
1701 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1702 : ill_formed_operator, "concat ('##')", main_pos);
1703 0 : return false;
1704 : }
1705 :
1706 : // replace prev##next with the concatenated value, skip whitespace
1707 : // before and after the '##' operator
1708 0 : while (IS_CATEGORY(*next, WhiteSpaceTokenType)) {
1709 0 : ++next;
1710 0 : if (next == end) {
1711 : // error, '##' should be in between two tokens
1712 0 : BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1713 : ill_formed_operator, "concat ('##')", main_pos);
1714 : return false;
1715 : }
1716 : }
1717 :
1718 : #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1719 0 : if (boost::wave::need_variadics(ctx.get_language())) {
1720 0 : if (T_PLACEMARKER == token_id(*next)) {
1721 : // remove the '##' and the next tokens from the sequence
1722 0 : iterator_type first_to_delete = prev;
1723 :
1724 0 : expanded.erase(++first_to_delete, ++next);
1725 0 : it = next;
1726 0 : continue;
1727 : }
1728 0 : else if (T_PLACEMARKER == token_id(*prev)) {
1729 : // remove the '##' and the next tokens from the sequence
1730 0 : iterator_type first_to_delete = prev;
1731 :
1732 0 : *prev = *next;
1733 0 : expanded.erase(++first_to_delete, ++next);
1734 0 : it = next;
1735 0 : continue;
1736 : }
1737 : }
1738 : #endif // BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1739 :
1740 : // test if the concat operator has to concatenate two unrelated
1741 : // tokens i.e. the result yields more then one token
1742 0 : string_type concat_result;
1743 0 : ContainerT rescanned;
1744 :
1745 0 : concat_result = ((*prev).get_value() + (*next).get_value());
1746 :
1747 : // analyze the validity of the concatenation result
1748 0 : if (!is_valid_concat(concat_result, (*prev).get_position(),
1749 0 : rescanned) &&
1750 0 : !IS_CATEGORY(*prev, WhiteSpaceTokenType) &&
1751 0 : !IS_CATEGORY(*next, WhiteSpaceTokenType))
1752 : {
1753 0 : report_invalid_concatenation(ctx, *prev, *next, main_pos);
1754 0 : return false;
1755 : }
1756 :
1757 : #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1758 0 : if (boost::wave::need_variadics(ctx.get_language())) {
1759 : // remove the prev, '##' and the next tokens from the sequence
1760 0 : expanded.erase(prev, ++next); // remove not needed tokens
1761 :
1762 : // some stl implementations clear() the container if we erased all
1763 : // the elements, which orphans all iterators. we re-initialize these
1764 : // here
1765 0 : if (expanded.empty())
1766 0 : end = next = expanded.end();
1767 :
1768 : // replace the old token (pointed to by *prev) with the re-tokenized
1769 : // sequence
1770 0 : expanded.splice(next, rescanned);
1771 :
1772 : // the last token of the inserted sequence is the new previous
1773 0 : prev = next;
1774 0 : if (next != expanded.end())
1775 0 : --prev;
1776 : }
1777 : else
1778 : #endif // BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1779 : {
1780 : // we leave the token_id unchanged, but unmark the token as
1781 : // disabled, if appropriate
1782 0 : (*prev).set_value(concat_result);
1783 0 : if (T_NONREPLACABLE_IDENTIFIER == token_id(*prev))
1784 0 : (*prev).set_token_id(T_IDENTIFIER);
1785 :
1786 : // remove the '##' and the next tokens from the sequence
1787 0 : iterator_type first_to_delete = prev;
1788 :
1789 0 : expanded.erase(++first_to_delete, ++next);
1790 : }
1791 0 : it = next;
1792 0 : continue;
1793 : }
1794 :
1795 : // save last non-whitespace token position
1796 0 : if (!IS_CATEGORY(*it, WhiteSpaceTokenType))
1797 0 : prev = it;
1798 :
1799 0 : ++it; // next token, please
1800 : }
1801 : return true;
1802 : }
1803 :
1804 : ///////////////////////////////////////////////////////////////////////////////
1805 : //
1806 : // predefine_macro(): predefine a single macro
1807 : //
1808 : ///////////////////////////////////////////////////////////////////////////////
1809 : template <typename ContextT>
1810 : inline void
1811 0 : macromap<ContextT>::predefine_macro(defined_macros_type *scope,
1812 : string_type const &name, token_type const &t)
1813 : {
1814 0 : definition_container_type macrodefinition;
1815 0 : std::vector<token_type> param;
1816 :
1817 0 : macrodefinition.push_back(t);
1818 0 : add_macro(token_type(T_IDENTIFIER, name, t.get_position()),
1819 : false, param, macrodefinition, true, scope);
1820 0 : }
1821 :
1822 : ///////////////////////////////////////////////////////////////////////////////
1823 : //
1824 : // init_predefined_macros(): init the predefined macros
1825 : //
1826 : ///////////////////////////////////////////////////////////////////////////////
1827 : template <typename ContextT>
1828 : inline void
1829 0 : macromap<ContextT>::init_predefined_macros(char const *fname,
1830 : defined_macros_type *scope, bool at_global_scope)
1831 : {
1832 : // if no scope is given, use the current one
1833 0 : defined_macros_type *current_scope = scope ? scope : current_macros;
1834 :
1835 : // first, add the static macros
1836 0 : position_type pos("<built-in>");
1837 :
1838 : #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1839 0 : if (boost::wave::need_c99(ctx.get_language())) {
1840 : // define C99 specifics
1841 0 : for (int i = 0; 0 != predef.static_data_c99(i).name; ++i) {
1842 0 : predefined_macros::static_macros const& m = predef.static_data_c99(i);
1843 0 : predefine_macro(current_scope, m.name,
1844 0 : token_type(m.token_id, m.value, pos));
1845 : }
1846 : }
1847 : else
1848 : #endif
1849 : {
1850 : #if BOOST_WAVE_SUPPORT_CPP0X != 0
1851 0 : if (boost::wave::need_cpp0x(ctx.get_language())) {
1852 : // define C++11 specifics
1853 0 : for (int i = 0; 0 != predef.static_data_cpp0x(i).name; ++i) {
1854 0 : predefined_macros::static_macros const& m = predef.static_data_cpp0x(i);
1855 0 : predefine_macro(current_scope, m.name,
1856 0 : token_type(m.token_id, m.value, pos));
1857 : }
1858 : }
1859 : else
1860 : #endif
1861 : {
1862 : // define C++ specifics
1863 0 : for (int i = 0; 0 != predef.static_data_cpp(i).name; ++i) {
1864 0 : predefined_macros::static_macros const& m = predef.static_data_cpp(i);
1865 0 : predefine_macro(current_scope, m.name,
1866 0 : token_type(m.token_id, m.value, pos));
1867 : }
1868 :
1869 : #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1870 : // define __WAVE_HAS_VARIADICS__, if appropriate
1871 0 : if (boost::wave::need_variadics(ctx.get_language())) {
1872 0 : predefine_macro(current_scope, "__WAVE_HAS_VARIADICS__",
1873 : token_type(T_INTLIT, "1", pos));
1874 : }
1875 : #endif
1876 : }
1877 : }
1878 :
1879 : // predefine the __BASE_FILE__ macro which contains the main file name
1880 : namespace fs = boost::filesystem;
1881 0 : if (string_type(fname) != "<Unknown>") {
1882 0 : fs::path filename(create_path(fname));
1883 :
1884 : using boost::wave::util::impl::escape_lit;
1885 0 : predefine_macro(current_scope, "__BASE_FILE__",
1886 : token_type(T_STRINGLIT, string_type("\"") +
1887 : escape_lit(native_file_string(filename)).c_str() + "\"", pos));
1888 0 : base_name = fname;
1889 : }
1890 0 : else if (!base_name.empty()) {
1891 0 : fs::path filename(create_path(base_name.c_str()));
1892 :
1893 : using boost::wave::util::impl::escape_lit;
1894 0 : predefine_macro(current_scope, "__BASE_FILE__",
1895 : token_type(T_STRINGLIT, string_type("\"") +
1896 : escape_lit(native_file_string(filename)).c_str() + "\"", pos));
1897 : }
1898 :
1899 : // now add the dynamic macros
1900 0 : for (int j = 0; 0 != predef.dynamic_data(j).name; ++j) {
1901 0 : predefined_macros::dynamic_macros const& m = predef.dynamic_data(j);
1902 0 : predefine_macro(current_scope, m.name,
1903 0 : token_type(m.token_id, (predef.* m.generator)(), pos));
1904 : }
1905 0 : }
1906 :
1907 : ///////////////////////////////////////////////////////////////////////////////
1908 : //
1909 : // reset_macromap(): initialize the internal macro symbol namespace
1910 : //
1911 : ///////////////////////////////////////////////////////////////////////////////
1912 : template <typename ContextT>
1913 : inline void
1914 0 : macromap<ContextT>::reset_macromap()
1915 : {
1916 0 : current_macros->clear();
1917 0 : predef.reset();
1918 0 : act_token = token_type();
1919 0 : }
1920 :
1921 : ///////////////////////////////////////////////////////////////////////////////
1922 : }}} // namespace boost::wave::util
1923 :
1924 : #if BOOST_WAVE_SERIALIZATION != 0
1925 : namespace boost { namespace serialization {
1926 :
1927 : template<typename ContextT>
1928 : struct version<boost::wave::util::macromap<ContextT> >
1929 : {
1930 : typedef boost::wave::util::macromap<ContextT> target_type;
1931 : typedef mpl::int_<target_type::version> type;
1932 : typedef mpl::integral_c_tag tag;
1933 : BOOST_STATIC_CONSTANT(unsigned int, value = version::type::value);
1934 : };
1935 :
1936 : }} // namespace boost::serialization
1937 : #endif
1938 :
1939 : // the suffix header occurs after all of the code
1940 : #ifdef BOOST_HAS_ABI_HEADERS
1941 : #include BOOST_ABI_SUFFIX
1942 : #endif
1943 :
1944 : #endif // !defined(CPP_MACROMAP_HPP_CB8F51B0_A3F0_411C_AEF4_6FF631B8B414_INCLUDED)
|