sl@0: /*============================================================================= sl@0: Boost.Wave: A Standard compliant C++ preprocessor library sl@0: Definition of the preprocessor context sl@0: sl@0: http://www.boost.org/ sl@0: sl@0: Copyright (c) 2001-2007 Hartmut Kaiser. Distributed under the Boost sl@0: Software License, Version 1.0. (See accompanying file sl@0: LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) sl@0: =============================================================================*/ sl@0: sl@0: #if !defined(CPP_CONTEXT_HPP_907485E2_6649_4A87_911B_7F7225F3E5B8_INCLUDED) sl@0: #define CPP_CONTEXT_HPP_907485E2_6649_4A87_911B_7F7225F3E5B8_INCLUDED sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #include sl@0: #if BOOST_WAVE_SERIALIZATION != 0 sl@0: #include sl@0: #include sl@0: #endif sl@0: #include sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: // this must occur after all of the includes and before any code appears sl@0: #ifdef BOOST_HAS_ABI_HEADERS sl@0: #include BOOST_ABI_PREFIX sl@0: #endif sl@0: sl@0: /////////////////////////////////////////////////////////////////////////////// sl@0: namespace boost { sl@0: namespace wave { sl@0: sl@0: /////////////////////////////////////////////////////////////////////////////// sl@0: // sl@0: // The C preprocessor context template class sl@0: // sl@0: // The boost::wave::context template is the main interface class to sl@0: // control the behaviour of the preprocessing engine. sl@0: // sl@0: // The following template parameters has to be supplied: sl@0: // sl@0: // IteratorT The iterator type of the underlying input stream sl@0: // LexIteratorT The lexer iterator type to use as the token factory sl@0: // InputPolicyT The input policy type to use for loading the files sl@0: // to be included. This template parameter is optional and sl@0: // defaults to the sl@0: // iteration_context_policies::load_file_to_string sl@0: // type. sl@0: // HooksT The hooks policy to use for different notification sl@0: // callbacks. This template parameter is optional and sl@0: // defaults to the sl@0: // context_policies::default_preprocessing_hooks sl@0: // type. sl@0: // sl@0: /////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: template < sl@0: typename IteratorT, sl@0: typename LexIteratorT, sl@0: typename InputPolicyT = iteration_context_policies::load_file_to_string, sl@0: typename HooksT = context_policies::eat_whitespace sl@0: > sl@0: class context : private boost::noncopyable sl@0: { sl@0: public: sl@0: sl@0: // concept checks sl@0: // the given iterator shall be at least a forward iterator type sl@0: BOOST_CLASS_REQUIRE(IteratorT, boost, ForwardIteratorConcept); sl@0: sl@0: // public typedefs sl@0: typedef typename LexIteratorT::token_type token_type; sl@0: typedef context sl@0: self_type; sl@0: sl@0: typedef IteratorT target_iterator_type; sl@0: typedef LexIteratorT lexer_type; sl@0: typedef pp_iterator iterator_type; sl@0: sl@0: typedef InputPolicyT input_policy_type; sl@0: typedef typename token_type::position_type position_type; sl@0: sl@0: sl@0: // type of a token sequence sl@0: typedef std::list > sl@0: token_sequence_type; sl@0: // types of the policies sl@0: typedef HooksT hook_policy_type; sl@0: sl@0: private: sl@0: // stack of shared_ptr's to the pending iteration contexts sl@0: typedef boost::shared_ptr > sl@0: iteration_ptr_type; sl@0: typedef boost::wave::util::iteration_context_stack sl@0: iteration_context_stack_type; sl@0: typedef typename iteration_context_stack_type::size_type iter_size_type; sl@0: sl@0: context *this_() { return this; } // avoid warning in constructor sl@0: sl@0: public: sl@0: context(target_iterator_type const &first_, target_iterator_type const &last_, sl@0: char const *fname = "", HooksT const &hooks_ = HooksT()) sl@0: : first(first_), last(last_), filename(fname) sl@0: #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 sl@0: , current_filename(fname) sl@0: #endif sl@0: , macros(*this_()) sl@0: , language(language_support( sl@0: support_cpp sl@0: | support_option_convert_trigraphs sl@0: | support_option_emit_line_directives sl@0: #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 sl@0: | support_option_include_guard_detection sl@0: #endif sl@0: )) sl@0: , hooks(hooks_) sl@0: { sl@0: macros.init_predefined_macros(fname); sl@0: includes.init_initial_path(); sl@0: } sl@0: sl@0: // default copy constructor sl@0: // default assignment operator sl@0: // default destructor sl@0: sl@0: // iterator interface sl@0: iterator_type begin() sl@0: { sl@0: std::string fname(filename); sl@0: if (filename != "" && filename != "") { sl@0: using namespace boost::filesystem; sl@0: path fpath(complete(path(filename))); sl@0: fname = fpath.string(); sl@0: includes.set_current_directory(fname.c_str()); sl@0: } sl@0: return iterator_type(*this, first, last, position_type(fname.c_str())); sl@0: } sl@0: iterator_type begin( sl@0: target_iterator_type const &first_, sl@0: target_iterator_type const &last_) sl@0: { sl@0: std::string fname(filename); sl@0: if (filename != "" && filename != "") { sl@0: using namespace boost::filesystem; sl@0: path fpath(complete(path(filename))); sl@0: fname = fpath.string(); sl@0: includes.set_current_directory(fname.c_str()); sl@0: } sl@0: return iterator_type(*this, first_, last_, position_type(fname.c_str())); sl@0: } sl@0: iterator_type end() const sl@0: { return iterator_type(); } sl@0: sl@0: // maintain include paths sl@0: bool add_include_path(char const *path_) sl@0: { return includes.add_include_path(path_, false);} sl@0: bool add_sysinclude_path(char const *path_) sl@0: { return includes.add_include_path(path_, true);} sl@0: void set_sysinclude_delimiter() { includes.set_sys_include_delimiter(); } sl@0: typename iteration_context_stack_type::size_type get_iteration_depth() const sl@0: { return iter_ctxs.size(); } sl@0: sl@0: // maintain defined macros sl@0: #if BOOST_WAVE_ENABLE_COMMANDLINE_MACROS != 0 sl@0: bool add_macro_definition(std::string macrostring, sl@0: bool is_predefined = false) sl@0: { return boost::wave::util::add_macro_definition(*this, macrostring, sl@0: is_predefined, get_language()); } sl@0: #endif sl@0: bool add_macro_definition(token_type const &name, bool has_params, sl@0: std::vector ¶meters, token_sequence_type &definition, sl@0: bool is_predefined = false) sl@0: { return macros.add_macro(name, has_params, parameters, definition, sl@0: is_predefined); } sl@0: template sl@0: bool is_defined_macro(IteratorT2 const &begin, IteratorT2 const &end) sl@0: { return macros.is_defined(begin, end); } sl@0: bool get_macro_definition(typename token_type::string_type const &name, sl@0: bool &has_params, bool &is_predefined, position_type &pos, sl@0: std::vector ¶meters, token_sequence_type &definition) sl@0: { sl@0: return macros.get_macro(name, has_params, is_predefined, pos, sl@0: parameters, definition); sl@0: } sl@0: bool remove_macro_definition(typename token_type::string_type const &name, sl@0: bool even_predefined = false) sl@0: { sl@0: #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 sl@0: // ensure this gets remove from the list of include guards as well sl@0: includes.remove_pragma_once_header(std::string(name.c_str())); sl@0: #endif sl@0: return macros.remove_macro( sl@0: token_type(T_IDENTIFIER, name, macros.get_main_pos()), sl@0: even_predefined); sl@0: } sl@0: void reset_macro_definitions() sl@0: { macros.reset_macromap(); macros.init_predefined_macros(); } sl@0: sl@0: // get the Wave version information sl@0: static std::string get_version() sl@0: { return boost::wave::util::predefined_macros::get_fullversion(false); } sl@0: static std::string get_version_string() sl@0: { return boost::wave::util::predefined_macros::get_versionstr(false); } sl@0: sl@0: // access current language options sl@0: void set_language(boost::wave::language_support language_, sl@0: bool reset_macros = true) sl@0: { sl@0: language = language_; sl@0: if (reset_macros) sl@0: reset_macro_definitions(); sl@0: } sl@0: boost::wave::language_support get_language() const { return language; } sl@0: sl@0: // change and ask for maximal possible include nesting depth sl@0: void set_max_include_nesting_depth(iter_size_type new_depth) sl@0: { iter_ctxs.set_max_include_nesting_depth(new_depth); } sl@0: iter_size_type get_max_include_nesting_depth() const sl@0: { return iter_ctxs.get_max_include_nesting_depth(); } sl@0: sl@0: // access the policies sl@0: hook_policy_type &get_hooks() { return hooks; } sl@0: sl@0: // return the directory of the currently preprocessed file sl@0: boost::filesystem::path get_current_directory() const sl@0: { return includes.get_current_directory(); } sl@0: sl@0: #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) sl@0: protected: sl@0: friend class boost::wave::pp_iterator< sl@0: boost::wave::context >; sl@0: friend class boost::wave::impl::pp_iterator_functor< sl@0: boost::wave::context >; sl@0: #endif sl@0: sl@0: // maintain include paths (helper functions) sl@0: bool find_include_file (std::string &s, std::string &d, bool is_system, sl@0: char const *current_file) const sl@0: { return includes.find_include_file(s, d, is_system, current_file); } sl@0: void set_current_directory(char const *path_) sl@0: { includes.set_current_directory(path_); } sl@0: sl@0: // conditional compilation contexts sl@0: bool get_if_block_status() const { return ifblocks.get_status(); } sl@0: bool get_if_block_some_part_status() const sl@0: { return ifblocks.get_some_part_status(); } sl@0: bool get_enclosing_if_block_status() const sl@0: { return ifblocks.get_enclosing_status(); } sl@0: void enter_if_block(bool new_status) sl@0: { ifblocks.enter_if_block(new_status); } sl@0: bool enter_elif_block(bool new_status) sl@0: { return ifblocks.enter_elif_block(new_status); } sl@0: bool enter_else_block() { return ifblocks.enter_else_block(); } sl@0: bool exit_if_block() { return ifblocks.exit_if_block(); } sl@0: typename boost::wave::util::if_block_stack::size_type get_if_block_depth() const sl@0: { return ifblocks.get_if_block_depth(); } sl@0: sl@0: // stack of iteration contexts sl@0: iteration_ptr_type pop_iteration_context() sl@0: { iteration_ptr_type top = iter_ctxs.top(); iter_ctxs.pop(); return top; } sl@0: void push_iteration_context(position_type const &act_pos, iteration_ptr_type iter_ctx) sl@0: { iter_ctxs.push(act_pos, iter_ctx); } sl@0: sl@0: position_type &get_main_pos() { return macros.get_main_pos(); } sl@0: sl@0: /////////////////////////////////////////////////////////////////////////////// sl@0: // sl@0: // expand_tokensequence(): sl@0: // expands all macros contained in a given token sequence, handles '##' sl@0: // and '#' pp operators and re-scans the resulting sequence sl@0: // (essentially pre-processes the token sequence). sl@0: // sl@0: // The expand_undefined parameter is true during macro expansion inside sl@0: // a C++ expression given for a #if or #elif statement. sl@0: // sl@0: /////////////////////////////////////////////////////////////////////////////// sl@0: template sl@0: token_type expand_tokensequence(IteratorT2 &first_, IteratorT2 const &last_, sl@0: token_sequence_type &pending, token_sequence_type &expanded, sl@0: bool expand_undefined = false) sl@0: { sl@0: return macros.expand_tokensequence(first_, last_, pending, expanded, sl@0: expand_undefined); sl@0: } sl@0: sl@0: template sl@0: void expand_whole_tokensequence(IteratorT2 &first_, IteratorT2 const &last_, sl@0: token_sequence_type &expanded, bool expand_undefined = true) sl@0: { sl@0: macros.expand_whole_tokensequence(expanded, first_, last_, sl@0: expand_undefined); sl@0: sl@0: // remove any contained placeholder sl@0: boost::wave::util::impl::remove_placeholders(expanded); sl@0: } sl@0: sl@0: public: sl@0: #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 sl@0: // support for #pragma once sl@0: // maintain the real name of the current preprocessed file sl@0: void set_current_filename(char const *real_name) sl@0: { current_filename = real_name; } sl@0: std::string const &get_current_filename() const sl@0: { return current_filename; } sl@0: sl@0: // maintain the list of known headers containing #pragma once sl@0: bool has_pragma_once(std::string const &filename_) sl@0: { return includes.has_pragma_once(filename_); } sl@0: bool add_pragma_once_header(std::string const &filename_, sl@0: std::string const& guard_name = "__BOOST_WAVE_PRAGMA_ONCE__") sl@0: { return includes.add_pragma_once_header(filename_, guard_name); } sl@0: #endif sl@0: sl@0: // forwarding functions for the context policy hooks sl@0: template sl@0: bool interpret_pragma(ContainerT &pending, token_type const &option, sl@0: ContainerT const &values, token_type const &act_token) sl@0: { sl@0: return hooks.interpret_pragma(*this, pending, option, values, act_token); sl@0: } sl@0: sl@0: #if BOOST_WAVE_SERIALIZATION != 0 sl@0: public: sl@0: BOOST_STATIC_CONSTANT(unsigned int, version = 0x10); sl@0: BOOST_STATIC_CONSTANT(unsigned int, version_mask = 0x0f); sl@0: sl@0: private: sl@0: friend class boost::serialization::access; sl@0: template sl@0: void save(Archive & ar, const unsigned int version) const sl@0: { sl@0: typedef typename token_type::string_type string_type; sl@0: sl@0: string_type cfg(BOOST_PP_STRINGIZE(BOOST_WAVE_CONFIG)); sl@0: string_type kwd(BOOST_WAVE_PRAGMA_KEYWORD); sl@0: string_type strtype(BOOST_PP_STRINGIZE((BOOST_WAVE_STRINGTYPE))); sl@0: ar & cfg; sl@0: ar & kwd; sl@0: ar & strtype; sl@0: sl@0: ar & language; sl@0: ar & macros; sl@0: ar & includes; sl@0: } sl@0: template sl@0: void load(Archive & ar, const unsigned int loaded_version) sl@0: { sl@0: if (version != (loaded_version & ~version_mask)) { sl@0: BOOST_WAVE_THROW(preprocess_exception, incompatible_config, sl@0: "cpp_context state version", get_main_pos()); sl@0: } sl@0: sl@0: // check compatibility of the stored information sl@0: typedef typename token_type::string_type string_type; sl@0: string_type config, pragma_keyword, string_type_str; sl@0: sl@0: ar & config; // BOOST_WAVE_CONFIG sl@0: if (config != BOOST_PP_STRINGIZE(BOOST_WAVE_CONFIG)) { sl@0: BOOST_WAVE_THROW(preprocess_exception, incompatible_config, sl@0: "BOOST_WAVE_CONFIG", get_main_pos()); sl@0: } sl@0: sl@0: ar & pragma_keyword; // BOOST_WAVE_PRAGMA_KEYWORD sl@0: if (pragma_keyword != BOOST_WAVE_PRAGMA_KEYWORD) { sl@0: BOOST_WAVE_THROW(preprocess_exception, incompatible_config, sl@0: "BOOST_WAVE_PRAGMA_KEYWORD", get_main_pos()); sl@0: } sl@0: sl@0: ar & string_type_str; // BOOST_PP_STRINGIZE((BOOST_WAVE_STRINGTYPE)) sl@0: if (string_type_str != BOOST_PP_STRINGIZE((BOOST_WAVE_STRINGTYPE))) { sl@0: BOOST_WAVE_THROW(preprocess_exception, incompatible_config, sl@0: "BOOST_WAVE_STRINGTYPE", get_main_pos()); sl@0: } sl@0: sl@0: // read in the useful bits sl@0: ar & language; sl@0: ar & macros; sl@0: ar & includes; sl@0: } sl@0: BOOST_SERIALIZATION_SPLIT_MEMBER() sl@0: #endif sl@0: sl@0: private: sl@0: // the main input stream sl@0: target_iterator_type first; // underlying input stream sl@0: target_iterator_type last; sl@0: std::string filename; // associated main filename sl@0: #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 sl@0: std::string current_filename; // real name of current preprocessed file sl@0: #endif sl@0: sl@0: boost::wave::util::if_block_stack ifblocks; // conditional compilation contexts sl@0: boost::wave::util::include_paths includes; // lists of include directories to search sl@0: iteration_context_stack_type iter_ctxs; // iteration contexts sl@0: boost::wave::util::macromap macros; // map of defined macros sl@0: boost::wave::language_support language; // supported language/extensions sl@0: hook_policy_type hooks; // hook policy instance sl@0: }; sl@0: sl@0: /////////////////////////////////////////////////////////////////////////////// sl@0: } // namespace wave sl@0: } // namespace boost sl@0: sl@0: #if BOOST_WAVE_SERIALIZATION != 0 sl@0: namespace boost { namespace serialization { sl@0: sl@0: template< sl@0: typename Iterator, typename LexIterator, sl@0: typename InputPolicy, typename Hooks sl@0: > sl@0: struct tracking_level > sl@0: { sl@0: typedef mpl::integral_c_tag tag; sl@0: typedef mpl::int_ type; sl@0: BOOST_STATIC_CONSTANT( sl@0: int, sl@0: value = tracking_level::type::value sl@0: ); sl@0: }; sl@0: sl@0: template< sl@0: typename Iterator, typename LexIterator, sl@0: typename InputPolicy, typename Hooks sl@0: > sl@0: struct version > sl@0: { sl@0: typedef boost::wave::context sl@0: target_type; sl@0: typedef mpl::int_ type; sl@0: typedef mpl::integral_c_tag tag; sl@0: BOOST_STATIC_CONSTANT(unsigned int, value = version::type::value); sl@0: }; sl@0: sl@0: }} // namespace boost::serialization sl@0: #endif sl@0: sl@0: // the suffix header occurs after all of the code sl@0: #ifdef BOOST_HAS_ABI_HEADERS sl@0: #include BOOST_ABI_SUFFIX sl@0: #endif sl@0: sl@0: #endif // !defined(CPP_CONTEXT_HPP_907485E2_6649_4A87_911B_7F7225F3E5B8_INCLUDED)