source: NonGTP/Boost/boost/wave/cpp_context.hpp @ 857

Revision 857, 12.8 KB checked in by igarcia, 18 years ago (diff)
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-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///////////////////////////////////////////////////////////////////////////////
36namespace boost {
37namespace 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
60template <
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>
66class context {
67
68public:
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   
93private:
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   
105public:
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> &parameters, 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)
189protected:
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
253public:
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 &parameters, 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   
290private:
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)
Note: See TracBrowser for help on using the repository browser.