| 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-2005 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 |  | 
|---|
| 21 | #include <boost/wave/wave_config.hpp> | 
|---|
| 22 | #include <boost/wave/token_ids.hpp> | 
|---|
| 23 |  | 
|---|
| 24 | #include <boost/wave/util/unput_queue_iterator.hpp> | 
|---|
| 25 | #include <boost/wave/util/cpp_ifblock.hpp> | 
|---|
| 26 | #include <boost/wave/util/cpp_include_paths.hpp> | 
|---|
| 27 | #include <boost/wave/util/iteration_context.hpp> | 
|---|
| 28 | #include <boost/wave/util/cpp_iterator.hpp> | 
|---|
| 29 | #include <boost/wave/util/cpp_macromap.hpp> | 
|---|
| 30 |  | 
|---|
| 31 | #include <boost/wave/preprocessing_hooks.hpp> | 
|---|
| 32 | #include <boost/wave/cpp_iteration_context.hpp> | 
|---|
| 33 | #include <boost/wave/language_support.hpp> | 
|---|
| 34 |  | 
|---|
| 35 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 36 | namespace boost { | 
|---|
| 37 | namespace wave { | 
|---|
| 38 |  | 
|---|
| 39 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 40 | //  | 
|---|
| 41 | //  The C preprocessor context template class | 
|---|
| 42 | // | 
|---|
| 43 | //      The boost::wave::context template is the main interface class to  | 
|---|
| 44 | //      control the behaviour of the preprocessing engine. | 
|---|
| 45 | // | 
|---|
| 46 | //      The following template parameters has to be supplied: | 
|---|
| 47 | // | 
|---|
| 48 | //      IteratorT       The iterator type of the underlying input stream | 
|---|
| 49 | //      LexIteratorT    The lexer iterator type to use as the token factory | 
|---|
| 50 | //      InputPolicyT    The input policy type to use for loading the files | 
|---|
| 51 | //                      to be included. This template parameter is optional and  | 
|---|
| 52 | //                      defaults to the  | 
|---|
| 53 | //                          iteration_context_policies::load_file_to_string | 
|---|
| 54 | //                      type | 
|---|
| 55 | //      TraceT          The trace policy to use for trace and include file | 
|---|
| 56 | //                      notification callback. | 
|---|
| 57 | // | 
|---|
| 58 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 59 |  | 
|---|
| 60 | template < | 
|---|
| 61 |     typename IteratorT, | 
|---|
| 62 |     typename LexIteratorT,  | 
|---|
| 63 |     typename InputPolicyT = iteration_context_policies::load_file_to_string, | 
|---|
| 64 |     typename TraceT = context_policies::default_preprocessing_hooks | 
|---|
| 65 | > | 
|---|
| 66 | class context { | 
|---|
| 67 |  | 
|---|
| 68 | public: | 
|---|
| 69 |  | 
|---|
| 70 | // concept checks | 
|---|
| 71 | // the given iterator shall be at least a forward iterator type | 
|---|
| 72 |     BOOST_CLASS_REQUIRE(IteratorT, boost, ForwardIteratorConcept); | 
|---|
| 73 |      | 
|---|
| 74 | // public typedefs | 
|---|
| 75 |     typedef typename LexIteratorT::token_type       token_type; | 
|---|
| 76 |     typedef context<IteratorT, LexIteratorT, InputPolicyT, TraceT>  | 
|---|
| 77 |         self_type; | 
|---|
| 78 |      | 
|---|
| 79 |     typedef IteratorT                               target_iterator_type; | 
|---|
| 80 |     typedef LexIteratorT                            lexer_type; | 
|---|
| 81 |     typedef pp_iterator<self_type>                  iterator_type; | 
|---|
| 82 |  | 
|---|
| 83 |     typedef InputPolicyT                            input_policy_type; | 
|---|
| 84 |     typedef typename token_type::position_type      position_type; | 
|---|
| 85 |          | 
|---|
| 86 | // type of a token sequence | 
|---|
| 87 |     typedef std::list<token_type, boost::fast_pool_allocator<token_type> >  | 
|---|
| 88 |         token_sequence_type; | 
|---|
| 89 |  | 
|---|
| 90 | // types of the policies | 
|---|
| 91 |     typedef TraceT                                  trace_policy_type; | 
|---|
| 92 |      | 
|---|
| 93 | private: | 
|---|
| 94 | // stack of shared_ptr's to the pending iteration contexts  | 
|---|
| 95 |     typedef boost::shared_ptr<base_iteration_context<lexer_type> >  | 
|---|
| 96 |         iteration_ptr_type; | 
|---|
| 97 |     typedef boost::wave::util::iteration_context_stack<iteration_ptr_type>  | 
|---|
| 98 |             iteration_context_stack_type; | 
|---|
| 99 |     typedef typename iteration_context_stack_type::size_type iter_size_type; | 
|---|
| 100 |  | 
|---|
| 101 | // the context object should not be copied around | 
|---|
| 102 |     context(context const& rhs); | 
|---|
| 103 |     context& operator= (context const& rhs); | 
|---|
| 104 |      | 
|---|
| 105 | public: | 
|---|
| 106 |     context(target_iterator_type const &first_, target_iterator_type const &last_,  | 
|---|
| 107 |             char const *fname = "<Unknown>", TraceT const &trace_ = TraceT()) | 
|---|
| 108 |     :   first(first_), last(last_), filename(fname) | 
|---|
| 109 | #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 | 
|---|
| 110 |         , current_filename(fname) | 
|---|
| 111 | #endif  | 
|---|
| 112 |         , macros(*this), language(boost::wave::support_cpp), trace(trace_) | 
|---|
| 113 |     { | 
|---|
| 114 |         macros.init_predefined_macros(fname); | 
|---|
| 115 |         includes.init_initial_path(); | 
|---|
| 116 |     } | 
|---|
| 117 |  | 
|---|
| 118 | // iterator interface | 
|---|
| 119 |     iterator_type begin()  | 
|---|
| 120 |     {  | 
|---|
| 121 |         includes.set_current_directory(filename.c_str()); | 
|---|
| 122 |         return iterator_type(*this, first, last, position_type(filename.c_str()), | 
|---|
| 123 |             get_language());  | 
|---|
| 124 |     } | 
|---|
| 125 |     iterator_type end() const  | 
|---|
| 126 |         { return iterator_type(); } | 
|---|
| 127 |  | 
|---|
| 128 | // maintain include paths | 
|---|
| 129 |     bool add_include_path(char const *path_) | 
|---|
| 130 |         { return includes.add_include_path(path_, false);} | 
|---|
| 131 |     bool add_sysinclude_path(char const *path_) | 
|---|
| 132 |         { return includes.add_include_path(path_, true);} | 
|---|
| 133 |     void set_sysinclude_delimiter() { includes.set_sys_include_delimiter(); } | 
|---|
| 134 |     typename iteration_context_stack_type::size_type get_iteration_depth() const  | 
|---|
| 135 |         { return iter_ctxs.size(); } | 
|---|
| 136 |  | 
|---|
| 137 | // maintain defined macros | 
|---|
| 138 | #if BOOST_WAVE_ENABLE_COMMANDLINE_MACROS != 0 | 
|---|
| 139 |     bool add_macro_definition(std::string macrostring,  | 
|---|
| 140 |             bool is_predefined = false) | 
|---|
| 141 |         { return boost::wave::util::add_macro_definition(*this, macrostring,  | 
|---|
| 142 |             is_predefined, get_language()); } | 
|---|
| 143 | #endif  | 
|---|
| 144 |     bool add_macro_definition(token_type const &name, bool has_params, | 
|---|
| 145 |             std::vector<token_type> ¶meters, token_sequence_type &definition, | 
|---|
| 146 |             bool is_predefined = false) | 
|---|
| 147 |         { return macros.add_macro(name, has_params, parameters, definition,  | 
|---|
| 148 |             is_predefined); } | 
|---|
| 149 |     template <typename IteratorT2> | 
|---|
| 150 |     bool is_defined_macro(IteratorT2 const &begin, IteratorT2 const &end)  | 
|---|
| 151 |         { return macros.is_defined(begin, end); } | 
|---|
| 152 |     bool remove_macro_definition(typename token_type::string_type const &name,  | 
|---|
| 153 |             bool even_predefined = false) | 
|---|
| 154 |         {  | 
|---|
| 155 |             return macros.remove_macro( | 
|---|
| 156 |                 token_type(T_IDENTIFIER, name, macros.get_main_pos()),  | 
|---|
| 157 |                 even_predefined);  | 
|---|
| 158 |         } | 
|---|
| 159 |     bool remove_macro_definition(token_type const &token,  | 
|---|
| 160 |             bool even_predefined = false) | 
|---|
| 161 |         { return macros.remove_macro(token, even_predefined); } | 
|---|
| 162 |     void reset_macro_definitions()  | 
|---|
| 163 |         { macros.reset_macromap(); macros.init_predefined_macros(); } | 
|---|
| 164 |  | 
|---|
| 165 | // get the pp-iterator version information  | 
|---|
| 166 |     static std::string get_version()   | 
|---|
| 167 |         { return boost::wave::util::predefined_macros::get_fullversion(false); } | 
|---|
| 168 |     static std::string get_version_string()   | 
|---|
| 169 |         { return boost::wave::util::predefined_macros::get_versionstr(false); } | 
|---|
| 170 |  | 
|---|
| 171 |     void set_language(boost::wave::language_support language_)  | 
|---|
| 172 |     {  | 
|---|
| 173 |         language = language_;  | 
|---|
| 174 |         reset_macro_definitions(); | 
|---|
| 175 |     } | 
|---|
| 176 |     boost::wave::language_support get_language() const { return language; } | 
|---|
| 177 |          | 
|---|
| 178 | // change and ask for maximal possible include nesting depth | 
|---|
| 179 |     void set_max_include_nesting_depth(iter_size_type new_depth) | 
|---|
| 180 |         { iter_ctxs.set_max_include_nesting_depth(new_depth); } | 
|---|
| 181 |     iter_size_type get_max_include_nesting_depth() const | 
|---|
| 182 |         { return iter_ctxs.get_max_include_nesting_depth(); } | 
|---|
| 183 |  | 
|---|
| 184 | // access the trace policy | 
|---|
| 185 |     trace_policy_type &get_trace_policy()  | 
|---|
| 186 |         { return trace; } | 
|---|
| 187 |  | 
|---|
| 188 | #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) | 
|---|
| 189 | protected: | 
|---|
| 190 |     friend class boost::wave::pp_iterator< | 
|---|
| 191 |         boost::wave::context<IteratorT, lexer_type, InputPolicyT, TraceT> >; | 
|---|
| 192 |     friend class boost::wave::impl::pp_iterator_functor< | 
|---|
| 193 |         boost::wave::context<IteratorT, lexer_type, InputPolicyT, TraceT> >; | 
|---|
| 194 | #endif | 
|---|
| 195 |      | 
|---|
| 196 | // maintain include paths (helper functions) | 
|---|
| 197 |     bool find_include_file (std::string &s, std::string &d, bool is_system,  | 
|---|
| 198 |         char const *current_file) const | 
|---|
| 199 |     { return includes.find_include_file(s, d, is_system, current_file); } | 
|---|
| 200 |     void set_current_directory(char const *path_)  | 
|---|
| 201 |         { includes.set_current_directory(path_); } | 
|---|
| 202 |      | 
|---|
| 203 | // conditional compilation contexts | 
|---|
| 204 |     bool get_if_block_status() const { return ifblocks.get_status(); } | 
|---|
| 205 |     void enter_if_block(bool new_status)  | 
|---|
| 206 |         { ifblocks.enter_if_block(new_status); } | 
|---|
| 207 |     bool enter_elif_block(bool new_status)  | 
|---|
| 208 |         { return ifblocks.enter_elif_block(new_status); } | 
|---|
| 209 |     bool enter_else_block() { return ifblocks.enter_else_block(); } | 
|---|
| 210 |     bool exit_if_block() { return ifblocks.exit_if_block(); } | 
|---|
| 211 |     typename boost::wave::util::if_block_stack::size_type get_if_block_depth() const  | 
|---|
| 212 |         { return ifblocks.get_if_block_depth(); } | 
|---|
| 213 |  | 
|---|
| 214 | // stack of iteration contexts | 
|---|
| 215 |     iteration_ptr_type pop_iteration_context() | 
|---|
| 216 |         { iteration_ptr_type top = iter_ctxs.top(); iter_ctxs.pop(); return top; } | 
|---|
| 217 |     void push_iteration_context(position_type const &act_pos, iteration_ptr_type iter_ctx) | 
|---|
| 218 |         { iter_ctxs.push(act_pos, iter_ctx); } | 
|---|
| 219 |  | 
|---|
| 220 |     position_type &get_main_pos() { return macros.get_main_pos(); } | 
|---|
| 221 |      | 
|---|
| 222 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 223 | // | 
|---|
| 224 | //  expand_tokensequence():  | 
|---|
| 225 | //      expands all macros contained in a given token sequence, handles '##'  | 
|---|
| 226 | //      and '#' pp operators and re-scans the resulting sequence  | 
|---|
| 227 | //      (essentially preprocesses the token sequence). | 
|---|
| 228 | // | 
|---|
| 229 | //      The expand_undefined parameter is true during macro expansion inside | 
|---|
| 230 | //      a C++ expression given for a #if or #elif statement.  | 
|---|
| 231 | // | 
|---|
| 232 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 233 |     template <typename IteratorT2> | 
|---|
| 234 |     token_type expand_tokensequence(IteratorT2 &first, IteratorT2 const &last,  | 
|---|
| 235 |         token_sequence_type &pending, token_sequence_type &expanded,  | 
|---|
| 236 |         bool expand_undefined = false) | 
|---|
| 237 |     { | 
|---|
| 238 |         return macros.expand_tokensequence(first, last, pending, expanded,  | 
|---|
| 239 |             expand_undefined); | 
|---|
| 240 |     } | 
|---|
| 241 |  | 
|---|
| 242 |     template <typename IteratorT2> | 
|---|
| 243 |     void expand_whole_tokensequence(IteratorT2 &first, IteratorT2 const &last,  | 
|---|
| 244 |         token_sequence_type &expanded, bool expand_undefined = true) | 
|---|
| 245 |     { | 
|---|
| 246 |         macros.expand_whole_tokensequence(expanded, first, last,  | 
|---|
| 247 |             expand_undefined); | 
|---|
| 248 |  | 
|---|
| 249 |     // remove any contained placeholder | 
|---|
| 250 |         boost::wave::util::impl::remove_placeholders(expanded); | 
|---|
| 251 |     } | 
|---|
| 252 |  | 
|---|
| 253 | public: | 
|---|
| 254 | #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 | 
|---|
| 255 | // support for #pragma once | 
|---|
| 256 | // maintain the real name of the current preprocessed file | 
|---|
| 257 |     void set_current_filename(char const *real_name) | 
|---|
| 258 |         { current_filename = real_name; } | 
|---|
| 259 |     std::string const &get_current_filename() const  | 
|---|
| 260 |         { return current_filename; } | 
|---|
| 261 |  | 
|---|
| 262 | // maintain the list of known headers containing #pragma once  | 
|---|
| 263 |     bool has_pragma_once(std::string const &filename) | 
|---|
| 264 |         { return includes.has_pragma_once(filename); } | 
|---|
| 265 |     bool add_pragma_once_header(std::string const &filename) | 
|---|
| 266 |         { return includes.add_pragma_once_header(filename); } | 
|---|
| 267 | #endif  | 
|---|
| 268 |  | 
|---|
| 269 | // forwarding functions for the context policy hooks     | 
|---|
| 270 |     template <typename ContainerT> | 
|---|
| 271 |     bool interpret_pragma(ContainerT &pending, token_type const &option,  | 
|---|
| 272 |         ContainerT const &values, token_type const &act_token) | 
|---|
| 273 |     { | 
|---|
| 274 |         return trace.interpret_pragma(*this, pending, option, values,  | 
|---|
| 275 |             act_token); | 
|---|
| 276 |     } | 
|---|
| 277 |     template <typename ParametersT, typename DefinitionT> | 
|---|
| 278 |     void defined_macro(token_type const &name, bool is_functionlike,  | 
|---|
| 279 |         ParametersT const ¶meters, DefinitionT const &definition,  | 
|---|
| 280 |         bool is_predefined) | 
|---|
| 281 |     { | 
|---|
| 282 |         trace.defined_macro(name, is_functionlike, parameters, definition,  | 
|---|
| 283 |             is_predefined); | 
|---|
| 284 |     } | 
|---|
| 285 |     void undefined_macro(token_type const &token) | 
|---|
| 286 |     { | 
|---|
| 287 |         trace.undefined_macro(token); | 
|---|
| 288 |     } | 
|---|
| 289 |      | 
|---|
| 290 | private: | 
|---|
| 291 | // the main input stream | 
|---|
| 292 |     target_iterator_type first;         // underlying input stream | 
|---|
| 293 |     target_iterator_type last; | 
|---|
| 294 |     std::string filename;               // associated main filename | 
|---|
| 295 | #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 | 
|---|
| 296 |     std::string current_filename;       // real name of current preprocessed file | 
|---|
| 297 | #endif  | 
|---|
| 298 |      | 
|---|
| 299 |     boost::wave::util::if_block_stack ifblocks;   // conditional compilation contexts | 
|---|
| 300 |     boost::wave::util::include_paths includes;    // lists of include directories to search | 
|---|
| 301 |     iteration_context_stack_type iter_ctxs;       // iteration contexts | 
|---|
| 302 |     boost::wave::util::macromap<self_type> macros;  // map of defined macros | 
|---|
| 303 |     boost::wave::language_support language;       // supported language/extensions | 
|---|
| 304 |     trace_policy_type trace;                      // trace policy instance | 
|---|
| 305 | }; | 
|---|
| 306 |  | 
|---|
| 307 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 308 | }   // namespace wave | 
|---|
| 309 | }   // namespace boost | 
|---|
| 310 |  | 
|---|
| 311 | #endif // !defined(CPP_CONTEXT_HPP_907485E2_6649_4A87_911B_7F7225F3E5B8_INCLUDED) | 
|---|