File indexing completed on 2025-01-18 09:53:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #if !defined(BOOST_CPP_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
1611
1612 ctx.get_hooks().opened_include_file(ctx.derived(), dir_path, file_path,
1613 is_system);
1614
1615
1616 iter_ctx->real_relative_filename = ctx.get_current_relative_filename().c_str();
1617 iter_ctx->filename = act_pos.get_file();
1618 iter_ctx->line = act_pos.get_line();
1619 iter_ctx->if_block_depth = ctx.get_if_block_depth();
1620 iter_ctx->emitted_lines = (unsigned int)(-1);
1621
1622
1623 ctx.push_iteration_context(act_pos, iter_ctx);
1624 iter_ctx = new_iter_ctx;
1625 seen_newline = true;
1626 must_emit_line_directive = true;
1627
1628 act_pos.set_file(iter_ctx->filename);
1629 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
1630 fs::path rfp(wave::util::create_path(iter_ctx->real_filename.c_str()));
1631 std::string real_filename(rfp.string());
1632 ctx.set_current_filename(real_filename.c_str());
1633 #endif
1634
1635 ctx.set_current_relative_filename(dir_path.c_str());
1636 iter_ctx->real_relative_filename = dir_path.c_str();
1637
1638 act_pos.set_line(iter_ctx->line);
1639 act_pos.set_column(0);
1640 }
1641 return true;
1642 }
1643
1644
1645
1646
1647
1648
1649
1650 template <typename ContextT>
1651 inline void
1652 pp_iterator_functor<ContextT>::on_include(
1653 typename parse_tree_type::const_iterator const &begin,
1654 typename parse_tree_type::const_iterator const &end, bool include_next)
1655 {
1656 BOOST_ASSERT(ctx.get_if_block_status());
1657
1658
1659 get_token_value<result_type, parse_node_type> get_value;
1660 token_sequence_type expanded;
1661 token_sequence_type toexpand;
1662
1663 std::copy(make_ref_transform_iterator(begin, get_value),
1664 make_ref_transform_iterator(end, get_value),
1665 std::inserter(toexpand, toexpand.end()));
1666
1667 typename token_sequence_type::iterator begin2 = toexpand.begin();
1668
1669 ctx.expand_whole_tokensequence(begin2, toexpand.end(), expanded,
1670 false, false);
1671
1672
1673 using namespace boost::wave::util::impl;
1674 string_type s (trim_whitespace(as_string(expanded)));
1675 bool is_system = '<' == s[0] && '>' == s[s.size()-1];
1676
1677 if (!is_system && !('\"' == s[0] && '\"' == s[s.size()-1])) {
1678
1679 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_include_statement,
1680 s.c_str(), act_pos);
1681 return;
1682 }
1683 on_include(s, is_system, include_next);
1684 }
1685
1686
1687
1688
1689
1690
1691
1692 template <typename ContextT>
1693 inline void
1694 pp_iterator_functor<ContextT>::on_define (parse_node_type const &node)
1695 {
1696 BOOST_ASSERT(ctx.get_if_block_status());
1697
1698
1699 result_type macroname;
1700 std::vector<result_type> macroparameters;
1701 token_sequence_type macrodefinition;
1702 bool has_parameters = false;
1703 position_type pos(act_token.get_position());
1704
1705 if (!boost::wave::util::retrieve_macroname(ctx, node,
1706 BOOST_WAVE_PLAIN_DEFINE_ID, macroname, pos, false))
1707 return;
1708 has_parameters = boost::wave::util::retrieve_macrodefinition(node,
1709 BOOST_WAVE_MACRO_PARAMETERS_ID, macroparameters, pos, false);
1710 boost::wave::util::retrieve_macrodefinition(node,
1711 BOOST_WAVE_MACRO_DEFINITION_ID, macrodefinition, pos, false);
1712
1713 if (has_parameters) {
1714 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
1715 if (boost::wave::need_variadics(ctx.get_language())) {
1716
1717
1718 using namespace cpplexer;
1719 typedef typename std::vector<result_type>::iterator
1720 parameter_iterator_t;
1721
1722 bool seen_ellipses = false;
1723 parameter_iterator_t end = macroparameters.end();
1724 for (parameter_iterator_t pit = macroparameters.begin();
1725 pit != end; ++pit)
1726 {
1727 if (seen_ellipses) {
1728
1729 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1730 bad_define_statement, macroname.get_value().c_str(),
1731 (*pit).get_position());
1732 return;
1733 }
1734 if (T_ELLIPSIS == token_id(*pit))
1735 seen_ellipses = true;
1736
1737
1738 if ("__VA_ARGS__" == (*pit).get_value()) {
1739 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1740 bad_define_statement_va_args,
1741 macroname.get_value().c_str(), (*pit).get_position());
1742 return;
1743 }
1744
1745 #if BOOST_WAVE_SUPPORT_VA_OPT != 0
1746
1747 if (boost::wave::need_va_opt(ctx.get_language()) &&
1748 ("__VA_OPT__" == (*pit).get_value())) {
1749 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1750 bad_define_statement_va_opt,
1751 macroname.get_value().c_str(), (*pit).get_position());
1752 return;
1753 }
1754 #endif
1755 }
1756
1757
1758
1759 if (!seen_ellipses) {
1760 typedef typename token_sequence_type::iterator definition_iterator_t;
1761
1762 bool seen_va_args = false;
1763 #if BOOST_WAVE_SUPPORT_VA_OPT != 0
1764 bool seen_va_opt = false;
1765 #endif
1766 definition_iterator_t pend = macrodefinition.end();
1767 for (definition_iterator_t dit = macrodefinition.begin();
1768 dit != pend; ++dit)
1769 {
1770 if (T_IDENTIFIER == token_id(*dit) &&
1771 "__VA_ARGS__" == (*dit).get_value())
1772 {
1773 seen_va_args = true;
1774 }
1775 #if BOOST_WAVE_SUPPORT_VA_OPT != 0
1776 if (T_IDENTIFIER == token_id(*dit) &&
1777 "__VA_OPT__" == (*dit).get_value())
1778 {
1779 seen_va_opt = true;
1780 }
1781 #endif
1782 }
1783 if (seen_va_args) {
1784
1785 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1786 bad_define_statement_va_args,
1787 macroname.get_value().c_str(), act_token.get_position());
1788 return;
1789 }
1790 #if BOOST_WAVE_SUPPORT_VA_OPT != 0
1791 if (seen_va_opt) {
1792 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1793 bad_define_statement_va_opt,
1794 macroname.get_value().c_str(), act_token.get_position());
1795 return;
1796 }
1797 #endif
1798 }
1799 }
1800 else
1801 #endif
1802 {
1803
1804 using namespace cpplexer;
1805 typedef typename std::vector<result_type>::iterator
1806 parameter_iterator_t;
1807
1808 parameter_iterator_t end = macroparameters.end();
1809 for (parameter_iterator_t pit = macroparameters.begin();
1810 pit != end; ++pit)
1811 {
1812 if (T_ELLIPSIS == token_id(*pit)) {
1813
1814 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
1815 bad_define_statement, macroname.get_value().c_str(),
1816 (*pit).get_position());
1817 return;
1818 }
1819 }
1820 }
1821 }
1822
1823
1824 ctx.add_macro_definition(macroname, has_parameters, macroparameters,
1825 macrodefinition);
1826 }
1827
1828
1829
1830
1831
1832
1833 template <typename ContextT>
1834 inline void
1835 pp_iterator_functor<ContextT>::on_undefine (lexer_type const &it)
1836 {
1837 BOOST_ASSERT(ctx.get_if_block_status());
1838
1839
1840 ctx.remove_macro_definition((*it).get_value());
1841 }
1842
1843
1844
1845
1846
1847
1848 template <typename ContextT>
1849 inline void
1850 pp_iterator_functor<ContextT>::on_ifdef(
1851 result_type const& found_directive,
1852 typename parse_tree_type::const_iterator const &begin,
1853 typename parse_tree_type::const_iterator const &end)
1854 {
1855 get_token_value<result_type, parse_node_type> get_value;
1856 token_sequence_type toexpand;
1857
1858 std::copy(make_ref_transform_iterator((*begin).children.begin(), get_value),
1859 make_ref_transform_iterator((*begin).children.end(), get_value),
1860 std::inserter(toexpand, toexpand.end()));
1861
1862 bool is_defined = false;
1863
1864 do {
1865 is_defined = ctx.is_defined_macro(toexpand.begin(), toexpand.end());
1866 } while (ctx.get_hooks().evaluated_conditional_expression(ctx.derived(),
1867 found_directive, toexpand, is_defined));
1868 ctx.enter_if_block(is_defined);
1869 }
1870
1871
1872
1873
1874
1875
1876 template <typename ContextT>
1877 inline void
1878 pp_iterator_functor<ContextT>::on_ifndef(
1879 result_type const& found_directive,
1880 typename parse_tree_type::const_iterator const &begin,
1881 typename parse_tree_type::const_iterator const &end)
1882 {
1883 get_token_value<result_type, parse_node_type> get_value;
1884 token_sequence_type toexpand;
1885
1886 std::copy(make_ref_transform_iterator((*begin).children.begin(), get_value),
1887 make_ref_transform_iterator((*begin).children.end(), get_value),
1888 std::inserter(toexpand, toexpand.end()));
1889
1890 bool is_defined = false;
1891
1892 do {
1893 is_defined = ctx.is_defined_macro(toexpand.begin(), toexpand.end());
1894 } while (ctx.get_hooks().evaluated_conditional_expression(ctx.derived(),
1895 found_directive, toexpand, is_defined));
1896 ctx.enter_if_block(!is_defined);
1897 }
1898
1899
1900
1901
1902
1903
1904 template <typename ContextT>
1905 inline void
1906 pp_iterator_functor<ContextT>::on_else()
1907 {
1908 if (!ctx.enter_else_block()) {
1909
1910 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, missing_matching_if,
1911 "#else", act_pos);
1912 }
1913 }
1914
1915
1916
1917
1918
1919
1920 template <typename ContextT>
1921 inline void
1922 pp_iterator_functor<ContextT>::on_endif()
1923 {
1924 if (!ctx.exit_if_block()) {
1925
1926 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, missing_matching_if,
1927 "#endif", act_pos);
1928 }
1929 }
1930
1931
1932
1933 template <typename ContextT>
1934 inline void
1935 pp_iterator_functor<ContextT>::replace_undefined_identifiers(
1936 token_sequence_type &expanded)
1937 {
1938 typename token_sequence_type::iterator exp_end = expanded.end();
1939 for (typename token_sequence_type::iterator exp_it = expanded.begin();
1940 exp_it != exp_end; ++exp_it)
1941 {
1942 using namespace boost::wave;
1943
1944 token_id id = token_id(*exp_it);
1945 if (IS_CATEGORY(id, IdentifierTokenType) ||
1946 IS_CATEGORY(id, KeywordTokenType))
1947 {
1948 (*exp_it).set_token_id(T_INTLIT);
1949 (*exp_it).set_value("0");
1950 }
1951 }
1952 }
1953
1954
1955
1956
1957
1958
1959 template <typename ContextT>
1960 inline void
1961 pp_iterator_functor<ContextT>::on_if(
1962 result_type const& found_directive,
1963 typename parse_tree_type::const_iterator const &begin,
1964 typename parse_tree_type::const_iterator const &end)
1965 {
1966
1967 get_token_value<result_type, parse_node_type> get_value;
1968 token_sequence_type toexpand;
1969
1970 std::copy(make_ref_transform_iterator(begin, get_value),
1971 make_ref_transform_iterator(end, get_value),
1972 std::inserter(toexpand, toexpand.end()));
1973
1974 impl::remove_leading_whitespace(ctx, toexpand);
1975
1976 bool if_status = false;
1977 grammars::value_error status = grammars::error_noerror;
1978 token_sequence_type expanded;
1979
1980 do {
1981 expanded.clear();
1982
1983 typename token_sequence_type::iterator begin2 = toexpand.begin();
1984 ctx.expand_whole_tokensequence(begin2, toexpand.end(), expanded);
1985
1986
1987 replace_undefined_identifiers(expanded);
1988
1989 #if BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS != 0
1990 {
1991 string_type outstr(boost::wave::util::impl::as_string(toexpand));
1992 outstr += "(" + boost::wave::util::impl::as_string(expanded) + ")";
1993 BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS_OUT << "#if " << outstr
1994 << std::endl;
1995 }
1996 #endif
1997 try {
1998
1999 if_status = grammars::expression_grammar_gen<result_type>::
2000 evaluate(expanded.begin(), expanded.end(), act_pos,
2001 ctx.get_if_block_status(), status);
2002 }
2003 catch (boost::wave::preprocess_exception const& e) {
2004
2005 ctx.get_hooks().throw_exception(ctx.derived(), e);
2006 break;
2007 }
2008
2009 } while (ctx.get_hooks().evaluated_conditional_expression(ctx.derived(),
2010 found_directive, toexpand, if_status)
2011 && status == grammars::error_noerror);
2012
2013 ctx.enter_if_block(if_status);
2014 if (grammars::error_noerror != status) {
2015
2016 string_type expression = util::impl::as_string(expanded);
2017 if (0 == expression.size())
2018 expression = "<empty expression>";
2019
2020 if (grammars::error_division_by_zero & status) {
2021 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, division_by_zero,
2022 expression.c_str(), act_pos);
2023 }
2024 else if (grammars::error_integer_overflow & status) {
2025 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, integer_overflow,
2026 expression.c_str(), act_pos);
2027 }
2028 else if (grammars::error_character_overflow & status) {
2029 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
2030 character_literal_out_of_range, expression.c_str(), act_pos);
2031 }
2032 }
2033 }
2034
2035
2036
2037
2038
2039
2040 template <typename ContextT>
2041 inline void
2042 pp_iterator_functor<ContextT>::on_elif(
2043 result_type const& found_directive,
2044 typename parse_tree_type::const_iterator const &begin,
2045 typename parse_tree_type::const_iterator const &end)
2046 {
2047
2048 get_token_value<result_type, parse_node_type> get_value;
2049 token_sequence_type toexpand;
2050
2051 std::copy(make_ref_transform_iterator(begin, get_value),
2052 make_ref_transform_iterator(end, get_value),
2053 std::inserter(toexpand, toexpand.end()));
2054
2055 impl::remove_leading_whitespace(ctx, toexpand);
2056
2057
2058 if (ctx.get_if_block_some_part_status()) {
2059 if (!ctx.enter_elif_block(false)) {
2060
2061 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
2062 missing_matching_if, "#elif", act_pos);
2063
2064 }
2065
2066
2067 typename token_sequence_type::iterator begin2 = toexpand.begin();
2068
2069 impl::skip_to_eol(ctx, begin2, toexpand.end());
2070 return;
2071 }
2072
2073
2074 bool if_status = false;
2075 grammars::value_error status = grammars::error_noerror;
2076 token_sequence_type expanded;
2077
2078 do {
2079 expanded.clear();
2080
2081 typename token_sequence_type::iterator begin2 = toexpand.begin();
2082 ctx.expand_whole_tokensequence(begin2, toexpand.end(), expanded);
2083
2084
2085 replace_undefined_identifiers(expanded);
2086
2087 #if BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS != 0
2088 {
2089 string_type outstr(boost::wave::util::impl::as_string(toexpand));
2090 outstr += "(" + boost::wave::util::impl::as_string(expanded) + ")";
2091 BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS_OUT << "#elif " << outstr << std::endl;
2092 }
2093 #endif
2094
2095 try {
2096
2097 if_status = grammars::expression_grammar_gen<result_type>::
2098 evaluate(expanded.begin(), expanded.end(), act_pos,
2099 ctx.get_if_block_status(), status);
2100 }
2101 catch (boost::wave::preprocess_exception const& e) {
2102
2103 ctx.get_hooks().throw_exception(ctx.derived(), e);
2104 }
2105
2106 } while (ctx.get_hooks().evaluated_conditional_expression(ctx.derived(),
2107 found_directive, toexpand, if_status)
2108 && status == grammars::error_noerror);
2109
2110 if (!ctx.enter_elif_block(if_status)) {
2111
2112 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, missing_matching_if,
2113 "#elif", act_pos);
2114 return;
2115 }
2116
2117 if (grammars::error_noerror != status) {
2118
2119 string_type expression = util::impl::as_string(expanded);
2120 if (0 == expression.size())
2121 expression = "<empty expression>";
2122
2123 if (grammars::error_division_by_zero & status) {
2124 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, division_by_zero,
2125 expression.c_str(), act_pos);
2126 }
2127 else if (grammars::error_integer_overflow & status) {
2128 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
2129 integer_overflow, expression.c_str(), act_pos);
2130 }
2131 else if (grammars::error_character_overflow & status) {
2132 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
2133 character_literal_out_of_range, expression.c_str(), act_pos);
2134 }
2135 }
2136 }
2137
2138
2139
2140
2141
2142
2143 template <typename ContextT>
2144 inline void
2145 pp_iterator_functor<ContextT>::on_illformed(
2146 typename result_type::string_type s)
2147 {
2148 BOOST_ASSERT(ctx.get_if_block_status());
2149
2150
2151 typename string_type::size_type p = s.find_last_not_of('\n');
2152 if (string_type::npos != p)
2153 s = s.substr(0, p+1);
2154
2155
2156 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_directive,
2157 s.c_str(), act_pos);
2158 }
2159
2160
2161
2162
2163
2164
2165
2166 namespace impl {
2167
2168 template <typename IteratorT, typename StringT>
2169 bool retrieve_line_info (IteratorT first, IteratorT const &last,
2170 unsigned int &line, StringT &file,
2171 boost::wave::preprocess_exception::error_code& error)
2172 {
2173 using namespace boost::wave;
2174 token_id id = token_id(*first);
2175 if (T_PP_NUMBER == id || T_INTLIT == id) {
2176
2177 using namespace std;
2178 line = (unsigned int)atoi((*first).get_value().c_str());
2179 if (0 == line)
2180 error = preprocess_exception::bad_line_number;
2181
2182
2183 using namespace boost::spirit::classic;
2184 if (!parse((*first).get_value().c_str(), int_p).full)
2185 error = preprocess_exception::bad_line_number;
2186
2187
2188 while (++first != last && IS_CATEGORY(*first, WhiteSpaceTokenType))
2189 ;
2190
2191 if (first != last) {
2192 if (T_STRINGLIT != token_id(*first)) {
2193 error = preprocess_exception::bad_line_filename;
2194 return false;
2195 }
2196
2197 StringT const& file_lit = (*first).get_value();
2198
2199 if ('L' == file_lit[0]) {
2200 error = preprocess_exception::bad_line_filename;
2201 return false;
2202 }
2203
2204 file = file_lit.substr(1, file_lit.size()-2);
2205
2206
2207 while (++first != last && IS_CATEGORY(*first, WhiteSpaceTokenType))
2208 ;
2209 }
2210 return first == last;
2211 }
2212 error = preprocess_exception::bad_line_statement;
2213 return false;
2214 }
2215 }
2216
2217 template <typename ContextT>
2218 inline void
2219 pp_iterator_functor<ContextT>::on_line(
2220 typename parse_tree_type::const_iterator const &begin,
2221 typename parse_tree_type::const_iterator const &end)
2222 {
2223 BOOST_ASSERT(ctx.get_if_block_status());
2224
2225
2226
2227
2228 token_sequence_type expanded;
2229 get_token_value<result_type, parse_node_type> get_value;
2230
2231 typedef typename ref_transform_iterator_generator<
2232 get_token_value<result_type, parse_node_type>,
2233 typename parse_tree_type::const_iterator
2234 >::type const_tree_iterator_t;
2235
2236 const_tree_iterator_t first = make_ref_transform_iterator(begin, get_value);
2237 const_tree_iterator_t last = make_ref_transform_iterator(end, get_value);
2238
2239
2240
2241 unsigned int line = 0;
2242 preprocess_exception::error_code error = preprocess_exception::no_error;
2243 string_type file_name;
2244 token_sequence_type toexpand;
2245
2246 std::copy(first, last, std::inserter(toexpand, toexpand.end()));
2247 if (!impl::retrieve_line_info(first, last, line, file_name, error)) {
2248
2249 typename token_sequence_type::iterator begin2 = toexpand.begin();
2250 ctx.expand_whole_tokensequence(begin2, toexpand.end(),
2251 expanded, false, false);
2252
2253 error = preprocess_exception::no_error;
2254 if (!impl::retrieve_line_info(expanded.begin(), expanded.end(),
2255 line, file_name, error))
2256 {
2257 typename ContextT::string_type msg(
2258 boost::wave::util::impl::as_string(expanded));
2259 BOOST_WAVE_THROW_VAR_CTX(ctx, preprocess_exception, error,
2260 msg.c_str(), act_pos);
2261 return;
2262 }
2263
2264
2265 ctx.get_hooks().found_line_directive(ctx.derived(), expanded, line,
2266 file_name.c_str());
2267 }
2268 else {
2269
2270 ctx.get_hooks().found_line_directive(ctx.derived(), toexpand, line,
2271 file_name.c_str());
2272 }
2273
2274
2275 BOOST_ASSERT(unput_queue.empty());
2276 BOOST_ASSERT(pending_queue.empty());
2277
2278
2279 must_emit_line_directive = true;
2280
2281
2282 if (error != preprocess_exception::no_error) {
2283 typename ContextT::string_type msg(
2284 boost::wave::util::impl::as_string(expanded));
2285 BOOST_WAVE_THROW_VAR_CTX(ctx, preprocess_exception, error,
2286 msg.c_str(), act_pos);
2287 return;
2288 }
2289
2290
2291 if (!file_name.empty()) {
2292 using boost::wave::util::impl::unescape_lit;
2293 act_pos.set_file(unescape_lit(file_name).c_str());
2294 }
2295 act_pos.set_line(line);
2296 if (iter_ctx->first != iter_ctx->last)
2297 {
2298 iter_ctx->first.set_position(act_pos);
2299 }
2300 }
2301
2302
2303
2304
2305
2306
2307 template <typename ContextT>
2308 inline void
2309 pp_iterator_functor<ContextT>::on_error(
2310 typename parse_tree_type::const_iterator const &begin,
2311 typename parse_tree_type::const_iterator const &end)
2312 {
2313 BOOST_ASSERT(ctx.get_if_block_status());
2314
2315
2316 token_sequence_type expanded;
2317 get_token_value<result_type, parse_node_type> get_value;
2318
2319 typename ref_transform_iterator_generator<
2320 get_token_value<result_type, parse_node_type>,
2321 typename parse_tree_type::const_iterator
2322 >::type first = make_ref_transform_iterator(begin, get_value);
2323
2324 #if BOOST_WAVE_PREPROCESS_ERROR_MESSAGE_BODY != 0
2325
2326 token_sequence_type toexpand;
2327
2328 std::copy(first, make_ref_transform_iterator(end, get_value),
2329 std::inserter(toexpand, toexpand.end()));
2330
2331 typename token_sequence_type::iterator begin2 = toexpand.begin();
2332 ctx.expand_whole_tokensequence(begin2, toexpand.end(), expanded,
2333 false, false);
2334 if (!ctx.get_hooks().found_error_directive(ctx.derived(), toexpand))
2335 #else
2336
2337
2338 std::copy(first, make_ref_transform_iterator(end, get_value),
2339 std::inserter(expanded, expanded.end()));
2340 if (!ctx.get_hooks().found_error_directive(ctx.derived(), expanded))
2341 #endif
2342 {
2343
2344 BOOST_WAVE_STRINGTYPE msg(boost::wave::util::impl::as_string(expanded));
2345 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, error_directive,
2346 msg.c_str(), act_pos);
2347 }
2348 }
2349
2350 #if BOOST_WAVE_SUPPORT_WARNING_DIRECTIVE != 0
2351
2352
2353
2354
2355
2356 template <typename ContextT>
2357 inline void
2358 pp_iterator_functor<ContextT>::on_warning(
2359 typename parse_tree_type::const_iterator const &begin,
2360 typename parse_tree_type::const_iterator const &end)
2361 {
2362 BOOST_ASSERT(ctx.get_if_block_status());
2363
2364
2365 token_sequence_type expanded;
2366 get_token_value<result_type, parse_node_type> get_value;
2367
2368 typename ref_transform_iterator_generator<
2369 get_token_value<result_type, parse_node_type>,
2370 typename parse_tree_type::const_iterator
2371 >::type first = make_ref_transform_iterator(begin, get_value);
2372
2373 #if BOOST_WAVE_PREPROCESS_ERROR_MESSAGE_BODY != 0
2374
2375 token_sequence_type toexpand;
2376
2377 std::copy(first, make_ref_transform_iterator(end, get_value),
2378 std::inserter(toexpand, toexpand.end()));
2379
2380 typename token_sequence_type::iterator begin2 = toexpand.begin();
2381 ctx.expand_whole_tokensequence(begin2, toexpand.end(), expanded,
2382 false, false);
2383 if (!ctx.get_hooks().found_warning_directive(ctx.derived(), toexpand))
2384 #else
2385
2386
2387 std::copy(first, make_ref_transform_iterator(end, get_value),
2388 std::inserter(expanded, expanded.end()));
2389 if (!ctx.get_hooks().found_warning_directive(ctx.derived(), expanded))
2390 #endif
2391 {
2392
2393 BOOST_WAVE_STRINGTYPE msg(boost::wave::util::impl::as_string(expanded));
2394 BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, warning_directive,
2395 msg.c_str(), act_pos);
2396 }
2397 }
2398 #endif
2399
2400
2401
2402
2403
2404
2405 template <typename ContextT>
2406 inline bool
2407 pp_iterator_functor<ContextT>::on_pragma(
2408 typename parse_tree_type::const_iterator const &begin,
2409 typename parse_tree_type::const_iterator const &end)
2410 {
2411 using namespace boost::wave;
2412
2413 BOOST_ASSERT(ctx.get_if_block_status());
2414
2415
2416
2417
2418 token_sequence_type expanded;
2419 get_token_value<result_type, parse_node_type> get_value;
2420
2421 typedef typename ref_transform_iterator_generator<
2422 get_token_value<result_type, parse_node_type>,
2423 typename parse_tree_type::const_iterator
2424 >::type const_tree_iterator_t;
2425
2426 const_tree_iterator_t first = make_ref_transform_iterator(begin, get_value);
2427 const_tree_iterator_t last = make_ref_transform_iterator(end, get_value);
2428
2429 expanded.push_back(result_type(T_PP_PRAGMA, "#pragma", act_token.get_position()));
2430
2431 while (first != last && IS_CATEGORY(*first, WhiteSpaceTokenType))
2432 expanded.push_back(*first++);
2433
2434 if (first != last) {
2435 if (T_IDENTIFIER == token_id(*first) &&
2436 boost::wave::need_c99(ctx.get_language()) &&
2437 (*first).get_value() == "STDC")
2438 {
2439
2440 std::copy(first, last, std::inserter(expanded, expanded.end()));
2441 }
2442 else {
2443 #if BOOST_WAVE_PREPROCESS_PRAGMA_BODY != 0
2444
2445 token_sequence_type toexpand;
2446
2447 std::copy(first, last, std::inserter(toexpand, toexpand.end()));
2448
2449 typename token_sequence_type::iterator begin2 = toexpand.begin();
2450 ctx.expand_whole_tokensequence(begin2, toexpand.end(),
2451 expanded, false, false);
2452 #else
2453
2454 std::copy(first, last, std::inserter(expanded, expanded.end()));
2455 #endif
2456 }
2457 }
2458
2459
2460 BOOST_ASSERT(unput_queue.empty());
2461 BOOST_ASSERT(pending_queue.empty());
2462
2463
2464 token_sequence_type pending;
2465 if (interpret_pragma(expanded, pending)) {
2466
2467 if (!pending.empty())
2468 pending_queue.splice(pending_queue.begin(), pending);
2469 return true;
2470 }
2471
2472 #if BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES != 0
2473
2474
2475 if (boost::wave::need_emit_pragma_directives(ctx.get_language())) {
2476 pending_queue.splice(pending_queue.begin(), expanded);
2477 return false;
2478 }
2479 #endif
2480 return true;
2481 }
2482
2483 template <typename ContextT>
2484 inline bool
2485 pp_iterator_functor<ContextT>::interpret_pragma(
2486 token_sequence_type const &pragma_body, token_sequence_type &result)
2487 {
2488 using namespace cpplexer;
2489
2490 typename token_sequence_type::const_iterator end = pragma_body.end();
2491 typename token_sequence_type::const_iterator it = pragma_body.begin();
2492 for (++it; it != end && IS_CATEGORY(*it, WhiteSpaceTokenType); ++it)
2493 ;
2494
2495 if (it == end)
2496 return false;
2497
2498 return boost::wave::util::interpret_pragma(
2499 ctx.derived(), act_token, it, end, result);
2500 }
2501
2502
2503 }
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514 template <typename ContextT>
2515 class pp_iterator
2516 : public boost::spirit::classic::multi_pass<
2517 boost::wave::impl::pp_iterator_functor<ContextT>,
2518 boost::wave::util::functor_input
2519 >
2520 {
2521 public:
2522 typedef boost::wave::impl::pp_iterator_functor<ContextT> input_policy_type;
2523
2524 private:
2525 typedef
2526 boost::spirit::classic::multi_pass<input_policy_type, boost::wave::util::functor_input>
2527 base_type;
2528 typedef pp_iterator<ContextT> self_type;
2529 typedef boost::wave::util::functor_input functor_input_type;
2530
2531 public:
2532 pp_iterator()
2533 {}
2534
2535 template <typename IteratorT>
2536 pp_iterator(ContextT &ctx, IteratorT const &first, IteratorT const &last,
2537 typename ContextT::position_type const &pos)
2538 : base_type(input_policy_type(ctx, first, last, pos))
2539 {}
2540
2541 bool force_include(char const *path_, bool is_last)
2542 {
2543 bool result = this->get_functor().on_include_helper(path_, path_,
2544 false, false);
2545 if (is_last) {
2546 this->functor_input_type::
2547 template inner<input_policy_type>::advance_input();
2548 }
2549 return result;
2550 }
2551 };
2552
2553
2554 }
2555 }
2556
2557
2558 #ifdef BOOST_HAS_ABI_HEADERS
2559 #include BOOST_ABI_SUFFIX
2560 #endif
2561
2562 #endif