]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/wave/samples/preprocess_pragma_output/preprocess_pragma_output.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / libs / wave / samples / preprocess_pragma_output / preprocess_pragma_output.hpp
CommitLineData
7c673cae
FG
1/*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
3 Example demonstrating how to preprocess the token stream generated by a
4 #pragma directive
5
6 http://www.boost.org/
7
8 Copyright (c) 2001-2010 Hartmut Kaiser. Distributed under the Boost
9 Software License, Version 1.0. (See accompanying file
10 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11=============================================================================*/
12
13#if !defined(BOOST_WAVE_SAMPLE_PREPROCESS_PRAGMA_OUTPUT_APR_03_2008_0813AM)
14#define BOOST_WAVE_SAMPLE_PREPROCESS_PRAGMA_OUTPUT_APR_03_2008_0813AM
15
16template <typename String, typename Iterator>
17inline String
18as_unescaped_string(Iterator it, Iterator const& end)
19{
20 using namespace boost::wave;
21
22 String result;
23 for (/**/; it != end; ++it)
24 {
25 switch (token_id(*it)) {
26 case T_STRINGLIT:
27 {
f67539c2 28 String val (util::impl::unescape_lit((*it).get_value()).c_str());
7c673cae
FG
29 val.erase(val.size()-1);
30 val.erase(0, 1);
31 result += val;
32 }
33 break;
34
35 default: // just skip everything else (hey it's a sample)
36 break;
37 }
38 }
39 return result;
40}
41
42// return the string representation of a token sequence
43template <typename String, typename Container>
44inline String
45as_unescaped_string(Container const &token_sequence)
46{
47 return as_unescaped_string<String>(token_sequence.begin(),
48 token_sequence.end());
49}
50
51///////////////////////////////////////////////////////////////////////////////
52//
53// The preprocess_pragma_output_hooks policy class is used implement a special
54// #pragma wave pp("some C++ code") directive allowing to insert preprocessed
55// code into the output sequence generated by the tool.
56//
57// This policy type is used as a template parameter to the boost::wave::context<>
58// object.
59//
60///////////////////////////////////////////////////////////////////////////////
61class preprocess_pragma_output_hooks
62: public boost::wave::context_policies::default_preprocessing_hooks
63{
64public:
65 preprocess_pragma_output_hooks() {}
66
67 template <typename Context>
68 struct reset_language_support
69 {
70 reset_language_support(Context& ctx)
71 : ctx_(ctx), lang_(ctx.get_language())
72 {
73 ctx.set_language(boost::wave::enable_single_line(lang_), false);
74 }
75 ~reset_language_support()
76 {
77 ctx_.set_language(lang_, false);
78 }
79
80 Context& ctx_;
81 boost::wave::language_support lang_;
82 };
83
84 ///////////////////////////////////////////////////////////////////////////
85 //
86 // The function 'interpret_pragma' is called, whenever a #pragma command
87 // directive is found which isn't known to the core Wave library, where
88 // command is the value defined as the BOOST_WAVE_PRAGMA_KEYWORD constant
89 // which defaults to "wave".
90 //
91 // The parameter 'ctx' is a reference to the context object used for
92 // instantiating the preprocessing iterators by the user.
93 //
94 // The parameter 'pending' may be used to push tokens back into the input
95 // stream, which are to be used as the replacement text for the whole
96 // #pragma directive.
97 //
98 // The parameter 'option' contains the name of the interpreted pragma.
99 //
100 // The parameter 'values' holds the values of the parameter provided to
101 // the pragma operator.
102 //
103 // The parameter 'act_token' contains the actual #pragma token, which may
104 // be used for error output.
105 //
106 // If the return value is 'false', the whole #pragma directive is
107 // interpreted as unknown and a corresponding error message is issued. A
108 // return value of 'true' signs a successful interpretation of the given
109 // #pragma.
110 //
111 ///////////////////////////////////////////////////////////////////////////
112 template <typename Context, typename Container>
113 bool
114 interpret_pragma(Context& ctx, Container &pending,
115 typename Context::token_type const& option,
116 Container const& values, typename Context::token_type const& act_token)
117 {
7c673cae
FG
118 typedef typename Context::iterator_type iterator_type;
119
120 if (option.get_value() == "pp") {
121 // Concatenate the string(s) passed as the options to this pragma,
122 // preprocess the result using the current context and insert the
123 // generated token sequence in place of the pragma directive into the
124 // output stream.
125
126 try {
127 // We're explicitly using a std::string here since the type of the
128 // iterators passed to the ctx.begin() below must match the types
129 // of the iterator the original context instance has been created
130 // with.
131 std::string s (as_unescaped_string<std::string>(values));
132 reset_language_support<Context> lang(ctx);
133
134 using namespace boost::wave;
135
136 // The expanded token sequence is stored in the 'pragma' container
137 // to ensure consistency in the output in the case of an error
138 // while preprocessing the pragma option strings.
139 Container pragma;
140 iterator_type end = ctx.end();
141 for (iterator_type it = ctx.begin(s.begin(), s.end());
20effc67
TL
142 it != end && token_id(*it) != T_EOF;
143 std::advance(it, 2)) // skip over whitespace
7c673cae
FG
144 {
145 pragma.push_back(*it);
7c673cae
FG
146 }
147
148 // prepend the newly generated token sequence to the 'pending'
149 // container
150 pending.splice(pending.begin(), pragma);
151 }
152 catch (boost::wave::preprocess_exception const& /*e*/) {
153 // the library will report an 'ill_formed_pragma_option' for us
154 return false;
155 }
156 return true;
157 }
158
159 // we don't know anything about this #pragma wave directive
160 return false;
161 }
162};
163
164
165#endif
166