File indexing completed on 2025-09-17 08:52:58
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #if !defined(BOOST_CPP_ITERATOR_HPP_175CA88F_7273_43FA_9039_BCF7459E1F29_INCLUDED)
0014 #define BOOST_CPP_ITERATOR_HPP_175CA88F_7273_43FA_9039_BCF7459E1F29_INCLUDED
0015
0016 #include <string>
0017 #include <vector>
0018 #include <list>
0019 #include <cstdlib>
0020 #include <cctype>
0021
0022 #include <boost/assert.hpp>
0023 #include <boost/shared_ptr.hpp>
0024 #include <boost/filesystem/path.hpp>
0025 #include <boost/filesystem/operations.hpp>
0026 #include <boost/lexical_cast.hpp>
0027 #include <boost/spirit/include/classic_multi_pass.hpp>
0028 #include <boost/spirit/include/classic_parse_tree_utils.hpp>
0029
0030 #include <boost/wave/wave_config.hpp>
0031 #include <boost/pool/pool_alloc.hpp>
0032
0033 #include <boost/wave/util/insert_whitespace_detection.hpp>
0034 #include <boost/wave/util/macro_helpers.hpp>
0035 #include <boost/wave/util/cpp_macromap_utils.hpp>
0036 #include <boost/wave/util/interpret_pragma.hpp>
0037 #include <boost/wave/util/transform_iterator.hpp>
0038 #include <boost/wave/util/functor_input.hpp>
0039 #include <boost/wave/util/filesystem_compatibility.hpp>
0040
0041 #include <boost/wave/grammars/cpp_grammar_gen.hpp>
0042 #include <boost/wave/grammars/cpp_expression_grammar_gen.hpp>
0043 #if BOOST_WAVE_ENABLE_COMMANDLINE_MACROS != 0
0044 #include <boost/wave/grammars/cpp_predef_macros_gen.hpp>
0045 #endif
0046
0047 #include <boost/wave/whitespace_handling.hpp>
0048 #include <boost/wave/cpp_iteration_context.hpp>
0049 #include <boost/wave/cpp_exceptions.hpp>
0050 #include <boost/wave/language_support.hpp>
0051
0052
0053 #ifdef BOOST_HAS_ABI_HEADERS
0054 #include BOOST_ABI_PREFIX
0055 #endif
0056
0057
0058 namespace boost {
0059 namespace wave {
0060 namespace util {
0061
0062
0063
0064 template <
0065 typename ContextT, typename ParseNodeT, typename TokenT,
0066 typename PositionT
0067 >
0068 inline bool
0069 retrieve_macroname(ContextT& ctx, ParseNodeT const &node,
0070 boost::spirit::classic::parser_id id, TokenT ¯oname, PositionT& act_pos,
0071 bool update_position)
0072 {
0073 ParseNodeT const* name_node = 0;
0074
0075 using boost::spirit::classic::find_node;
0076 if (!find_node(node, id, &name_node))
0077 {
0078
0079 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_define_statement,
0080 "bad parse tree (unexpected)", act_pos);
0081 return false;
0082 }
0083
0084 typename ParseNodeT::children_t const& children = name_node->children;
0085
0086 if (0 == children.size() ||
0087 children.front().value.begin() == children.front().value.end())
0088 {
0089
0090 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_define_statement,
0091 "bad parse tree (unexpected)", act_pos);
0092 return false;
0093 }
0094
0095
0096 macroname = *children.front().value.begin();
0097 if (update_position) {
0098 macroname.set_position(act_pos);
0099 act_pos.set_column(act_pos.get_column() + macroname.get_value().size());
0100 }
0101 return true;
0102 }
0103
0104
0105
0106 template <typename ParseNodeT, typename ContainerT, typename PositionT>
0107 inline bool
0108 retrieve_macrodefinition(
0109 ParseNodeT const &node, boost::spirit::classic::parser_id id,
0110 ContainerT ¯odefinition, PositionT& act_pos, bool update_position)
0111 {
0112 using namespace boost::wave;
0113 typedef typename ParseNodeT::const_tree_iterator const_tree_iterator;
0114
0115
0116 std::pair<const_tree_iterator, const_tree_iterator> nodes;
0117
0118 using boost::spirit::classic::get_node_range;
0119 if (get_node_range(node, id, nodes)) {
0120
0121 typename ContainerT::iterator last_nonwhite = macrodefinition.end();
0122 const_tree_iterator end = nodes.second;
0123
0124 for (const_tree_iterator cit = nodes.first; cit != end; ++cit) {
0125 if ((*cit).value.begin() != (*cit).value.end()) {
0126 typename ContainerT::iterator inserted = macrodefinition.insert(
0127 macrodefinition.end(), *(*cit).value.begin());
0128
0129 if (!IS_CATEGORY(macrodefinition.back(), WhiteSpaceTokenType) &&
0130 T_NEWLINE != token_id(macrodefinition.back()) &&
0131 T_EOF != token_id(macrodefinition.back()))
0132 {
0133 last_nonwhite = inserted;
0134 }
0135
0136 if (update_position) {
0137 (*inserted).set_position(act_pos);
0138 act_pos.set_column(
0139 act_pos.get_column() + (*inserted).get_value().size());
0140 }
0141 }
0142 }
0143
0144
0145 if (last_nonwhite != macrodefinition.end()) {
0146 if (update_position) {
0147 act_pos.set_column((*last_nonwhite).get_position().get_column() +
0148 (*last_nonwhite).get_value().size());
0149 }
0150 macrodefinition.erase(++last_nonwhite, macrodefinition.end());
0151 }
0152 return true;
0153 }
0154 return false;
0155 }
0156
0157 #if BOOST_WAVE_ENABLE_COMMANDLINE_MACROS != 0
0158
0159
0160 template <typename ContextT>
0161 bool add_macro_definition(ContextT &ctx, std::string macrostring,
0162 bool is_predefined, boost::wave::language_support language)
0163 {
0164 typedef typename ContextT::token_type token_type;
0165 typedef typename ContextT::lexer_type lexer_type;
0166 typedef typename token_type::position_type position_type;
0167 typedef boost::wave::grammars::predefined_macros_grammar_gen<lexer_type>
0168 predef_macros_type;
0169
0170 using namespace boost::wave;
0171 using namespace std;
0172
0173
0174 std::string::iterator begin = macrostring.begin();
0175 std::string::iterator end = macrostring.end();
0176
0177 while(begin != end && isspace(*begin))
0178 ++begin;
0179
0180
0181 position_type act_pos("<command line>");
0182 boost::spirit::classic::tree_parse_info<lexer_type> hit =
0183 predef_macros_type::parse_predefined_macro(
0184 lexer_type(begin, end, position_type(), language), lexer_type());
0185
0186 if (!hit.match || (!hit.full && T_EOF != token_id(*hit.stop))) {
0187 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_macro_definition,
0188 macrostring.c_str(), act_pos);
0189 return false;
0190 }
0191
0192
0193 token_type macroname;
0194 std::vector<token_type> macroparameters;
0195 typename ContextT::token_sequence_type macrodefinition;
0196 bool has_parameters = false;
0197
0198 if (!boost::wave::util::retrieve_macroname(ctx, *hit.trees.begin(),
0199 BOOST_WAVE_PLAIN_DEFINE_ID, macroname, act_pos, true))
0200 return false;
0201 has_parameters = boost::wave::util::retrieve_macrodefinition(*hit.trees.begin(),
0202 BOOST_WAVE_MACRO_PARAMETERS_ID, macroparameters, act_pos, true);
0203 boost::wave::util::retrieve_macrodefinition(*hit.trees.begin(),
0204 BOOST_WAVE_MACRO_DEFINITION_ID, macrodefinition, act_pos, true);
0205
0206
0207 if (!macrodefinition.empty() && token_id(macrodefinition.back()) == T_EOF)
0208 macrodefinition.pop_back();
0209
0210
0211
0212 if (macrodefinition.empty() && '=' != macrostring[macrostring.size()-1])
0213 macrodefinition.push_back(token_type(T_INTLIT, "1", act_pos));
0214
0215
0216 return ctx.add_macro_definition(macroname, has_parameters, macroparameters,
0217 macrodefinition, is_predefined);
0218 }
0219 #endif
0220
0221
0222 }
0223
0224
0225
0226 template <typename ContextT> class pp_iterator;
0227
0228 namespace impl {
0229
0230
0231
0232
0233
0234
0235 template <typename ContextT>
0236 class pp_iterator_functor {
0237
0238 public:
0239
0240 typedef typename ContextT::token_type result_type;
0241
0242
0243 static result_type const eof;
0244
0245 private:
0246
0247 typedef typename ContextT::token_sequence_type token_sequence_type;
0248
0249 typedef typename ContextT::lexer_type lexer_type;
0250 typedef typename result_type::string_type string_type;
0251 typedef typename result_type::position_type position_type;
0252 typedef boost::wave::grammars::cpp_grammar_gen<lexer_type, token_sequence_type>
0253 cpp_grammar_type;
0254
0255
0256
0257 typedef base_iteration_context<ContextT, lexer_type>
0258 base_iteration_context_type;
0259 typedef iteration_context<ContextT, lexer_type> iteration_context_type;
0260
0261
0262 typedef typename cpp_grammar_type::node_factory_type node_factory_type;
0263 typedef boost::spirit::classic::tree_parse_info<lexer_type, node_factory_type>
0264 tree_parse_info_type;
0265 typedef boost::spirit::classic::tree_match<lexer_type, node_factory_type>
0266 parse_tree_match_type;
0267 typedef typename parse_tree_match_type::node_t parse_node_type;
0268 typedef typename parse_tree_match_type::parse_node_t parse_node_value_type;
0269 typedef typename parse_tree_match_type::container_t parse_tree_type;
0270
0271 public:
0272 template <typename IteratorT>
0273 pp_iterator_functor(ContextT &ctx_, IteratorT const &first_,
0274 IteratorT const &last_, typename ContextT::position_type const &pos_)
0275 : ctx(ctx_),
0276 iter_ctx(new base_iteration_context_type(ctx,
0277 lexer_type(first_, last_, pos_,
0278 boost::wave::enable_prefer_pp_numbers(ctx.get_language())),
0279 lexer_type(),
0280 pos_.get_file().c_str()
0281 )),
0282 seen_newline(true), skipped_newline(false),
0283 must_emit_line_directive(false), act_pos(ctx_.get_main_pos()),
0284 whitespace(boost::wave::need_insert_whitespace(ctx.get_language()))
0285 {
0286 act_pos.set_file(pos_.get_file());
0287 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
0288 ctx_.set_current_filename(pos_.get_file().c_str());
0289 #endif
0290 iter_ctx->emitted_lines = (unsigned int)(-1);
0291 }
0292
0293
0294 result_type const &operator()();
0295
0296
0297 result_type const ¤t_token() const { return act_token; }
0298
0299 protected:
0300 friend class pp_iterator<ContextT>;
0301 bool on_include_helper(char const *t, char const *s, bool is_system,
0302 bool include_next);
0303
0304 protected:
0305 result_type const &get_next_token();
0306 result_type const &pp_token();
0307
0308 template <typename IteratorT>
0309 bool extract_identifier(IteratorT &it);
0310 template <typename IteratorT>
0311 bool ensure_is_last_on_line(IteratorT& it, bool call_hook = true);
0312 template <typename IteratorT>
0313 bool skip_to_eol_with_check(IteratorT &it, bool call_hook = true);
0314
0315 bool pp_directive();
0316 template <typename IteratorT>
0317 bool handle_pp_directive(IteratorT &it);
0318 bool dispatch_directive(tree_parse_info_type const &hit,
0319 result_type const& found_directive,
0320 token_sequence_type const& found_eoltokens);
0321 void replace_undefined_identifiers(token_sequence_type &expanded);
0322
0323 void on_include(string_type const &s, bool is_system, bool include_next);
0324 void on_include(typename parse_tree_type::const_iterator const &begin,
0325 typename parse_tree_type::const_iterator const &end, bool include_next);
0326
0327 void on_define(parse_node_type const &node);
0328 void on_undefine(lexer_type const &it);
0329
0330 void on_ifdef(result_type const& found_directive,
0331 typename parse_tree_type::const_iterator const &begin,
0332 typename parse_tree_type::const_iterator const &end);
0333 void on_ifndef(result_type const& found_directive,
0334 typename parse_tree_type::const_iterator const &begin,
0335 typename parse_tree_type::const_iterator const &end);
0336 void on_else();
0337 void on_endif();
0338 void on_illformed(typename result_type::string_type s);
0339
0340 void on_line(typename parse_tree_type::const_iterator const &begin,
0341 typename parse_tree_type::const_iterator const &end);
0342 void on_if(result_type const& found_directive,
0343 typename parse_tree_type::const_iterator const &begin,
0344 typename parse_tree_type::const_iterator const &end);
0345 void on_elif(result_type const& found_directive,
0346 typename parse_tree_type::const_iterator const &begin,
0347 typename parse_tree_type::const_iterator const &end);
0348 void on_error(typename parse_tree_type::const_iterator const &begin,
0349 typename parse_tree_type::const_iterator const &end);
0350 #if BOOST_WAVE_SUPPORT_WARNING_DIRECTIVE != 0
0351 void on_warning(typename parse_tree_type::const_iterator const &begin,
0352 typename parse_tree_type::const_iterator const &end);
0353 #endif
0354 bool on_pragma(typename parse_tree_type::const_iterator const &begin,
0355 typename parse_tree_type::const_iterator const &end);
0356
0357 bool emit_line_directive();
0358 bool returned_from_include();
0359
0360 bool interpret_pragma(token_sequence_type const &pragma_body,
0361 token_sequence_type &result);
0362
0363 private:
0364 ContextT &ctx;
0365 boost::shared_ptr<base_iteration_context_type> iter_ctx;
0366
0367 bool seen_newline;
0368 bool skipped_newline;
0369 bool must_emit_line_directive;
0370 result_type act_token;
0371 typename result_type::position_type &act_pos;
0372
0373 token_sequence_type unput_queue;
0374 token_sequence_type pending_queue;
0375
0376
0377
0378
0379 boost::wave::util::insert_whitespace_detection whitespace;
0380 };
0381
0382
0383
0384 template <typename ContextT>
0385 typename pp_iterator_functor<ContextT>::result_type const
0386 pp_iterator_functor<ContextT>::eof;
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397 template <typename ContextT>
0398 inline bool
0399 pp_iterator_functor<ContextT>::returned_from_include()
0400 {
0401 if (iter_ctx->first == iter_ctx->last && ctx.get_iteration_depth() > 0) {
0402
0403 ctx.get_hooks().returning_from_include_file(ctx.derived());
0404
0405
0406
0407 BOOST_WAVE_STRINGTYPE oldfile = iter_ctx->real_filename;
0408 position_type old_pos (act_pos);
0409
0410
0411 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
0412 if (need_include_guard_detection(ctx.get_language())) {
0413 std::string guard_name;
0414 if (iter_ctx->first.has_include_guards(guard_name))
0415 ctx.add_pragma_once_header(ctx.get_current_filename(), guard_name);
0416 }
0417 #endif
0418 iter_ctx = ctx.pop_iteration_context();
0419
0420 must_emit_line_directive = true;
0421 iter_ctx->emitted_lines = (unsigned int)(-1);
0422 seen_newline = true;
0423
0424
0425 act_pos.set_file(iter_ctx->filename);
0426 act_pos.set_line(iter_ctx->line);
0427 act_pos.set_column(0);
0428
0429
0430 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
0431 namespace fs = boost::filesystem;
0432 fs::path rfp(wave::util::create_path(iter_ctx->real_filename.c_str()));
0433 std::string real_filename(rfp.string());
0434 ctx.set_current_filename(real_filename.c_str());
0435 #endif
0436 ctx.set_current_directory(iter_ctx->real_filename.c_str());
0437 ctx.set_current_relative_filename(iter_ctx->real_relative_filename.c_str());
0438
0439
0440
0441 if (iter_ctx->if_block_depth != ctx.get_if_block_depth()) {
0442 using boost::wave::util::impl::escape_lit;
0443 BOOST_WAVE_STRINGTYPE msg(escape_lit(oldfile));
0444 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, unbalanced_if_endif,
0445 msg.c_str(), old_pos);
0446 }
0447 return true;
0448 }
0449 return false;
0450 }
0451
0452
0453
0454
0455
0456
0457
0458
0459 namespace impl {
0460
0461
0462
0463
0464
0465
0466 template <typename ContextT>
0467 bool consider_emitting_line_directive(ContextT const& ctx, token_id id)
0468 {
0469 if (need_preserve_comments(ctx.get_language()))
0470 {
0471 if (!IS_CATEGORY(id, EOLTokenType) && !IS_CATEGORY(id, EOFTokenType))
0472 {
0473 return true;
0474 }
0475 }
0476 if (!IS_CATEGORY(id, WhiteSpaceTokenType) &&
0477 !IS_CATEGORY(id, EOLTokenType) && !IS_CATEGORY(id, EOFTokenType))
0478 {
0479 return true;
0480 }
0481 return false;
0482 }
0483 }
0484
0485 template <typename ContextT>
0486 inline typename pp_iterator_functor<ContextT>::result_type const &
0487 pp_iterator_functor<ContextT>::operator()()
0488 {
0489 using namespace boost::wave;
0490
0491
0492 ctx.init_context();
0493
0494
0495 bool was_seen_newline = seen_newline;
0496 bool was_skipped_newline = skipped_newline;
0497 token_id id = T_UNKNOWN;
0498
0499 try {
0500 do {
0501 if (skipped_newline) {
0502 was_skipped_newline = true;
0503 skipped_newline = false;
0504 }
0505
0506
0507 get_next_token();
0508
0509
0510 id = token_id(act_token);
0511 if (!need_preserve_comments(ctx.get_language()) &&
0512 (T_CPPCOMMENT == id || context_policies::util::ccomment_has_newline(act_token)))
0513 {
0514 act_token.set_token_id(id = T_NEWLINE);
0515 act_token.set_value("\n");
0516 }
0517
0518 if (IS_CATEGORY(id, EOLTokenType))
0519 seen_newline = true;
0520
0521 } while (ctx.get_hooks().may_skip_whitespace(ctx.derived(), act_token, skipped_newline));
0522 }
0523 catch (boost::wave::cpplexer::lexing_exception const& e) {
0524
0525 ctx.get_hooks().throw_exception(ctx.derived(), e);
0526 return act_token;
0527 }
0528
0529
0530 if (was_skipped_newline)
0531 skipped_newline = true;
0532
0533
0534 if ((must_emit_line_directive || (was_seen_newline && skipped_newline)) &&
0535 impl::consider_emitting_line_directive(ctx, id))
0536 {
0537
0538 if (need_emit_line_directives(ctx.get_language()) && emit_line_directive())
0539 {
0540 skipped_newline = false;
0541 ctx.get_hooks().may_skip_whitespace(ctx.derived(), act_token, skipped_newline);
0542 id = token_id(act_token);
0543 }
0544 }
0545
0546
0547 seen_newline = false;
0548 switch (id) {
0549 case T_NONREPLACABLE_IDENTIFIER:
0550 act_token.set_token_id(id = T_IDENTIFIER);
0551 break;
0552
0553 case T_GENERATEDNEWLINE:
0554 act_token.set_token_id(id = T_NEWLINE);
0555 ++iter_ctx->emitted_lines;
0556 seen_newline = true;
0557 break;
0558
0559 case T_NEWLINE:
0560 case T_CPPCOMMENT:
0561 seen_newline = true;
0562 ++iter_ctx->emitted_lines;
0563 break;
0564
0565 #if BOOST_WAVE_SUPPORT_CPP0X != 0
0566 case T_RAWSTRINGLIT:
0567 iter_ctx->emitted_lines +=
0568 context_policies::util::rawstring_count_newlines(act_token);
0569 break;
0570 #endif
0571
0572 case T_CCOMMENT:
0573 iter_ctx->emitted_lines +=
0574 context_policies::util::ccomment_count_newlines(act_token);
0575 break;
0576
0577 case T_PP_NUMBER:
0578 {
0579 token_sequence_type rescanned;
0580
0581 std::string pp_number(
0582 util::to_string<std::string>(act_token.get_value()));
0583
0584 lexer_type it = lexer_type(pp_number.begin(),
0585 pp_number.end(), act_token.get_position(),
0586 ctx.get_language());
0587 lexer_type end = lexer_type();
0588
0589 for (; it != end && T_EOF != token_id(*it); ++it)
0590 rescanned.push_back(*it);
0591
0592 pending_queue.splice(pending_queue.begin(), rescanned);
0593 act_token = pending_queue.front();
0594 id = token_id(act_token);
0595 pending_queue.pop_front();
0596 }
0597 break;
0598
0599 case T_EOF:
0600 seen_newline = true;
0601 break;
0602
0603 default:
0604 if (IS_CATEGORY(id, WhiteSpaceTokenType))
0605 seen_newline = was_seen_newline;
0606 break;
0607 }
0608
0609 if (token_is_valid(act_token) && whitespace.must_insert(id, act_token.get_value())) {
0610
0611
0612 whitespace.shift_tokens(T_SPACE);
0613 pending_queue.push_front(act_token);
0614 return act_token = result_type(T_SPACE,
0615 typename result_type::string_type(" "),
0616 act_token.get_position());
0617 }
0618 whitespace.shift_tokens(id);
0619 return ctx.get_hooks().generated_token(ctx.derived(), act_token);
0620 }
0621
0622
0623 template <typename ContextT>
0624 inline typename pp_iterator_functor<ContextT>::result_type const &
0625 pp_iterator_functor<ContextT>::get_next_token()
0626 {
0627 using namespace boost::wave;
0628
0629
0630
0631 if (!pending_queue.empty() || !unput_queue.empty())
0632 return pp_token();
0633
0634
0635
0636 bool returned_from_include_file = returned_from_include();
0637
0638
0639 if (iter_ctx->first != iter_ctx->last) {
0640 do {
0641
0642
0643
0644 if (!pending_queue.empty()) {
0645 util::on_exit::pop_front<token_sequence_type>
0646 pop_front_token(pending_queue);
0647
0648 return act_token = pending_queue.front();
0649 }
0650
0651
0652 bool was_seen_newline = seen_newline || returned_from_include_file;
0653
0654
0655 act_token = *iter_ctx->first;
0656 act_pos = act_token.get_position();
0657
0658
0659 token_id id = token_id(act_token);
0660
0661 if (T_EOF == id) {
0662
0663 whitespace.shift_tokens(T_EOF);
0664 ++iter_ctx->first;
0665
0666
0667 if ((!seen_newline || act_pos.get_column() > 1) &&
0668 !need_single_line(ctx.get_language()))
0669 {
0670 if (need_no_newline_at_end_of_file(ctx.get_language()))
0671 {
0672 seen_newline = true;
0673 pending_queue.push_back(
0674 result_type(T_NEWLINE, "\n", act_pos)
0675 );
0676 }
0677 else
0678 {
0679
0680 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
0681 last_line_not_terminated, "", act_pos);
0682 }
0683 }
0684 continue;
0685 }
0686 else if (T_NEWLINE == id || T_CPPCOMMENT == id) {
0687
0688
0689 seen_newline = true;
0690 ++iter_ctx->first;
0691
0692 if (!ctx.get_if_block_status()) {
0693
0694 whitespace.shift_tokens(id);
0695 util::impl::call_skipped_token_hook(ctx, act_token);
0696 continue;
0697 }
0698 return act_token;
0699 }
0700 seen_newline = false;
0701
0702 if (was_seen_newline && pp_directive()) {
0703
0704
0705
0706
0707 if (iter_ctx->first == iter_ctx->last)
0708 {
0709 seen_newline = true;
0710 act_token = result_type(T_NEWLINE, "\n", act_pos);
0711 }
0712
0713
0714
0715
0716 }
0717 else if (ctx.get_if_block_status()) {
0718
0719
0720 return pp_token();
0721 }
0722 else {
0723
0724
0725
0726 if (T_NEWLINE == token_id(act_token)) {
0727 seen_newline = true;
0728 must_emit_line_directive = true;
0729 }
0730
0731
0732 util::impl::call_skipped_token_hook(ctx, act_token);
0733 ++iter_ctx->first;
0734 }
0735
0736 } while ((iter_ctx->first != iter_ctx->last) ||
0737 (returned_from_include_file = returned_from_include()));
0738
0739
0740 if (ctx.get_if_block_depth() > 0 && !need_single_line(ctx.get_language()))
0741 {
0742
0743 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
0744 missing_matching_endif, "", act_pos);
0745 }
0746 }
0747 else {
0748 act_token = eof;
0749 }
0750
0751
0752 return act_token;
0753 }
0754
0755
0756
0757
0758
0759
0760 template <typename ContextT>
0761 inline bool
0762 pp_iterator_functor<ContextT>::emit_line_directive()
0763 {
0764 using namespace boost::wave;
0765
0766 typename ContextT::position_type pos = act_token.get_position();
0767
0768
0769
0770
0771
0772
0773
0774
0775
0776 if (must_emit_line_directive ||
0777 iter_ctx->emitted_lines+1 != act_pos.get_line())
0778 {
0779
0780 pending_queue.push_front(act_token);
0781 pos.set_line(act_pos.get_line());
0782
0783 if (iter_ctx->emitted_lines+2 == act_pos.get_line() && act_pos.get_line() != 1) {
0784
0785
0786 act_token = result_type(T_NEWLINE, "\n", pos);
0787 }
0788 else {
0789
0790 act_pos.set_line(act_pos.get_line()-1);
0791 iter_ctx->emitted_lines = act_pos.get_line()-1;
0792
0793 token_sequence_type pending;
0794
0795 if (!ctx.get_hooks().emit_line_directive(ctx, pending, act_token))
0796 {
0797 unsigned int column = 6;
0798
0799
0800 pos.set_column(1);
0801 pending.push_back(result_type(T_PP_LINE, "#line", pos));
0802
0803 pos.set_column(column);
0804 pending.push_back(result_type(T_SPACE, " ", pos));
0805
0806
0807
0808
0809 std::string buffer = lexical_cast<std::string>(pos.get_line());
0810
0811 pos.set_column(++column);
0812 pending.push_back(result_type(T_INTLIT, buffer.c_str(), pos));
0813 pos.set_column(column += (unsigned int)buffer.size());
0814 pending.push_back(result_type(T_SPACE, " ", pos));
0815 pos.set_column(++column);
0816
0817 std::string file("\"");
0818 boost::filesystem::path filename(
0819 wave::util::create_path(act_pos.get_file().c_str()));
0820
0821 using wave::util::impl::escape_lit;
0822 file += escape_lit(wave::util::native_file_string(filename)) + "\"";
0823
0824 pending.push_back(result_type(T_STRINGLIT, file.c_str(), pos));
0825 pos.set_column(column += (unsigned int)file.size());
0826 pending.push_back(result_type(T_GENERATEDNEWLINE, "\n", pos));
0827 }
0828
0829
0830 if (!pending.empty()) {
0831 pending_queue.splice(pending_queue.begin(), pending);
0832 act_token = pending_queue.front();
0833 pending_queue.pop_front();
0834 }
0835 }
0836
0837 must_emit_line_directive = false;
0838 return true;
0839 }
0840
0841 must_emit_line_directive = false;
0842 return false;
0843 }
0844
0845
0846
0847
0848
0849
0850 template <typename ContextT>
0851 inline typename pp_iterator_functor<ContextT>::result_type const &
0852 pp_iterator_functor<ContextT>::pp_token()
0853 {
0854 using namespace boost::wave;
0855
0856 token_id id = token_id(*iter_ctx->first);
0857
0858
0859
0860 do {
0861 if (!pending_queue.empty()) {
0862
0863 act_token = pending_queue.front();
0864 pending_queue.pop_front();
0865 act_pos = act_token.get_position();
0866 }
0867 else if (!unput_queue.empty()
0868 || T_IDENTIFIER == id
0869 || IS_CATEGORY(id, KeywordTokenType)
0870 || IS_EXTCATEGORY(id, OperatorTokenType|AltExtTokenType)
0871 || IS_CATEGORY(id, BoolLiteralTokenType))
0872 {
0873
0874
0875 act_token = ctx.expand_tokensequence(iter_ctx->first,
0876 iter_ctx->last, pending_queue, unput_queue, skipped_newline);
0877 }
0878 else {
0879
0880 act_token = *iter_ctx->first;
0881 ++iter_ctx->first;
0882 }
0883 id = token_id(act_token);
0884
0885 } while (T_PLACEHOLDER == id);
0886 return act_token;
0887 }
0888
0889
0890
0891
0892
0893
0894 namespace impl {
0895
0896
0897 template <typename ContextT>
0898 bool call_found_directive_hook(ContextT& ctx,
0899 typename ContextT::token_type const& found_directive)
0900 {
0901 if (ctx.get_hooks().found_directive(ctx.derived(), found_directive))
0902 return true;
0903 return false;
0904 }
0905
0906
0907
0908
0909
0910
0911
0912
0913
0914 template <typename ContextT, typename IteratorT>
0915 bool next_token_is_pp_directive(ContextT &ctx, IteratorT &it, IteratorT const &end)
0916 {
0917 using namespace boost::wave;
0918
0919 token_id id = T_UNKNOWN;
0920 for (; it != end; ++it) {
0921 id = token_id(*it);
0922 if (!IS_CATEGORY(id, WhiteSpaceTokenType))
0923 break;
0924 if (IS_CATEGORY(id, EOLTokenType) || IS_CATEGORY(id, EOFTokenType))
0925 break;
0926 if (T_CPPCOMMENT == id ||
0927 context_policies::util::ccomment_has_newline(*it))
0928 {
0929 break;
0930 }
0931
0932
0933 util::impl::call_skipped_token_hook(ctx, *it);
0934 }
0935 BOOST_ASSERT(it == end || id != T_UNKNOWN);
0936 return it != end && IS_CATEGORY(id, PPTokenType);
0937 }
0938
0939
0940 template <typename ContextT, typename IteratorT>
0941 bool pp_is_last_on_line(ContextT &ctx, IteratorT &it, IteratorT const &end,
0942 bool call_hook = true)
0943 {
0944 using namespace boost::wave;
0945
0946
0947 if (call_hook)
0948 util::impl::call_skipped_token_hook(ctx, *it);
0949
0950 for (++it; it != end; ++it) {
0951 token_id id = token_id(*it);
0952
0953 if (T_CPPCOMMENT == id || T_NEWLINE == id ||
0954 context_policies::util::ccomment_has_newline(*it))
0955 {
0956 if (call_hook)
0957 util::impl::call_skipped_token_hook(ctx, *it);
0958 ++it;
0959 return true;
0960 }
0961
0962 if (!IS_CATEGORY(id, WhiteSpaceTokenType))
0963 break;
0964
0965
0966 if (call_hook)
0967 util::impl::call_skipped_token_hook(ctx, *it);
0968 }
0969 return need_no_newline_at_end_of_file(ctx.get_language()) &&
0970 ((it == end) || (T_EOF == token_id(*it)));
0971 }
0972
0973
0974 template <typename ContextT, typename IteratorT>
0975 bool skip_to_eol(ContextT &ctx, IteratorT &it, IteratorT const &end,
0976 bool call_hook = true)
0977 {
0978 using namespace boost::wave;
0979
0980 for (; it != end; ++it) {
0981 token_id id = token_id(*it);
0982
0983 if (T_CPPCOMMENT == id || T_NEWLINE == id ||
0984 context_policies::util::ccomment_has_newline(*it))
0985 {
0986
0987 util::impl::call_skipped_token_hook(ctx, *it);
0988 ++it;
0989 return true;
0990 }
0991
0992 if (call_hook)
0993 util::impl::call_skipped_token_hook(ctx, *it);
0994 }
0995 return false;
0996 }
0997
0998
0999 template <typename ContextT, typename ContainerT>
1000 inline void
1001 remove_leading_whitespace(ContextT &ctx, ContainerT& c, bool call_hook = true)
1002 {
1003 typename ContainerT::iterator it = c.begin();
1004 while (IS_CATEGORY(*it, WhiteSpaceTokenType)) {
1005 typename ContainerT::iterator save = it++;
1006 if (call_hook)
1007 util::impl::call_skipped_token_hook(ctx, *save);
1008 c.erase(save);
1009 }
1010 }
1011 }
1012
1013
1014 template <typename ContextT>
1015 template <typename IteratorT>
1016 inline bool
1017 pp_iterator_functor<ContextT>::extract_identifier(IteratorT &it)
1018 {
1019 token_id id = util::impl::skip_whitespace(it, iter_ctx->last);
1020 if (T_IDENTIFIER == id || IS_CATEGORY(id, KeywordTokenType) ||
1021 IS_EXTCATEGORY(id, OperatorTokenType|AltExtTokenType) ||
1022 IS_CATEGORY(id, BoolLiteralTokenType))
1023 {
1024 IteratorT save = it;
1025 if (impl::pp_is_last_on_line(ctx, save, iter_ctx->last, false))
1026 return true;
1027 }
1028
1029
1030 impl::skip_to_eol(ctx, it, iter_ctx->last);
1031
1032 string_type str(util::impl::as_string<string_type>(iter_ctx->first, it));
1033
1034 seen_newline = true;
1035 iter_ctx->first = it;
1036 on_illformed(str);
1037 return false;
1038 }
1039
1040
1041 template <typename ContextT>
1042 template <typename IteratorT>
1043 inline bool
1044 pp_iterator_functor<ContextT>::ensure_is_last_on_line(IteratorT& it, bool call_hook)
1045 {
1046 if (!impl::pp_is_last_on_line(ctx, it, iter_ctx->last, call_hook))
1047 {
1048
1049 impl::skip_to_eol(ctx, it, iter_ctx->last);
1050
1051 string_type str(util::impl::as_string<string_type>(iter_ctx->first, it));
1052
1053 seen_newline = true;
1054 iter_ctx->first = it;
1055
1056
1057 on_illformed(str);
1058 return false;
1059 }
1060
1061 if (it == iter_ctx->last && !need_single_line(ctx.get_language()))
1062 {
1063
1064 seen_newline = true;
1065 iter_ctx->first = it;
1066
1067 if (!need_no_newline_at_end_of_file(ctx.get_language()))
1068 {
1069
1070
1071 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1072 last_line_not_terminated, "", act_pos);
1073 }
1074
1075 return false;
1076 }
1077 return true;
1078 }
1079
1080 template <typename ContextT>
1081 template <typename IteratorT>
1082 inline bool
1083 pp_iterator_functor<ContextT>::skip_to_eol_with_check(IteratorT &it, bool call_hook)
1084 {
1085 typename ContextT::string_type value ((*it).get_value());
1086 if (!impl::skip_to_eol(ctx, it, iter_ctx->last, call_hook) &&
1087 !need_single_line(ctx.get_language()))
1088 {
1089
1090 seen_newline = true;
1091 iter_ctx->first = it;
1092
1093 if (!need_no_newline_at_end_of_file(ctx.get_language()))
1094 {
1095
1096
1097 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1098 last_line_not_terminated, "", act_pos);
1099 }
1100 return false;
1101 }
1102
1103
1104 seen_newline = true;
1105 iter_ctx->first = it;
1106 return true;
1107 }
1108
1109
1110
1111 template <typename ContextT>
1112 template <typename IteratorT>
1113 inline bool
1114 pp_iterator_functor<ContextT>::handle_pp_directive(IteratorT &it)
1115 {
1116 token_id id = token_id(*it);
1117 bool can_exit = true;
1118 bool call_hook_in_skip = true;
1119 if (!ctx.get_if_block_status()) {
1120 if (IS_EXTCATEGORY(*it, PPConditionalTokenType)) {
1121
1122 switch (id) {
1123 case T_PP_IFDEF:
1124 case T_PP_IFNDEF:
1125 case T_PP_IF:
1126 ctx.enter_if_block(false);
1127 break;
1128
1129 case T_PP_ELIF:
1130 if (!ctx.get_enclosing_if_block_status()) {
1131 if (!ctx.enter_elif_block(false)) {
1132
1133 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1134 missing_matching_if, "#elif", act_pos);
1135 return true;
1136 }
1137 }
1138 else {
1139 can_exit = false;
1140 }
1141 break;
1142
1143 case T_PP_ELSE:
1144 case T_PP_ENDIF:
1145 {
1146
1147 if (T_PP_ELSE == token_id(*it))
1148 on_else();
1149 else
1150 on_endif();
1151
1152
1153
1154 ensure_is_last_on_line(it);
1155
1156
1157 seen_newline = true;
1158 iter_ctx->first = it;
1159 }
1160 if (T_PP_ENDIF == id)
1161 must_emit_line_directive = true;
1162 return true;
1163
1164 default:
1165 on_illformed((*it).get_value());
1166 break;
1167 }
1168 }
1169 else {
1170 util::impl::call_skipped_token_hook(ctx, *it);
1171 ++it;
1172 }
1173 }
1174 else {
1175
1176 result_type directive = *it;
1177 bool include_next = false;
1178 switch (id) {
1179 case T_PP_QHEADER:
1180 #if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0
1181 case T_PP_QHEADER_NEXT:
1182 #endif
1183 include_next = (T_PP_QHEADER_NEXT == id) ? true : false;
1184 if (!impl::call_found_directive_hook(ctx, *it))
1185 {
1186 string_type dir((*it).get_value());
1187
1188
1189
1190 if (ensure_is_last_on_line(it))
1191 {
1192 seen_newline = true;
1193 iter_ctx->first = it;
1194 on_include (dir, false, include_next);
1195 }
1196 return true;
1197 }
1198 break;
1199
1200 case T_PP_HHEADER:
1201 #if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0
1202 case T_PP_HHEADER_NEXT:
1203 #endif
1204 include_next = (T_PP_HHEADER_NEXT == id) ? true : false;
1205 if (!impl::call_found_directive_hook(ctx, *it))
1206 {
1207 string_type dir((*it).get_value());
1208
1209
1210
1211 if (ensure_is_last_on_line(it))
1212 {
1213 seen_newline = true;
1214 iter_ctx->first = it;
1215 on_include (dir, true, include_next);
1216 }
1217 return true;
1218 }
1219 break;
1220
1221 case T_PP_ELSE:
1222 case T_PP_ENDIF:
1223 if (!impl::call_found_directive_hook(ctx, *it))
1224 {
1225
1226 if (T_PP_ELSE == token_id(*it))
1227 on_else();
1228 else
1229 on_endif();
1230
1231
1232
1233 ensure_is_last_on_line(it);
1234
1235
1236 seen_newline = true;
1237 iter_ctx->first = it;
1238 if (T_PP_ENDIF == id)
1239 must_emit_line_directive = true;
1240 return true;
1241 }
1242 break;
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254 case T_PP_UNDEF:
1255 if (!impl::call_found_directive_hook(ctx, *it) &&
1256 extract_identifier(it))
1257 {
1258 on_undefine(it);
1259 }
1260 call_hook_in_skip = false;
1261 break;
1262
1263 #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0
1264
1265
1266
1267
1268
1269 #endif
1270
1271 default:
1272 can_exit = false;
1273 break;
1274 }
1275 }
1276
1277
1278 if (can_exit) {
1279 skip_to_eol_with_check(it, call_hook_in_skip);
1280 return true;
1281 }
1282 return false;
1283 }
1284
1285
1286
1287 template <typename ContextT>
1288 inline bool
1289 pp_iterator_functor<ContextT>::pp_directive()
1290 {
1291 using namespace cpplexer;
1292
1293
1294 lexer_type it = iter_ctx->first;
1295
1296 if (!impl::next_token_is_pp_directive(ctx, it, iter_ctx->last)) {
1297
1298 if (it != iter_ctx->last && T_POUND == BASE_TOKEN(token_id(*it))) {
1299 if (impl::pp_is_last_on_line(ctx, it, iter_ctx->last)) {
1300
1301 seen_newline = true;
1302 iter_ctx->first = it;
1303 return true;
1304 }
1305 else if (ctx.get_if_block_status()) {
1306
1307 impl::skip_to_eol(ctx, it, iter_ctx->last);
1308 seen_newline = true;
1309
1310 string_type str(boost::wave::util::impl::as_string<string_type>(
1311 iter_ctx->first, it));
1312
1313 token_sequence_type faulty_line;
1314
1315 for (; iter_ctx->first != it; ++iter_ctx->first)
1316 faulty_line.push_back(*iter_ctx->first);
1317
1318 token_sequence_type pending;
1319 if (ctx.get_hooks().found_unknown_directive(ctx, faulty_line, pending))
1320 {
1321
1322 if (!pending.empty())
1323 pending_queue.splice(pending_queue.begin(), pending);
1324 return true;
1325 }
1326
1327
1328 on_illformed(str);
1329 }
1330 }
1331
1332
1333 return false;
1334 }
1335
1336
1337 if (it == iter_ctx->last)
1338 return false;
1339
1340
1341
1342 if (handle_pp_directive(it)) {
1343
1344
1345 return true;
1346 }
1347
1348
1349 bool found_eof = false;
1350 result_type found_directive;
1351 token_sequence_type found_eoltokens;
1352
1353 tree_parse_info_type hit = cpp_grammar_type::parse_cpp_grammar(
1354 it, iter_ctx->last, act_pos, found_eof, found_directive, found_eoltokens);
1355
1356 if (hit.match) {
1357
1358
1359 iter_ctx->first = hit.stop;
1360 seen_newline = true;
1361 must_emit_line_directive = true;
1362
1363
1364
1365 bool result = dispatch_directive(hit, found_directive, found_eoltokens);
1366
1367 if (found_eof && !need_single_line(ctx.get_language()) &&
1368 !need_no_newline_at_end_of_file(ctx.get_language()))
1369 {
1370
1371
1372
1373 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1374 last_line_not_terminated, "", act_pos);
1375 }
1376 return result;
1377 }
1378 else if (token_id(found_directive) != T_EOF) {
1379
1380 impl::skip_to_eol(ctx, it, iter_ctx->last);
1381 seen_newline = true;
1382
1383 string_type str(boost::wave::util::impl::as_string<string_type>(
1384 iter_ctx->first, it));
1385 iter_ctx->first = it;
1386
1387
1388 on_illformed(str);
1389 }
1390 return false;
1391 }
1392
1393
1394
1395
1396
1397
1398 template <typename ContextT>
1399 inline bool
1400 pp_iterator_functor<ContextT>::dispatch_directive(
1401 tree_parse_info_type const &hit, result_type const& found_directive,
1402 token_sequence_type const& found_eoltokens)
1403 {
1404 using namespace cpplexer;
1405
1406 typedef typename parse_tree_type::const_iterator const_child_iterator_t;
1407
1408
1409 const_child_iterator_t begin = hit.trees.begin();
1410
1411
1412 parse_tree_type const& root = (*begin).children;
1413 parse_node_value_type const& nodeval = get_first_leaf(*root.begin()).value;
1414
1415
1416 const_child_iterator_t begin_child_it = (*root.begin()).children.begin();
1417 const_child_iterator_t end_child_it = (*root.begin()).children.end();
1418
1419 token_id id = token_id(found_directive);
1420
1421
1422 if (impl::call_found_directive_hook(ctx, found_directive))
1423 return true;
1424
1425 switch (id) {
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442 case T_PP_INCLUDE:
1443 #if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0
1444 case T_PP_INCLUDE_NEXT:
1445 #endif
1446 on_include (begin_child_it, end_child_it, T_PP_INCLUDE_NEXT == id);
1447 break;
1448
1449 case T_PP_DEFINE:
1450 on_define (*begin);
1451 break;
1452
1453
1454
1455
1456
1457 case T_PP_IFDEF:
1458 on_ifdef(found_directive, begin_child_it, end_child_it);
1459 break;
1460
1461 case T_PP_IFNDEF:
1462 on_ifndef(found_directive, begin_child_it, end_child_it);
1463 break;
1464
1465 case T_PP_IF:
1466 on_if(found_directive, begin_child_it, end_child_it);
1467 break;
1468
1469 case T_PP_ELIF:
1470 on_elif(found_directive, begin_child_it, end_child_it);
1471 break;
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481 case T_PP_LINE:
1482 on_line(begin_child_it, end_child_it);
1483 break;
1484
1485 case T_PP_ERROR:
1486 on_error(begin_child_it, end_child_it);
1487 break;
1488
1489 #if BOOST_WAVE_SUPPORT_WARNING_DIRECTIVE != 0
1490 case T_PP_WARNING:
1491 on_warning(begin_child_it, end_child_it);
1492 break;
1493 #endif
1494
1495 case T_PP_PRAGMA:
1496 return on_pragma(begin_child_it, end_child_it);
1497
1498 #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0
1499 case T_MSEXT_PP_REGION:
1500 case T_MSEXT_PP_ENDREGION:
1501 break;
1502 #endif
1503
1504 default:
1505 on_illformed((*nodeval.begin()).get_value());
1506
1507
1508
1509 {
1510 token_sequence_type expanded;
1511 get_token_value<result_type, parse_node_type> get_value;
1512
1513 std::copy(make_ref_transform_iterator(begin_child_it, get_value),
1514 make_ref_transform_iterator(end_child_it, get_value),
1515 std::inserter(expanded, expanded.end()));
1516 pending_queue.splice(pending_queue.begin(), expanded);
1517 }
1518 break;
1519 }
1520
1521
1522 typename token_sequence_type::const_iterator eol = found_eoltokens.begin();
1523 impl::skip_to_eol(ctx, eol, found_eoltokens.end());
1524 return true;
1525 }
1526
1527
1528
1529
1530
1531
1532 template <typename ContextT>
1533 inline void
1534 pp_iterator_functor<ContextT>::on_include (string_type const &s,
1535 bool is_system, bool include_next)
1536 {
1537 BOOST_ASSERT(ctx.get_if_block_status());
1538
1539
1540 typename string_type::size_type pos_end = s.find_last_of(is_system ? '>' : '\"');
1541
1542 if (string_type::npos == pos_end) {
1543 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_include_statement,
1544 s.c_str(), act_pos);
1545 return;
1546 }
1547
1548 typename string_type::size_type pos_begin =
1549 s.find_last_of(is_system ? '<' : '\"', pos_end-1);
1550
1551 if (string_type::npos == pos_begin) {
1552 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_include_statement,
1553 s.c_str(), act_pos);
1554 return;
1555 }
1556
1557 std::string file_token(s.substr(pos_begin, pos_end - pos_begin + 1).c_str());
1558 std::string file_path(s.substr(pos_begin + 1, pos_end - pos_begin - 1).c_str());
1559
1560
1561 on_include_helper(file_token.c_str(), file_path.c_str(), is_system,
1562 include_next);
1563 }
1564
1565 template <typename ContextT>
1566 inline bool
1567 pp_iterator_functor<ContextT>::on_include_helper(char const* f, char const* s,
1568 bool is_system, bool include_next)
1569 {
1570 namespace fs = boost::filesystem;
1571
1572
1573 std::string file_path(s);
1574 std::string dir_path;
1575 #if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0
1576 char const* current_name = include_next ? iter_ctx->real_filename.c_str() : 0;
1577 #else
1578 char const* current_name = 0;
1579 #endif
1580
1581
1582 if (ctx.get_hooks().found_include_directive(ctx.derived(), f, include_next))
1583 return true;
1584
1585 file_path = util::impl::unescape_lit(file_path);
1586 std::string native_path_str;
1587
1588 if (!ctx.get_hooks().locate_include_file(ctx, file_path, is_system,
1589 current_name, dir_path, native_path_str))
1590 {
1591 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_include_file,
1592 file_path.c_str(), act_pos);
1593 return false;
1594 }
1595
1596
1597 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
1598 if (!ctx.has_pragma_once(native_path_str))
1599 #endif
1600 {
1601
1602 ctx.set_current_directory(native_path_str.c_str());
1603
1604
1605 boost::shared_ptr<base_iteration_context_type> new_iter_ctx(
1606 new iteration_context_type(ctx, native_path_str.c_str(), act_pos,
1607 boost::wave::enable_prefer_pp_numbers(ctx.get_language()),
1608 is_system ? base_iteration_context_type::system_header :
1609 base_iteration_context_type::user_header));
1610 new_iter_ctx->emitted_lines = (unsigned int)(-1);
1611
1612
1613 ctx.get_hooks().opened_include_file(ctx.derived(), dir_path, file_path,
1614 is_system);
1615
1616
1617 iter_ctx->real_relative_filename = ctx.get_current_relative_filename().c_str();
1618 iter_ctx->filename = act_pos.get_file();
1619 iter_ctx->line = act_pos.get_line();
1620 iter_ctx->if_block_depth = ctx.get_if_block_depth();
1621 iter_ctx->emitted_lines = (unsigned int)(-1);
1622
1623
1624 ctx.push_iteration_context(act_pos, iter_ctx);
1625 iter_ctx = new_iter_ctx;
1626 seen_newline = true;
1627 must_emit_line_directive = true;
1628
1629 act_pos.set_file(iter_ctx->filename);
1630 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
1631 fs::path rfp(wave::util::create_path(iter_ctx->real_filename.c_str()));
1632 std::string real_filename(rfp.string());
1633 ctx.set_current_filename(real_filename.c_str());
1634 #endif
1635
1636 ctx.set_current_relative_filename(dir_path.c_str());
1637 iter_ctx->real_relative_filename = dir_path.c_str();
1638
1639 act_pos.set_line(iter_ctx->line);
1640 act_pos.set_column(0);
1641 }
1642 return true;
1643 }
1644
1645
1646
1647
1648
1649
1650
1651 template <typename ContextT>
1652 inline void
1653 pp_iterator_functor<ContextT>::on_include(
1654 typename parse_tree_type::const_iterator const &begin,
1655 typename parse_tree_type::const_iterator const &end, bool include_next)
1656 {
1657 BOOST_ASSERT(ctx.get_if_block_status());
1658
1659
1660 get_token_value<result_type, parse_node_type> get_value;
1661 token_sequence_type expanded;
1662 token_sequence_type toexpand;
1663
1664 std::copy(make_ref_transform_iterator(begin, get_value),
1665 make_ref_transform_iterator(end, get_value),
1666 std::inserter(toexpand, toexpand.end()));
1667
1668 typename token_sequence_type::iterator begin2 = toexpand.begin();
1669
1670 ctx.expand_whole_tokensequence(begin2, toexpand.end(), expanded,
1671 false, false);
1672
1673
1674 using namespace boost::wave::util::impl;
1675 string_type s (trim_whitespace(as_string(expanded)));
1676 bool is_system = '<' == s[0] && '>' == s[s.size()-1];
1677
1678 if (!is_system && !('\"' == s[0] && '\"' == s[s.size()-1])) {
1679
1680 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_include_statement,
1681 s.c_str(), act_pos);
1682 return;
1683 }
1684 on_include(s, is_system, include_next);
1685 }
1686
1687
1688
1689
1690
1691
1692
1693 template <typename ContextT>
1694 inline void
1695 pp_iterator_functor<ContextT>::on_define (parse_node_type const &node)
1696 {
1697 BOOST_ASSERT(ctx.get_if_block_status());
1698
1699
1700 result_type macroname;
1701 std::vector<result_type> macroparameters;
1702 token_sequence_type macrodefinition;
1703 bool has_parameters = false;
1704 position_type pos(act_token.get_position());
1705
1706 if (!boost::wave::util::retrieve_macroname(ctx, node,
1707 BOOST_WAVE_PLAIN_DEFINE_ID, macroname, pos, false))
1708 return;
1709 has_parameters = boost::wave::util::retrieve_macrodefinition(node,
1710 BOOST_WAVE_MACRO_PARAMETERS_ID, macroparameters, pos, false);
1711 boost::wave::util::retrieve_macrodefinition(node,
1712 BOOST_WAVE_MACRO_DEFINITION_ID, macrodefinition, pos, false);
1713
1714 if (has_parameters) {
1715 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1716 if (boost::wave::need_variadics(ctx.get_language())) {
1717
1718
1719 using namespace cpplexer;
1720 typedef typename std::vector<result_type>::iterator
1721 parameter_iterator_t;
1722
1723 bool seen_ellipses = false;
1724 parameter_iterator_t end = macroparameters.end();
1725 for (parameter_iterator_t pit = macroparameters.begin();
1726 pit != end; ++pit)
1727 {
1728 if (seen_ellipses) {
1729
1730 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1731 bad_define_statement, macroname.get_value().c_str(),
1732 (*pit).get_position());
1733 return;
1734 }
1735 if (T_ELLIPSIS == token_id(*pit))
1736 seen_ellipses = true;
1737
1738
1739 if ("__VA_ARGS__" == (*pit).get_value()) {
1740 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1741 bad_define_statement_va_args,
1742 macroname.get_value().c_str(), (*pit).get_position());
1743 return;
1744 }
1745
1746 #if BOOST_WAVE_SUPPORT_VA_OPT != 0
1747
1748 if (boost::wave::need_va_opt(ctx.get_language()) &&
1749 ("__VA_OPT__" == (*pit).get_value())) {
1750 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1751 bad_define_statement_va_opt,
1752 macroname.get_value().c_str(), (*pit).get_position());
1753 return;
1754 }
1755 #endif
1756 }
1757
1758
1759
1760 if (!seen_ellipses) {
1761 typedef typename token_sequence_type::iterator definition_iterator_t;
1762
1763 bool seen_va_args = false;
1764 #if BOOST_WAVE_SUPPORT_VA_OPT != 0
1765 bool seen_va_opt = false;
1766 #endif
1767 definition_iterator_t pend = macrodefinition.end();
1768 for (definition_iterator_t dit = macrodefinition.begin();
1769 dit != pend; ++dit)
1770 {
1771 if (T_IDENTIFIER == token_id(*dit) &&
1772 "__VA_ARGS__" == (*dit).get_value())
1773 {
1774 seen_va_args = true;
1775 }
1776 #if BOOST_WAVE_SUPPORT_VA_OPT != 0
1777 if (T_IDENTIFIER == token_id(*dit) &&
1778 "__VA_OPT__" == (*dit).get_value())
1779 {
1780 seen_va_opt = true;
1781 }
1782 #endif
1783 }
1784 if (seen_va_args) {
1785
1786 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1787 bad_define_statement_va_args,
1788 macroname.get_value().c_str(), act_token.get_position());
1789 return;
1790 }
1791 #if BOOST_WAVE_SUPPORT_VA_OPT != 0
1792 if (seen_va_opt) {
1793 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1794 bad_define_statement_va_opt,
1795 macroname.get_value().c_str(), act_token.get_position());
1796 return;
1797 }
1798 #endif
1799 }
1800 }
1801 else
1802 #endif
1803 {
1804
1805 using namespace cpplexer;
1806 typedef typename std::vector<result_type>::iterator
1807 parameter_iterator_t;
1808
1809 parameter_iterator_t end = macroparameters.end();
1810 for (parameter_iterator_t pit = macroparameters.begin();
1811 pit != end; ++pit)
1812 {
1813 if (T_ELLIPSIS == token_id(*pit)) {
1814
1815 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1816 bad_define_statement, macroname.get_value().c_str(),
1817 (*pit).get_position());
1818 return;
1819 }
1820 }
1821 }
1822 }
1823
1824
1825 ctx.add_macro_definition(macroname, has_parameters, macroparameters,
1826 macrodefinition);
1827 }
1828
1829
1830
1831
1832
1833
1834 template <typename ContextT>
1835 inline void
1836 pp_iterator_functor<ContextT>::on_undefine (lexer_type const &it)
1837 {
1838 BOOST_ASSERT(ctx.get_if_block_status());
1839
1840
1841 ctx.remove_macro_definition((*it).get_value());
1842 }
1843
1844
1845
1846
1847
1848
1849 template <typename ContextT>
1850 inline void
1851 pp_iterator_functor<ContextT>::on_ifdef(
1852 result_type const& found_directive,
1853 typename parse_tree_type::const_iterator const &begin,
1854 typename parse_tree_type::const_iterator const &end)
1855 {
1856 get_token_value<result_type, parse_node_type> get_value;
1857 token_sequence_type toexpand;
1858
1859 std::copy(make_ref_transform_iterator((*begin).children.begin(), get_value),
1860 make_ref_transform_iterator((*begin).children.end(), get_value),
1861 std::inserter(toexpand, toexpand.end()));
1862
1863 bool is_defined = false;
1864
1865 do {
1866 is_defined = ctx.is_defined_macro(toexpand.begin(), toexpand.end());
1867 } while (ctx.get_hooks().evaluated_conditional_expression(ctx.derived(),
1868 found_directive, toexpand, is_defined));
1869 ctx.enter_if_block(is_defined);
1870 }
1871
1872
1873
1874
1875
1876
1877 template <typename ContextT>
1878 inline void
1879 pp_iterator_functor<ContextT>::on_ifndef(
1880 result_type const& found_directive,
1881 typename parse_tree_type::const_iterator const &begin,
1882 typename parse_tree_type::const_iterator const &end)
1883 {
1884 get_token_value<result_type, parse_node_type> get_value;
1885 token_sequence_type toexpand;
1886
1887 std::copy(make_ref_transform_iterator((*begin).children.begin(), get_value),
1888 make_ref_transform_iterator((*begin).children.end(), get_value),
1889 std::inserter(toexpand, toexpand.end()));
1890
1891 bool is_defined = false;
1892
1893 do {
1894 is_defined = ctx.is_defined_macro(toexpand.begin(), toexpand.end());
1895 } while (ctx.get_hooks().evaluated_conditional_expression(ctx.derived(),
1896 found_directive, toexpand, is_defined));
1897 ctx.enter_if_block(!is_defined);
1898 }
1899
1900
1901
1902
1903
1904
1905 template <typename ContextT>
1906 inline void
1907 pp_iterator_functor<ContextT>::on_else()
1908 {
1909 if (!ctx.enter_else_block()) {
1910
1911 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, missing_matching_if,
1912 "#else", act_pos);
1913 }
1914 }
1915
1916
1917
1918
1919
1920
1921 template <typename ContextT>
1922 inline void
1923 pp_iterator_functor<ContextT>::on_endif()
1924 {
1925 if (!ctx.exit_if_block()) {
1926
1927 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, missing_matching_if,
1928 "#endif", act_pos);
1929 }
1930 }
1931
1932
1933
1934 template <typename ContextT>
1935 inline void
1936 pp_iterator_functor<ContextT>::replace_undefined_identifiers(
1937 token_sequence_type &expanded)
1938 {
1939 typename token_sequence_type::iterator exp_end = expanded.end();
1940 for (typename token_sequence_type::iterator exp_it = expanded.begin();
1941 exp_it != exp_end; ++exp_it)
1942 {
1943 using namespace boost::wave;
1944
1945 token_id id = token_id(*exp_it);
1946 if (IS_CATEGORY(id, IdentifierTokenType) ||
1947 IS_CATEGORY(id, KeywordTokenType))
1948 {
1949 (*exp_it).set_token_id(T_INTLIT);
1950 (*exp_it).set_value("0");
1951 }
1952 }
1953 }
1954
1955
1956
1957
1958
1959
1960 template <typename ContextT>
1961 inline void
1962 pp_iterator_functor<ContextT>::on_if(
1963 result_type const& found_directive,
1964 typename parse_tree_type::const_iterator const &begin,
1965 typename parse_tree_type::const_iterator const &end)
1966 {
1967
1968 get_token_value<result_type, parse_node_type> get_value;
1969 token_sequence_type toexpand;
1970
1971 std::copy(make_ref_transform_iterator(begin, get_value),
1972 make_ref_transform_iterator(end, get_value),
1973 std::inserter(toexpand, toexpand.end()));
1974
1975 impl::remove_leading_whitespace(ctx, toexpand);
1976
1977 bool if_status = false;
1978 grammars::value_error status = grammars::error_noerror;
1979 token_sequence_type expanded;
1980
1981 do {
1982 expanded.clear();
1983
1984 typename token_sequence_type::iterator begin2 = toexpand.begin();
1985 ctx.expand_whole_tokensequence(begin2, toexpand.end(), expanded);
1986
1987
1988 replace_undefined_identifiers(expanded);
1989
1990 #if BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS != 0
1991 {
1992 string_type outstr(boost::wave::util::impl::as_string(toexpand));
1993 outstr += "(" + boost::wave::util::impl::as_string(expanded) + ")";
1994 BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS_OUT << "#if " << outstr
1995 << std::endl;
1996 }
1997 #endif
1998 try {
1999
2000 if_status = grammars::expression_grammar_gen<result_type>::
2001 evaluate(expanded.begin(), expanded.end(), act_pos,
2002 ctx.get_if_block_status(), status);
2003 }
2004 catch (boost::wave::preprocess_exception const& e) {
2005
2006 ctx.get_hooks().throw_exception(ctx.derived(), e);
2007 break;
2008 }
2009
2010 } while (ctx.get_hooks().evaluated_conditional_expression(ctx.derived(),
2011 found_directive, toexpand, if_status)
2012 && status == grammars::error_noerror);
2013
2014 ctx.enter_if_block(if_status);
2015 if (grammars::error_noerror != status) {
2016
2017 string_type expression = util::impl::as_string(expanded);
2018 if (0 == expression.size())
2019 expression = "<empty expression>";
2020
2021 if (grammars::error_division_by_zero & status) {
2022 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, division_by_zero,
2023 expression.c_str(), act_pos);
2024 }
2025 else if (grammars::error_integer_overflow & status) {
2026 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, integer_overflow,
2027 expression.c_str(), act_pos);
2028 }
2029 else if (grammars::error_character_overflow & status) {
2030 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
2031 character_literal_out_of_range, expression.c_str(), act_pos);
2032 }
2033 }
2034 }
2035
2036
2037
2038
2039
2040
2041 template <typename ContextT>
2042 inline void
2043 pp_iterator_functor<ContextT>::on_elif(
2044 result_type const& found_directive,
2045 typename parse_tree_type::const_iterator const &begin,
2046 typename parse_tree_type::const_iterator const &end)
2047 {
2048
2049 get_token_value<result_type, parse_node_type> get_value;
2050 token_sequence_type toexpand;
2051
2052 std::copy(make_ref_transform_iterator(begin, get_value),
2053 make_ref_transform_iterator(end, get_value),
2054 std::inserter(toexpand, toexpand.end()));
2055
2056 impl::remove_leading_whitespace(ctx, toexpand);
2057
2058
2059 if (ctx.get_if_block_some_part_status()) {
2060 if (!ctx.enter_elif_block(false)) {
2061
2062 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
2063 missing_matching_if, "#elif", act_pos);
2064
2065 }
2066
2067
2068 typename token_sequence_type::iterator begin2 = toexpand.begin();
2069
2070 impl::skip_to_eol(ctx, begin2, toexpand.end());
2071 return;
2072 }
2073
2074
2075 bool if_status = false;
2076 grammars::value_error status = grammars::error_noerror;
2077 token_sequence_type expanded;
2078
2079 do {
2080 expanded.clear();
2081
2082 typename token_sequence_type::iterator begin2 = toexpand.begin();
2083 ctx.expand_whole_tokensequence(begin2, toexpand.end(), expanded);
2084
2085
2086 replace_undefined_identifiers(expanded);
2087
2088 #if BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS != 0
2089 {
2090 string_type outstr(boost::wave::util::impl::as_string(toexpand));
2091 outstr += "(" + boost::wave::util::impl::as_string(expanded) + ")";
2092 BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS_OUT << "#elif " << outstr << std::endl;
2093 }
2094 #endif
2095
2096 try {
2097
2098 if_status = grammars::expression_grammar_gen<result_type>::
2099 evaluate(expanded.begin(), expanded.end(), act_pos,
2100 ctx.get_if_block_status(), status);
2101 }
2102 catch (boost::wave::preprocess_exception const& e) {
2103
2104 ctx.get_hooks().throw_exception(ctx.derived(), e);
2105 }
2106
2107 } while (ctx.get_hooks().evaluated_conditional_expression(ctx.derived(),
2108 found_directive, toexpand, if_status)
2109 && status == grammars::error_noerror);
2110
2111 if (!ctx.enter_elif_block(if_status)) {
2112
2113 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, missing_matching_if,
2114 "#elif", act_pos);
2115 return;
2116 }
2117
2118 if (grammars::error_noerror != status) {
2119
2120 string_type expression = util::impl::as_string(expanded);
2121 if (0 == expression.size())
2122 expression = "<empty expression>";
2123
2124 if (grammars::error_division_by_zero & status) {
2125 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, division_by_zero,
2126 expression.c_str(), act_pos);
2127 }
2128 else if (grammars::error_integer_overflow & status) {
2129 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
2130 integer_overflow, expression.c_str(), act_pos);
2131 }
2132 else if (grammars::error_character_overflow & status) {
2133 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
2134 character_literal_out_of_range, expression.c_str(), act_pos);
2135 }
2136 }
2137 }
2138
2139
2140
2141
2142
2143
2144 template <typename ContextT>
2145 inline void
2146 pp_iterator_functor<ContextT>::on_illformed(
2147 typename result_type::string_type s)
2148 {
2149 BOOST_ASSERT(ctx.get_if_block_status());
2150
2151
2152 typename string_type::size_type p = s.find_last_not_of('\n');
2153 if (string_type::npos != p)
2154 s = s.substr(0, p+1);
2155
2156
2157 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_directive,
2158 s.c_str(), act_pos);
2159 }
2160
2161
2162
2163
2164
2165
2166
2167 namespace impl {
2168
2169 template <typename IteratorT, typename StringT>
2170 bool retrieve_line_info (IteratorT first, IteratorT const &last,
2171 unsigned int &line, StringT &file,
2172 boost::wave::preprocess_exception::error_code& error)
2173 {
2174 using namespace boost::wave;
2175 token_id id = token_id(*first);
2176 if (T_PP_NUMBER == id || T_INTLIT == id) {
2177
2178 using namespace std;
2179 line = (unsigned int)atoi((*first).get_value().c_str());
2180 if (0 == line)
2181 error = preprocess_exception::bad_line_number;
2182
2183
2184 using namespace boost::spirit::classic;
2185 if (!parse((*first).get_value().c_str(), int_p).full)
2186 error = preprocess_exception::bad_line_number;
2187
2188
2189 while (++first != last && IS_CATEGORY(*first, WhiteSpaceTokenType))
2190 ;
2191
2192 if (first != last) {
2193 if (T_STRINGLIT != token_id(*first)) {
2194 error = preprocess_exception::bad_line_filename;
2195 return false;
2196 }
2197
2198 StringT const& file_lit = (*first).get_value();
2199
2200 if ('L' == file_lit[0]) {
2201 error = preprocess_exception::bad_line_filename;
2202 return false;
2203 }
2204
2205 file = file_lit.substr(1, file_lit.size()-2);
2206
2207
2208 while (++first != last && IS_CATEGORY(*first, WhiteSpaceTokenType))
2209 ;
2210 }
2211 return first == last;
2212 }
2213 error = preprocess_exception::bad_line_statement;
2214 return false;
2215 }
2216 }
2217
2218 template <typename ContextT>
2219 inline void
2220 pp_iterator_functor<ContextT>::on_line(
2221 typename parse_tree_type::const_iterator const &begin,
2222 typename parse_tree_type::const_iterator const &end)
2223 {
2224 BOOST_ASSERT(ctx.get_if_block_status());
2225
2226
2227
2228
2229 token_sequence_type expanded;
2230 get_token_value<result_type, parse_node_type> get_value;
2231
2232 typedef typename ref_transform_iterator_generator<
2233 get_token_value<result_type, parse_node_type>,
2234 typename parse_tree_type::const_iterator
2235 >::type const_tree_iterator_t;
2236
2237 const_tree_iterator_t first = make_ref_transform_iterator(begin, get_value);
2238 const_tree_iterator_t last = make_ref_transform_iterator(end, get_value);
2239
2240
2241
2242 unsigned int line = 0;
2243 preprocess_exception::error_code error = preprocess_exception::no_error;
2244 string_type file_name;
2245 token_sequence_type toexpand;
2246
2247 std::copy(first, last, std::inserter(toexpand, toexpand.end()));
2248 if (!impl::retrieve_line_info(first, last, line, file_name, error)) {
2249
2250 typename token_sequence_type::iterator begin2 = toexpand.begin();
2251 ctx.expand_whole_tokensequence(begin2, toexpand.end(),
2252 expanded, false, false);
2253
2254 error = preprocess_exception::no_error;
2255 if (!impl::retrieve_line_info(expanded.begin(), expanded.end(),
2256 line, file_name, error))
2257 {
2258 typename ContextT::string_type msg(
2259 boost::wave::util::impl::as_string(expanded));
2260 BOOST_WAVE_THROW_VAR_CTX(ctx, preprocess_exception, error,
2261 msg.c_str(), act_pos);
2262 return;
2263 }
2264
2265
2266 ctx.get_hooks().found_line_directive(ctx.derived(), expanded, line,
2267 file_name.c_str());
2268 }
2269 else {
2270
2271 ctx.get_hooks().found_line_directive(ctx.derived(), toexpand, line,
2272 file_name.c_str());
2273 }
2274
2275
2276 BOOST_ASSERT(unput_queue.empty());
2277 BOOST_ASSERT(pending_queue.empty());
2278
2279
2280 must_emit_line_directive = true;
2281
2282
2283 if (error != preprocess_exception::no_error) {
2284 typename ContextT::string_type msg(
2285 boost::wave::util::impl::as_string(expanded));
2286 BOOST_WAVE_THROW_VAR_CTX(ctx, preprocess_exception, error,
2287 msg.c_str(), act_pos);
2288 return;
2289 }
2290
2291
2292 if (!file_name.empty()) {
2293 using boost::wave::util::impl::unescape_lit;
2294 act_pos.set_file(unescape_lit(file_name).c_str());
2295 }
2296 act_pos.set_line(line);
2297 if (iter_ctx->first != iter_ctx->last)
2298 {
2299 iter_ctx->first.set_position(act_pos);
2300 }
2301 }
2302
2303
2304
2305
2306
2307
2308 template <typename ContextT>
2309 inline void
2310 pp_iterator_functor<ContextT>::on_error(
2311 typename parse_tree_type::const_iterator const &begin,
2312 typename parse_tree_type::const_iterator const &end)
2313 {
2314 BOOST_ASSERT(ctx.get_if_block_status());
2315
2316
2317 token_sequence_type expanded;
2318 get_token_value<result_type, parse_node_type> get_value;
2319
2320 typename ref_transform_iterator_generator<
2321 get_token_value<result_type, parse_node_type>,
2322 typename parse_tree_type::const_iterator
2323 >::type first = make_ref_transform_iterator(begin, get_value);
2324
2325 #if BOOST_WAVE_PREPROCESS_ERROR_MESSAGE_BODY != 0
2326
2327 token_sequence_type toexpand;
2328
2329 std::copy(first, make_ref_transform_iterator(end, get_value),
2330 std::inserter(toexpand, toexpand.end()));
2331
2332 typename token_sequence_type::iterator begin2 = toexpand.begin();
2333 ctx.expand_whole_tokensequence(begin2, toexpand.end(), expanded,
2334 false, false);
2335 if (!ctx.get_hooks().found_error_directive(ctx.derived(), toexpand))
2336 #else
2337
2338
2339 std::copy(first, make_ref_transform_iterator(end, get_value),
2340 std::inserter(expanded, expanded.end()));
2341 if (!ctx.get_hooks().found_error_directive(ctx.derived(), expanded))
2342 #endif
2343 {
2344
2345 BOOST_WAVE_STRINGTYPE msg(boost::wave::util::impl::as_string(expanded));
2346 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, error_directive,
2347 msg.c_str(), act_pos);
2348 }
2349 }
2350
2351 #if BOOST_WAVE_SUPPORT_WARNING_DIRECTIVE != 0
2352
2353
2354
2355
2356
2357 template <typename ContextT>
2358 inline void
2359 pp_iterator_functor<ContextT>::on_warning(
2360 typename parse_tree_type::const_iterator const &begin,
2361 typename parse_tree_type::const_iterator const &end)
2362 {
2363 BOOST_ASSERT(ctx.get_if_block_status());
2364
2365
2366 token_sequence_type expanded;
2367 get_token_value<result_type, parse_node_type> get_value;
2368
2369 typename ref_transform_iterator_generator<
2370 get_token_value<result_type, parse_node_type>,
2371 typename parse_tree_type::const_iterator
2372 >::type first = make_ref_transform_iterator(begin, get_value);
2373
2374 #if BOOST_WAVE_PREPROCESS_ERROR_MESSAGE_BODY != 0
2375
2376 token_sequence_type toexpand;
2377
2378 std::copy(first, make_ref_transform_iterator(end, get_value),
2379 std::inserter(toexpand, toexpand.end()));
2380
2381 typename token_sequence_type::iterator begin2 = toexpand.begin();
2382 ctx.expand_whole_tokensequence(begin2, toexpand.end(), expanded,
2383 false, false);
2384 if (!ctx.get_hooks().found_warning_directive(ctx.derived(), toexpand))
2385 #else
2386
2387
2388 std::copy(first, make_ref_transform_iterator(end, get_value),
2389 std::inserter(expanded, expanded.end()));
2390 if (!ctx.get_hooks().found_warning_directive(ctx.derived(), expanded))
2391 #endif
2392 {
2393
2394 BOOST_WAVE_STRINGTYPE msg(boost::wave::util::impl::as_string(expanded));
2395 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, warning_directive,
2396 msg.c_str(), act_pos);
2397 }
2398 }
2399 #endif
2400
2401
2402
2403
2404
2405
2406 template <typename ContextT>
2407 inline bool
2408 pp_iterator_functor<ContextT>::on_pragma(
2409 typename parse_tree_type::const_iterator const &begin,
2410 typename parse_tree_type::const_iterator const &end)
2411 {
2412 using namespace boost::wave;
2413
2414 BOOST_ASSERT(ctx.get_if_block_status());
2415
2416
2417
2418
2419 token_sequence_type expanded;
2420 get_token_value<result_type, parse_node_type> get_value;
2421
2422 typedef typename ref_transform_iterator_generator<
2423 get_token_value<result_type, parse_node_type>,
2424 typename parse_tree_type::const_iterator
2425 >::type const_tree_iterator_t;
2426
2427 const_tree_iterator_t first = make_ref_transform_iterator(begin, get_value);
2428 const_tree_iterator_t last = make_ref_transform_iterator(end, get_value);
2429
2430 expanded.push_back(result_type(T_PP_PRAGMA, "#pragma", act_token.get_position()));
2431
2432 while (first != last && IS_CATEGORY(*first, WhiteSpaceTokenType))
2433 expanded.push_back(*first++);
2434
2435 if (first != last) {
2436 if (T_IDENTIFIER == token_id(*first) &&
2437 boost::wave::need_c99(ctx.get_language()) &&
2438 (*first).get_value() == "STDC")
2439 {
2440
2441 std::copy(first, last, std::inserter(expanded, expanded.end()));
2442 }
2443 else {
2444 #if BOOST_WAVE_PREPROCESS_PRAGMA_BODY != 0
2445
2446 token_sequence_type toexpand;
2447
2448 std::copy(first, last, std::inserter(toexpand, toexpand.end()));
2449
2450 typename token_sequence_type::iterator begin2 = toexpand.begin();
2451 ctx.expand_whole_tokensequence(begin2, toexpand.end(),
2452 expanded, false, false);
2453 #else
2454
2455 std::copy(first, last, std::inserter(expanded, expanded.end()));
2456 #endif
2457 }
2458 }
2459 expanded.push_back(result_type(T_NEWLINE, "\n", act_token.get_position()));
2460
2461
2462 BOOST_ASSERT(unput_queue.empty());
2463 BOOST_ASSERT(pending_queue.empty());
2464
2465
2466 token_sequence_type pending;
2467 if (interpret_pragma(expanded, pending)) {
2468
2469 if (!pending.empty())
2470 pending_queue.splice(pending_queue.begin(), pending);
2471 return true;
2472 }
2473
2474 #if BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES != 0
2475
2476
2477 if (boost::wave::need_emit_pragma_directives(ctx.get_language())) {
2478 pending_queue.splice(pending_queue.begin(), expanded);
2479 return false;
2480 }
2481 #endif
2482 return true;
2483 }
2484
2485 template <typename ContextT>
2486 inline bool
2487 pp_iterator_functor<ContextT>::interpret_pragma(
2488 token_sequence_type const &pragma_body, token_sequence_type &result)
2489 {
2490 using namespace cpplexer;
2491
2492 typename token_sequence_type::const_iterator end = pragma_body.end();
2493 typename token_sequence_type::const_iterator it = pragma_body.begin();
2494 for (++it; it != end && IS_CATEGORY(*it, WhiteSpaceTokenType); ++it)
2495 ;
2496
2497 if (it == end)
2498 return false;
2499
2500 return boost::wave::util::interpret_pragma(
2501 ctx.derived(), act_token, it, end, result);
2502 }
2503
2504
2505 }
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516 template <typename ContextT>
2517 class pp_iterator
2518 : public boost::spirit::classic::multi_pass<
2519 boost::wave::impl::pp_iterator_functor<ContextT>,
2520 boost::wave::util::functor_input
2521 >
2522 {
2523 public:
2524 typedef boost::wave::impl::pp_iterator_functor<ContextT> input_policy_type;
2525
2526 private:
2527 typedef
2528 boost::spirit::classic::multi_pass<input_policy_type, boost::wave::util::functor_input>
2529 base_type;
2530 typedef pp_iterator<ContextT> self_type;
2531 typedef boost::wave::util::functor_input functor_input_type;
2532
2533 public:
2534 pp_iterator()
2535 {}
2536
2537 template <typename IteratorT>
2538 pp_iterator(ContextT &ctx, IteratorT const &first, IteratorT const &last,
2539 typename ContextT::position_type const &pos)
2540 : base_type(input_policy_type(ctx, first, last, pos))
2541 {}
2542
2543 bool force_include(char const *path_, bool is_last)
2544 {
2545 bool result = this->get_functor().on_include_helper(path_, path_,
2546 false, false);
2547 if (is_last) {
2548 this->functor_input_type::
2549 template inner<input_policy_type>::advance_input();
2550 }
2551 return result;
2552 }
2553 };
2554
2555
2556 }
2557 }
2558
2559
2560 #ifdef BOOST_HAS_ABI_HEADERS
2561 #include BOOST_ABI_SUFFIX
2562 #endif
2563
2564 #endif