• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(BOOST_CPP_CONTEXT_HPP_907485E2_6649_4A87_911B_7F7225F3E5B8_INCLUDED)
13 #define BOOST_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 
this_()129     context *this_() { return this; }           // avoid warning in constructor
130 
131 public:
context(target_iterator_type const & first_,target_iterator_type const & last_,char const * fname="<Unknown>",HooksT const & hooks_=HooksT ())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
begin()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     }
begin(target_iterator_type const & first_,target_iterator_type const & last_)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     }
end() const185     iterator_type end() const
186         { return iterator_type(); }
187 
188 // maintain include paths
add_include_path(char const * path_)189     bool add_include_path(char const *path_)
190         { return includes.add_include_path(path_, false);}
add_sysinclude_path(char const * path_)191     bool add_sysinclude_path(char const *path_)
192         { return includes.add_include_path(path_, true);}
set_sysinclude_delimiter()193     void set_sysinclude_delimiter() { includes.set_sys_include_delimiter(); }
get_iteration_depth() const194     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>
add_macro_definition(StringT macrostring,bool is_predefined=false)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>
add_macro_definition(StringT const & name,position_type const & pos,bool has_params,std::vector<token_type> & parameters,token_sequence_type & definition,bool is_predefined=false)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>
is_defined_macro(StringT const & str) const218     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>
get_macro_definition(StringT const & name,bool & has_params,bool & is_predefined,position_type & pos,std::vector<token_type> & parameters,token_sequence_type & definition) const223     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>
remove_macro_definition(StringT const & undefname,bool even_predefined=false)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     }
reset_macro_definitions()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 
macro_names_begin()257     name_iterator macro_names_begin() { return macros.begin(); }
macro_names_end()258     name_iterator macro_names_end() { return macros.end(); }
macro_names_begin() const259     const_name_iterator macro_names_begin() const { return macros.begin(); }
macro_names_end() const260     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.
add_macro_definition(token_type const & name,bool has_params,std::vector<token_type> & parameters,token_sequence_type & definition,bool is_predefined=false)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
get_version()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     }
get_version_string()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
set_language(boost::wave::language_support language_,bool reset_macros=true)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     }
get_language() const292     boost::wave::language_support get_language() const { return language; }
293 
get_main_pos()294     position_type &get_main_pos() { return macros.get_main_pos(); }
get_main_pos() const295     position_type const& get_main_pos() const { return macros.get_main_pos(); }
296 
297 // change and ask for maximal possible include nesting depth
set_max_include_nesting_depth(iter_size_type new_depth)298     void set_max_include_nesting_depth(iter_size_type new_depth)
299         { iter_ctxs.set_max_include_nesting_depth(new_depth); }
get_max_include_nesting_depth() const300     iter_size_type get_max_include_nesting_depth() const
301         { return iter_ctxs.get_max_include_nesting_depth(); }
302 
303 // access the policies
get_hooks()304     hook_policy_type &get_hooks() { return hooks; }
get_hooks() const305     hook_policy_type const &get_hooks() const { return hooks; }
306 
307 // return type of actually used context type (might be the derived type)
derived()308     actual_context_type& derived()
309         { return *static_cast<actual_context_type*>(this); }
derived() const310     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
get_current_directory() const314     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     friend class boost::wave::util::macromap<context>;
322 #endif
323 
324 // make sure the context has been initialized
init_context()325     void init_context()
326     {
327         if (!has_been_initialized) {
328             std::string fname(filename);
329             if (filename != "<Unknown>" && filename != "<stdin>") {
330                 using namespace boost::filesystem;
331                 path fpath(util::complete_path(path(filename)));
332                 fname = fpath.string();
333                 includes.set_current_directory(fname.c_str());
334             }
335             has_been_initialized = true;  // execute once
336         }
337     }
338 
339     template <typename IteratorT2>
is_defined_macro(IteratorT2 const & begin,IteratorT2 const & end) const340     bool is_defined_macro(IteratorT2 const &begin, IteratorT2 const &end) const
341         { return macros.is_defined(begin, end); }
342 
343 // maintain include paths (helper functions)
set_current_directory(char const * path_)344     void set_current_directory(char const *path_)
345         { includes.set_current_directory(path_); }
346 
347 // conditional compilation contexts
get_if_block_status() const348     bool get_if_block_status() const { return ifblocks.get_status(); }
get_if_block_some_part_status() const349     bool get_if_block_some_part_status() const
350         { return ifblocks.get_some_part_status(); }
get_enclosing_if_block_status() const351     bool get_enclosing_if_block_status() const
352         { return ifblocks.get_enclosing_status(); }
enter_if_block(bool new_status)353     void enter_if_block(bool new_status)
354         { ifblocks.enter_if_block(new_status); }
enter_elif_block(bool new_status)355     bool enter_elif_block(bool new_status)
356         { return ifblocks.enter_elif_block(new_status); }
enter_else_block()357     bool enter_else_block() { return ifblocks.enter_else_block(); }
exit_if_block()358     bool exit_if_block() { return ifblocks.exit_if_block(); }
get_if_block_depth() const359     typename boost::wave::util::if_block_stack::size_type get_if_block_depth() const
360         { return ifblocks.get_if_block_depth(); }
361 
362 // stack of iteration contexts
pop_iteration_context()363     iteration_ptr_type pop_iteration_context()
364         { iteration_ptr_type top = iter_ctxs.top(); iter_ctxs.pop(); return top; }
push_iteration_context(position_type const & act_pos,iteration_ptr_type iter_ctx)365     void push_iteration_context(position_type const &act_pos, iteration_ptr_type iter_ctx)
366         { iter_ctxs.push(*this, act_pos, iter_ctx); }
367 
368 ///////////////////////////////////////////////////////////////////////////////
369 //
370 //  expand_tokensequence():
371 //      expands all macros contained in a given token sequence, handles '##'
372 //      and '#' pp operators and re-scans the resulting sequence
373 //      (essentially pre-processes the token sequence).
374 //
375 //      The expand_defined parameter is true during macro expansion inside
376 //      a C++ expression given for a #if or #elif statement.
377 //
378 ///////////////////////////////////////////////////////////////////////////////
379     template <typename IteratorT2>
expand_tokensequence(IteratorT2 & first_,IteratorT2 const & last_,token_sequence_type & pending,token_sequence_type & expanded,bool & seen_newline,bool expand_defined=false,bool expand_has_include=false)380     token_type expand_tokensequence(IteratorT2 &first_, IteratorT2 const &last_,
381         token_sequence_type &pending, token_sequence_type &expanded,
382         bool& seen_newline, bool expand_defined = false,
383         bool expand_has_include = false)
384     {
385         return macros.expand_tokensequence(first_, last_, pending, expanded,
386             seen_newline, expand_defined, expand_has_include);
387     }
388 
389     template <typename IteratorT2>
expand_whole_tokensequence(IteratorT2 & first_,IteratorT2 const & last_,token_sequence_type & expanded,bool expand_defined=true,bool expand_has_include=true)390     void expand_whole_tokensequence(IteratorT2 &first_, IteratorT2 const &last_,
391         token_sequence_type &expanded, bool expand_defined = true,
392         bool expand_has_include = true)
393     {
394         macros.expand_whole_tokensequence(
395             expanded, first_, last_,
396             expand_defined, expand_has_include);
397 
398     // remove any contained placeholder
399         boost::wave::util::impl::remove_placeholders(expanded);
400     }
401 
402 public:
403 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
404 // support for #pragma once
405 // maintain the real name of the current preprocessed file
set_current_filename(char const * real_name)406     void set_current_filename(char const *real_name)
407         { current_filename = real_name; }
get_current_filename() const408     std::string const &get_current_filename() const
409         { return current_filename; }
410 
411 // maintain the list of known headers containing #pragma once
has_pragma_once(std::string const & filename_)412     bool has_pragma_once(std::string const &filename_)
413         { return includes.has_pragma_once(filename_); }
add_pragma_once_header(std::string const & filename_,std::string const & guard_name)414     bool add_pragma_once_header(std::string const &filename_,
415             std::string const& guard_name)
416     {
417         get_hooks().detected_include_guard(derived(), filename_, guard_name);
418         return includes.add_pragma_once_header(filename_, guard_name);
419     }
add_pragma_once_header(token_type const & pragma_,std::string const & filename_)420     bool add_pragma_once_header(token_type const &pragma_,
421         std::string const &filename_)
422     {
423         get_hooks().detected_pragma_once(derived(), pragma_, filename_);
424         return includes.add_pragma_once_header(filename_,
425             "__BOOST_WAVE_PRAGMA_ONCE__");
426     }
427 #endif
428 
set_current_relative_filename(char const * real_name)429     void set_current_relative_filename(char const *real_name)
430         { current_relative_filename = real_name; }
get_current_relative_filename() const431     std::string const &get_current_relative_filename() const
432         { return current_relative_filename; }
433 
find_include_file(std::string & s,std::string & d,bool is_system,char const * current_file) const434     bool find_include_file (std::string &s, std::string &d, bool is_system,
435         char const *current_file) const
436     { return includes.find_include_file(s, d, is_system, current_file); }
437 
438 #if BOOST_WAVE_SERIALIZATION != 0
439 public:
440     BOOST_STATIC_CONSTANT(unsigned int, version = 0x10);
441     BOOST_STATIC_CONSTANT(unsigned int, version_mask = 0x0f);
442 
443 private:
444     friend class boost::serialization::access;
445     template<class Archive>
save(Archive & ar,const unsigned int version) const446     void save(Archive & ar, const unsigned int version) const
447     {
448         using namespace boost::serialization;
449 
450         string_type cfg(BOOST_PP_STRINGIZE(BOOST_WAVE_CONFIG));
451         string_type kwd(BOOST_WAVE_PRAGMA_KEYWORD);
452         string_type strtype(BOOST_PP_STRINGIZE((BOOST_WAVE_STRINGTYPE)));
453         ar & make_nvp("config", cfg);
454         ar & make_nvp("pragma_keyword", kwd);
455         ar & make_nvp("string_type", strtype);
456 
457         ar & make_nvp("language_options", language);
458         ar & make_nvp("macro_definitions", macros);
459         ar & make_nvp("include_settings", includes);
460     }
461     template<class Archive>
load(Archive & ar,const unsigned int loaded_version)462     void load(Archive & ar, const unsigned int loaded_version)
463     {
464         using namespace boost::serialization;
465         if (version != (loaded_version & ~version_mask)) {
466             BOOST_WAVE_THROW_CTX((*this), preprocess_exception,
467                 incompatible_config, "cpp_context state version",
468                 get_main_pos());
469             return;
470         }
471 
472         // check compatibility of the stored information
473         string_type config, pragma_keyword, string_type_str;
474 
475         // BOOST_PP_STRINGIZE(BOOST_WAVE_CONFIG)
476         ar & make_nvp("config", config);
477         if (config != BOOST_PP_STRINGIZE(BOOST_WAVE_CONFIG)) {
478             BOOST_WAVE_THROW_CTX((*this), preprocess_exception,
479                 incompatible_config, "BOOST_WAVE_CONFIG", get_main_pos());
480             return;
481         }
482 
483         // BOOST_WAVE_PRAGMA_KEYWORD
484         ar & make_nvp("pragma_keyword", pragma_keyword);
485         if (pragma_keyword != BOOST_WAVE_PRAGMA_KEYWORD) {
486             BOOST_WAVE_THROW_CTX((*this), preprocess_exception,
487                 incompatible_config, "BOOST_WAVE_PRAGMA_KEYWORD",
488                 get_main_pos());
489             return;
490         }
491 
492         // BOOST_PP_STRINGIZE((BOOST_WAVE_STRINGTYPE))
493         ar & make_nvp("string_type", string_type_str);
494         if (string_type_str != BOOST_PP_STRINGIZE((BOOST_WAVE_STRINGTYPE))) {
495             BOOST_WAVE_THROW_CTX((*this), preprocess_exception,
496                 incompatible_config, "BOOST_WAVE_STRINGTYPE", get_main_pos());
497             return;
498         }
499 
500         try {
501             // read in the useful bits
502             ar & make_nvp("language_options", language);
503             ar & make_nvp("macro_definitions", macros);
504             ar & make_nvp("include_settings", includes);
505         }
506         catch (boost::wave::preprocess_exception const& e) {
507         // catch version mismatch exceptions and call error handler
508             get_hooks().throw_exception(derived(), e);
509         }
510     }
511     BOOST_SERIALIZATION_SPLIT_MEMBER()
512 #endif
513 
514 private:
515 // the main input stream
516     target_iterator_type first;         // underlying input stream
517     target_iterator_type last;
518     std::string filename;               // associated main filename
519     bool has_been_initialized;          // set cwd once
520 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
521     std::string current_filename;       // real name of current preprocessed file
522 #endif
523     std::string current_relative_filename;        // real relative name of current preprocessed file
524 
525     boost::wave::util::if_block_stack ifblocks;   // conditional compilation contexts
526     boost::wave::util::include_paths includes;    // lists of include directories to search
527     iteration_context_stack_type iter_ctxs;       // iteration contexts
528     macromap_type macros;                         // map of defined macros
529     boost::wave::language_support language;       // supported language/extensions
530     hook_policy_type hooks;                       // hook policy instance
531 };
532 
533 ///////////////////////////////////////////////////////////////////////////////
534 }   // namespace wave
535 }   // namespace boost
536 
537 #if BOOST_WAVE_SERIALIZATION != 0
538 namespace boost { namespace serialization {
539 
540 template<
541     typename Iterator, typename LexIterator,
542     typename InputPolicy, typename Hooks
543 >
544 struct tracking_level<boost::wave::context<Iterator, LexIterator, InputPolicy, Hooks> >
545 {
546     typedef mpl::integral_c_tag tag;
547     typedef mpl::int_<track_never> type;
548     BOOST_STATIC_CONSTANT(
549         int,
550         value = tracking_level::type::value
551     );
552 };
553 
554 template<
555     typename Iterator, typename LexIterator,
556     typename InputPolicy, typename Hooks
557 >
558 struct version<boost::wave::context<Iterator, LexIterator, InputPolicy, Hooks> >
559 {
560     typedef boost::wave::context<Iterator, LexIterator, InputPolicy, Hooks>
561         target_type;
562     typedef mpl::int_<target_type::version> type;
563     typedef mpl::integral_c_tag tag;
564     BOOST_STATIC_CONSTANT(unsigned int, value = version::type::value);
565 };
566 
567 }}  // namespace boost::serialization
568 #endif
569 
570 // the suffix header occurs after all of the code
571 #ifdef BOOST_HAS_ABI_HEADERS
572 #include BOOST_ABI_SUFFIX
573 #endif
574 
575 #endif // !defined(BOOST_CPP_CONTEXT_HPP_907485E2_6649_4A87_911B_7F7225F3E5B8_INCLUDED)
576