File indexing completed on 2025-01-18 09:53:43
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #if !defined(BOOST_CPP_CONTEXT_HPP_907485E2_6649_4A87_911B_7F7225F3E5B8_INCLUDED)
0013 #define BOOST_CPP_CONTEXT_HPP_907485E2_6649_4A87_911B_7F7225F3E5B8_INCLUDED
0014
0015 #include <string>
0016 #include <vector>
0017 #include <stack>
0018
0019 #include <boost/concept_check.hpp>
0020 #include <boost/noncopyable.hpp>
0021 #include <boost/filesystem/path.hpp>
0022 #include <boost/mpl/if.hpp>
0023 #include <boost/type_traits/is_same.hpp>
0024 #include <boost/pool/pool_alloc.hpp>
0025
0026 #include <boost/wave/wave_config.hpp>
0027 #if BOOST_WAVE_SERIALIZATION != 0
0028 #include <boost/serialization/serialization.hpp>
0029 #include <boost/wave/wave_config_constant.hpp>
0030 #endif
0031 #include <boost/wave/token_ids.hpp>
0032
0033 #include <boost/wave/util/unput_queue_iterator.hpp>
0034 #include <boost/wave/util/cpp_ifblock.hpp>
0035 #include <boost/wave/util/cpp_include_paths.hpp>
0036 #include <boost/wave/util/iteration_context.hpp>
0037 #include <boost/wave/util/cpp_iterator.hpp>
0038 #include <boost/wave/util/cpp_macromap.hpp>
0039
0040 #include <boost/wave/preprocessing_hooks.hpp>
0041 #include <boost/wave/whitespace_handling.hpp>
0042 #include <boost/wave/cpp_iteration_context.hpp>
0043 #include <boost/wave/language_support.hpp>
0044
0045
0046 #ifdef BOOST_HAS_ABI_HEADERS
0047 #include BOOST_ABI_PREFIX
0048 #endif
0049
0050
0051 namespace boost {
0052 namespace wave {
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 struct this_type {};
0083
0084 template <
0085 typename IteratorT,
0086 typename LexIteratorT,
0087 typename InputPolicyT = iteration_context_policies::load_file_to_string,
0088 typename HooksT = context_policies::eat_whitespace<typename LexIteratorT::token_type>,
0089 typename DerivedT = this_type
0090 >
0091 class context : private boost::noncopyable
0092 {
0093 private:
0094 typedef typename mpl::if_<
0095 is_same<DerivedT, this_type>, context, DerivedT
0096 >::type actual_context_type;
0097
0098 public:
0099
0100
0101 BOOST_CLASS_REQUIRE(IteratorT, boost, ForwardIteratorConcept);
0102
0103
0104 typedef typename LexIteratorT::token_type token_type;
0105 typedef typename token_type::string_type string_type;
0106
0107 typedef IteratorT target_iterator_type;
0108 typedef LexIteratorT lexer_type;
0109 typedef pp_iterator<context> iterator_type;
0110
0111 typedef InputPolicyT input_policy_type;
0112 typedef typename token_type::position_type position_type;
0113
0114
0115 typedef std::list<token_type, boost::fast_pool_allocator<token_type> >
0116 token_sequence_type;
0117
0118 typedef HooksT hook_policy_type;
0119
0120 private:
0121
0122 typedef boost::shared_ptr<base_iteration_context<context, lexer_type> >
0123 iteration_ptr_type;
0124 typedef boost::wave::util::iteration_context_stack<iteration_ptr_type>
0125 iteration_context_stack_type;
0126 typedef typename iteration_context_stack_type::size_type iter_size_type;
0127
0128 context *this_() { return this; }
0129
0130 public:
0131 context(target_iterator_type const &first_, target_iterator_type const &last_,
0132 char const *fname = "<Unknown>", HooksT const &hooks_ = HooksT())
0133 : first(first_), last(last_), filename(fname)
0134 , has_been_initialized(false)
0135 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
0136 , current_filename(fname)
0137 #endif
0138 , current_relative_filename(fname)
0139 , macros(*this_())
0140 , language(language_support(
0141 support_cpp
0142 | support_option_convert_trigraphs
0143 | support_option_emit_line_directives
0144 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
0145 | support_option_include_guard_detection
0146 #endif
0147 #if BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES != 0
0148 | support_option_emit_pragma_directives
0149 #endif
0150 | support_option_insert_whitespace
0151 ))
0152 , hooks(hooks_)
0153 {
0154 macros.init_predefined_macros(fname);
0155 }
0156
0157
0158
0159
0160
0161
0162 iterator_type begin()
0163 {
0164 std::string fname(filename);
0165 if (filename != "<Unknown>" && filename != "<stdin>") {
0166 using namespace boost::filesystem;
0167 path fpath(util::complete_path(path(filename)));
0168 fname = fpath.string();
0169 }
0170 return iterator_type(*this, first, last, position_type(fname.c_str()));
0171 }
0172 iterator_type begin(
0173 target_iterator_type const &first_,
0174 target_iterator_type const &last_)
0175 {
0176 std::string fname(filename);
0177 if (filename != "<Unknown>" && filename != "<stdin>") {
0178 using namespace boost::filesystem;
0179 path fpath(util::complete_path(path(filename)));
0180 fname = fpath.string();
0181 }
0182 return iterator_type(*this, first_, last_, position_type(fname.c_str()));
0183 }
0184 iterator_type end() const
0185 { return iterator_type(); }
0186
0187
0188 bool add_include_path(char const *path_)
0189 { return includes.add_include_path(path_, false);}
0190 bool add_sysinclude_path(char const *path_)
0191 { return includes.add_include_path(path_, true);}
0192 void set_sysinclude_delimiter() { includes.set_sys_include_delimiter(); }
0193 typename iteration_context_stack_type::size_type get_iteration_depth() const
0194 { return iter_ctxs.size(); }
0195
0196
0197 #if BOOST_WAVE_ENABLE_COMMANDLINE_MACROS != 0
0198 template <typename StringT>
0199 bool add_macro_definition(StringT macrostring, bool is_predefined = false)
0200 {
0201 return boost::wave::util::add_macro_definition(*this,
0202 util::to_string<std::string>(macrostring), is_predefined,
0203 get_language());
0204 }
0205 #endif
0206
0207 template <typename StringT>
0208 bool add_macro_definition(StringT const &name, position_type const& pos,
0209 bool has_params, std::vector<token_type> ¶meters,
0210 token_sequence_type &definition, bool is_predefined = false)
0211 {
0212 return macros.add_macro(
0213 token_type(T_IDENTIFIER, util::to_string<string_type>(name), pos),
0214 has_params, parameters, definition, is_predefined);
0215 }
0216 template <typename StringT>
0217 bool is_defined_macro(StringT const &str) const
0218 {
0219 return macros.is_defined(util::to_string<string_type>(str));
0220 }
0221 template <typename StringT>
0222 bool get_macro_definition(StringT const &name,
0223 bool &has_params, bool &is_predefined, position_type &pos,
0224 std::vector<token_type> ¶meters,
0225 token_sequence_type &definition) const
0226 {
0227 return macros.get_macro(util::to_string<string_type>(name),
0228 has_params, is_predefined, pos, parameters, definition);
0229 }
0230 template <typename StringT>
0231 bool remove_macro_definition(StringT const& undefname, bool even_predefined = false)
0232 {
0233
0234 string_type name = util::to_string<string_type>(undefname);
0235 typename string_type::size_type pos = name.find_first_not_of(" \t");
0236 if (pos != string_type::npos) {
0237 typename string_type::size_type endpos = name.find_last_not_of(" \t");
0238 name = name.substr(pos, endpos-pos+1);
0239 }
0240
0241 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
0242
0243 includes.remove_pragma_once_header(
0244 util::to_string<std::string>(name));
0245 #endif
0246 return macros.remove_macro(name, macros.get_main_pos(), even_predefined);
0247 }
0248 void reset_macro_definitions()
0249 { macros.reset_macromap(); macros.init_predefined_macros(); }
0250
0251
0252 typedef boost::wave::util::macromap<context> macromap_type;
0253 typedef typename macromap_type::name_iterator name_iterator;
0254 typedef typename macromap_type::const_name_iterator const_name_iterator;
0255
0256 name_iterator macro_names_begin() { return macros.begin(); }
0257 name_iterator macro_names_end() { return macros.end(); }
0258 const_name_iterator macro_names_begin() const { return macros.begin(); }
0259 const_name_iterator macro_names_end() const { return macros.end(); }
0260
0261
0262
0263 bool add_macro_definition(token_type const &name, bool has_params,
0264 std::vector<token_type> ¶meters, token_sequence_type &definition,
0265 bool is_predefined = false)
0266 {
0267 return macros.add_macro(name, has_params, parameters, definition,
0268 is_predefined);
0269 }
0270
0271
0272 static std::string get_version()
0273 {
0274 boost::wave::util::predefined_macros p;
0275 return util::to_string<std::string>(p.get_fullversion());
0276 }
0277 static std::string get_version_string()
0278 {
0279 boost::wave::util::predefined_macros p;
0280 return util::to_string<std::string>(p.get_versionstr());
0281 }
0282
0283
0284 void set_language(boost::wave::language_support language_,
0285 bool reset_macros = true)
0286 {
0287 language = language_;
0288 if (reset_macros)
0289 reset_macro_definitions();
0290 }
0291 boost::wave::language_support get_language() const { return language; }
0292
0293 position_type &get_main_pos() { return macros.get_main_pos(); }
0294 position_type const& get_main_pos() const { return macros.get_main_pos(); }
0295
0296
0297 void set_max_include_nesting_depth(iter_size_type new_depth)
0298 { iter_ctxs.set_max_include_nesting_depth(new_depth); }
0299 iter_size_type get_max_include_nesting_depth() const
0300 { return iter_ctxs.get_max_include_nesting_depth(); }
0301
0302
0303 hook_policy_type &get_hooks() { return hooks; }
0304 hook_policy_type const &get_hooks() const { return hooks; }
0305
0306
0307 actual_context_type& derived()
0308 { return *static_cast<actual_context_type*>(this); }
0309 actual_context_type const& derived() const
0310 { return *static_cast<actual_context_type const*>(this); }
0311
0312
0313 boost::filesystem::path get_current_directory() const
0314 { return includes.get_current_directory(); }
0315
0316 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
0317 protected:
0318 friend class boost::wave::pp_iterator<context>;
0319 friend class boost::wave::impl::pp_iterator_functor<context>;
0320 friend class boost::wave::util::macromap<context>;
0321 #endif
0322
0323
0324 void init_context()
0325 {
0326 if (!has_been_initialized) {
0327 std::string fname(filename);
0328 if (filename != "<Unknown>" && filename != "<stdin>") {
0329 using namespace boost::filesystem;
0330 path fpath(util::complete_path(path(filename)));
0331 fname = fpath.string();
0332 includes.set_current_directory(fname.c_str());
0333 }
0334 has_been_initialized = true;
0335 }
0336 }
0337
0338 template <typename IteratorT2>
0339 bool is_defined_macro(IteratorT2 const &begin, IteratorT2 const &end) const
0340 { return macros.is_defined(begin, end); }
0341
0342
0343 void set_current_directory(char const *path_)
0344 { includes.set_current_directory(path_); }
0345
0346
0347 bool get_if_block_status() const { return ifblocks.get_status(); }
0348 bool get_if_block_some_part_status() const
0349 { return ifblocks.get_some_part_status(); }
0350 bool get_enclosing_if_block_status() const
0351 { return ifblocks.get_enclosing_status(); }
0352 void enter_if_block(bool new_status)
0353 { ifblocks.enter_if_block(new_status); }
0354 bool enter_elif_block(bool new_status)
0355 { return ifblocks.enter_elif_block(new_status); }
0356 bool enter_else_block() { return ifblocks.enter_else_block(); }
0357 bool exit_if_block() { return ifblocks.exit_if_block(); }
0358 typename boost::wave::util::if_block_stack::size_type get_if_block_depth() const
0359 { return ifblocks.get_if_block_depth(); }
0360
0361
0362 iteration_ptr_type pop_iteration_context()
0363 { iteration_ptr_type top = iter_ctxs.top(); iter_ctxs.pop(); return top; }
0364 void push_iteration_context(position_type const &act_pos, iteration_ptr_type iter_ctx)
0365 { iter_ctxs.push(*this, act_pos, iter_ctx); }
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378 template <typename IteratorT2>
0379 token_type expand_tokensequence(IteratorT2 &first_, IteratorT2 const &last_,
0380 token_sequence_type &pending, token_sequence_type &expanded,
0381 bool& seen_newline, bool expand_defined = false,
0382 bool expand_has_include = false)
0383 {
0384 return macros.expand_tokensequence(first_, last_, pending, expanded,
0385 seen_newline, expand_defined, expand_has_include);
0386 }
0387
0388 template <typename IteratorT2>
0389 void expand_whole_tokensequence(IteratorT2 &first_, IteratorT2 const &last_,
0390 token_sequence_type &expanded, bool expand_defined = true,
0391 bool expand_has_include = true)
0392 {
0393 macros.expand_whole_tokensequence(
0394 expanded, first_, last_,
0395 expand_defined, expand_has_include);
0396
0397
0398 boost::wave::util::impl::remove_placeholders(expanded);
0399 }
0400
0401 public:
0402 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
0403
0404
0405 void set_current_filename(char const *real_name)
0406 { current_filename = real_name; }
0407 std::string const &get_current_filename() const
0408 { return current_filename; }
0409
0410
0411 bool has_pragma_once(std::string const &filename_)
0412 { return includes.has_pragma_once(filename_); }
0413 bool add_pragma_once_header(std::string const &filename_,
0414 std::string const& guard_name)
0415 {
0416 get_hooks().detected_include_guard(derived(), filename_, guard_name);
0417 return includes.add_pragma_once_header(filename_, guard_name);
0418 }
0419 bool add_pragma_once_header(token_type const &pragma_,
0420 std::string const &filename_)
0421 {
0422 get_hooks().detected_pragma_once(derived(), pragma_, filename_);
0423 return includes.add_pragma_once_header(filename_,
0424 "__BOOST_WAVE_PRAGMA_ONCE__");
0425 }
0426 #endif
0427
0428 void set_current_relative_filename(char const *real_name)
0429 { current_relative_filename = real_name; }
0430 std::string const &get_current_relative_filename() const
0431 { return current_relative_filename; }
0432
0433 bool find_include_file (std::string &s, std::string &d, bool is_system,
0434 char const *current_file) const
0435 { return includes.find_include_file(s, d, is_system, current_file); }
0436
0437 #if BOOST_WAVE_SERIALIZATION != 0
0438 public:
0439 BOOST_STATIC_CONSTANT(unsigned int, version = 0x10);
0440 BOOST_STATIC_CONSTANT(unsigned int, version_mask = 0x0f);
0441
0442 private:
0443 friend class boost::serialization::access;
0444 template<class Archive>
0445 void save(Archive & ar, const unsigned int version) const
0446 {
0447 using namespace boost::serialization;
0448
0449 string_type cfg(BOOST_PP_STRINGIZE(BOOST_WAVE_CONFIG));
0450 string_type kwd(BOOST_WAVE_PRAGMA_KEYWORD);
0451 string_type strtype(BOOST_PP_STRINGIZE((BOOST_WAVE_STRINGTYPE)));
0452 ar & make_nvp("config", cfg);
0453 ar & make_nvp("pragma_keyword", kwd);
0454 ar & make_nvp("string_type", strtype);
0455
0456 ar & make_nvp("language_options", language);
0457 ar & make_nvp("macro_definitions", macros);
0458 ar & make_nvp("include_settings", includes);
0459 }
0460 template<class Archive>
0461 void load(Archive & ar, const unsigned int loaded_version)
0462 {
0463 using namespace boost::serialization;
0464 if (version != (loaded_version & ~version_mask)) {
0465 BOOST_WAVE_THROW_CTX((*this), preprocess_exception,
0466 incompatible_config, "cpp_context state version",
0467 get_main_pos());
0468 return;
0469 }
0470
0471
0472 string_type config, pragma_keyword, string_type_str;
0473
0474
0475 ar & make_nvp("config", config);
0476 if (config != BOOST_PP_STRINGIZE(BOOST_WAVE_CONFIG)) {
0477 BOOST_WAVE_THROW_CTX((*this), preprocess_exception,
0478 incompatible_config, "BOOST_WAVE_CONFIG", get_main_pos());
0479 return;
0480 }
0481
0482
0483 ar & make_nvp("pragma_keyword", pragma_keyword);
0484 if (pragma_keyword != BOOST_WAVE_PRAGMA_KEYWORD) {
0485 BOOST_WAVE_THROW_CTX((*this), preprocess_exception,
0486 incompatible_config, "BOOST_WAVE_PRAGMA_KEYWORD",
0487 get_main_pos());
0488 return;
0489 }
0490
0491
0492 ar & make_nvp("string_type", string_type_str);
0493 if (string_type_str != BOOST_PP_STRINGIZE((BOOST_WAVE_STRINGTYPE))) {
0494 BOOST_WAVE_THROW_CTX((*this), preprocess_exception,
0495 incompatible_config, "BOOST_WAVE_STRINGTYPE", get_main_pos());
0496 return;
0497 }
0498
0499 try {
0500
0501 ar & make_nvp("language_options", language);
0502 ar & make_nvp("macro_definitions", macros);
0503 ar & make_nvp("include_settings", includes);
0504 }
0505 catch (boost::wave::preprocess_exception const& e) {
0506
0507 get_hooks().throw_exception(derived(), e);
0508 }
0509 }
0510 BOOST_SERIALIZATION_SPLIT_MEMBER()
0511 #endif
0512
0513 private:
0514
0515 target_iterator_type first;
0516 target_iterator_type last;
0517 std::string filename;
0518 bool has_been_initialized;
0519 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
0520 std::string current_filename;
0521 #endif
0522 std::string current_relative_filename;
0523
0524 boost::wave::util::if_block_stack ifblocks;
0525 boost::wave::util::include_paths includes;
0526 iteration_context_stack_type iter_ctxs;
0527 macromap_type macros;
0528 boost::wave::language_support language;
0529 hook_policy_type hooks;
0530 };
0531
0532
0533 }
0534 }
0535
0536 #if BOOST_WAVE_SERIALIZATION != 0
0537 namespace boost { namespace serialization {
0538
0539 template<
0540 typename Iterator, typename LexIterator,
0541 typename InputPolicy, typename Hooks
0542 >
0543 struct tracking_level<boost::wave::context<Iterator, LexIterator, InputPolicy, Hooks> >
0544 {
0545 typedef mpl::integral_c_tag tag;
0546 typedef mpl::int_<track_never> type;
0547 BOOST_STATIC_CONSTANT(
0548 int,
0549 value = tracking_level::type::value
0550 );
0551 };
0552
0553 template<
0554 typename Iterator, typename LexIterator,
0555 typename InputPolicy, typename Hooks
0556 >
0557 struct version<boost::wave::context<Iterator, LexIterator, InputPolicy, Hooks> >
0558 {
0559 typedef boost::wave::context<Iterator, LexIterator, InputPolicy, Hooks>
0560 target_type;
0561 typedef mpl::int_<target_type::version> type;
0562 typedef mpl::integral_c_tag tag;
0563 BOOST_STATIC_CONSTANT(unsigned int, value = version::type::value);
0564 };
0565
0566 }}
0567 #endif
0568
0569
0570 #ifdef BOOST_HAS_ABI_HEADERS
0571 #include BOOST_ABI_SUFFIX
0572 #endif
0573
0574 #endif