File indexing completed on 2025-10-15 08:54:17
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 #if BOOST_WAVE_SUPPORT_CPP2A != 0
1266 if (i >= arguments.size()) {
1267
1268 BOOST_ASSERT(boost::wave::need_cpp2a(ctx.get_language()));
1269 position_type last_valid(arguments.back().back().get_position());
1270
1271 expanded.push_back(token_type(T_STRINGLIT, "\"\"", last_valid));
1272 }
1273 else
1274 #endif
1275 {
1276
1277 BOOST_ASSERT(i < arguments.size() && !arguments[i].empty());
1278
1279 position_type pos((*arguments[i].begin()).get_position());
1280
1281 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1282 if (is_ellipsis && boost::wave::need_variadics(ctx.get_language())) {
1283 impl::trim_sequence_left(arguments[i]);
1284 impl::trim_sequence_right(arguments.back());
1285 expanded.push_back(token_type(T_STRINGLIT,
1286 impl::as_stringlit(arguments, i, pos), pos));
1287 }
1288 else
1289 #endif
1290 {
1291 impl::trim_sequence(arguments[i]);
1292 expanded.push_back(token_type(T_STRINGLIT,
1293 impl::as_stringlit(arguments[i], pos), pos));
1294 }
1295 }
1296 adjacent_stringize = false;
1297 }
1298 else {
1299
1300 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1301 if (is_ellipsis) {
1302 position_type const& pos = (*cit).get_position();
1303 #if BOOST_WAVE_SUPPORT_CPP2A != 0
1304 if (i < arguments.size())
1305 #endif
1306 {
1307
1308 impl::trim_sequence_left(arguments[i]);
1309 impl::trim_sequence_right(arguments.back());
1310 BOOST_ASSERT(boost::wave::need_variadics(ctx.get_language()));
1311 impl::replace_ellipsis(arguments, i, expanded, pos);
1312 }
1313 #if BOOST_WAVE_SUPPORT_CPP2A != 0
1314 else if (boost::wave::need_cpp2a(ctx.get_language())) {
1315 BOOST_ASSERT(i == arguments.size());
1316
1317 expanded.push_back(
1318 typename ContainerT::value_type(T_PLACEMARKER, "\xA7", pos));
1319 }
1320 #endif
1321 }
1322 else
1323 #endif
1324 {
1325 ContainerT& arg = arguments[i];
1326
1327 impl::trim_sequence(arg);
1328 std::copy(arg.begin(), arg.end(),
1329 std::inserter(expanded, expanded.end()));
1330 }
1331 }
1332 }
1333 else if (!adjacent_stringize || T_POUND != base_id) {
1334
1335 expanded.push_back(*cit);
1336 }
1337 }
1338
1339 if (adjacent_stringize) {
1340
1341 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_operator,
1342 "stringize ('#')", main_pos);
1343 return;
1344 }
1345
1346
1347 if (seen_concat)
1348 concat_tokensequence(expanded);
1349 }
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359 template <typename ContextT>
1360 template <typename IteratorT, typename ContainerT>
1361 inline void
1362 macromap<ContextT>::rescan_replacement_list(token_type const &curr_token,
1363 macro_definition_type ¯o_def, ContainerT &replacement_list,
1364 ContainerT &expanded,
1365 bool expand_operator_defined,
1366 bool expand_operator_has_include,
1367 IteratorT &nfirst, IteratorT const &nlast)
1368 {
1369 if (!replacement_list.empty()) {
1370 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1371
1372 if (boost::wave::need_variadics(ctx.get_language())) {
1373 typename ContainerT::iterator end = replacement_list.end();
1374 typename ContainerT::iterator it = replacement_list.begin();
1375
1376 while (it != end) {
1377 using namespace boost::wave;
1378 if (T_PLACEMARKER == token_id(*it)) {
1379 typename ContainerT::iterator placemarker = it;
1380
1381 ++it;
1382 replacement_list.erase(placemarker);
1383 }
1384 else {
1385 ++it;
1386 }
1387 }
1388 }
1389 #endif
1390
1391
1392
1393 on_exit::reset<bool> on_exit(macro_def.is_available_for_replacement, false);
1394 typename ContainerT::iterator begin_it = replacement_list.begin();
1395 typename ContainerT::iterator end_it = replacement_list.end();
1396
1397 expand_whole_tokensequence(
1398 expanded, begin_it, end_it,
1399 expand_operator_defined, expand_operator_has_include);
1400
1401
1402 impl::trim_replacement_list(expanded);
1403 }
1404
1405 if (expanded.empty()) {
1406
1407
1408 expanded.push_back(token_type(T_PLACEHOLDER, "_", curr_token.get_position()));
1409 }
1410 }
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421 template <typename ContextT>
1422 template <typename IteratorT, typename ContainerT>
1423 inline bool
1424 macromap<ContextT>::expand_macro(ContainerT &expanded,
1425 token_type const &curr_token, typename defined_macros_type::iterator it,
1426 IteratorT &first, IteratorT const &last,
1427 bool& seen_newline, bool expand_operator_defined,
1428 bool expand_operator_has_include,
1429 boost::optional<position_type> expanding_pos,
1430 defined_macros_type *scope, ContainerT *queue_symbol)
1431 {
1432 using namespace boost::wave;
1433
1434 if (0 == scope) scope = current_macros;
1435
1436 BOOST_ASSERT(T_IDENTIFIER == token_id(curr_token) ||
1437 IS_CATEGORY(token_id(curr_token), KeywordTokenType) ||
1438 IS_EXTCATEGORY(token_id(curr_token), OperatorTokenType|AltExtTokenType) ||
1439 IS_CATEGORY(token_id(curr_token), BoolLiteralTokenType));
1440
1441 if (it == scope->end()) {
1442 ++first;
1443
1444
1445 if (expand_predefined_macro(curr_token, expanded))
1446 return false;
1447
1448
1449 if (0 != queue_symbol) {
1450 expanded.splice(expanded.end(), *queue_symbol);
1451 }
1452 else {
1453 expanded.push_back(curr_token);
1454 }
1455 return false;
1456 }
1457
1458
1459 macro_definition_type& macro_def = *(*it).second.get();
1460
1461 macro_def.replace_parameters(ctx);
1462
1463
1464 if (!macro_def.is_available_for_replacement) {
1465
1466
1467 if (0 != queue_symbol) {
1468 queue_symbol->push_back(token_type(T_NONREPLACABLE_IDENTIFIER,
1469 curr_token.get_value(), curr_token.get_position()));
1470 expanded.splice(expanded.end(), *queue_symbol);
1471 }
1472 else {
1473 expanded.push_back(token_type(T_NONREPLACABLE_IDENTIFIER,
1474 curr_token.get_value(), curr_token.get_position()));
1475 }
1476 ++first;
1477 return false;
1478 }
1479
1480
1481 ContainerT replacement_list;
1482
1483 if (T_LEFTPAREN == impl::next_token<IteratorT>::peek(first, last)) {
1484
1485 impl::skip_to_token(ctx, first, last, T_LEFTPAREN, seen_newline);
1486
1487 IteratorT seqstart = first;
1488 IteratorT seqend = first;
1489
1490 if (macro_def.is_functionlike) {
1491
1492
1493
1494 std::vector<ContainerT> arguments;
1495 typename std::vector<ContainerT>::size_type count_args =
1496 collect_arguments(curr_token, arguments, first, seqend, last,
1497 macro_def.macroparameters.size(), seen_newline);
1498
1499 std::size_t parm_count_required = macro_def.macroparameters.size();
1500 #if BOOST_WAVE_SUPPORT_CPP2A
1501 if (boost::wave::need_cpp2a(ctx.get_language())) {
1502
1503
1504
1505 if ((parm_count_required > 0) &&
1506 (T_ELLIPSIS == token_id(macro_def.macroparameters.back()))) {
1507 --parm_count_required;
1508 }
1509 }
1510 #endif
1511
1512
1513 if (count_args < parm_count_required ||
1514 arguments.size() < parm_count_required)
1515 {
1516 if (count_args != arguments.size()) {
1517
1518 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1519 empty_macroarguments, curr_token.get_value().c_str(),
1520 main_pos);
1521 }
1522 else {
1523
1524 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1525 too_few_macroarguments, curr_token.get_value().c_str(),
1526 main_pos);
1527 }
1528 return false;
1529 }
1530
1531 if (count_args > macro_def.macroparameters.size() ||
1532 arguments.size() > macro_def.macroparameters.size())
1533 {
1534 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1535 if (!macro_def.has_ellipsis)
1536 #endif
1537 {
1538
1539 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1540 too_many_macroarguments,
1541 curr_token.get_value().c_str(), main_pos);
1542 return false;
1543 }
1544 }
1545
1546
1547 if (ctx.get_hooks().expanding_function_like_macro(ctx.derived(),
1548 macro_def.macroname, macro_def.macroparameters,
1549 macro_def.macrodefinition, curr_token, arguments,
1550 seqstart, seqend))
1551 {
1552
1553
1554
1555
1556
1557 expanded.push_back(curr_token);
1558 expanded.push_back(*seqstart);
1559 first = ++seqstart;
1560 return false;
1561 }
1562
1563
1564 expand_replacement_list(macro_def.macrodefinition.begin(),
1565 macro_def.macrodefinition.end(),
1566 arguments, expand_operator_defined,
1567 expand_operator_has_include,
1568 replacement_list);
1569
1570 if (!expanding_pos)
1571 expanding_pos = curr_token.get_expand_position();
1572 set_expand_positions(replacement_list, *expanding_pos);
1573 }
1574 else {
1575
1576 if (ctx.get_hooks().expanding_object_like_macro(ctx.derived(),
1577 macro_def.macroname, macro_def.macrodefinition, curr_token))
1578 {
1579
1580 expanded.push_back(curr_token);
1581 return false;
1582 }
1583
1584 bool found = false;
1585 impl::find_concat_operator concat_tag(found);
1586
1587 std::remove_copy_if(macro_def.macrodefinition.begin(),
1588 macro_def.macrodefinition.end(),
1589 std::inserter(replacement_list, replacement_list.end()),
1590 concat_tag);
1591
1592
1593 if (found && !concat_tokensequence(replacement_list))
1594 return false;
1595 }
1596 }
1597 else {
1598
1599 if ((*it).second->is_functionlike) {
1600
1601 if (0 != queue_symbol) {
1602 queue_symbol->push_back(curr_token);
1603 expanded.splice(expanded.end(), *queue_symbol);
1604 }
1605 else {
1606 expanded.push_back(curr_token);
1607 }
1608 ++first;
1609 return false;
1610 }
1611 else {
1612
1613 if (ctx.get_hooks().expanding_object_like_macro(ctx.derived(),
1614 macro_def.macroname, macro_def.macrodefinition, curr_token))
1615 {
1616
1617 expanded.push_back(curr_token);
1618 ++first;
1619 return false;
1620 }
1621
1622 bool found = false;
1623 impl::find_concat_operator concat_tag(found);
1624
1625 std::remove_copy_if(macro_def.macrodefinition.begin(),
1626 macro_def.macrodefinition.end(),
1627 std::inserter(replacement_list, replacement_list.end()),
1628 concat_tag);
1629
1630
1631 if (found && !concat_tokensequence(replacement_list))
1632 return false;
1633
1634 ++first;
1635 }
1636 }
1637
1638
1639 ContainerT expanded_list;
1640
1641 ctx.get_hooks().expanded_macro(ctx.derived(), replacement_list);
1642
1643 rescan_replacement_list(
1644 curr_token, macro_def, replacement_list,
1645 expanded_list, expand_operator_defined,
1646 expand_operator_has_include, first, last);
1647
1648 ctx.get_hooks().rescanned_macro(ctx.derived(), expanded_list);
1649
1650 if (!expanding_pos)
1651
1652 expanding_pos = curr_token.get_expand_position();
1653
1654
1655 set_expand_positions(expanded_list, *expanding_pos);
1656
1657 expanded.splice(expanded.end(), expanded_list);
1658 return true;
1659 }
1660
1661
1662
1663
1664
1665
1666
1667
1668 template <typename ContextT>
1669 template <typename ContainerT>
1670 inline bool
1671 macromap<ContextT>::expand_predefined_macro(token_type const &curr_token,
1672 ContainerT &expanded)
1673 {
1674 using namespace boost::wave;
1675
1676 string_type const& value = curr_token.get_value();
1677
1678 if ((value != "__LINE__") && (value != "__FILE__") && (value != "__INCLUDE_LEVEL__"))
1679 return false;
1680
1681
1682 token_type deftoken(T_IDENTIFIER, value, position_type("<built-in>"));
1683
1684 if (ctx.get_hooks().expanding_object_like_macro(ctx.derived(),
1685 deftoken, ContainerT(), curr_token))
1686 {
1687
1688 expanded.push_back(curr_token);
1689 return false;
1690 }
1691
1692 token_type replacement;
1693
1694 if (value == "__LINE__") {
1695
1696 std::string buffer = lexical_cast<std::string>(curr_token.get_expand_position().get_line());
1697
1698 replacement = token_type(T_INTLIT, buffer.c_str(), curr_token.get_position());
1699 }
1700 else if (value == "__FILE__") {
1701
1702 namespace fs = boost::filesystem;
1703
1704 std::string file("\"");
1705 fs::path filename(
1706 wave::util::create_path(curr_token.get_expand_position().get_file().c_str()));
1707
1708 using boost::wave::util::impl::escape_lit;
1709 file += escape_lit(wave::util::native_file_string(filename)) + "\"";
1710 replacement = token_type(T_STRINGLIT, file.c_str(),
1711 curr_token.get_position());
1712 }
1713 else if (value == "__INCLUDE_LEVEL__") {
1714
1715 std::string buffer = std::to_string(ctx.get_iteration_depth());
1716 replacement = token_type(T_INTLIT, buffer.c_str(), curr_token.get_position());
1717 }
1718
1719
1720 ContainerT replacement_list;
1721 replacement_list.push_back(replacement);
1722
1723 ctx.get_hooks().expanded_macro(ctx.derived(), replacement_list);
1724
1725 expanded.push_back(replacement);
1726
1727 ctx.get_hooks().rescanned_macro(ctx.derived(), expanded);
1728
1729 return true;
1730
1731 }
1732
1733
1734
1735
1736
1737
1738
1739 template <typename ContextT>
1740 template <typename IteratorT, typename ContainerT>
1741 inline typename ContextT::token_type const &
1742 macromap<ContextT>::resolve_defined(IteratorT &first,
1743 IteratorT const &last, ContainerT &pending)
1744 {
1745 using namespace boost::wave;
1746 using namespace boost::wave::grammars;
1747
1748 ContainerT result;
1749 IteratorT start = first;
1750 boost::spirit::classic::parse_info<IteratorT> hit =
1751 defined_grammar_gen<typename ContextT::lexer_type>::
1752 parse_operator_defined(start, last, result);
1753
1754 if (!hit.hit) {
1755 string_type msg ("defined(): ");
1756 msg = msg + util::impl::as_string<string_type>(first, last);
1757 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_expression,
1758 msg.c_str(), main_pos);
1759
1760
1761 pending.push_back(token_type(T_INTLIT, "0", main_pos));
1762 }
1763 else {
1764 impl::assign_iterator<IteratorT>::do_(first, hit.stop);
1765
1766
1767 pending.push_back(token_type(T_INTLIT,
1768 is_defined(result.begin(), result.end()) ? "1" : "0",
1769 main_pos));
1770 }
1771
1772 on_exit::pop_front<definition_container_type> pop_front_token(pending);
1773
1774 return act_token = pending.front();
1775 }
1776
1777 #if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
1778
1779
1780
1781
1782
1783
1784 template <typename ContextT>
1785 template <typename IteratorT, typename ContainerT>
1786 inline typename ContextT::token_type const &
1787 macromap<ContextT>::resolve_has_include(IteratorT &first,
1788 IteratorT const &last, ContainerT &pending)
1789 {
1790 using namespace boost::wave;
1791 using namespace boost::wave::grammars;
1792
1793 ContainerT result;
1794 bool is_quoted_filename;
1795 bool is_system;
1796 IteratorT start = first;
1797
1798 boost::spirit::classic::parse_info<IteratorT> hit =
1799 has_include_grammar_gen<typename ContextT::lexer_type>::
1800 parse_operator_has_include(start, last, result, is_quoted_filename, is_system);
1801
1802 if (!hit.hit) {
1803 string_type msg ("__has_include(): ");
1804 msg = msg + util::impl::as_string<string_type>(first, last);
1805 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_expression,
1806 msg.c_str(), main_pos);
1807
1808
1809 pending.push_back(token_type(T_INTLIT, "0", main_pos));
1810 }
1811 else {
1812 impl::assign_iterator<IteratorT>::do_(first, hit.stop);
1813
1814
1815 pending.push_back(
1816 token_type(T_INTLIT,
1817 has_include(result.begin(), result.end(),
1818 is_quoted_filename, is_system) ? "1" : "0",
1819 main_pos));
1820 }
1821
1822 on_exit::pop_front<definition_container_type> pop_front_token(pending);
1823
1824 return act_token = pending.front();
1825 }
1826 #endif
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839 template <typename ContextT>
1840 template <typename IteratorT, typename ContainerT>
1841 inline bool
1842 macromap<ContextT>::resolve_operator_pragma(IteratorT &first,
1843 IteratorT const &last, ContainerT &pending, bool& seen_newline)
1844 {
1845
1846 token_type pragma_token = *first;
1847
1848 if (!impl::skip_to_token(ctx, first, last, T_LEFTPAREN, seen_newline)) {
1849
1850 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_expression,
1851 "operator _Pragma()", pragma_token.get_position());
1852 return false;
1853 }
1854
1855 std::vector<ContainerT> arguments;
1856 IteratorT endparen = first;
1857 typename std::vector<ContainerT>::size_type count_args =
1858 collect_arguments (pragma_token, arguments, first, endparen, last, 1,
1859 seen_newline);
1860
1861
1862 if (pragma_token.get_position().get_file().empty())
1863 pragma_token.set_position(act_token.get_position());
1864
1865 if (count_args < 1 || arguments.size() < 1) {
1866
1867 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, too_few_macroarguments,
1868 pragma_token.get_value().c_str(), pragma_token.get_position());
1869 return false;
1870 }
1871 if (count_args > 1 || arguments.size() > 1) {
1872
1873 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, too_many_macroarguments,
1874 pragma_token.get_value().c_str(), pragma_token.get_position());
1875 return false;
1876 }
1877
1878
1879 typedef typename std::vector<ContainerT>::value_type::iterator
1880 argument_iterator_type;
1881
1882 ContainerT expanded;
1883 argument_iterator_type begin_it = arguments[0].begin();
1884 argument_iterator_type end_it = arguments[0].end();
1885 expand_whole_tokensequence(expanded, begin_it, end_it, false, false);
1886
1887
1888 typedef typename token_type::string_type string_type;
1889
1890 string_type pragma_cmd;
1891 typename ContainerT::const_iterator end_exp = expanded.end();
1892 for (typename ContainerT::const_iterator it_exp = expanded.begin();
1893 it_exp != end_exp; ++it_exp)
1894 {
1895 if (T_EOF == token_id(*it_exp))
1896 break;
1897 if (IS_CATEGORY(*it_exp, WhiteSpaceTokenType))
1898 continue;
1899
1900 if (T_STRINGLIT != token_id(*it_exp)) {
1901
1902 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1903 ill_formed_pragma_option, "_Pragma",
1904 pragma_token.get_position());
1905 return false;
1906 }
1907 if (pragma_cmd.size() > 0) {
1908
1909
1910
1911 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1912 ill_formed_pragma_option, "_Pragma",
1913 pragma_token.get_position());
1914 return false;
1915 }
1916
1917
1918 string_type token_str = (*it_exp).get_value();
1919 pragma_cmd += token_str.substr(1, token_str.size() - 2);
1920 }
1921 string_type pragma_cmd_unesc = impl::unescape_lit(pragma_cmd);
1922
1923
1924 typedef typename ContextT::lexer_type lexer_type;
1925
1926 ContainerT pragma;
1927 std::string pragma_cmd_str(pragma_cmd_unesc.c_str());
1928 lexer_type it = lexer_type(pragma_cmd_str.begin(), pragma_cmd_str.end(),
1929 pragma_token.get_position(), ctx.get_language());
1930 lexer_type end = lexer_type();
1931 for (; it != end; ++it)
1932 pragma.push_back(*it);
1933
1934
1935
1936 if (interpret_pragma(ctx, pragma_token, pragma.begin(), pragma.end(),
1937 pending))
1938 {
1939 return true;
1940 }
1941
1942
1943 pending.push_front(token_type(T_SPACE, " ", pragma_token.get_position()));
1944 pending.push_front(token_type(T_RIGHTPAREN, ")", pragma_token.get_position()));
1945 pending.push_front(token_type(T_STRINGLIT, string_type("\"") + pragma_cmd + "\"",
1946 pragma_token.get_position()));
1947 pending.push_front(token_type(T_LEFTPAREN, "(", pragma_token.get_position()));
1948 pending.push_front(pragma_token);
1949 return false;
1950 }
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960 template <typename ContextT>
1961 template <typename ContainerT>
1962 inline bool
1963 macromap<ContextT>::is_valid_concat(string_type new_value,
1964 position_type const &pos, ContainerT &rescanned)
1965 {
1966
1967 typedef typename ContextT::lexer_type lexer_type;
1968
1969 std::string value_to_test(new_value.c_str());
1970
1971 boost::wave::language_support lang =
1972 boost::wave::enable_prefer_pp_numbers(ctx.get_language());
1973 lang = boost::wave::enable_single_line(lang);
1974
1975 lexer_type it = lexer_type(value_to_test.begin(), value_to_test.end(), pos,
1976 lang);
1977 lexer_type end = lexer_type();
1978 for (; it != end && T_EOF != token_id(*it); ++it)
1979 {
1980
1981
1982 if (!is_pp_token(*it))
1983 return false;
1984 rescanned.push_back(*it);
1985 }
1986
1987 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1988 if (boost::wave::need_variadics(ctx.get_language()))
1989 return true;
1990 #endif
1991
1992
1993 return 1 == rescanned.size();
1994 }
1995
1996
1997
1998
1999
2000
2001
2002 template <typename ContextT>
2003 template <typename ContainerT>
2004 void macromap<ContextT>::set_expand_positions(ContainerT &tokens, position_type pos)
2005 {
2006 typename ContainerT::iterator ex_end = tokens.end();
2007 for (typename ContainerT::iterator it = tokens.begin();
2008 it != ex_end; ++it) {
2009
2010 if (token_id(*it) == T_IDENTIFIER)
2011 it->set_expand_position(pos);
2012 }
2013 }
2014
2015
2016
2017
2018
2019
2020
2021 template <typename Context>
2022 inline void report_invalid_concatenation(Context& ctx,
2023 typename Context::token_type const& prev,
2024 typename Context::token_type const& next,
2025 typename Context::position_type const& main_pos)
2026 {
2027 typename Context::string_type error_string("\"");
2028
2029 error_string += prev.get_value();
2030 error_string += "\" and \"";
2031 error_string += next.get_value();
2032 error_string += "\"";
2033 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, invalid_concat,
2034 error_string.c_str(), main_pos);
2035 }
2036
2037 template <typename ContextT>
2038 template <typename ContainerT>
2039 inline bool
2040 macromap<ContextT>::concat_tokensequence(ContainerT &expanded)
2041 {
2042 using namespace boost::wave;
2043 typedef typename ContainerT::iterator iterator_type;
2044
2045 iterator_type end = expanded.end();
2046 iterator_type prev = end;
2047 for (iterator_type it = expanded.begin(); it != end; )
2048 {
2049 if (T_POUND_POUND == BASE_TOKEN(token_id(*it))) {
2050 iterator_type next = it;
2051
2052 ++next;
2053 if (prev == end || 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
2062 while (IS_CATEGORY(*next, WhiteSpaceTokenType)) {
2063 ++next;
2064 if (next == end) {
2065
2066 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
2067 ill_formed_operator, "concat ('##')", main_pos);
2068 return false;
2069 }
2070 }
2071
2072 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
2073 if (boost::wave::need_variadics(ctx.get_language())) {
2074 if (T_PLACEMARKER == token_id(*next)) {
2075
2076 iterator_type first_to_delete = prev;
2077
2078 expanded.erase(++first_to_delete, ++next);
2079 it = next;
2080 continue;
2081 }
2082 else if (T_PLACEMARKER == token_id(*prev)) {
2083
2084 iterator_type first_to_delete = prev;
2085
2086 *prev = *next;
2087 expanded.erase(++first_to_delete, ++next);
2088 it = next;
2089 continue;
2090 }
2091 }
2092 #endif
2093
2094
2095
2096 string_type concat_result;
2097 ContainerT rescanned;
2098
2099 concat_result = ((*prev).get_value() + (*next).get_value());
2100
2101
2102 if (!is_valid_concat(concat_result, (*prev).get_position(),
2103 rescanned) &&
2104 !IS_CATEGORY(*prev, WhiteSpaceTokenType) &&
2105 !IS_CATEGORY(*next, WhiteSpaceTokenType))
2106 {
2107 report_invalid_concatenation(ctx, *prev, *next, main_pos);
2108 return false;
2109 }
2110
2111 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
2112 if (boost::wave::need_variadics(ctx.get_language())) {
2113
2114 expanded.erase(prev, ++next);
2115
2116
2117
2118
2119 if (expanded.empty())
2120 end = next = expanded.end();
2121
2122
2123
2124 expanded.splice(next, rescanned);
2125
2126
2127 prev = next;
2128 if (next != expanded.end())
2129 --prev;
2130 }
2131 else
2132 #endif
2133 {
2134
2135
2136 (*prev).set_value(concat_result);
2137 if (T_NONREPLACABLE_IDENTIFIER == token_id(*prev))
2138 (*prev).set_token_id(T_IDENTIFIER);
2139
2140
2141 iterator_type first_to_delete = prev;
2142
2143 expanded.erase(++first_to_delete, ++next);
2144 }
2145 it = next;
2146 continue;
2147 }
2148
2149
2150 if (!IS_CATEGORY(*it, WhiteSpaceTokenType))
2151 prev = it;
2152
2153 ++it;
2154 }
2155 return true;
2156 }
2157
2158
2159
2160
2161
2162
2163 template <typename ContextT>
2164 inline void
2165 macromap<ContextT>::predefine_macro(defined_macros_type *scope,
2166 string_type const &name, token_type const &t)
2167 {
2168 definition_container_type macrodefinition;
2169 std::vector<token_type> param;
2170
2171 macrodefinition.push_back(t);
2172 add_macro(token_type(T_IDENTIFIER, name, t.get_position()),
2173 false, param, macrodefinition, true, scope);
2174 }
2175
2176
2177
2178
2179
2180
2181 template <typename ContextT>
2182 inline void
2183 macromap<ContextT>::init_predefined_macros(char const *fname,
2184 defined_macros_type *scope, bool at_global_scope)
2185 {
2186
2187 defined_macros_type* current_scope = scope ? scope : current_macros;
2188
2189
2190 position_type pos("<built-in>");
2191
2192 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
2193 if (boost::wave::need_c99(ctx.get_language())) {
2194
2195 for (int i = 0; 0 != predef.static_data_c99(i).name; ++i) {
2196 predefined_macros::static_macros const& m = predef.static_data_c99(i);
2197 predefine_macro(current_scope, m.name,
2198 token_type(m.token_id, m.value, pos));
2199 }
2200 }
2201 else
2202 #endif
2203 {
2204 #if BOOST_WAVE_SUPPORT_CPP0X != 0
2205 if (boost::wave::need_cpp0x(ctx.get_language())) {
2206
2207 for (int i = 0; 0 != predef.static_data_cpp0x(i).name; ++i) {
2208 predefined_macros::static_macros const& m = predef.static_data_cpp0x(i);
2209 predefine_macro(current_scope, m.name,
2210 token_type(m.token_id, m.value, pos));
2211 }
2212 }
2213 else
2214 #endif
2215 #if BOOST_WAVE_SUPPORT_CPP2A != 0
2216 if (boost::wave::need_cpp2a(ctx.get_language())) {
2217
2218 for (int i = 0; 0 != predef.static_data_cpp2a(i).name; ++i) {
2219 predefined_macros::static_macros const& m = predef.static_data_cpp2a(i);
2220 predefine_macro(current_scope, m.name,
2221 token_type(m.token_id, m.value, pos));
2222 }
2223 }
2224 else
2225 #endif
2226 {
2227
2228 for (int i = 0; 0 != predef.static_data_cpp(i).name; ++i) {
2229 predefined_macros::static_macros const& m = predef.static_data_cpp(i);
2230 predefine_macro(current_scope, m.name,
2231 token_type(m.token_id, m.value, pos));
2232 }
2233
2234 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
2235
2236 if (boost::wave::need_variadics(ctx.get_language())) {
2237 predefine_macro(current_scope, "__WAVE_HAS_VARIADICS__",
2238 token_type(T_INTLIT, "1", pos));
2239 }
2240 #endif
2241 }
2242 }
2243
2244
2245 namespace fs = boost::filesystem;
2246 if (string_type(fname) != "<Unknown>") {
2247 fs::path filename(create_path(fname));
2248
2249 using boost::wave::util::impl::escape_lit;
2250 predefine_macro(current_scope, "__BASE_FILE__",
2251 token_type(T_STRINGLIT, string_type("\"") +
2252 escape_lit(native_file_string(filename)).c_str() + "\"", pos));
2253 base_name = fname;
2254 }
2255 else if (!base_name.empty()) {
2256 fs::path filename(create_path(base_name.c_str()));
2257
2258 using boost::wave::util::impl::escape_lit;
2259 predefine_macro(current_scope, "__BASE_FILE__",
2260 token_type(T_STRINGLIT, string_type("\"") +
2261 escape_lit(native_file_string(filename)).c_str() + "\"", pos));
2262 }
2263
2264
2265 for (int j = 0; 0 != predef.dynamic_data(j).name; ++j) {
2266 predefined_macros::dynamic_macros const& m = predef.dynamic_data(j);
2267 predefine_macro(current_scope, m.name,
2268 token_type(m.token_id, (predef.* m.generator)(), pos));
2269 }
2270 }
2271
2272
2273
2274
2275
2276
2277 template <typename ContextT>
2278 inline void
2279 macromap<ContextT>::reset_macromap()
2280 {
2281 current_macros->clear();
2282 predef.reset();
2283 act_token = token_type();
2284 }
2285
2286
2287 }}}
2288
2289 #if BOOST_WAVE_SERIALIZATION != 0
2290 namespace boost { namespace serialization {
2291
2292 template<typename ContextT>
2293 struct version<boost::wave::util::macromap<ContextT> >
2294 {
2295 typedef boost::wave::util::macromap<ContextT> target_type;
2296 typedef mpl::int_<target_type::version> type;
2297 typedef mpl::integral_c_tag tag;
2298 BOOST_STATIC_CONSTANT(unsigned int, value = version::type::value);
2299 };
2300
2301 }}
2302 #endif
2303
2304
2305 #ifdef BOOST_HAS_ABI_HEADERS
2306 #include BOOST_ABI_SUFFIX
2307 #endif
2308
2309 #endif