Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/wave/cpp_context.hpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 17.8 KB
Line 
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///////////////////////////////////////////////////////////////////////////////
48namespace boost {
49namespace 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
75template <
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>
81class context : private boost::noncopyable
82{
83public:
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   
108private:
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   
118public:
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)
247protected:
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
315public:
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
341public:
342    BOOST_STATIC_CONSTANT(unsigned int, version = 0x10);
343    BOOST_STATIC_CONSTANT(unsigned int, version_mask = 0x0f);
344
345private:
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
401private:
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
423namespace boost { namespace serialization {
424
425template<
426    typename Iterator, typename LexIterator, 
427    typename InputPolicy, typename Hooks
428>
429struct 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
439template<
440    typename Iterator, typename LexIterator, 
441    typename InputPolicy, typename Hooks
442>
443struct 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)
Note: See TracBrowser for help on using the repository browser.