Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:43

0001 /*=============================================================================
0002     Boost.Wave: A Standard compliant C++ preprocessor library
0003     Definition of the preprocessor context
0004 
0005     http://www.boost.org/
0006 
0007     Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
0008     Software License, Version 1.0. (See accompanying file
0009     LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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 // this must occur after all of the includes and before any code appears
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 //  The C/C++ preprocessor context template class
0057 //
0058 //      The boost::wave::context template is the main interface class to
0059 //      control the behavior of the preprocessing engine.
0060 //
0061 //      The following template parameters has to be supplied:
0062 //
0063 //      IteratorT       The iterator type of the underlying input stream
0064 //      LexIteratorT    The lexer iterator type to use as the token factory
0065 //      InputPolicyT    The input policy type to use for loading the files
0066 //                      to be included. This template parameter is optional and
0067 //                      defaults to the
0068 //                          iteration_context_policies::load_file_to_string
0069 //                      type.
0070 //      HooksT          The hooks policy to use for different notification
0071 //                      callbacks. This template parameter is optional and
0072 //                      defaults to the
0073 //                          context_policies::default_preprocessing_hooks
0074 //                      type.
0075 //      DerivedT        The type of the type being derived from the context
0076 //                      type (if any). This template parameter is optional and
0077 //                      defaults to 'this_type', which means that the context
0078 //                      type will be used assuming no derived type exists.
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     // concept checks
0100     // the given iterator should be at least a forward iterator type
0101     BOOST_CLASS_REQUIRE(IteratorT, boost, ForwardIteratorConcept);
0102 
0103     // public typedefs
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     // type of a token sequence
0115     typedef std::list<token_type, boost::fast_pool_allocator<token_type> >
0116         token_sequence_type;
0117     // type of the policies
0118     typedef HooksT                                  hook_policy_type;
0119 
0120 private:
0121     // stack of shared_ptr's to the pending iteration contexts
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; }           // avoid warning in constructor
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     // default copy constructor
0158     // default assignment operator
0159     // default destructor
0160 
0161     // iterator interface
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     // maintain include paths
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 // maintain defined macros
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     // Define and undefine macros, macro introspection
0207     template <typename StringT>
0208     bool add_macro_definition(StringT const &name, position_type const& pos,
0209         bool has_params, std::vector<token_type> &parameters,
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> &parameters,
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         // strip leading and trailing whitespace
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         // ensure this gets removed from the list of include guards as well
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     // Iterate over names of defined macros
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     // This version now is used internally mainly, but since it was a documented
0262     // API function we leave it in the public interface.
0263     bool add_macro_definition(token_type const &name, bool has_params,
0264         std::vector<token_type> &parameters, 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     // get the Wave version information
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     // access current language options
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     // change and ask for maximal possible include nesting depth
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     // access the policies
0303     hook_policy_type &get_hooks() { return hooks; }
0304     hook_policy_type const &get_hooks() const { return hooks; }
0305 
0306     // return type of actually used context type (might be the derived type)
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 // return the directory of the currently preprocessed file
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     // make sure the context has been initialized
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;  // execute once
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     // maintain include paths (helper functions)
0343     void set_current_directory(char const *path_)
0344         { includes.set_current_directory(path_); }
0345 
0346     // conditional compilation contexts
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     // stack of iteration contexts
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     //  expand_tokensequence():
0370     //      expands all macros contained in a given token sequence, handles '##'
0371     //      and '#' pp operators and re-scans the resulting sequence
0372     //      (essentially pre-processes the token sequence).
0373     //
0374     //      The expand_defined parameter is true during macro expansion inside
0375     //      a C++ expression given for a #if or #elif statement.
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         // remove any contained placeholder
0398         boost::wave::util::impl::remove_placeholders(expanded);
0399     }
0400 
0401 public:
0402 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
0403     // support for #pragma once
0404     // maintain the real name of the current preprocessed file
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     // maintain the list of known headers containing #pragma once
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         // check compatibility of the stored information
0472         string_type config, pragma_keyword, string_type_str;
0473 
0474         // BOOST_PP_STRINGIZE(BOOST_WAVE_CONFIG)
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         // BOOST_WAVE_PRAGMA_KEYWORD
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         // BOOST_PP_STRINGIZE((BOOST_WAVE_STRINGTYPE))
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             // read in the useful bits
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             // catch version mismatch exceptions and call error handler
0507             get_hooks().throw_exception(derived(), e);
0508         }
0509     }
0510     BOOST_SERIALIZATION_SPLIT_MEMBER()
0511 #endif
0512 
0513 private:
0514     // the main input stream
0515     target_iterator_type first;         // underlying input stream
0516     target_iterator_type last;
0517     std::string filename;               // associated main filename
0518     bool has_been_initialized;          // set cwd once
0519 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
0520     std::string current_filename;       // real name of current preprocessed file
0521 #endif
0522     std::string current_relative_filename;        // real relative name of current preprocessed file
0523 
0524     boost::wave::util::if_block_stack ifblocks;   // conditional compilation contexts
0525     boost::wave::util::include_paths includes;    // lists of include directories to search
0526     iteration_context_stack_type iter_ctxs;       // iteration contexts
0527     macromap_type macros;                         // map of defined macros
0528     boost::wave::language_support language;       // supported language/extensions
0529     hook_policy_type hooks;                       // hook policy instance
0530 };
0531 
0532 ///////////////////////////////////////////////////////////////////////////////
0533 }   // namespace wave
0534 }   // namespace boost
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 }}  // namespace boost::serialization
0567 #endif
0568 
0569 // the suffix header occurs after all of the code
0570 #ifdef BOOST_HAS_ABI_HEADERS
0571 #include BOOST_ABI_SUFFIX
0572 #endif
0573 
0574 #endif // !defined(BOOST_CPP_CONTEXT_HPP_907485E2_6649_4A87_911B_7F7225F3E5B8_INCLUDED)