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