File indexing completed on 2025-01-18 09:53:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #if !defined(BOOST_CPP_MACROMAP_HPP_CB8F51B0_A3F0_411C_AEF4_6FF631B8B414_INCLUDED)
0014 #define BOOST_CPP_MACROMAP_HPP_CB8F51B0_A3F0_411C_AEF4_6FF631B8B414_INCLUDED
0015
0016 #include <cstdlib>
0017 #include <ctime>
0018
0019 #include <list>
0020 #include <map>
0021 #include <set>
0022 #include <vector>
0023 #include <iterator>
0024 #include <algorithm>
0025 #include <string>
0026
0027 #include <boost/assert.hpp>
0028 #include <boost/wave/wave_config.hpp>
0029 #if BOOST_WAVE_SERIALIZATION != 0
0030 #include <boost/serialization/serialization.hpp>
0031 #include <boost/serialization/shared_ptr.hpp>
0032 #endif
0033
0034 #include <boost/filesystem/path.hpp>
0035 #include <boost/lexical_cast.hpp>
0036 #include <boost/optional.hpp>
0037
0038 #include <boost/wave/util/time_conversion_helper.hpp>
0039 #include <boost/wave/util/unput_queue_iterator.hpp>
0040 #include <boost/wave/util/macro_helpers.hpp>
0041 #include <boost/wave/util/macro_definition.hpp>
0042 #include <boost/wave/util/symbol_table.hpp>
0043 #include <boost/wave/util/cpp_macromap_utils.hpp>
0044 #include <boost/wave/util/cpp_macromap_predef.hpp>
0045 #include <boost/wave/util/filesystem_compatibility.hpp>
0046 #include <boost/wave/grammars/cpp_defined_grammar_gen.hpp>
0047 #if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
0048 #include <boost/wave/grammars/cpp_has_include_grammar_gen.hpp>
0049 #endif
0050
0051 #include <boost/wave/wave_version.hpp>
0052 #include <boost/wave/cpp_exceptions.hpp>
0053 #include <boost/wave/language_support.hpp>
0054
0055
0056 #ifdef BOOST_HAS_ABI_HEADERS
0057 #include BOOST_ABI_PREFIX
0058 #endif
0059
0060
0061 namespace boost { namespace wave { namespace util {
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 template <typename ContextT>
0072 class macromap {
0073
0074 typedef macromap<ContextT> self_type;
0075 typedef typename ContextT::token_type token_type;
0076 typedef typename token_type::string_type string_type;
0077 typedef typename token_type::position_type position_type;
0078
0079 typedef typename ContextT::token_sequence_type definition_container_type;
0080 typedef std::vector<token_type> parameter_container_type;
0081
0082 typedef macro_definition<token_type, definition_container_type>
0083 macro_definition_type;
0084 typedef symbol_table<string_type, macro_definition_type>
0085 defined_macros_type;
0086 typedef typename defined_macros_type::value_type::second_type
0087 macro_ref_type;
0088
0089 public:
0090 macromap(ContextT &ctx_)
0091 : current_macros(0), defined_macros(new defined_macros_type(1)),
0092 main_pos("", 0), ctx(ctx_), macro_uid(1)
0093 {
0094 current_macros = defined_macros.get();
0095 }
0096 ~macromap() {}
0097
0098
0099 bool add_macro(token_type const &name, bool has_parameters,
0100 parameter_container_type ¶meters,
0101 definition_container_type &definition, bool is_predefined = false,
0102 defined_macros_type *scope = 0);
0103
0104
0105 bool is_defined(string_type const &name,
0106 typename defined_macros_type::iterator &it,
0107 defined_macros_type *scope = 0) const;
0108
0109
0110 template <typename IteratorT>
0111 bool is_defined(IteratorT const &begin, IteratorT const &end) const;
0112
0113
0114 bool is_defined(string_type const &str) const;
0115
0116 #if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
0117
0118 template <typename IteratorT>
0119 bool has_include(IteratorT const &begin, IteratorT const &end,
0120 bool is_quoted_filename, bool is_system) const;
0121 #endif
0122
0123
0124 bool get_macro(string_type const &name, bool &has_parameters,
0125 bool &is_predefined, position_type &pos,
0126 parameter_container_type ¶meters,
0127 definition_container_type &definition,
0128 defined_macros_type *scope = 0) const;
0129
0130
0131 bool remove_macro(string_type const &name, position_type const& pos,
0132 bool even_predefined = false);
0133
0134 template <typename IteratorT, typename ContainerT>
0135 token_type const &expand_tokensequence(IteratorT &first,
0136 IteratorT const &last, ContainerT &pending, ContainerT &expanded,
0137 bool& seen_newline, bool expand_operator_defined,
0138 bool expand_operator_has_include);
0139
0140
0141 template <typename IteratorT, typename ContainerT>
0142 void expand_whole_tokensequence(ContainerT &expanded,
0143 IteratorT &first, IteratorT const &last,
0144 bool expand_operator_defined,
0145 bool expand_operator_has_include);
0146
0147
0148 void init_predefined_macros(char const *fname = "<Unknown>",
0149 defined_macros_type *scope = 0, bool at_global_scope = true);
0150 void predefine_macro(defined_macros_type *scope, string_type const &name,
0151 token_type const &t);
0152
0153
0154 void reset_macromap();
0155
0156 position_type &get_main_pos() { return main_pos; }
0157 position_type const& get_main_pos() const { return main_pos; }
0158
0159
0160 typedef typename defined_macros_type::name_iterator name_iterator;
0161 typedef typename defined_macros_type::const_name_iterator const_name_iterator;
0162
0163 name_iterator begin()
0164 { return defined_macros_type::make_iterator(current_macros->begin()); }
0165 name_iterator end()
0166 { return defined_macros_type::make_iterator(current_macros->end()); }
0167 const_name_iterator begin() const
0168 { return defined_macros_type::make_iterator(current_macros->begin()); }
0169 const_name_iterator end() const
0170 { return defined_macros_type::make_iterator(current_macros->end()); }
0171
0172 protected:
0173
0174 template <typename IteratorT, typename ContainerT>
0175 token_type const &expand_tokensequence_worker(ContainerT &pending,
0176 unput_queue_iterator<IteratorT, token_type, ContainerT> &first,
0177 unput_queue_iterator<IteratorT, token_type, ContainerT> const &last,
0178 bool& seen_newline, bool expand_operator_defined,
0179 bool expand_operator_has_include,
0180 boost::optional<position_type> expanding_pos);
0181
0182
0183 template <typename IteratorT, typename ContainerT, typename SizeT>
0184 typename std::vector<ContainerT>::size_type collect_arguments (
0185 token_type const curr_token, std::vector<ContainerT> &arguments,
0186 IteratorT &next, IteratorT &endparen, IteratorT const &end,
0187 SizeT const ¶meter_count, bool& seen_newline);
0188
0189
0190 template <typename IteratorT, typename ContainerT>
0191 bool expand_macro(ContainerT &pending, token_type const &name,
0192 typename defined_macros_type::iterator it,
0193 IteratorT &first, IteratorT const &last,
0194 bool& seen_newline, bool expand_operator_defined,
0195 bool expand_operator_has_include,
0196 boost::optional<position_type> expanding_pos,
0197 defined_macros_type *scope = 0, ContainerT *queue_symbol = 0);
0198
0199
0200 template <typename ContainerT>
0201 bool expand_predefined_macro(token_type const &curr_token,
0202 ContainerT &expanded);
0203
0204
0205 template <typename ContainerT>
0206 void expand_argument (typename std::vector<ContainerT>::size_type arg,
0207 std::vector<ContainerT> &arguments,
0208 std::vector<ContainerT> &expanded_args, bool expand_operator_defined,
0209 bool expand_operator_has_include,
0210 std::vector<bool> &has_expanded_args);
0211
0212
0213 template <typename ContainerT>
0214 void expand_replacement_list(
0215 typename macro_definition_type::const_definition_iterator_t cbeg,
0216 typename macro_definition_type::const_definition_iterator_t cend,
0217 std::vector<ContainerT> &arguments,
0218 bool expand_operator_defined,
0219 bool expand_operator_has_include,
0220 ContainerT &expanded);
0221
0222
0223 template <typename IteratorT, typename ContainerT>
0224 void rescan_replacement_list(token_type const &curr_token,
0225 macro_definition_type ¯odef, ContainerT &replacement_list,
0226 ContainerT &expanded, bool expand_operator_defined,
0227 bool expand_operator_has_include,
0228 IteratorT &nfirst, IteratorT const &nlast);
0229
0230
0231 template <typename IteratorT, typename ContainerT>
0232 token_type const &resolve_defined(IteratorT &first, IteratorT const &last,
0233 ContainerT &expanded);
0234
0235 #if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
0236
0237 template <typename IteratorT, typename ContainerT>
0238 token_type const &resolve_has_include(IteratorT &first, IteratorT const &last,
0239 ContainerT &expanded);
0240 #endif
0241
0242
0243 template <typename IteratorT, typename ContainerT>
0244 bool resolve_operator_pragma(IteratorT &first,
0245 IteratorT const &last, ContainerT &expanded, bool& seen_newline);
0246
0247
0248 template <typename ContainerT>
0249 bool concat_tokensequence(ContainerT &expanded);
0250
0251 template <typename ContainerT>
0252 bool is_valid_concat(string_type new_value,
0253 position_type const &pos, ContainerT &rescanned);
0254
0255 static bool is_space(char);
0256
0257
0258 template <typename ContainerT>
0259 static void set_expand_positions(ContainerT &tokens, position_type pos);
0260
0261 #if BOOST_WAVE_SERIALIZATION != 0
0262 public:
0263 BOOST_STATIC_CONSTANT(unsigned int, version = 0x10);
0264 BOOST_STATIC_CONSTANT(unsigned int, version_mask = 0x0f);
0265
0266 private:
0267 friend class boost::serialization::access;
0268 template<typename Archive>
0269 void save(Archive &ar, const unsigned int version) const
0270 {
0271 using namespace boost::serialization;
0272 ar & make_nvp("defined_macros", defined_macros);
0273 }
0274 template<typename Archive>
0275 void load(Archive &ar, const unsigned int loaded_version)
0276 {
0277 using namespace boost::serialization;
0278 if (version != (loaded_version & ~version_mask)) {
0279 BOOST_WAVE_THROW(preprocess_exception, incompatible_config,
0280 "cpp_context state version", get_main_pos());
0281 }
0282 ar & make_nvp("defined_macros", defined_macros);
0283 current_macros = defined_macros.get();
0284 }
0285 BOOST_SERIALIZATION_SPLIT_MEMBER()
0286 #endif
0287
0288 private:
0289 defined_macros_type *current_macros;
0290 boost::shared_ptr<defined_macros_type> defined_macros;
0291
0292 token_type act_token;
0293 position_type main_pos;
0294 string_type base_name;
0295 ContextT &ctx;
0296 long macro_uid;
0297 predefined_macros predef;
0298 };
0299
0300
0301
0302
0303
0304
0305
0306 template <typename ContextT>
0307 inline bool
0308 macromap<ContextT>::add_macro(token_type const &name, bool has_parameters,
0309 parameter_container_type ¶meters, definition_container_type &definition,
0310 bool is_predefined, defined_macros_type *scope)
0311 {
0312 if (!is_predefined && impl::is_special_macroname (ctx, name.get_value())) {
0313
0314 BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
0315 illegal_redefinition, name.get_value().c_str(), main_pos,
0316 name.get_value().c_str());
0317 return false;
0318 }
0319 if (boost::wave::need_variadics(ctx.get_language()) &&
0320 "__VA_ARGS__" == name.get_value())
0321 {
0322
0323 BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
0324 bad_define_statement_va_args, name.get_value().c_str(), main_pos,
0325 name.get_value().c_str());
0326 return false;
0327 }
0328 if (boost::wave::need_variadics(ctx.get_language()) &&
0329 "__VA_OPT__" == name.get_value())
0330 {
0331
0332 BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
0333 bad_define_statement_va_opt, name.get_value().c_str(), main_pos,
0334 name.get_value().c_str());
0335 return false;
0336 }
0337 #if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
0338 if (boost::wave::need_has_include(ctx.get_language()) &&
0339 "__has_include" == name.get_value())
0340 {
0341
0342 BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
0343 bad_define_statement_va_opt, name.get_value().c_str(), main_pos,
0344 name.get_value().c_str());
0345 return false;
0346 }
0347 #endif
0348 if (AltExtTokenType == (token_id(name) & ExtTokenOnlyMask)) {
0349
0350 BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
0351 illegal_operator_redefinition, name.get_value().c_str(), main_pos,
0352 name.get_value().c_str());
0353 return false;
0354 }
0355
0356
0357 defined_macros_type* current_scope = scope ? scope : current_macros;
0358 typename defined_macros_type::iterator it = current_scope->find(name.get_value());
0359
0360 if (it != current_scope->end()) {
0361
0362 macro_definition_type* macrodef = (*it).second.get();
0363 if (macrodef->is_functionlike != has_parameters ||
0364 !impl::parameters_equal(macrodef->macroparameters, parameters) ||
0365 !impl::definition_equals(macrodef->macrodefinition, definition))
0366 {
0367 BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
0368 macro_redefinition, name.get_value().c_str(), main_pos,
0369 name.get_value().c_str());
0370 }
0371 return false;
0372 }
0373
0374
0375 if (has_parameters) {
0376 std::set<typename token_type::string_type> names;
0377
0378 typedef typename parameter_container_type::iterator
0379 parameter_iterator_type;
0380 typedef typename std::set<typename token_type::string_type>::iterator
0381 name_iterator_type;
0382
0383 parameter_iterator_type end = parameters.end();
0384 for (parameter_iterator_type itp = parameters.begin(); itp != end; ++itp)
0385 {
0386 name_iterator_type pit = names.find((*itp).get_value());
0387
0388 if (pit != names.end()) {
0389
0390 BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
0391 duplicate_parameter_name, (*pit).c_str(), main_pos,
0392 name.get_value().c_str());
0393 return false;
0394 }
0395 names.insert((*itp).get_value());
0396 }
0397 }
0398
0399 #if BOOST_WAVE_SUPPORT_VA_OPT != 0
0400
0401 if (boost::wave::need_va_opt(ctx.get_language())) {
0402
0403 typedef typename macro_definition_type::const_definition_iterator_t iter_t;
0404 iter_t mdit = definition.begin();
0405 iter_t mdend = definition.end();
0406 for (; mdit != mdend; ++mdit) {
0407
0408 if ((IS_EXTCATEGORY((*mdit), OptParameterTokenType)) ||
0409 ("__VA_OPT__" == (*mdit).get_value())) {
0410 iter_t va_opt_it = mdit;
0411
0412 if ((++mdit == mdend) ||
0413 (T_LEFTPAREN != token_id(*mdit))) {
0414 BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
0415 bad_define_statement_va_opt_parens,
0416 name.get_value().c_str(), main_pos,
0417 name.get_value().c_str());
0418 return false;
0419 }
0420
0421 iter_t va_opt_end = va_opt_it;
0422 if (!impl::find_va_opt_args(va_opt_end, mdend)) {
0423 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
0424 improperly_terminated_macro, "missing ')' in __VA_OPT__",
0425 main_pos);
0426 return false;
0427 }
0428
0429 ++va_opt_it; ++va_opt_it;
0430 for (;va_opt_it != va_opt_end; ++va_opt_it) {
0431 if ((IS_EXTCATEGORY((*va_opt_it), OptParameterTokenType)) ||
0432 ("__VA_OPT__" == (*va_opt_it).get_value())) {
0433 BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
0434 bad_define_statement_va_opt_recurse,
0435 name.get_value().c_str(), (*va_opt_it).get_position(),
0436 name.get_value().c_str());
0437 }
0438 }
0439 }
0440 }
0441 }
0442 #endif
0443
0444
0445 std::pair<typename defined_macros_type::iterator, bool> p =
0446 current_scope->insert(
0447 typename defined_macros_type::value_type(
0448 name.get_value(),
0449 macro_ref_type(new macro_definition_type(name,
0450 has_parameters, is_predefined, ++macro_uid)
0451 )
0452 )
0453 );
0454
0455 if (!p.second) {
0456 BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
0457 macro_insertion_error, name.get_value().c_str(), main_pos,
0458 name.get_value().c_str());
0459 return false;
0460 }
0461
0462
0463 std::swap((*p.first).second->macroparameters, parameters);
0464 std::swap((*p.first).second->macrodefinition, definition);
0465
0466
0467 ctx.get_hooks().defined_macro(ctx.derived(), name, has_parameters,
0468 (*p.first).second->macroparameters,
0469 (*p.first).second->macrodefinition, is_predefined);
0470 return true;
0471 }
0472
0473
0474
0475
0476
0477
0478 template <typename ContextT>
0479 inline bool
0480 macromap<ContextT>::is_defined(typename token_type::string_type const &name,
0481 typename defined_macros_type::iterator &it,
0482 defined_macros_type *scope) const
0483 {
0484 if (0 == scope) scope = current_macros;
0485
0486 if ((it = scope->find(name)) != scope->end())
0487 return true;
0488
0489
0490 if (name.size() < 8 || '_' != name[0] || '_' != name[1])
0491 return false;
0492
0493 if (name == "__LINE__" || name == "__FILE__" ||
0494 name == "__INCLUDE_LEVEL__")
0495 return true;
0496
0497 #if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
0498 return (boost::wave::need_has_include(ctx.get_language()) &&
0499 (name == "__has_include"));
0500 #else
0501 return false;
0502 #endif
0503 }
0504
0505 template <typename ContextT>
0506 template <typename IteratorT>
0507 inline bool
0508 macromap<ContextT>::is_defined(IteratorT const &begin,
0509 IteratorT const &end) const
0510 {
0511
0512
0513 token_id id = token_id(*begin);
0514
0515 if (T_IDENTIFIER != id &&
0516 !IS_CATEGORY(id, KeywordTokenType) &&
0517 !IS_EXTCATEGORY(id, OperatorTokenType|AltExtTokenType) &&
0518 !IS_CATEGORY(id, BoolLiteralTokenType))
0519 {
0520 std::string msg(impl::get_full_name(begin, end));
0521 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, invalid_macroname,
0522 msg.c_str(), main_pos);
0523 return false;
0524 }
0525
0526 IteratorT it = begin;
0527 string_type name((*it).get_value());
0528 typename defined_macros_type::iterator cit;
0529
0530 if (++it != end) {
0531
0532 std::string msg(impl::get_full_name(begin, end));
0533 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, invalid_macroname,
0534 msg.c_str(), main_pos);
0535 return false;
0536 }
0537 return is_defined(name, cit, 0);
0538 }
0539
0540
0541
0542 template <typename ContextT>
0543 inline bool
0544 macromap<ContextT>::is_defined(string_type const &str) const
0545 {
0546 typename defined_macros_type::iterator cit;
0547 return is_defined(str, cit, 0);
0548 }
0549
0550 #if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
0551
0552
0553
0554
0555
0556 template <typename ContextT>
0557 template <typename IteratorT>
0558 inline bool
0559 macromap<ContextT>::has_include(
0560 IteratorT const &begin, IteratorT const &end,
0561 bool is_quoted_filename, bool is_system) const
0562 {
0563 typename ContextT::token_sequence_type filetoks;
0564
0565 if (is_quoted_filename) {
0566 filetoks = typename ContextT::token_sequence_type(begin, end);
0567 } else {
0568 IteratorT first = begin;
0569 IteratorT last = end;
0570 ctx.expand_whole_tokensequence(first, last, filetoks);
0571 }
0572
0573
0574 using namespace boost::wave::util::impl;
0575 std::string fn(trim_whitespace(as_string(filetoks)).c_str());
0576
0577
0578 if (!((fn.size() >= 3) &&
0579 (((fn[0] == '"') && (*fn.rbegin() == '"')) ||
0580 ((fn[0] == '<') && (*fn.rbegin() == '>')))))
0581 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_has_include_expression,
0582 fn.c_str(), ctx.get_main_pos());
0583
0584 fn = fn.substr(1, fn.size() - 2);
0585
0586
0587 std::string dir_path;
0588 std::string native_path;
0589 return ctx.get_hooks().locate_include_file(
0590 ctx, fn, is_system, 0, dir_path, native_path);
0591
0592 }
0593 #endif
0594
0595
0596
0597
0598
0599
0600 template <typename ContextT>
0601 inline bool
0602 macromap<ContextT>::get_macro(string_type const &name, bool &has_parameters,
0603 bool &is_predefined, position_type &pos,
0604 parameter_container_type ¶meters,
0605 definition_container_type &definition,
0606 defined_macros_type *scope) const
0607 {
0608 typename defined_macros_type::iterator it;
0609 if (!is_defined(name, it, scope))
0610 return false;
0611
0612 macro_definition_type& macro_def = *(*it).second.get();
0613
0614 has_parameters = macro_def.is_functionlike;
0615 is_predefined = macro_def.is_predefined;
0616 pos = macro_def.macroname.get_position();
0617 parameters = macro_def.macroparameters;
0618 definition = macro_def.macrodefinition;
0619 return true;
0620 }
0621
0622
0623
0624
0625
0626
0627 template <typename ContextT>
0628 inline bool
0629 macromap<ContextT>::remove_macro(string_type const &name,
0630 position_type const& pos, bool even_predefined)
0631 {
0632 typename defined_macros_type::iterator it = current_macros->find(name);
0633
0634 if (it != current_macros->end()) {
0635 if ((*it).second->is_predefined) {
0636 if (!even_predefined || impl::is_special_macroname(ctx, name)) {
0637 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
0638 bad_undefine_statement, name.c_str(), main_pos);
0639 return false;
0640 }
0641 }
0642 current_macros->erase(it);
0643
0644
0645 token_type tok(T_IDENTIFIER, name, pos);
0646
0647 ctx.get_hooks().undefined_macro(ctx.derived(), tok);
0648 return true;
0649 }
0650 else if (impl::is_special_macroname(ctx, name)) {
0651 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_undefine_statement,
0652 name.c_str(), pos);
0653 }
0654 return false;
0655 }
0656
0657
0658
0659
0660
0661
0662
0663
0664
0665
0666
0667
0668
0669 template <typename ContextT>
0670 template <typename IteratorT, typename ContainerT>
0671 inline typename ContextT::token_type const &
0672 macromap<ContextT>::expand_tokensequence(IteratorT &first,
0673 IteratorT const &last, ContainerT &pending, ContainerT &expanded,
0674 bool& seen_newline, bool expand_operator_defined,
0675 bool expand_operator_has_include)
0676 {
0677 typedef impl::gen_unput_queue_iterator<IteratorT, token_type, ContainerT>
0678 gen_type;
0679 typedef typename gen_type::return_type iterator_type;
0680
0681 iterator_type first_it = gen_type::generate(expanded, first);
0682 iterator_type last_it = gen_type::generate(last);
0683
0684 on_exit::assign<IteratorT, iterator_type> on_exit(first, first_it);
0685
0686 return expand_tokensequence_worker(pending, first_it, last_it,
0687 seen_newline, expand_operator_defined, expand_operator_has_include,
0688 boost::none);
0689 }
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703 template <typename ContextT>
0704 template <typename IteratorT, typename ContainerT>
0705 inline typename ContextT::token_type const &
0706 macromap<ContextT>::expand_tokensequence_worker(
0707 ContainerT &pending,
0708 unput_queue_iterator<IteratorT, token_type, ContainerT> &first,
0709 unput_queue_iterator<IteratorT, token_type, ContainerT> const &last,
0710 bool& seen_newline, bool expand_operator_defined,
0711 bool expand_operator_has_include,
0712 boost::optional<position_type> expanding_pos)
0713 {
0714
0715
0716 if (!pending.empty()) {
0717 on_exit::pop_front<definition_container_type> pop_front_token(pending);
0718
0719 return act_token = pending.front();
0720 }
0721
0722
0723
0724 using namespace boost::wave;
0725
0726 if (first != last) {
0727 token_id id = token_id(*first);
0728
0729
0730 if (T_PLACEHOLDER == id) {
0731 token_type placeholder = *first;
0732
0733 ++first;
0734 if (first == last)
0735 return act_token = placeholder;
0736 id = token_id(*first);
0737 }
0738
0739 if (T_IDENTIFIER == id || IS_CATEGORY(id, KeywordTokenType) ||
0740 IS_EXTCATEGORY(id, OperatorTokenType|AltExtTokenType) ||
0741 IS_CATEGORY(id, BoolLiteralTokenType))
0742 {
0743
0744 if (expand_operator_defined && (*first).get_value() == "defined") {
0745
0746 return resolve_defined(first, last, pending);
0747 }
0748 #if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
0749 else if (boost::wave::need_has_include(ctx.get_language()) &&
0750 expand_operator_has_include &&
0751 (*first).get_value() == "__has_include") {
0752
0753 return resolve_has_include(first, last, pending);
0754 }
0755 #endif
0756 else if (boost::wave::need_variadics(ctx.get_language()) &&
0757 (*first).get_value() == "_Pragma")
0758 {
0759
0760 token_type curr_token = *first;
0761
0762 if (!resolve_operator_pragma(first, last, pending, seen_newline) ||
0763 pending.size() > 0)
0764 {
0765
0766
0767 on_exit::pop_front<definition_container_type> pop_token(pending);
0768
0769 return act_token = pending.front();
0770 }
0771
0772
0773 return act_token = token_type(T_PLACEHOLDER, "_",
0774 curr_token.get_position());
0775 }
0776
0777 token_type name_token(*first);
0778 typename defined_macros_type::iterator it;
0779
0780 if (is_defined(name_token.get_value(), it)) {
0781
0782
0783 if (expand_macro(pending, name_token, it, first, last,
0784 seen_newline, expand_operator_defined,
0785 expand_operator_has_include,
0786 expanding_pos))
0787 {
0788
0789
0790 if (first != last) {
0791
0792 typename ContainerT::reverse_iterator rit = pending.rbegin();
0793
0794 first.get_unput_queue().splice(
0795 first.get_unput_queue().begin(), pending,
0796 (++rit).base(), pending.end());
0797 }
0798
0799
0800 }
0801 else if (!pending.empty()) {
0802
0803 on_exit::pop_front<definition_container_type> pop_queue(pending);
0804
0805 return act_token = pending.front();
0806 }
0807 else {
0808
0809 return act_token = token_type();
0810 }
0811
0812
0813 if (!expanding_pos)
0814 expanding_pos = name_token.get_expand_position();
0815
0816 typename ContextT::token_type const & result =
0817 expand_tokensequence_worker(
0818 pending, first, last,
0819 seen_newline, expand_operator_defined,
0820 expand_operator_has_include,
0821 expanding_pos);
0822
0823 return result;
0824 }
0825 else {
0826 act_token = name_token;
0827 ++first;
0828 return act_token;
0829 }
0830 }
0831 else if (expand_operator_defined && IS_CATEGORY(*first, BoolLiteralTokenType)) {
0832
0833
0834
0835
0836
0837 return act_token = token_type(T_INTLIT, T_TRUE != id ? "0" : "1",
0838 (*first++).get_position());
0839 }
0840 else {
0841 act_token = *first;
0842 ++first;
0843 return act_token;
0844 }
0845 }
0846 return act_token = token_type();
0847 }
0848
0849
0850
0851
0852
0853
0854
0855
0856 template <typename ContextT>
0857 template <typename IteratorT, typename ContainerT, typename SizeT>
0858 inline typename std::vector<ContainerT>::size_type
0859 macromap<ContextT>::collect_arguments (token_type const curr_token,
0860 std::vector<ContainerT> &arguments, IteratorT &next, IteratorT &endparen,
0861 IteratorT const &end, SizeT const ¶meter_count, bool& seen_newline)
0862 {
0863 using namespace boost::wave;
0864
0865 arguments.push_back(ContainerT());
0866
0867
0868 typename std::vector<ContainerT>::size_type count_arguments = 0;
0869 int nested_parenthesis_level = 1;
0870 ContainerT* argument = &arguments[0];
0871 bool was_whitespace = false;
0872 token_type startof_argument_list = *next;
0873
0874 while (++next != end && nested_parenthesis_level) {
0875 token_id id = token_id(*next);
0876
0877 if (0 == parameter_count &&
0878 !IS_CATEGORY((*next), WhiteSpaceTokenType) && id != T_NEWLINE &&
0879 id != T_RIGHTPAREN && id != T_LEFTPAREN)
0880 {
0881
0882 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
0883 too_many_macroarguments, curr_token.get_value().c_str(),
0884 main_pos);
0885 return 0;
0886 }
0887
0888 switch (id) {
0889 case T_LEFTPAREN:
0890 ++nested_parenthesis_level;
0891 argument->push_back(*next);
0892 was_whitespace = false;
0893 break;
0894
0895 case T_RIGHTPAREN:
0896 {
0897 if (--nested_parenthesis_level >= 1)
0898 argument->push_back(*next);
0899 else {
0900
0901
0902 endparen = next;
0903 if (parameter_count > 0) {
0904 if (argument->empty() ||
0905 impl::is_whitespace_only(*argument))
0906 {
0907 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
0908 if (boost::wave::need_variadics(ctx.get_language())) {
0909
0910 argument->push_back(token_type(T_PLACEMARKER, "\xA7",
0911 (*next).get_position()));
0912 ++count_arguments;
0913 }
0914 #endif
0915 }
0916 else {
0917 ++count_arguments;
0918 }
0919 }
0920 }
0921 was_whitespace = false;
0922 }
0923 break;
0924
0925 case T_COMMA:
0926 if (1 == nested_parenthesis_level) {
0927
0928
0929 if (argument->empty() ||
0930 impl::is_whitespace_only(*argument))
0931 {
0932 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
0933 if (boost::wave::need_variadics(ctx.get_language())) {
0934
0935 argument->push_back(token_type(T_PLACEMARKER, "\xA7",
0936 (*next).get_position()));
0937 ++count_arguments;
0938 }
0939 #endif
0940 }
0941 else {
0942 ++count_arguments;
0943 }
0944 arguments.push_back(ContainerT());
0945 argument = &arguments[arguments.size()-1];
0946 }
0947 else {
0948
0949 argument->push_back(*next);
0950 }
0951 was_whitespace = false;
0952 break;
0953
0954 case T_NEWLINE:
0955 seen_newline = true;
0956
0957 case T_SPACE:
0958 case T_SPACE2:
0959 case T_CCOMMENT:
0960 if (!was_whitespace)
0961 argument->push_back(token_type(T_SPACE, " ", (*next).get_position()));
0962 was_whitespace = true;
0963 break;
0964
0965 case T_PLACEHOLDER:
0966 break;
0967
0968 default:
0969 argument->push_back(*next);
0970 was_whitespace = false;
0971 break;
0972 }
0973 }
0974
0975 if (nested_parenthesis_level >= 1) {
0976
0977 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
0978 improperly_terminated_macro, "missing ')'", main_pos);
0979 return 0;
0980 }
0981
0982
0983
0984 if (0 == parameter_count && 0 == count_arguments) {
0985 BOOST_ASSERT(1 == arguments.size());
0986 arguments.clear();
0987 }
0988 return count_arguments;
0989 }
0990
0991
0992
0993
0994
0995
0996
0997
0998 template <typename ContextT>
0999 template <typename IteratorT, typename ContainerT>
1000 inline void
1001 macromap<ContextT>::expand_whole_tokensequence(ContainerT &expanded,
1002 IteratorT &first, IteratorT const &last,
1003 bool expand_operator_defined,
1004 bool expand_operator_has_include)
1005 {
1006 typedef impl::gen_unput_queue_iterator<IteratorT, token_type, ContainerT>
1007 gen_type;
1008 typedef typename gen_type::return_type iterator_type;
1009
1010 ContainerT empty;
1011 iterator_type first_it = gen_type::generate(empty, first);
1012 iterator_type last_it = gen_type::generate(last);
1013
1014 on_exit::assign<IteratorT, iterator_type> on_exit(first, first_it);
1015 ContainerT pending_queue;
1016 bool seen_newline;
1017
1018 while (!pending_queue.empty() || first_it != last_it) {
1019 expanded.push_back(
1020 expand_tokensequence_worker(
1021 pending_queue, first_it,
1022 last_it, seen_newline, expand_operator_defined,
1023 expand_operator_has_include,
1024 boost::none)
1025 );
1026 }
1027
1028
1029 BOOST_ASSERT(pending_queue.empty());
1030 }
1031
1032
1033
1034
1035
1036
1037
1038
1039 template <typename ContextT>
1040 template <typename ContainerT>
1041 inline void
1042 macromap<ContextT>::expand_argument (
1043 typename std::vector<ContainerT>::size_type arg,
1044 std::vector<ContainerT> &arguments, std::vector<ContainerT> &expanded_args,
1045 bool expand_operator_defined, bool expand_operator_has_include,
1046 std::vector<bool> &has_expanded_args)
1047 {
1048 if (!has_expanded_args[arg]) {
1049
1050 typedef typename std::vector<ContainerT>::value_type::iterator
1051 argument_iterator_type;
1052
1053 argument_iterator_type begin_it = arguments[arg].begin();
1054 argument_iterator_type end_it = arguments[arg].end();
1055
1056 expand_whole_tokensequence(
1057 expanded_args[arg], begin_it, end_it,
1058 expand_operator_defined, expand_operator_has_include);
1059 impl::remove_placeholders(expanded_args[arg]);
1060 has_expanded_args[arg] = true;
1061 }
1062 }
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073 template <typename ContextT>
1074 template <typename ContainerT>
1075 inline void
1076 macromap<ContextT>::expand_replacement_list(
1077 typename macro_definition_type::const_definition_iterator_t cit,
1078 typename macro_definition_type::const_definition_iterator_t cend,
1079 std::vector<ContainerT> &arguments, bool expand_operator_defined,
1080 bool expand_operator_has_include,
1081 ContainerT &expanded)
1082 {
1083 using namespace boost::wave;
1084 typedef typename macro_definition_type::const_definition_iterator_t
1085 macro_definition_iter_t;
1086
1087 std::vector<ContainerT> expanded_args(arguments.size());
1088 std::vector<bool> has_expanded_args(arguments.size());
1089 bool seen_concat = false;
1090 bool adjacent_concat = false;
1091 bool adjacent_stringize = false;
1092
1093 for (;cit != cend; ++cit)
1094 {
1095 bool use_replaced_arg = true;
1096 token_id base_id = BASE_TOKEN(token_id(*cit));
1097
1098 if (T_POUND_POUND == base_id) {
1099
1100 adjacent_concat = true;
1101 seen_concat = true;
1102 }
1103 else if (T_POUND == base_id) {
1104
1105 adjacent_stringize = true;
1106 }
1107 else {
1108 if (adjacent_stringize || adjacent_concat ||
1109 T_POUND_POUND == impl::next_token<macro_definition_iter_t>
1110 ::peek(cit, cend))
1111 {
1112 use_replaced_arg = false;
1113 }
1114 if (adjacent_concat)
1115 adjacent_concat = IS_CATEGORY(*cit, WhiteSpaceTokenType);
1116 }
1117
1118 if (IS_CATEGORY((*cit), ParameterTokenType)) {
1119
1120 typename ContainerT::size_type i;
1121 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1122 bool is_ellipsis = false;
1123 #if BOOST_WAVE_SUPPORT_VA_OPT != 0
1124 bool is_va_opt = false;
1125 #endif
1126
1127 if (IS_EXTCATEGORY((*cit), ExtParameterTokenType)) {
1128 BOOST_ASSERT(boost::wave::need_variadics(ctx.get_language()));
1129 i = token_id(*cit) - T_EXTPARAMETERBASE;
1130 is_ellipsis = true;
1131 }
1132 else
1133 #if BOOST_WAVE_SUPPORT_VA_OPT != 0
1134
1135 if (IS_EXTCATEGORY((*cit), OptParameterTokenType)) {
1136 BOOST_ASSERT(boost::wave::need_va_opt(ctx.get_language()));
1137 i = token_id(*cit) - T_OPTPARAMETERBASE;
1138 is_va_opt = true;
1139 }
1140 else
1141 #endif
1142 #endif
1143 {
1144 i = token_id(*cit) - T_PARAMETERBASE;
1145 }
1146
1147 BOOST_ASSERT(i <= arguments.size());
1148 if (use_replaced_arg) {
1149
1150 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1151 if (is_ellipsis) {
1152 position_type const& pos = (*cit).get_position();
1153
1154 BOOST_ASSERT(boost::wave::need_variadics(ctx.get_language()));
1155
1156
1157 for (typename vector<ContainerT>::size_type arg = i;
1158 arg < expanded_args.size(); ++arg)
1159 {
1160 expand_argument(
1161 arg, arguments, expanded_args,
1162 expand_operator_defined, expand_operator_has_include,
1163 has_expanded_args);
1164 }
1165 impl::replace_ellipsis(expanded_args, i, expanded, pos);
1166 }
1167 else
1168
1169 #if BOOST_WAVE_SUPPORT_VA_OPT != 0
1170 if (is_va_opt) {
1171 position_type const &pos = (*cit).get_position();
1172
1173 BOOST_ASSERT(boost::wave::need_va_opt(ctx.get_language()));
1174
1175
1176 for (typename vector<ContainerT>::size_type arg = i;
1177 arg < expanded_args.size(); ++arg)
1178 {
1179 expand_argument(
1180 arg, arguments, expanded_args,
1181 expand_operator_defined, expand_operator_has_include,
1182 has_expanded_args);
1183 }
1184
1185
1186 typename macro_definition_type::const_definition_iterator_t cstart = cit;
1187 if (!impl::find_va_opt_args(cit, cend)) {
1188 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1189 improperly_terminated_macro, "missing '(' or ')' in __VA_OPT__",
1190 pos);
1191 }
1192
1193
1194
1195 typename macro_definition_type::const_definition_iterator_t arg_start = cstart;
1196 ++arg_start;
1197 ++arg_start;
1198
1199
1200 token_type macroname(T_IDENTIFIER, "__VA_OPT__", position_type("<built-in>"));
1201 parameter_container_type macroparameters;
1202 macroparameters.push_back(token_type(T_ELLIPSIS, "...", position_type("<built-in>")));
1203 definition_container_type macrodefinition;
1204
1205 bool suppress_expand = false;
1206
1207
1208 typename std::vector<ContainerT> va_opt_args(1, ContainerT(arg_start, cit));
1209 suppress_expand = ctx.get_hooks().expanding_function_like_macro(
1210 ctx.derived(),
1211 macroname, macroparameters, macrodefinition,
1212 *cstart, va_opt_args,
1213 cstart, cit);
1214
1215 if (suppress_expand) {
1216
1217 std::copy(cstart, cit, std::back_inserter(expanded));
1218 expanded.push_back(*cit);
1219 } else {
1220 ContainerT va_expanded;
1221 if ((i == arguments.size()) ||
1222 impl::is_whitespace_only(arguments[i])) {
1223
1224 va_expanded.push_back(
1225 typename ContainerT::value_type(T_PLACEMARKER, "\xA7", pos));
1226 } else if (!impl::is_blank_only(arguments[i])) {
1227
1228
1229 expand_replacement_list(arg_start, cit, arguments,
1230 expand_operator_defined,
1231 expand_operator_has_include,
1232 va_expanded);
1233 }
1234
1235 ctx.get_hooks().expanded_macro(ctx.derived(), va_expanded);
1236
1237
1238 expanded.splice(expanded.end(), va_expanded);
1239 }
1240
1241 }
1242 else
1243
1244 #endif
1245 #endif
1246 {
1247 BOOST_ASSERT(i < arguments.size());
1248
1249 expand_argument(
1250 i, arguments, expanded_args,
1251 expand_operator_defined, expand_operator_has_include,
1252 has_expanded_args);
1253
1254
1255 BOOST_ASSERT(i < expanded_args.size());
1256 ContainerT const& arg = expanded_args[i];
1257
1258 std::copy(arg.begin(), arg.end(),
1259 std::inserter(expanded, expanded.end()));
1260 }
1261 }
1262 else if (adjacent_stringize &&
1263 !IS_CATEGORY(*cit, WhiteSpaceTokenType))
1264 {
1265
1266 BOOST_ASSERT(!arguments[i].empty());
1267
1268
1269 position_type pos((*arguments[i].begin()).get_position());
1270
1271 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1272 if (is_ellipsis && boost::wave::need_variadics(ctx.get_language())) {
1273 impl::trim_sequence_left(arguments[i]);
1274 impl::trim_sequence_right(arguments.back());
1275 expanded.push_back(token_type(T_STRINGLIT,
1276 impl::as_stringlit(arguments, i, pos), pos));
1277 }
1278 else
1279 #endif
1280 {
1281 impl::trim_sequence(arguments[i]);
1282 expanded.push_back(token_type(T_STRINGLIT,
1283 impl::as_stringlit(arguments[i], pos), pos));
1284 }
1285 adjacent_stringize = false;
1286 }
1287 else {
1288
1289 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1290 if (is_ellipsis) {
1291 position_type const& pos = (*cit).get_position();
1292 #if BOOST_WAVE_SUPPORT_CPP2A != 0
1293 if (i < arguments.size())
1294 #endif
1295 {
1296
1297 impl::trim_sequence_left(arguments[i]);
1298 impl::trim_sequence_right(arguments.back());
1299 BOOST_ASSERT(boost::wave::need_variadics(ctx.get_language()));
1300 impl::replace_ellipsis(arguments, i, expanded, pos);
1301 }
1302 #if BOOST_WAVE_SUPPORT_CPP2A != 0
1303 else if (boost::wave::need_cpp2a(ctx.get_language())) {
1304 BOOST_ASSERT(i == arguments.size());
1305
1306 expanded.push_back(
1307 typename ContainerT::value_type(T_PLACEMARKER, "\xA7", pos));
1308 }
1309 #endif
1310 }
1311 else
1312 #endif
1313 {
1314 ContainerT& arg = arguments[i];
1315
1316 impl::trim_sequence(arg);
1317 std::copy(arg.begin(), arg.end(),
1318 std::inserter(expanded, expanded.end()));
1319 }
1320 }
1321 }
1322 else if (!adjacent_stringize || T_POUND != base_id) {
1323
1324 expanded.push_back(*cit);
1325 }
1326 }
1327
1328 if (adjacent_stringize) {
1329
1330 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_operator,
1331 "stringize ('#')", main_pos);
1332 return;
1333 }
1334
1335
1336 if (seen_concat)
1337 concat_tokensequence(expanded);
1338 }
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348 template <typename ContextT>
1349 template <typename IteratorT, typename ContainerT>
1350 inline void
1351 macromap<ContextT>::rescan_replacement_list(token_type const &curr_token,
1352 macro_definition_type ¯o_def, ContainerT &replacement_list,
1353 ContainerT &expanded,
1354 bool expand_operator_defined,
1355 bool expand_operator_has_include,
1356 IteratorT &nfirst, IteratorT const &nlast)
1357 {
1358 if (!replacement_list.empty()) {
1359 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1360
1361 if (boost::wave::need_variadics(ctx.get_language())) {
1362 typename ContainerT::iterator end = replacement_list.end();
1363 typename ContainerT::iterator it = replacement_list.begin();
1364
1365 while (it != end) {
1366 using namespace boost::wave;
1367 if (T_PLACEMARKER == token_id(*it)) {
1368 typename ContainerT::iterator placemarker = it;
1369
1370 ++it;
1371 replacement_list.erase(placemarker);
1372 }
1373 else {
1374 ++it;
1375 }
1376 }
1377 }
1378 #endif
1379
1380
1381
1382 on_exit::reset<bool> on_exit(macro_def.is_available_for_replacement, false);
1383 typename ContainerT::iterator begin_it = replacement_list.begin();
1384 typename ContainerT::iterator end_it = replacement_list.end();
1385
1386 expand_whole_tokensequence(
1387 expanded, begin_it, end_it,
1388 expand_operator_defined, expand_operator_has_include);
1389
1390
1391 impl::trim_replacement_list(expanded);
1392 }
1393
1394 if (expanded.empty()) {
1395
1396
1397 expanded.push_back(token_type(T_PLACEHOLDER, "_", curr_token.get_position()));
1398 }
1399 }
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410 template <typename ContextT>
1411 template <typename IteratorT, typename ContainerT>
1412 inline bool
1413 macromap<ContextT>::expand_macro(ContainerT &expanded,
1414 token_type const &curr_token, typename defined_macros_type::iterator it,
1415 IteratorT &first, IteratorT const &last,
1416 bool& seen_newline, bool expand_operator_defined,
1417 bool expand_operator_has_include,
1418 boost::optional<position_type> expanding_pos,
1419 defined_macros_type *scope, ContainerT *queue_symbol)
1420 {
1421 using namespace boost::wave;
1422
1423 if (0 == scope) scope = current_macros;
1424
1425 BOOST_ASSERT(T_IDENTIFIER == token_id(curr_token) ||
1426 IS_CATEGORY(token_id(curr_token), KeywordTokenType) ||
1427 IS_EXTCATEGORY(token_id(curr_token), OperatorTokenType|AltExtTokenType) ||
1428 IS_CATEGORY(token_id(curr_token), BoolLiteralTokenType));
1429
1430 if (it == scope->end()) {
1431 ++first;
1432
1433
1434 if (expand_predefined_macro(curr_token, expanded))
1435 return false;
1436
1437
1438 if (0 != queue_symbol) {
1439 expanded.splice(expanded.end(), *queue_symbol);
1440 }
1441 else {
1442 expanded.push_back(curr_token);
1443 }
1444 return false;
1445 }
1446
1447
1448 macro_definition_type& macro_def = *(*it).second.get();
1449
1450 macro_def.replace_parameters(ctx);
1451
1452
1453 if (!macro_def.is_available_for_replacement) {
1454
1455
1456 if (0 != queue_symbol) {
1457 queue_symbol->push_back(token_type(T_NONREPLACABLE_IDENTIFIER,
1458 curr_token.get_value(), curr_token.get_position()));
1459 expanded.splice(expanded.end(), *queue_symbol);
1460 }
1461 else {
1462 expanded.push_back(token_type(T_NONREPLACABLE_IDENTIFIER,
1463 curr_token.get_value(), curr_token.get_position()));
1464 }
1465 ++first;
1466 return false;
1467 }
1468
1469
1470 ContainerT replacement_list;
1471
1472 if (T_LEFTPAREN == impl::next_token<IteratorT>::peek(first, last)) {
1473
1474 impl::skip_to_token(ctx, first, last, T_LEFTPAREN, seen_newline);
1475
1476 IteratorT seqstart = first;
1477 IteratorT seqend = first;
1478
1479 if (macro_def.is_functionlike) {
1480
1481
1482
1483 std::vector<ContainerT> arguments;
1484 typename std::vector<ContainerT>::size_type count_args =
1485 collect_arguments(curr_token, arguments, first, seqend, last,
1486 macro_def.macroparameters.size(), seen_newline);
1487
1488 std::size_t parm_count_required = macro_def.macroparameters.size();
1489 #if BOOST_WAVE_SUPPORT_CPP2A
1490 if (boost::wave::need_cpp2a(ctx.get_language())) {
1491
1492
1493
1494 if ((parm_count_required > 0) &&
1495 (T_ELLIPSIS == token_id(macro_def.macroparameters.back()))) {
1496 --parm_count_required;
1497 }
1498 }
1499 #endif
1500
1501
1502 if (count_args < parm_count_required ||
1503 arguments.size() < parm_count_required)
1504 {
1505 if (count_args != arguments.size()) {
1506
1507 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1508 empty_macroarguments, curr_token.get_value().c_str(),
1509 main_pos);
1510 }
1511 else {
1512
1513 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1514 too_few_macroarguments, curr_token.get_value().c_str(),
1515 main_pos);
1516 }
1517 return false;
1518 }
1519
1520 if (count_args > macro_def.macroparameters.size() ||
1521 arguments.size() > macro_def.macroparameters.size())
1522 {
1523 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1524 if (!macro_def.has_ellipsis)
1525 #endif
1526 {
1527
1528 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1529 too_many_macroarguments,
1530 curr_token.get_value().c_str(), main_pos);
1531 return false;
1532 }
1533 }
1534
1535
1536 if (ctx.get_hooks().expanding_function_like_macro(ctx.derived(),
1537 macro_def.macroname, macro_def.macroparameters,
1538 macro_def.macrodefinition, curr_token, arguments,
1539 seqstart, seqend))
1540 {
1541
1542
1543
1544
1545
1546 expanded.push_back(curr_token);
1547 expanded.push_back(*seqstart);
1548 first = ++seqstart;
1549 return false;
1550 }
1551
1552
1553 expand_replacement_list(macro_def.macrodefinition.begin(),
1554 macro_def.macrodefinition.end(),
1555 arguments, expand_operator_defined,
1556 expand_operator_has_include,
1557 replacement_list);
1558
1559 if (!expanding_pos)
1560 expanding_pos = curr_token.get_expand_position();
1561 set_expand_positions(replacement_list, *expanding_pos);
1562 }
1563 else {
1564
1565 if (ctx.get_hooks().expanding_object_like_macro(ctx.derived(),
1566 macro_def.macroname, macro_def.macrodefinition, curr_token))
1567 {
1568
1569 expanded.push_back(curr_token);
1570 return false;
1571 }
1572
1573 bool found = false;
1574 impl::find_concat_operator concat_tag(found);
1575
1576 std::remove_copy_if(macro_def.macrodefinition.begin(),
1577 macro_def.macrodefinition.end(),
1578 std::inserter(replacement_list, replacement_list.end()),
1579 concat_tag);
1580
1581
1582 if (found && !concat_tokensequence(replacement_list))
1583 return false;
1584 }
1585 }
1586 else {
1587
1588 if ((*it).second->is_functionlike) {
1589
1590 if (0 != queue_symbol) {
1591 queue_symbol->push_back(curr_token);
1592 expanded.splice(expanded.end(), *queue_symbol);
1593 }
1594 else {
1595 expanded.push_back(curr_token);
1596 }
1597 ++first;
1598 return false;
1599 }
1600 else {
1601
1602 if (ctx.get_hooks().expanding_object_like_macro(ctx.derived(),
1603 macro_def.macroname, macro_def.macrodefinition, curr_token))
1604 {
1605
1606 expanded.push_back(curr_token);
1607 ++first;
1608 return false;
1609 }
1610
1611 bool found = false;
1612 impl::find_concat_operator concat_tag(found);
1613
1614 std::remove_copy_if(macro_def.macrodefinition.begin(),
1615 macro_def.macrodefinition.end(),
1616 std::inserter(replacement_list, replacement_list.end()),
1617 concat_tag);
1618
1619
1620 if (found && !concat_tokensequence(replacement_list))
1621 return false;
1622
1623 ++first;
1624 }
1625 }
1626
1627
1628 ContainerT expanded_list;
1629
1630 ctx.get_hooks().expanded_macro(ctx.derived(), replacement_list);
1631
1632 rescan_replacement_list(
1633 curr_token, macro_def, replacement_list,
1634 expanded_list, expand_operator_defined,
1635 expand_operator_has_include, first, last);
1636
1637 ctx.get_hooks().rescanned_macro(ctx.derived(), expanded_list);
1638
1639 if (!expanding_pos)
1640
1641 expanding_pos = curr_token.get_expand_position();
1642
1643
1644 set_expand_positions(expanded_list, *expanding_pos);
1645
1646 expanded.splice(expanded.end(), expanded_list);
1647 return true;
1648 }
1649
1650
1651
1652
1653
1654
1655
1656
1657 template <typename ContextT>
1658 template <typename ContainerT>
1659 inline bool
1660 macromap<ContextT>::expand_predefined_macro(token_type const &curr_token,
1661 ContainerT &expanded)
1662 {
1663 using namespace boost::wave;
1664
1665 string_type const& value = curr_token.get_value();
1666
1667 if ((value != "__LINE__") && (value != "__FILE__") && (value != "__INCLUDE_LEVEL__"))
1668 return false;
1669
1670
1671 token_type deftoken(T_IDENTIFIER, value, position_type("<built-in>"));
1672
1673 if (ctx.get_hooks().expanding_object_like_macro(ctx.derived(),
1674 deftoken, ContainerT(), curr_token))
1675 {
1676
1677 expanded.push_back(curr_token);
1678 return false;
1679 }
1680
1681 token_type replacement;
1682
1683 if (value == "__LINE__") {
1684
1685 std::string buffer = lexical_cast<std::string>(curr_token.get_expand_position().get_line());
1686
1687 replacement = token_type(T_INTLIT, buffer.c_str(), curr_token.get_position());
1688 }
1689 else if (value == "__FILE__") {
1690
1691 namespace fs = boost::filesystem;
1692
1693 std::string file("\"");
1694 fs::path filename(
1695 wave::util::create_path(curr_token.get_expand_position().get_file().c_str()));
1696
1697 using boost::wave::util::impl::escape_lit;
1698 file += escape_lit(wave::util::native_file_string(filename)) + "\"";
1699 replacement = token_type(T_STRINGLIT, file.c_str(),
1700 curr_token.get_position());
1701 }
1702 else if (value == "__INCLUDE_LEVEL__") {
1703
1704 std::string buffer = std::to_string(ctx.get_iteration_depth());
1705 replacement = token_type(T_INTLIT, buffer.c_str(), curr_token.get_position());
1706 }
1707
1708
1709 ContainerT replacement_list;
1710 replacement_list.push_back(replacement);
1711
1712 ctx.get_hooks().expanded_macro(ctx.derived(), replacement_list);
1713
1714 expanded.push_back(replacement);
1715
1716 ctx.get_hooks().rescanned_macro(ctx.derived(), expanded);
1717
1718 return true;
1719
1720 }
1721
1722
1723
1724
1725
1726
1727
1728 template <typename ContextT>
1729 template <typename IteratorT, typename ContainerT>
1730 inline typename ContextT::token_type const &
1731 macromap<ContextT>::resolve_defined(IteratorT &first,
1732 IteratorT const &last, ContainerT &pending)
1733 {
1734 using namespace boost::wave;
1735 using namespace boost::wave::grammars;
1736
1737 ContainerT result;
1738 IteratorT start = first;
1739 boost::spirit::classic::parse_info<IteratorT> hit =
1740 defined_grammar_gen<typename ContextT::lexer_type>::
1741 parse_operator_defined(start, last, result);
1742
1743 if (!hit.hit) {
1744 string_type msg ("defined(): ");
1745 msg = msg + util::impl::as_string<string_type>(first, last);
1746 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_expression,
1747 msg.c_str(), main_pos);
1748
1749
1750 pending.push_back(token_type(T_INTLIT, "0", main_pos));
1751 }
1752 else {
1753 impl::assign_iterator<IteratorT>::do_(first, hit.stop);
1754
1755
1756 pending.push_back(token_type(T_INTLIT,
1757 is_defined(result.begin(), result.end()) ? "1" : "0",
1758 main_pos));
1759 }
1760
1761 on_exit::pop_front<definition_container_type> pop_front_token(pending);
1762
1763 return act_token = pending.front();
1764 }
1765
1766 #if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
1767
1768
1769
1770
1771
1772
1773 template <typename ContextT>
1774 template <typename IteratorT, typename ContainerT>
1775 inline typename ContextT::token_type const &
1776 macromap<ContextT>::resolve_has_include(IteratorT &first,
1777 IteratorT const &last, ContainerT &pending)
1778 {
1779 using namespace boost::wave;
1780 using namespace boost::wave::grammars;
1781
1782 ContainerT result;
1783 bool is_quoted_filename;
1784 bool is_system;
1785 IteratorT start = first;
1786
1787 boost::spirit::classic::parse_info<IteratorT> hit =
1788 has_include_grammar_gen<typename ContextT::lexer_type>::
1789 parse_operator_has_include(start, last, result, is_quoted_filename, is_system);
1790
1791 if (!hit.hit) {
1792 string_type msg ("__has_include(): ");
1793 msg = msg + util::impl::as_string<string_type>(first, last);
1794 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_expression,
1795 msg.c_str(), main_pos);
1796
1797
1798 pending.push_back(token_type(T_INTLIT, "0", main_pos));
1799 }
1800 else {
1801 impl::assign_iterator<IteratorT>::do_(first, hit.stop);
1802
1803
1804 pending.push_back(
1805 token_type(T_INTLIT,
1806 has_include(result.begin(), result.end(),
1807 is_quoted_filename, is_system) ? "1" : "0",
1808 main_pos));
1809 }
1810
1811 on_exit::pop_front<definition_container_type> pop_front_token(pending);
1812
1813 return act_token = pending.front();
1814 }
1815 #endif
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828 template <typename ContextT>
1829 template <typename IteratorT, typename ContainerT>
1830 inline bool
1831 macromap<ContextT>::resolve_operator_pragma(IteratorT &first,
1832 IteratorT const &last, ContainerT &pending, bool& seen_newline)
1833 {
1834
1835 token_type pragma_token = *first;
1836
1837 if (!impl::skip_to_token(ctx, first, last, T_LEFTPAREN, seen_newline)) {
1838
1839 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_expression,
1840 "operator _Pragma()", pragma_token.get_position());
1841 return false;
1842 }
1843
1844 std::vector<ContainerT> arguments;
1845 IteratorT endparen = first;
1846 typename std::vector<ContainerT>::size_type count_args =
1847 collect_arguments (pragma_token, arguments, first, endparen, last, 1,
1848 seen_newline);
1849
1850
1851 if (pragma_token.get_position().get_file().empty())
1852 pragma_token.set_position(act_token.get_position());
1853
1854 if (count_args < 1 || arguments.size() < 1) {
1855
1856 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, too_few_macroarguments,
1857 pragma_token.get_value().c_str(), pragma_token.get_position());
1858 return false;
1859 }
1860 if (count_args > 1 || arguments.size() > 1) {
1861
1862 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, too_many_macroarguments,
1863 pragma_token.get_value().c_str(), pragma_token.get_position());
1864 return false;
1865 }
1866
1867
1868 typedef typename std::vector<ContainerT>::value_type::iterator
1869 argument_iterator_type;
1870
1871 ContainerT expanded;
1872 argument_iterator_type begin_it = arguments[0].begin();
1873 argument_iterator_type end_it = arguments[0].end();
1874 expand_whole_tokensequence(expanded, begin_it, end_it, false, false);
1875
1876
1877 typedef typename token_type::string_type string_type;
1878
1879 string_type pragma_cmd;
1880 typename ContainerT::const_iterator end_exp = expanded.end();
1881 for (typename ContainerT::const_iterator it_exp = expanded.begin();
1882 it_exp != end_exp; ++it_exp)
1883 {
1884 if (T_EOF == token_id(*it_exp))
1885 break;
1886 if (IS_CATEGORY(*it_exp, WhiteSpaceTokenType))
1887 continue;
1888
1889 if (T_STRINGLIT != token_id(*it_exp)) {
1890
1891 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1892 ill_formed_pragma_option, "_Pragma",
1893 pragma_token.get_position());
1894 return false;
1895 }
1896 if (pragma_cmd.size() > 0) {
1897
1898
1899
1900 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1901 ill_formed_pragma_option, "_Pragma",
1902 pragma_token.get_position());
1903 return false;
1904 }
1905
1906
1907 string_type token_str = (*it_exp).get_value();
1908 pragma_cmd += token_str.substr(1, token_str.size() - 2);
1909 }
1910 string_type pragma_cmd_unesc = impl::unescape_lit(pragma_cmd);
1911
1912
1913 typedef typename ContextT::lexer_type lexer_type;
1914
1915 ContainerT pragma;
1916 std::string pragma_cmd_str(pragma_cmd_unesc.c_str());
1917 lexer_type it = lexer_type(pragma_cmd_str.begin(), pragma_cmd_str.end(),
1918 pragma_token.get_position(), ctx.get_language());
1919 lexer_type end = lexer_type();
1920 for (; it != end; ++it)
1921 pragma.push_back(*it);
1922
1923
1924
1925 if (interpret_pragma(ctx, pragma_token, pragma.begin(), pragma.end(),
1926 pending))
1927 {
1928 return true;
1929 }
1930
1931
1932 pending.push_front(token_type(T_SPACE, " ", pragma_token.get_position()));
1933 pending.push_front(token_type(T_RIGHTPAREN, ")", pragma_token.get_position()));
1934 pending.push_front(token_type(T_STRINGLIT, string_type("\"") + pragma_cmd + "\"",
1935 pragma_token.get_position()));
1936 pending.push_front(token_type(T_LEFTPAREN, "(", pragma_token.get_position()));
1937 pending.push_front(pragma_token);
1938 return false;
1939 }
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949 template <typename ContextT>
1950 template <typename ContainerT>
1951 inline bool
1952 macromap<ContextT>::is_valid_concat(string_type new_value,
1953 position_type const &pos, ContainerT &rescanned)
1954 {
1955
1956 typedef typename ContextT::lexer_type lexer_type;
1957
1958 std::string value_to_test(new_value.c_str());
1959
1960 boost::wave::language_support lang =
1961 boost::wave::enable_prefer_pp_numbers(ctx.get_language());
1962 lang = boost::wave::enable_single_line(lang);
1963
1964 lexer_type it = lexer_type(value_to_test.begin(), value_to_test.end(), pos,
1965 lang);
1966 lexer_type end = lexer_type();
1967 for (; it != end && T_EOF != token_id(*it); ++it)
1968 {
1969
1970
1971 if (!is_pp_token(*it))
1972 return false;
1973 rescanned.push_back(*it);
1974 }
1975
1976 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1977 if (boost::wave::need_variadics(ctx.get_language()))
1978 return true;
1979 #endif
1980
1981
1982 return 1 == rescanned.size();
1983 }
1984
1985
1986
1987
1988
1989
1990
1991 template <typename ContextT>
1992 template <typename ContainerT>
1993 void macromap<ContextT>::set_expand_positions(ContainerT &tokens, position_type pos)
1994 {
1995 typename ContainerT::iterator ex_end = tokens.end();
1996 for (typename ContainerT::iterator it = tokens.begin();
1997 it != ex_end; ++it) {
1998
1999 if (token_id(*it) == T_IDENTIFIER)
2000 it->set_expand_position(pos);
2001 }
2002 }
2003
2004
2005
2006
2007
2008
2009
2010 template <typename Context>
2011 inline void report_invalid_concatenation(Context& ctx,
2012 typename Context::token_type const& prev,
2013 typename Context::token_type const& next,
2014 typename Context::position_type const& main_pos)
2015 {
2016 typename Context::string_type error_string("\"");
2017
2018 error_string += prev.get_value();
2019 error_string += "\" and \"";
2020 error_string += next.get_value();
2021 error_string += "\"";
2022 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, invalid_concat,
2023 error_string.c_str(), main_pos);
2024 }
2025
2026 template <typename ContextT>
2027 template <typename ContainerT>
2028 inline bool
2029 macromap<ContextT>::concat_tokensequence(ContainerT &expanded)
2030 {
2031 using namespace boost::wave;
2032 typedef typename ContainerT::iterator iterator_type;
2033
2034 iterator_type end = expanded.end();
2035 iterator_type prev = end;
2036 for (iterator_type it = expanded.begin(); it != end; )
2037 {
2038 if (T_POUND_POUND == BASE_TOKEN(token_id(*it))) {
2039 iterator_type next = it;
2040
2041 ++next;
2042 if (prev == end || next == end) {
2043
2044 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
2045 ill_formed_operator, "concat ('##')", main_pos);
2046 return false;
2047 }
2048
2049
2050
2051 while (IS_CATEGORY(*next, WhiteSpaceTokenType)) {
2052 ++next;
2053 if (next == end) {
2054
2055 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
2056 ill_formed_operator, "concat ('##')", main_pos);
2057 return false;
2058 }
2059 }
2060
2061 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
2062 if (boost::wave::need_variadics(ctx.get_language())) {
2063 if (T_PLACEMARKER == token_id(*next)) {
2064
2065 iterator_type first_to_delete = prev;
2066
2067 expanded.erase(++first_to_delete, ++next);
2068 it = next;
2069 continue;
2070 }
2071 else if (T_PLACEMARKER == token_id(*prev)) {
2072
2073 iterator_type first_to_delete = prev;
2074
2075 *prev = *next;
2076 expanded.erase(++first_to_delete, ++next);
2077 it = next;
2078 continue;
2079 }
2080 }
2081 #endif
2082
2083
2084
2085 string_type concat_result;
2086 ContainerT rescanned;
2087
2088 concat_result = ((*prev).get_value() + (*next).get_value());
2089
2090
2091 if (!is_valid_concat(concat_result, (*prev).get_position(),
2092 rescanned) &&
2093 !IS_CATEGORY(*prev, WhiteSpaceTokenType) &&
2094 !IS_CATEGORY(*next, WhiteSpaceTokenType))
2095 {
2096 report_invalid_concatenation(ctx, *prev, *next, main_pos);
2097 return false;
2098 }
2099
2100 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
2101 if (boost::wave::need_variadics(ctx.get_language())) {
2102
2103 expanded.erase(prev, ++next);
2104
2105
2106
2107
2108 if (expanded.empty())
2109 end = next = expanded.end();
2110
2111
2112
2113 expanded.splice(next, rescanned);
2114
2115
2116 prev = next;
2117 if (next != expanded.end())
2118 --prev;
2119 }
2120 else
2121 #endif
2122 {
2123
2124
2125 (*prev).set_value(concat_result);
2126 if (T_NONREPLACABLE_IDENTIFIER == token_id(*prev))
2127 (*prev).set_token_id(T_IDENTIFIER);
2128
2129
2130 iterator_type first_to_delete = prev;
2131
2132 expanded.erase(++first_to_delete, ++next);
2133 }
2134 it = next;
2135 continue;
2136 }
2137
2138
2139 if (!IS_CATEGORY(*it, WhiteSpaceTokenType))
2140 prev = it;
2141
2142 ++it;
2143 }
2144 return true;
2145 }
2146
2147
2148
2149
2150
2151
2152 template <typename ContextT>
2153 inline void
2154 macromap<ContextT>::predefine_macro(defined_macros_type *scope,
2155 string_type const &name, token_type const &t)
2156 {
2157 definition_container_type macrodefinition;
2158 std::vector<token_type> param;
2159
2160 macrodefinition.push_back(t);
2161 add_macro(token_type(T_IDENTIFIER, name, t.get_position()),
2162 false, param, macrodefinition, true, scope);
2163 }
2164
2165
2166
2167
2168
2169
2170 template <typename ContextT>
2171 inline void
2172 macromap<ContextT>::init_predefined_macros(char const *fname,
2173 defined_macros_type *scope, bool at_global_scope)
2174 {
2175
2176 defined_macros_type* current_scope = scope ? scope : current_macros;
2177
2178
2179 position_type pos("<built-in>");
2180
2181 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
2182 if (boost::wave::need_c99(ctx.get_language())) {
2183
2184 for (int i = 0; 0 != predef.static_data_c99(i).name; ++i) {
2185 predefined_macros::static_macros const& m = predef.static_data_c99(i);
2186 predefine_macro(current_scope, m.name,
2187 token_type(m.token_id, m.value, pos));
2188 }
2189 }
2190 else
2191 #endif
2192 {
2193 #if BOOST_WAVE_SUPPORT_CPP0X != 0
2194 if (boost::wave::need_cpp0x(ctx.get_language())) {
2195
2196 for (int i = 0; 0 != predef.static_data_cpp0x(i).name; ++i) {
2197 predefined_macros::static_macros const& m = predef.static_data_cpp0x(i);
2198 predefine_macro(current_scope, m.name,
2199 token_type(m.token_id, m.value, pos));
2200 }
2201 }
2202 else
2203 #endif
2204 #if BOOST_WAVE_SUPPORT_CPP2A != 0
2205 if (boost::wave::need_cpp2a(ctx.get_language())) {
2206
2207 for (int i = 0; 0 != predef.static_data_cpp2a(i).name; ++i) {
2208 predefined_macros::static_macros const& m = predef.static_data_cpp2a(i);
2209 predefine_macro(current_scope, m.name,
2210 token_type(m.token_id, m.value, pos));
2211 }
2212 }
2213 else
2214 #endif
2215 {
2216
2217 for (int i = 0; 0 != predef.static_data_cpp(i).name; ++i) {
2218 predefined_macros::static_macros const& m = predef.static_data_cpp(i);
2219 predefine_macro(current_scope, m.name,
2220 token_type(m.token_id, m.value, pos));
2221 }
2222
2223 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
2224
2225 if (boost::wave::need_variadics(ctx.get_language())) {
2226 predefine_macro(current_scope, "__WAVE_HAS_VARIADICS__",
2227 token_type(T_INTLIT, "1", pos));
2228 }
2229 #endif
2230 }
2231 }
2232
2233
2234 namespace fs = boost::filesystem;
2235 if (string_type(fname) != "<Unknown>") {
2236 fs::path filename(create_path(fname));
2237
2238 using boost::wave::util::impl::escape_lit;
2239 predefine_macro(current_scope, "__BASE_FILE__",
2240 token_type(T_STRINGLIT, string_type("\"") +
2241 escape_lit(native_file_string(filename)).c_str() + "\"", pos));
2242 base_name = fname;
2243 }
2244 else if (!base_name.empty()) {
2245 fs::path filename(create_path(base_name.c_str()));
2246
2247 using boost::wave::util::impl::escape_lit;
2248 predefine_macro(current_scope, "__BASE_FILE__",
2249 token_type(T_STRINGLIT, string_type("\"") +
2250 escape_lit(native_file_string(filename)).c_str() + "\"", pos));
2251 }
2252
2253
2254 for (int j = 0; 0 != predef.dynamic_data(j).name; ++j) {
2255 predefined_macros::dynamic_macros const& m = predef.dynamic_data(j);
2256 predefine_macro(current_scope, m.name,
2257 token_type(m.token_id, (predef.* m.generator)(), pos));
2258 }
2259 }
2260
2261
2262
2263
2264
2265
2266 template <typename ContextT>
2267 inline void
2268 macromap<ContextT>::reset_macromap()
2269 {
2270 current_macros->clear();
2271 predef.reset();
2272 act_token = token_type();
2273 }
2274
2275
2276 }}}
2277
2278 #if BOOST_WAVE_SERIALIZATION != 0
2279 namespace boost { namespace serialization {
2280
2281 template<typename ContextT>
2282 struct version<boost::wave::util::macromap<ContextT> >
2283 {
2284 typedef boost::wave::util::macromap<ContextT> target_type;
2285 typedef mpl::int_<target_type::version> type;
2286 typedef mpl::integral_c_tag tag;
2287 BOOST_STATIC_CONSTANT(unsigned int, value = version::type::value);
2288 };
2289
2290 }}
2291 #endif
2292
2293
2294 #ifdef BOOST_HAS_ABI_HEADERS
2295 #include BOOST_ABI_SUFFIX
2296 #endif
2297
2298 #endif