Chris@16
|
1 /*=============================================================================
|
Chris@16
|
2 Boost.Wave: A Standard compliant C++ preprocessor library
|
Chris@16
|
3 Definition of the preprocessor context
|
Chris@16
|
4
|
Chris@16
|
5 http://www.boost.org/
|
Chris@16
|
6
|
Chris@16
|
7 Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
|
Chris@16
|
8 Software License, Version 1.0. (See accompanying file
|
Chris@16
|
9 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
10 =============================================================================*/
|
Chris@16
|
11
|
Chris@16
|
12 #if !defined(CPP_CONTEXT_HPP_907485E2_6649_4A87_911B_7F7225F3E5B8_INCLUDED)
|
Chris@16
|
13 #define CPP_CONTEXT_HPP_907485E2_6649_4A87_911B_7F7225F3E5B8_INCLUDED
|
Chris@16
|
14
|
Chris@16
|
15 #include <string>
|
Chris@16
|
16 #include <vector>
|
Chris@16
|
17 #include <stack>
|
Chris@16
|
18
|
Chris@16
|
19 #include <boost/concept_check.hpp>
|
Chris@16
|
20 #include <boost/noncopyable.hpp>
|
Chris@16
|
21 #include <boost/filesystem/path.hpp>
|
Chris@16
|
22 #include <boost/mpl/if.hpp>
|
Chris@16
|
23 #include <boost/type_traits/is_same.hpp>
|
Chris@16
|
24 #include <boost/pool/pool_alloc.hpp>
|
Chris@16
|
25
|
Chris@16
|
26 #include <boost/wave/wave_config.hpp>
|
Chris@16
|
27 #if BOOST_WAVE_SERIALIZATION != 0
|
Chris@16
|
28 #include <boost/serialization/serialization.hpp>
|
Chris@16
|
29 #include <boost/wave/wave_config_constant.hpp>
|
Chris@16
|
30 #endif
|
Chris@16
|
31 #include <boost/wave/token_ids.hpp>
|
Chris@16
|
32
|
Chris@16
|
33 #include <boost/wave/util/unput_queue_iterator.hpp>
|
Chris@16
|
34 #include <boost/wave/util/cpp_ifblock.hpp>
|
Chris@16
|
35 #include <boost/wave/util/cpp_include_paths.hpp>
|
Chris@16
|
36 #include <boost/wave/util/iteration_context.hpp>
|
Chris@16
|
37 #include <boost/wave/util/cpp_iterator.hpp>
|
Chris@16
|
38 #include <boost/wave/util/cpp_macromap.hpp>
|
Chris@16
|
39
|
Chris@16
|
40 #include <boost/wave/preprocessing_hooks.hpp>
|
Chris@16
|
41 #include <boost/wave/whitespace_handling.hpp>
|
Chris@16
|
42 #include <boost/wave/cpp_iteration_context.hpp>
|
Chris@16
|
43 #include <boost/wave/language_support.hpp>
|
Chris@16
|
44
|
Chris@16
|
45 // this must occur after all of the includes and before any code appears
|
Chris@16
|
46 #ifdef BOOST_HAS_ABI_HEADERS
|
Chris@16
|
47 #include BOOST_ABI_PREFIX
|
Chris@16
|
48 #endif
|
Chris@16
|
49
|
Chris@16
|
50 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
51 namespace boost {
|
Chris@16
|
52 namespace wave {
|
Chris@16
|
53
|
Chris@16
|
54 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
55 //
|
Chris@16
|
56 // The C/C++ preprocessor context template class
|
Chris@16
|
57 //
|
Chris@16
|
58 // The boost::wave::context template is the main interface class to
|
Chris@16
|
59 // control the behavior of the preprocessing engine.
|
Chris@16
|
60 //
|
Chris@16
|
61 // The following template parameters has to be supplied:
|
Chris@16
|
62 //
|
Chris@16
|
63 // IteratorT The iterator type of the underlying input stream
|
Chris@16
|
64 // LexIteratorT The lexer iterator type to use as the token factory
|
Chris@16
|
65 // InputPolicyT The input policy type to use for loading the files
|
Chris@16
|
66 // to be included. This template parameter is optional and
|
Chris@16
|
67 // defaults to the
|
Chris@16
|
68 // iteration_context_policies::load_file_to_string
|
Chris@16
|
69 // type.
|
Chris@16
|
70 // HooksT The hooks policy to use for different notification
|
Chris@16
|
71 // callbacks. This template parameter is optional and
|
Chris@16
|
72 // defaults to the
|
Chris@16
|
73 // context_policies::default_preprocessing_hooks
|
Chris@16
|
74 // type.
|
Chris@16
|
75 // DerivedT The type of the type being derived from the context
|
Chris@16
|
76 // type (if any). This template parameter is optional and
|
Chris@16
|
77 // defaults to 'this_type', which means that the context
|
Chris@16
|
78 // type will be used assuming no derived type exists.
|
Chris@16
|
79 //
|
Chris@16
|
80 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
81
|
Chris@16
|
82 struct this_type {};
|
Chris@16
|
83
|
Chris@16
|
84 template <
|
Chris@16
|
85 typename IteratorT,
|
Chris@16
|
86 typename LexIteratorT,
|
Chris@16
|
87 typename InputPolicyT = iteration_context_policies::load_file_to_string,
|
Chris@16
|
88 typename HooksT = context_policies::eat_whitespace<typename LexIteratorT::token_type>,
|
Chris@16
|
89 typename DerivedT = this_type
|
Chris@16
|
90 >
|
Chris@16
|
91 class context : private boost::noncopyable
|
Chris@16
|
92 {
|
Chris@16
|
93 private:
|
Chris@16
|
94 typedef typename mpl::if_<
|
Chris@16
|
95 is_same<DerivedT, this_type>, context, DerivedT
|
Chris@16
|
96 >::type actual_context_type;
|
Chris@16
|
97
|
Chris@16
|
98 public:
|
Chris@16
|
99
|
Chris@16
|
100 // concept checks
|
Chris@16
|
101 // the given iterator should be at least a forward iterator type
|
Chris@16
|
102 BOOST_CLASS_REQUIRE(IteratorT, boost, ForwardIteratorConcept);
|
Chris@16
|
103
|
Chris@16
|
104 // public typedefs
|
Chris@16
|
105 typedef typename LexIteratorT::token_type token_type;
|
Chris@16
|
106 typedef typename token_type::string_type string_type;
|
Chris@16
|
107
|
Chris@16
|
108 typedef IteratorT target_iterator_type;
|
Chris@16
|
109 typedef LexIteratorT lexer_type;
|
Chris@16
|
110 typedef pp_iterator<context> iterator_type;
|
Chris@16
|
111
|
Chris@16
|
112 typedef InputPolicyT input_policy_type;
|
Chris@16
|
113 typedef typename token_type::position_type position_type;
|
Chris@16
|
114
|
Chris@16
|
115 // type of a token sequence
|
Chris@16
|
116 typedef std::list<token_type, boost::fast_pool_allocator<token_type> >
|
Chris@16
|
117 token_sequence_type;
|
Chris@16
|
118 // type of the policies
|
Chris@16
|
119 typedef HooksT hook_policy_type;
|
Chris@16
|
120
|
Chris@16
|
121 private:
|
Chris@16
|
122 // stack of shared_ptr's to the pending iteration contexts
|
Chris@16
|
123 typedef boost::shared_ptr<base_iteration_context<context, lexer_type> >
|
Chris@16
|
124 iteration_ptr_type;
|
Chris@16
|
125 typedef boost::wave::util::iteration_context_stack<iteration_ptr_type>
|
Chris@16
|
126 iteration_context_stack_type;
|
Chris@16
|
127 typedef typename iteration_context_stack_type::size_type iter_size_type;
|
Chris@16
|
128
|
Chris@16
|
129 context *this_() { return this; } // avoid warning in constructor
|
Chris@16
|
130
|
Chris@16
|
131 public:
|
Chris@16
|
132 context(target_iterator_type const &first_, target_iterator_type const &last_,
|
Chris@16
|
133 char const *fname = "<Unknown>", HooksT const &hooks_ = HooksT())
|
Chris@16
|
134 : first(first_), last(last_), filename(fname)
|
Chris@16
|
135 , has_been_initialized(false)
|
Chris@16
|
136 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
|
Chris@16
|
137 , current_filename(fname)
|
Chris@16
|
138 #endif
|
Chris@16
|
139 , current_relative_filename(fname)
|
Chris@16
|
140 , macros(*this_())
|
Chris@16
|
141 , language(language_support(
|
Chris@16
|
142 support_cpp
|
Chris@16
|
143 | support_option_convert_trigraphs
|
Chris@16
|
144 | support_option_emit_line_directives
|
Chris@16
|
145 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
|
Chris@16
|
146 | support_option_include_guard_detection
|
Chris@16
|
147 #endif
|
Chris@16
|
148 #if BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES != 0
|
Chris@16
|
149 | support_option_emit_pragma_directives
|
Chris@16
|
150 #endif
|
Chris@16
|
151 | support_option_insert_whitespace
|
Chris@16
|
152 ))
|
Chris@16
|
153 , hooks(hooks_)
|
Chris@16
|
154 {
|
Chris@16
|
155 macros.init_predefined_macros(fname);
|
Chris@16
|
156 }
|
Chris@16
|
157
|
Chris@16
|
158 // default copy constructor
|
Chris@16
|
159 // default assignment operator
|
Chris@16
|
160 // default destructor
|
Chris@16
|
161
|
Chris@16
|
162 // iterator interface
|
Chris@16
|
163 iterator_type begin()
|
Chris@16
|
164 {
|
Chris@16
|
165 std::string fname(filename);
|
Chris@16
|
166 if (filename != "<Unknown>" && filename != "<stdin>") {
|
Chris@16
|
167 using namespace boost::filesystem;
|
Chris@16
|
168 path fpath(util::complete_path(path(filename)));
|
Chris@16
|
169 fname = fpath.string();
|
Chris@16
|
170 }
|
Chris@16
|
171 return iterator_type(*this, first, last, position_type(fname.c_str()));
|
Chris@16
|
172 }
|
Chris@16
|
173 iterator_type begin(
|
Chris@16
|
174 target_iterator_type const &first_,
|
Chris@16
|
175 target_iterator_type const &last_)
|
Chris@16
|
176 {
|
Chris@16
|
177 std::string fname(filename);
|
Chris@16
|
178 if (filename != "<Unknown>" && filename != "<stdin>") {
|
Chris@16
|
179 using namespace boost::filesystem;
|
Chris@16
|
180 path fpath(util::complete_path(path(filename)));
|
Chris@16
|
181 fname = fpath.string();
|
Chris@16
|
182 }
|
Chris@16
|
183 return iterator_type(*this, first_, last_, position_type(fname.c_str()));
|
Chris@16
|
184 }
|
Chris@16
|
185 iterator_type end() const
|
Chris@16
|
186 { return iterator_type(); }
|
Chris@16
|
187
|
Chris@16
|
188 // maintain include paths
|
Chris@16
|
189 bool add_include_path(char const *path_)
|
Chris@16
|
190 { return includes.add_include_path(path_, false);}
|
Chris@16
|
191 bool add_sysinclude_path(char const *path_)
|
Chris@16
|
192 { return includes.add_include_path(path_, true);}
|
Chris@16
|
193 void set_sysinclude_delimiter() { includes.set_sys_include_delimiter(); }
|
Chris@16
|
194 typename iteration_context_stack_type::size_type get_iteration_depth() const
|
Chris@16
|
195 { return iter_ctxs.size(); }
|
Chris@16
|
196
|
Chris@16
|
197 // maintain defined macros
|
Chris@16
|
198 #if BOOST_WAVE_ENABLE_COMMANDLINE_MACROS != 0
|
Chris@16
|
199 template <typename StringT>
|
Chris@16
|
200 bool add_macro_definition(StringT macrostring, bool is_predefined = false)
|
Chris@16
|
201 {
|
Chris@16
|
202 return boost::wave::util::add_macro_definition(*this,
|
Chris@16
|
203 util::to_string<std::string>(macrostring), is_predefined,
|
Chris@16
|
204 get_language());
|
Chris@16
|
205 }
|
Chris@16
|
206 #endif
|
Chris@16
|
207 // Define and undefine macros, macro introspection
|
Chris@16
|
208 template <typename StringT>
|
Chris@16
|
209 bool add_macro_definition(StringT const &name, position_type const& pos,
|
Chris@16
|
210 bool has_params, std::vector<token_type> ¶meters,
|
Chris@16
|
211 token_sequence_type &definition, bool is_predefined = false)
|
Chris@16
|
212 {
|
Chris@16
|
213 return macros.add_macro(
|
Chris@16
|
214 token_type(T_IDENTIFIER, util::to_string<string_type>(name), pos),
|
Chris@16
|
215 has_params, parameters, definition, is_predefined);
|
Chris@16
|
216 }
|
Chris@16
|
217 template <typename StringT>
|
Chris@16
|
218 bool is_defined_macro(StringT const &str) const
|
Chris@16
|
219 {
|
Chris@16
|
220 return macros.is_defined(util::to_string<string_type>(str));
|
Chris@16
|
221 }
|
Chris@16
|
222 template <typename StringT>
|
Chris@16
|
223 bool get_macro_definition(StringT const &name,
|
Chris@16
|
224 bool &has_params, bool &is_predefined, position_type &pos,
|
Chris@16
|
225 std::vector<token_type> ¶meters,
|
Chris@16
|
226 token_sequence_type &definition) const
|
Chris@16
|
227 {
|
Chris@16
|
228 return macros.get_macro(util::to_string<string_type>(name),
|
Chris@16
|
229 has_params, is_predefined, pos, parameters, definition);
|
Chris@16
|
230 }
|
Chris@16
|
231 template <typename StringT>
|
Chris@16
|
232 bool remove_macro_definition(StringT const& undefname, bool even_predefined = false)
|
Chris@16
|
233 {
|
Chris@16
|
234 // strip leading and trailing whitespace
|
Chris@16
|
235 string_type name = util::to_string<string_type>(undefname);
|
Chris@16
|
236 typename string_type::size_type pos = name.find_first_not_of(" \t");
|
Chris@16
|
237 if (pos != string_type::npos) {
|
Chris@16
|
238 typename string_type::size_type endpos = name.find_last_not_of(" \t");
|
Chris@16
|
239 name = name.substr(pos, endpos-pos+1);
|
Chris@16
|
240 }
|
Chris@16
|
241
|
Chris@16
|
242 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
|
Chris@16
|
243 // ensure this gets removed from the list of include guards as well
|
Chris@16
|
244 includes.remove_pragma_once_header(
|
Chris@16
|
245 util::to_string<std::string>(name));
|
Chris@16
|
246 #endif
|
Chris@16
|
247 return macros.remove_macro(name, macros.get_main_pos(), even_predefined);
|
Chris@16
|
248 }
|
Chris@16
|
249 void reset_macro_definitions()
|
Chris@16
|
250 { macros.reset_macromap(); macros.init_predefined_macros(); }
|
Chris@16
|
251
|
Chris@16
|
252 // Iterate over names of defined macros
|
Chris@16
|
253 typedef boost::wave::util::macromap<context> macromap_type;
|
Chris@16
|
254 typedef typename macromap_type::name_iterator name_iterator;
|
Chris@16
|
255 typedef typename macromap_type::const_name_iterator const_name_iterator;
|
Chris@16
|
256
|
Chris@16
|
257 name_iterator macro_names_begin() { return macros.begin(); }
|
Chris@16
|
258 name_iterator macro_names_end() { return macros.end(); }
|
Chris@16
|
259 const_name_iterator macro_names_begin() const { return macros.begin(); }
|
Chris@16
|
260 const_name_iterator macro_names_end() const { return macros.end(); }
|
Chris@16
|
261
|
Chris@16
|
262 // This version now is used internally mainly, but since it was a documented
|
Chris@16
|
263 // API function we leave it in the public interface.
|
Chris@16
|
264 bool add_macro_definition(token_type const &name, bool has_params,
|
Chris@16
|
265 std::vector<token_type> ¶meters, token_sequence_type &definition,
|
Chris@16
|
266 bool is_predefined = false)
|
Chris@16
|
267 {
|
Chris@16
|
268 return macros.add_macro(name, has_params, parameters, definition,
|
Chris@16
|
269 is_predefined);
|
Chris@16
|
270 }
|
Chris@16
|
271
|
Chris@16
|
272 // get the Wave version information
|
Chris@16
|
273 static std::string get_version()
|
Chris@16
|
274 {
|
Chris@16
|
275 boost::wave::util::predefined_macros p;
|
Chris@16
|
276 return util::to_string<std::string>(p.get_fullversion());
|
Chris@16
|
277 }
|
Chris@16
|
278 static std::string get_version_string()
|
Chris@16
|
279 {
|
Chris@16
|
280 boost::wave::util::predefined_macros p;
|
Chris@16
|
281 return util::to_string<std::string>(p.get_versionstr());
|
Chris@16
|
282 }
|
Chris@16
|
283
|
Chris@16
|
284 // access current language options
|
Chris@16
|
285 void set_language(boost::wave::language_support language_,
|
Chris@16
|
286 bool reset_macros = true)
|
Chris@16
|
287 {
|
Chris@16
|
288 language = language_;
|
Chris@16
|
289 if (reset_macros)
|
Chris@16
|
290 reset_macro_definitions();
|
Chris@16
|
291 }
|
Chris@16
|
292 boost::wave::language_support get_language() const { return language; }
|
Chris@16
|
293
|
Chris@16
|
294 position_type &get_main_pos() { return macros.get_main_pos(); }
|
Chris@16
|
295 position_type const& get_main_pos() const { return macros.get_main_pos(); }
|
Chris@16
|
296
|
Chris@16
|
297 // change and ask for maximal possible include nesting depth
|
Chris@16
|
298 void set_max_include_nesting_depth(iter_size_type new_depth)
|
Chris@16
|
299 { iter_ctxs.set_max_include_nesting_depth(new_depth); }
|
Chris@16
|
300 iter_size_type get_max_include_nesting_depth() const
|
Chris@16
|
301 { return iter_ctxs.get_max_include_nesting_depth(); }
|
Chris@16
|
302
|
Chris@16
|
303 // access the policies
|
Chris@16
|
304 hook_policy_type &get_hooks() { return hooks; }
|
Chris@16
|
305 hook_policy_type const &get_hooks() const { return hooks; }
|
Chris@16
|
306
|
Chris@16
|
307 // return type of actually used context type (might be the derived type)
|
Chris@16
|
308 actual_context_type& derived()
|
Chris@16
|
309 { return *static_cast<actual_context_type*>(this); }
|
Chris@16
|
310 actual_context_type const& derived() const
|
Chris@16
|
311 { return *static_cast<actual_context_type const*>(this); }
|
Chris@16
|
312
|
Chris@16
|
313 // return the directory of the currently preprocessed file
|
Chris@16
|
314 boost::filesystem::path get_current_directory() const
|
Chris@16
|
315 { return includes.get_current_directory(); }
|
Chris@16
|
316
|
Chris@16
|
317 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
Chris@16
|
318 protected:
|
Chris@16
|
319 friend class boost::wave::pp_iterator<context>;
|
Chris@16
|
320 friend class boost::wave::impl::pp_iterator_functor<context>;
|
Chris@16
|
321 #endif
|
Chris@16
|
322
|
Chris@16
|
323 // make sure the context has been initialized
|
Chris@16
|
324 void init_context()
|
Chris@16
|
325 {
|
Chris@16
|
326 if (!has_been_initialized) {
|
Chris@16
|
327 std::string fname(filename);
|
Chris@16
|
328 if (filename != "<Unknown>" && filename != "<stdin>") {
|
Chris@16
|
329 using namespace boost::filesystem;
|
Chris@16
|
330 path fpath(util::complete_path(path(filename)));
|
Chris@16
|
331 fname = fpath.string();
|
Chris@16
|
332 includes.set_current_directory(fname.c_str());
|
Chris@16
|
333 }
|
Chris@16
|
334 has_been_initialized = true; // execute once
|
Chris@16
|
335 }
|
Chris@16
|
336 }
|
Chris@16
|
337
|
Chris@16
|
338 template <typename IteratorT2>
|
Chris@16
|
339 bool is_defined_macro(IteratorT2 const &begin, IteratorT2 const &end) const
|
Chris@16
|
340 { return macros.is_defined(begin, end); }
|
Chris@16
|
341
|
Chris@16
|
342 // maintain include paths (helper functions)
|
Chris@16
|
343 void set_current_directory(char const *path_)
|
Chris@16
|
344 { includes.set_current_directory(path_); }
|
Chris@16
|
345
|
Chris@16
|
346 // conditional compilation contexts
|
Chris@16
|
347 bool get_if_block_status() const { return ifblocks.get_status(); }
|
Chris@16
|
348 bool get_if_block_some_part_status() const
|
Chris@16
|
349 { return ifblocks.get_some_part_status(); }
|
Chris@16
|
350 bool get_enclosing_if_block_status() const
|
Chris@16
|
351 { return ifblocks.get_enclosing_status(); }
|
Chris@16
|
352 void enter_if_block(bool new_status)
|
Chris@16
|
353 { ifblocks.enter_if_block(new_status); }
|
Chris@16
|
354 bool enter_elif_block(bool new_status)
|
Chris@16
|
355 { return ifblocks.enter_elif_block(new_status); }
|
Chris@16
|
356 bool enter_else_block() { return ifblocks.enter_else_block(); }
|
Chris@16
|
357 bool exit_if_block() { return ifblocks.exit_if_block(); }
|
Chris@16
|
358 typename boost::wave::util::if_block_stack::size_type get_if_block_depth() const
|
Chris@16
|
359 { return ifblocks.get_if_block_depth(); }
|
Chris@16
|
360
|
Chris@16
|
361 // stack of iteration contexts
|
Chris@16
|
362 iteration_ptr_type pop_iteration_context()
|
Chris@16
|
363 { iteration_ptr_type top = iter_ctxs.top(); iter_ctxs.pop(); return top; }
|
Chris@16
|
364 void push_iteration_context(position_type const &act_pos, iteration_ptr_type iter_ctx)
|
Chris@16
|
365 { iter_ctxs.push(*this, act_pos, iter_ctx); }
|
Chris@16
|
366
|
Chris@16
|
367 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
368 //
|
Chris@16
|
369 // expand_tokensequence():
|
Chris@16
|
370 // expands all macros contained in a given token sequence, handles '##'
|
Chris@16
|
371 // and '#' pp operators and re-scans the resulting sequence
|
Chris@16
|
372 // (essentially pre-processes the token sequence).
|
Chris@16
|
373 //
|
Chris@16
|
374 // The expand_undefined parameter is true during macro expansion inside
|
Chris@16
|
375 // a C++ expression given for a #if or #elif statement.
|
Chris@16
|
376 //
|
Chris@16
|
377 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
378 template <typename IteratorT2>
|
Chris@16
|
379 token_type expand_tokensequence(IteratorT2 &first_, IteratorT2 const &last_,
|
Chris@16
|
380 token_sequence_type &pending, token_sequence_type &expanded,
|
Chris@16
|
381 bool& seen_newline, bool expand_undefined = false)
|
Chris@16
|
382 {
|
Chris@16
|
383 return macros.expand_tokensequence(first_, last_, pending, expanded,
|
Chris@16
|
384 seen_newline, expand_undefined);
|
Chris@16
|
385 }
|
Chris@16
|
386
|
Chris@16
|
387 template <typename IteratorT2>
|
Chris@16
|
388 void expand_whole_tokensequence(IteratorT2 &first_, IteratorT2 const &last_,
|
Chris@16
|
389 token_sequence_type &expanded, bool expand_undefined = true)
|
Chris@16
|
390 {
|
Chris@16
|
391 macros.expand_whole_tokensequence(expanded, first_, last_,
|
Chris@16
|
392 expand_undefined);
|
Chris@16
|
393
|
Chris@16
|
394 // remove any contained placeholder
|
Chris@16
|
395 boost::wave::util::impl::remove_placeholders(expanded);
|
Chris@16
|
396 }
|
Chris@16
|
397
|
Chris@16
|
398 public:
|
Chris@16
|
399 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
|
Chris@16
|
400 // support for #pragma once
|
Chris@16
|
401 // maintain the real name of the current preprocessed file
|
Chris@16
|
402 void set_current_filename(char const *real_name)
|
Chris@16
|
403 { current_filename = real_name; }
|
Chris@16
|
404 std::string const &get_current_filename() const
|
Chris@16
|
405 { return current_filename; }
|
Chris@16
|
406
|
Chris@16
|
407 // maintain the list of known headers containing #pragma once
|
Chris@16
|
408 bool has_pragma_once(std::string const &filename_)
|
Chris@16
|
409 { return includes.has_pragma_once(filename_); }
|
Chris@16
|
410 bool add_pragma_once_header(std::string const &filename_,
|
Chris@16
|
411 std::string const& guard_name)
|
Chris@16
|
412 {
|
Chris@16
|
413 get_hooks().detected_include_guard(derived(), filename_, guard_name);
|
Chris@16
|
414 return includes.add_pragma_once_header(filename_, guard_name);
|
Chris@16
|
415 }
|
Chris@16
|
416 bool add_pragma_once_header(token_type const &pragma_,
|
Chris@16
|
417 std::string const &filename_)
|
Chris@16
|
418 {
|
Chris@16
|
419 get_hooks().detected_pragma_once(derived(), pragma_, filename_);
|
Chris@16
|
420 return includes.add_pragma_once_header(filename_,
|
Chris@16
|
421 "__BOOST_WAVE_PRAGMA_ONCE__");
|
Chris@16
|
422 }
|
Chris@16
|
423 #endif
|
Chris@16
|
424
|
Chris@16
|
425 void set_current_relative_filename(char const *real_name)
|
Chris@16
|
426 { current_relative_filename = real_name; }
|
Chris@16
|
427 std::string const &get_current_relative_filename() const
|
Chris@16
|
428 { return current_relative_filename; }
|
Chris@16
|
429
|
Chris@16
|
430 bool find_include_file (std::string &s, std::string &d, bool is_system,
|
Chris@16
|
431 char const *current_file) const
|
Chris@16
|
432 { return includes.find_include_file(s, d, is_system, current_file); }
|
Chris@16
|
433
|
Chris@16
|
434 #if BOOST_WAVE_SERIALIZATION != 0
|
Chris@16
|
435 public:
|
Chris@16
|
436 BOOST_STATIC_CONSTANT(unsigned int, version = 0x10);
|
Chris@16
|
437 BOOST_STATIC_CONSTANT(unsigned int, version_mask = 0x0f);
|
Chris@16
|
438
|
Chris@16
|
439 private:
|
Chris@16
|
440 friend class boost::serialization::access;
|
Chris@16
|
441 template<class Archive>
|
Chris@16
|
442 void save(Archive & ar, const unsigned int version) const
|
Chris@16
|
443 {
|
Chris@16
|
444 using namespace boost::serialization;
|
Chris@16
|
445
|
Chris@16
|
446 string_type cfg(BOOST_PP_STRINGIZE(BOOST_WAVE_CONFIG));
|
Chris@16
|
447 string_type kwd(BOOST_WAVE_PRAGMA_KEYWORD);
|
Chris@16
|
448 string_type strtype(BOOST_PP_STRINGIZE((BOOST_WAVE_STRINGTYPE)));
|
Chris@16
|
449 ar & make_nvp("config", cfg);
|
Chris@16
|
450 ar & make_nvp("pragma_keyword", kwd);
|
Chris@16
|
451 ar & make_nvp("string_type", strtype);
|
Chris@16
|
452
|
Chris@16
|
453 ar & make_nvp("language_options", language);
|
Chris@16
|
454 ar & make_nvp("macro_definitions", macros);
|
Chris@16
|
455 ar & make_nvp("include_settings", includes);
|
Chris@16
|
456 }
|
Chris@16
|
457 template<class Archive>
|
Chris@16
|
458 void load(Archive & ar, const unsigned int loaded_version)
|
Chris@16
|
459 {
|
Chris@16
|
460 using namespace boost::serialization;
|
Chris@16
|
461 if (version != (loaded_version & ~version_mask)) {
|
Chris@16
|
462 BOOST_WAVE_THROW_CTX((*this), preprocess_exception,
|
Chris@16
|
463 incompatible_config, "cpp_context state version",
|
Chris@16
|
464 get_main_pos());
|
Chris@16
|
465 return;
|
Chris@16
|
466 }
|
Chris@16
|
467
|
Chris@16
|
468 // check compatibility of the stored information
|
Chris@16
|
469 string_type config, pragma_keyword, string_type_str;
|
Chris@16
|
470
|
Chris@16
|
471 // BOOST_PP_STRINGIZE(BOOST_WAVE_CONFIG)
|
Chris@16
|
472 ar & make_nvp("config", config);
|
Chris@16
|
473 if (config != BOOST_PP_STRINGIZE(BOOST_WAVE_CONFIG)) {
|
Chris@16
|
474 BOOST_WAVE_THROW_CTX((*this), preprocess_exception,
|
Chris@16
|
475 incompatible_config, "BOOST_WAVE_CONFIG", get_main_pos());
|
Chris@16
|
476 return;
|
Chris@16
|
477 }
|
Chris@16
|
478
|
Chris@16
|
479 // BOOST_WAVE_PRAGMA_KEYWORD
|
Chris@16
|
480 ar & make_nvp("pragma_keyword", pragma_keyword);
|
Chris@16
|
481 if (pragma_keyword != BOOST_WAVE_PRAGMA_KEYWORD) {
|
Chris@16
|
482 BOOST_WAVE_THROW_CTX((*this), preprocess_exception,
|
Chris@16
|
483 incompatible_config, "BOOST_WAVE_PRAGMA_KEYWORD",
|
Chris@16
|
484 get_main_pos());
|
Chris@16
|
485 return;
|
Chris@16
|
486 }
|
Chris@16
|
487
|
Chris@16
|
488 // BOOST_PP_STRINGIZE((BOOST_WAVE_STRINGTYPE))
|
Chris@16
|
489 ar & make_nvp("string_type", string_type_str);
|
Chris@16
|
490 if (string_type_str != BOOST_PP_STRINGIZE((BOOST_WAVE_STRINGTYPE))) {
|
Chris@16
|
491 BOOST_WAVE_THROW_CTX((*this), preprocess_exception,
|
Chris@16
|
492 incompatible_config, "BOOST_WAVE_STRINGTYPE", get_main_pos());
|
Chris@16
|
493 return;
|
Chris@16
|
494 }
|
Chris@16
|
495
|
Chris@16
|
496 try {
|
Chris@16
|
497 // read in the useful bits
|
Chris@16
|
498 ar & make_nvp("language_options", language);
|
Chris@16
|
499 ar & make_nvp("macro_definitions", macros);
|
Chris@16
|
500 ar & make_nvp("include_settings", includes);
|
Chris@16
|
501 }
|
Chris@16
|
502 catch (boost::wave::preprocess_exception const& e) {
|
Chris@16
|
503 // catch version mismatch exceptions and call error handler
|
Chris@16
|
504 get_hooks().throw_exception(derived(), e);
|
Chris@16
|
505 }
|
Chris@16
|
506 }
|
Chris@16
|
507 BOOST_SERIALIZATION_SPLIT_MEMBER()
|
Chris@16
|
508 #endif
|
Chris@16
|
509
|
Chris@16
|
510 private:
|
Chris@16
|
511 // the main input stream
|
Chris@16
|
512 target_iterator_type first; // underlying input stream
|
Chris@16
|
513 target_iterator_type last;
|
Chris@16
|
514 std::string filename; // associated main filename
|
Chris@16
|
515 bool has_been_initialized; // set cwd once
|
Chris@16
|
516 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
|
Chris@16
|
517 std::string current_filename; // real name of current preprocessed file
|
Chris@16
|
518 #endif
|
Chris@16
|
519 std::string current_relative_filename; // real relative name of current preprocessed file
|
Chris@16
|
520
|
Chris@16
|
521 boost::wave::util::if_block_stack ifblocks; // conditional compilation contexts
|
Chris@16
|
522 boost::wave::util::include_paths includes; // lists of include directories to search
|
Chris@16
|
523 iteration_context_stack_type iter_ctxs; // iteration contexts
|
Chris@16
|
524 macromap_type macros; // map of defined macros
|
Chris@16
|
525 boost::wave::language_support language; // supported language/extensions
|
Chris@16
|
526 hook_policy_type hooks; // hook policy instance
|
Chris@16
|
527 };
|
Chris@16
|
528
|
Chris@16
|
529 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
530 } // namespace wave
|
Chris@16
|
531 } // namespace boost
|
Chris@16
|
532
|
Chris@16
|
533 #if BOOST_WAVE_SERIALIZATION != 0
|
Chris@16
|
534 namespace boost { namespace serialization {
|
Chris@16
|
535
|
Chris@16
|
536 template<
|
Chris@16
|
537 typename Iterator, typename LexIterator,
|
Chris@16
|
538 typename InputPolicy, typename Hooks
|
Chris@16
|
539 >
|
Chris@16
|
540 struct tracking_level<boost::wave::context<Iterator, LexIterator, InputPolicy, Hooks> >
|
Chris@16
|
541 {
|
Chris@16
|
542 typedef mpl::integral_c_tag tag;
|
Chris@16
|
543 typedef mpl::int_<track_never> type;
|
Chris@16
|
544 BOOST_STATIC_CONSTANT(
|
Chris@16
|
545 int,
|
Chris@16
|
546 value = tracking_level::type::value
|
Chris@16
|
547 );
|
Chris@16
|
548 };
|
Chris@16
|
549
|
Chris@16
|
550 template<
|
Chris@16
|
551 typename Iterator, typename LexIterator,
|
Chris@16
|
552 typename InputPolicy, typename Hooks
|
Chris@16
|
553 >
|
Chris@16
|
554 struct version<boost::wave::context<Iterator, LexIterator, InputPolicy, Hooks> >
|
Chris@16
|
555 {
|
Chris@16
|
556 typedef boost::wave::context<Iterator, LexIterator, InputPolicy, Hooks>
|
Chris@16
|
557 target_type;
|
Chris@16
|
558 typedef mpl::int_<target_type::version> type;
|
Chris@16
|
559 typedef mpl::integral_c_tag tag;
|
Chris@16
|
560 BOOST_STATIC_CONSTANT(unsigned int, value = version::type::value);
|
Chris@16
|
561 };
|
Chris@16
|
562
|
Chris@16
|
563 }} // namespace boost::serialization
|
Chris@16
|
564 #endif
|
Chris@16
|
565
|
Chris@16
|
566 // the suffix header occurs after all of the code
|
Chris@16
|
567 #ifdef BOOST_HAS_ABI_HEADERS
|
Chris@16
|
568 #include BOOST_ABI_SUFFIX
|
Chris@16
|
569 #endif
|
Chris@16
|
570
|
Chris@16
|
571 #endif // !defined(CPP_CONTEXT_HPP_907485E2_6649_4A87_911B_7F7225F3E5B8_INCLUDED)
|