os/ossrv/ossrv_pub/boost_apis/boost/wave/cpp_context.hpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /*=============================================================================
     2     Boost.Wave: A Standard compliant C++ preprocessor library
     3     Definition of the preprocessor context
     4     
     5     http://www.boost.org/
     6 
     7     Copyright (c) 2001-2007 Hartmut Kaiser. Distributed under the Boost
     8     Software License, Version 1.0. (See accompanying file
     9     LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
    10 =============================================================================*/
    11 
    12 #if !defined(CPP_CONTEXT_HPP_907485E2_6649_4A87_911B_7F7225F3E5B8_INCLUDED)
    13 #define CPP_CONTEXT_HPP_907485E2_6649_4A87_911B_7F7225F3E5B8_INCLUDED
    14 
    15 #include <string>
    16 #include <vector>
    17 #include <stack>
    18 
    19 #include <boost/concept_check.hpp>
    20 #include <boost/noncopyable.hpp>
    21 #include <boost/filesystem/path.hpp>
    22 
    23 #include <boost/wave/wave_config.hpp>
    24 #if BOOST_WAVE_SERIALIZATION != 0
    25 #include <boost/serialization/serialization.hpp>
    26 #include <boost/wave/wave_config_constant.hpp>
    27 #endif
    28 #include <boost/wave/token_ids.hpp>
    29 
    30 #include <boost/wave/util/unput_queue_iterator.hpp>
    31 #include <boost/wave/util/cpp_ifblock.hpp>
    32 #include <boost/wave/util/cpp_include_paths.hpp>
    33 #include <boost/wave/util/iteration_context.hpp>
    34 #include <boost/wave/util/cpp_iterator.hpp>
    35 #include <boost/wave/util/cpp_macromap.hpp>
    36 
    37 #include <boost/wave/preprocessing_hooks.hpp>
    38 #include <boost/wave/whitespace_handling.hpp>
    39 #include <boost/wave/cpp_iteration_context.hpp>
    40 #include <boost/wave/language_support.hpp>
    41 
    42 // this must occur after all of the includes and before any code appears
    43 #ifdef BOOST_HAS_ABI_HEADERS
    44 #include BOOST_ABI_PREFIX
    45 #endif
    46 
    47 ///////////////////////////////////////////////////////////////////////////////
    48 namespace boost {
    49 namespace wave {
    50 
    51 ///////////////////////////////////////////////////////////////////////////////
    52 // 
    53 //  The C preprocessor context template class
    54 //
    55 //      The boost::wave::context template is the main interface class to 
    56 //      control the behaviour of the preprocessing engine.
    57 //
    58 //      The following template parameters has to be supplied:
    59 //
    60 //      IteratorT       The iterator type of the underlying input stream
    61 //      LexIteratorT    The lexer iterator type to use as the token factory
    62 //      InputPolicyT    The input policy type to use for loading the files
    63 //                      to be included. This template parameter is optional and 
    64 //                      defaults to the 
    65 //                          iteration_context_policies::load_file_to_string
    66 //                      type.
    67 //      HooksT          The hooks policy to use for different notification 
    68 //                      callbacks. This template parameter is optional and
    69 //                      defaults to the
    70 //                          context_policies::default_preprocessing_hooks
    71 //                      type.
    72 //
    73 ///////////////////////////////////////////////////////////////////////////////
    74 
    75 template <
    76     typename IteratorT,
    77     typename LexIteratorT, 
    78     typename InputPolicyT = iteration_context_policies::load_file_to_string,
    79     typename HooksT = context_policies::eat_whitespace<typename LexIteratorT::token_type>
    80 >
    81 class context : private boost::noncopyable
    82 {
    83 public:
    84 
    85 // concept checks
    86 // the given iterator shall be at least a forward iterator type
    87     BOOST_CLASS_REQUIRE(IteratorT, boost, ForwardIteratorConcept);
    88     
    89 // public typedefs
    90     typedef typename LexIteratorT::token_type       token_type;
    91     typedef context<IteratorT, LexIteratorT, InputPolicyT, HooksT> 
    92         self_type;
    93     
    94     typedef IteratorT                               target_iterator_type;
    95     typedef LexIteratorT                            lexer_type;
    96     typedef pp_iterator<self_type>                  iterator_type;
    97 
    98     typedef InputPolicyT                            input_policy_type;
    99     typedef typename token_type::position_type      position_type;
   100 
   101     
   102 // type of a token sequence
   103     typedef std::list<token_type, boost::fast_pool_allocator<token_type> > 
   104         token_sequence_type;
   105 // types of the policies
   106     typedef HooksT                                  hook_policy_type;
   107     
   108 private:
   109 // stack of shared_ptr's to the pending iteration contexts 
   110     typedef boost::shared_ptr<base_iteration_context<lexer_type> > 
   111         iteration_ptr_type;
   112     typedef boost::wave::util::iteration_context_stack<iteration_ptr_type> 
   113             iteration_context_stack_type;
   114     typedef typename iteration_context_stack_type::size_type iter_size_type;
   115 
   116     context *this_() { return this; }           // avoid warning in constructor
   117     
   118 public:
   119     context(target_iterator_type const &first_, target_iterator_type const &last_, 
   120             char const *fname = "<Unknown>", HooksT const &hooks_ = HooksT())
   121     :   first(first_), last(last_), filename(fname)
   122 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
   123         , current_filename(fname)
   124 #endif 
   125         , macros(*this_())
   126         , language(language_support(
   127                       support_cpp 
   128                     | support_option_convert_trigraphs 
   129                     | support_option_emit_line_directives 
   130 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
   131                     | support_option_include_guard_detection
   132 #endif
   133                    ))
   134         , hooks(hooks_)
   135     {
   136         macros.init_predefined_macros(fname);
   137         includes.init_initial_path();
   138     }
   139     
   140 // default copy constructor
   141 // default assignment operator
   142 // default destructor
   143     
   144 // iterator interface
   145     iterator_type begin() 
   146     { 
   147         std::string fname(filename);
   148         if (filename != "<Unknown>" && filename != "<stdin>") {
   149             using namespace boost::filesystem;
   150             path fpath(complete(path(filename)));
   151             fname = fpath.string();
   152             includes.set_current_directory(fname.c_str());
   153         }
   154         return iterator_type(*this, first, last, position_type(fname.c_str())); 
   155     }
   156     iterator_type begin(
   157         target_iterator_type const &first_, 
   158         target_iterator_type const &last_) 
   159     { 
   160         std::string fname(filename);
   161         if (filename != "<Unknown>" && filename != "<stdin>") {
   162             using namespace boost::filesystem;
   163             path fpath(complete(path(filename)));
   164             fname = fpath.string();
   165             includes.set_current_directory(fname.c_str());
   166         }
   167         return iterator_type(*this, first_, last_, position_type(fname.c_str())); 
   168     }
   169     iterator_type end() const 
   170         { return iterator_type(); }
   171 
   172 // maintain include paths
   173     bool add_include_path(char const *path_)
   174         { return includes.add_include_path(path_, false);}
   175     bool add_sysinclude_path(char const *path_)
   176         { return includes.add_include_path(path_, true);}
   177     void set_sysinclude_delimiter() { includes.set_sys_include_delimiter(); }
   178     typename iteration_context_stack_type::size_type get_iteration_depth() const 
   179         { return iter_ctxs.size(); }
   180 
   181 // maintain defined macros
   182 #if BOOST_WAVE_ENABLE_COMMANDLINE_MACROS != 0
   183     bool add_macro_definition(std::string macrostring, 
   184             bool is_predefined = false)
   185         { return boost::wave::util::add_macro_definition(*this, macrostring, 
   186             is_predefined, get_language()); }
   187 #endif 
   188     bool add_macro_definition(token_type const &name, bool has_params,
   189             std::vector<token_type> &parameters, token_sequence_type &definition,
   190             bool is_predefined = false)
   191         { return macros.add_macro(name, has_params, parameters, definition, 
   192             is_predefined); }
   193     template <typename IteratorT2>
   194     bool is_defined_macro(IteratorT2 const &begin, IteratorT2 const &end) 
   195         { return macros.is_defined(begin, end); }
   196     bool get_macro_definition(typename token_type::string_type const &name, 
   197             bool &has_params, bool &is_predefined, position_type &pos,
   198             std::vector<token_type> &parameters, token_sequence_type &definition)
   199         { 
   200             return macros.get_macro(name, has_params, is_predefined, pos,
   201                 parameters, definition); 
   202         }
   203     bool remove_macro_definition(typename token_type::string_type const &name, 
   204             bool even_predefined = false)
   205         { 
   206 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
   207             // ensure this gets remove from the list of include guards as well
   208             includes.remove_pragma_once_header(std::string(name.c_str()));
   209 #endif
   210             return macros.remove_macro(
   211                 token_type(T_IDENTIFIER, name, macros.get_main_pos()), 
   212                 even_predefined); 
   213         }
   214     void reset_macro_definitions() 
   215         { macros.reset_macromap(); macros.init_predefined_macros(); }
   216 
   217 // get the Wave version information 
   218     static std::string get_version()  
   219         { return boost::wave::util::predefined_macros::get_fullversion(false); }
   220     static std::string get_version_string()  
   221         { return boost::wave::util::predefined_macros::get_versionstr(false); }
   222 
   223 // access current language options
   224     void set_language(boost::wave::language_support language_,
   225                       bool reset_macros = true) 
   226     { 
   227         language = language_; 
   228         if (reset_macros)
   229             reset_macro_definitions();
   230     }
   231     boost::wave::language_support get_language() const { return language; }
   232         
   233 // change and ask for maximal possible include nesting depth
   234     void set_max_include_nesting_depth(iter_size_type new_depth)
   235         { iter_ctxs.set_max_include_nesting_depth(new_depth); }
   236     iter_size_type get_max_include_nesting_depth() const
   237         { return iter_ctxs.get_max_include_nesting_depth(); }
   238 
   239 // access the policies
   240     hook_policy_type &get_hooks() { return hooks; }
   241 
   242 // return the directory of the currently preprocessed file
   243     boost::filesystem::path get_current_directory() const
   244         { return includes.get_current_directory(); }
   245         
   246 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
   247 protected:
   248     friend class boost::wave::pp_iterator<
   249         boost::wave::context<IteratorT, lexer_type, InputPolicyT, HooksT> >;
   250     friend class boost::wave::impl::pp_iterator_functor<
   251         boost::wave::context<IteratorT, lexer_type, InputPolicyT, HooksT> >;
   252 #endif
   253     
   254 // maintain include paths (helper functions)
   255     bool find_include_file (std::string &s, std::string &d, bool is_system, 
   256         char const *current_file) const
   257     { return includes.find_include_file(s, d, is_system, current_file); }
   258     void set_current_directory(char const *path_) 
   259         { includes.set_current_directory(path_); }
   260         
   261 // conditional compilation contexts
   262     bool get_if_block_status() const { return ifblocks.get_status(); }
   263     bool get_if_block_some_part_status() const 
   264         { return ifblocks.get_some_part_status(); } 
   265     bool get_enclosing_if_block_status() const
   266         { return ifblocks.get_enclosing_status(); }
   267     void enter_if_block(bool new_status) 
   268         { ifblocks.enter_if_block(new_status); }
   269     bool enter_elif_block(bool new_status) 
   270         { return ifblocks.enter_elif_block(new_status); }
   271     bool enter_else_block() { return ifblocks.enter_else_block(); }
   272     bool exit_if_block() { return ifblocks.exit_if_block(); }
   273     typename boost::wave::util::if_block_stack::size_type get_if_block_depth() const 
   274         { return ifblocks.get_if_block_depth(); }
   275 
   276 // stack of iteration contexts
   277     iteration_ptr_type pop_iteration_context()
   278         { iteration_ptr_type top = iter_ctxs.top(); iter_ctxs.pop(); return top; }
   279     void push_iteration_context(position_type const &act_pos, iteration_ptr_type iter_ctx)
   280         { iter_ctxs.push(act_pos, iter_ctx); }
   281 
   282     position_type &get_main_pos() { return macros.get_main_pos(); }
   283     
   284 ///////////////////////////////////////////////////////////////////////////////
   285 //
   286 //  expand_tokensequence(): 
   287 //      expands all macros contained in a given token sequence, handles '##' 
   288 //      and '#' pp operators and re-scans the resulting sequence 
   289 //      (essentially pre-processes the token sequence).
   290 //
   291 //      The expand_undefined parameter is true during macro expansion inside
   292 //      a C++ expression given for a #if or #elif statement. 
   293 //
   294 ///////////////////////////////////////////////////////////////////////////////
   295     template <typename IteratorT2>
   296     token_type expand_tokensequence(IteratorT2 &first_, IteratorT2 const &last_, 
   297         token_sequence_type &pending, token_sequence_type &expanded, 
   298         bool expand_undefined = false)
   299     {
   300         return macros.expand_tokensequence(first_, last_, pending, expanded, 
   301             expand_undefined);
   302     }
   303 
   304     template <typename IteratorT2>
   305     void expand_whole_tokensequence(IteratorT2 &first_, IteratorT2 const &last_, 
   306         token_sequence_type &expanded, bool expand_undefined = true)
   307     {
   308         macros.expand_whole_tokensequence(expanded, first_, last_, 
   309             expand_undefined);
   310 
   311     // remove any contained placeholder
   312         boost::wave::util::impl::remove_placeholders(expanded);
   313     }
   314 
   315 public:
   316 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
   317 // support for #pragma once
   318 // maintain the real name of the current preprocessed file
   319     void set_current_filename(char const *real_name)
   320         { current_filename = real_name; }
   321     std::string const &get_current_filename() const 
   322         { return current_filename; }
   323 
   324 // maintain the list of known headers containing #pragma once 
   325     bool has_pragma_once(std::string const &filename_)
   326         { return includes.has_pragma_once(filename_); }
   327     bool add_pragma_once_header(std::string const &filename_,
   328             std::string const& guard_name = "__BOOST_WAVE_PRAGMA_ONCE__")
   329         { return includes.add_pragma_once_header(filename_, guard_name); }
   330 #endif 
   331 
   332 // forwarding functions for the context policy hooks    
   333     template <typename ContainerT>
   334     bool interpret_pragma(ContainerT &pending, token_type const &option, 
   335         ContainerT const &values, token_type const &act_token)
   336     {
   337         return hooks.interpret_pragma(*this, pending, option, values, act_token);
   338     }
   339     
   340 #if BOOST_WAVE_SERIALIZATION != 0
   341 public:
   342     BOOST_STATIC_CONSTANT(unsigned int, version = 0x10);
   343     BOOST_STATIC_CONSTANT(unsigned int, version_mask = 0x0f);
   344 
   345 private:
   346     friend class boost::serialization::access;
   347     template<class Archive>
   348     void save(Archive & ar, const unsigned int version) const
   349     {
   350         typedef typename token_type::string_type string_type;
   351         
   352         string_type cfg(BOOST_PP_STRINGIZE(BOOST_WAVE_CONFIG));
   353         string_type kwd(BOOST_WAVE_PRAGMA_KEYWORD);
   354         string_type strtype(BOOST_PP_STRINGIZE((BOOST_WAVE_STRINGTYPE)));
   355         ar & cfg;
   356         ar & kwd;
   357         ar & strtype;
   358         
   359         ar & language;
   360         ar & macros;
   361         ar & includes;
   362     }
   363     template<class Archive>
   364     void load(Archive & ar, const unsigned int loaded_version)
   365     {
   366         if (version != (loaded_version & ~version_mask)) {
   367             BOOST_WAVE_THROW(preprocess_exception, incompatible_config, 
   368                 "cpp_context state version", get_main_pos());
   369         }
   370         
   371         // check compatibility of the stored information
   372         typedef typename token_type::string_type string_type;
   373         string_type config, pragma_keyword, string_type_str;
   374         
   375         ar & config;          // BOOST_WAVE_CONFIG
   376         if (config != BOOST_PP_STRINGIZE(BOOST_WAVE_CONFIG)) {
   377             BOOST_WAVE_THROW(preprocess_exception, incompatible_config, 
   378                 "BOOST_WAVE_CONFIG", get_main_pos());
   379         }
   380         
   381         ar & pragma_keyword;  // BOOST_WAVE_PRAGMA_KEYWORD
   382         if (pragma_keyword != BOOST_WAVE_PRAGMA_KEYWORD) {
   383             BOOST_WAVE_THROW(preprocess_exception, incompatible_config, 
   384                 "BOOST_WAVE_PRAGMA_KEYWORD", get_main_pos());
   385         }
   386 
   387         ar & string_type_str; // BOOST_PP_STRINGIZE((BOOST_WAVE_STRINGTYPE))
   388         if (string_type_str != BOOST_PP_STRINGIZE((BOOST_WAVE_STRINGTYPE))) {
   389             BOOST_WAVE_THROW(preprocess_exception, incompatible_config, 
   390                 "BOOST_WAVE_STRINGTYPE", get_main_pos());
   391         }
   392         
   393         // read in the useful bits
   394         ar & language;
   395         ar & macros;
   396         ar & includes;
   397     }
   398     BOOST_SERIALIZATION_SPLIT_MEMBER()
   399 #endif
   400 
   401 private:
   402 // the main input stream
   403     target_iterator_type first;         // underlying input stream
   404     target_iterator_type last;
   405     std::string filename;               // associated main filename
   406 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
   407     std::string current_filename;       // real name of current preprocessed file
   408 #endif 
   409     
   410     boost::wave::util::if_block_stack ifblocks;   // conditional compilation contexts
   411     boost::wave::util::include_paths includes;    // lists of include directories to search
   412     iteration_context_stack_type iter_ctxs;       // iteration contexts
   413     boost::wave::util::macromap<self_type> macros;  // map of defined macros
   414     boost::wave::language_support language;       // supported language/extensions
   415     hook_policy_type hooks;                       // hook policy instance
   416 };
   417 
   418 ///////////////////////////////////////////////////////////////////////////////
   419 }   // namespace wave
   420 }   // namespace boost
   421 
   422 #if BOOST_WAVE_SERIALIZATION != 0
   423 namespace boost { namespace serialization {
   424 
   425 template<
   426     typename Iterator, typename LexIterator, 
   427     typename InputPolicy, typename Hooks
   428 >
   429 struct tracking_level<boost::wave::context<Iterator, LexIterator, InputPolicy, Hooks> >
   430 {
   431     typedef mpl::integral_c_tag tag;
   432     typedef mpl::int_<track_never> type;
   433     BOOST_STATIC_CONSTANT(
   434         int,
   435         value = tracking_level::type::value
   436     );
   437 };
   438 
   439 template<
   440     typename Iterator, typename LexIterator, 
   441     typename InputPolicy, typename Hooks
   442 >
   443 struct version<boost::wave::context<Iterator, LexIterator, InputPolicy, Hooks> >
   444 {
   445     typedef boost::wave::context<Iterator, LexIterator, InputPolicy, Hooks>
   446         target_type;
   447     typedef mpl::int_<target_type::version> type;
   448     typedef mpl::integral_c_tag tag;
   449     BOOST_STATIC_CONSTANT(unsigned int, value = version::type::value);
   450 };
   451 
   452 }}  // namespace boost::serialization
   453 #endif
   454 
   455 // the suffix header occurs after all of the code
   456 #ifdef BOOST_HAS_ABI_HEADERS
   457 #include BOOST_ABI_SUFFIX
   458 #endif
   459 
   460 #endif // !defined(CPP_CONTEXT_HPP_907485E2_6649_4A87_911B_7F7225F3E5B8_INCLUDED)