Chris@16
|
1 /*=============================================================================
|
Chris@16
|
2 Boost.Wave: A Standard compliant C++ preprocessor library
|
Chris@16
|
3
|
Chris@16
|
4 http://www.boost.org/
|
Chris@16
|
5
|
Chris@16
|
6 State machine detecting include guards in an included file.
|
Chris@16
|
7 This detects two forms of include guards:
|
Chris@16
|
8
|
Chris@16
|
9 #ifndef INCLUDE_GUARD_MACRO
|
Chris@16
|
10 #define INCLUDE_GUARD_MACRO
|
Chris@16
|
11 ...
|
Chris@16
|
12 #endif
|
Chris@16
|
13
|
Chris@16
|
14 or
|
Chris@16
|
15
|
Chris@16
|
16 if !defined(INCLUDE_GUARD_MACRO)
|
Chris@16
|
17 #define INCLUDE_GUARD_MACRO
|
Chris@16
|
18 ...
|
Chris@16
|
19 #endif
|
Chris@16
|
20
|
Chris@16
|
21 note, that the parenthesis are optional (i.e. !defined INCLUDE_GUARD_MACRO
|
Chris@16
|
22 will work as well). The code allows for any whitespace, newline and single
|
Chris@16
|
23 '#' tokens before the #if/#ifndef and after the final #endif.
|
Chris@16
|
24
|
Chris@16
|
25 Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
|
Chris@16
|
26 Software License, Version 1.0. (See accompanying file
|
Chris@16
|
27 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
28 =============================================================================*/
|
Chris@16
|
29 #if !defined(DETECT_INCLUDE_GUARDS_HK060304_INCLUDED)
|
Chris@16
|
30 #define DETECT_INCLUDE_GUARDS_HK060304_INCLUDED
|
Chris@16
|
31
|
Chris@16
|
32 #include <boost/wave/wave_config.hpp>
|
Chris@16
|
33 #include <boost/wave/token_ids.hpp>
|
Chris@16
|
34
|
Chris@16
|
35 // this must occur after all of the includes and before any code appears
|
Chris@16
|
36 #ifdef BOOST_HAS_ABI_HEADERS
|
Chris@16
|
37 #include BOOST_ABI_PREFIX
|
Chris@16
|
38 #endif
|
Chris@16
|
39
|
Chris@16
|
40 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
41 namespace boost {
|
Chris@16
|
42 namespace wave {
|
Chris@16
|
43 namespace cpplexer {
|
Chris@16
|
44
|
Chris@16
|
45 template <typename Token>
|
Chris@16
|
46 class include_guards
|
Chris@16
|
47 {
|
Chris@16
|
48 public:
|
Chris@16
|
49 include_guards()
|
Chris@16
|
50 : state(&include_guards::state_0), detected_guards(false),
|
Chris@16
|
51 current_state(true), if_depth(0)
|
Chris@16
|
52 {}
|
Chris@16
|
53
|
Chris@16
|
54 Token& detect_guard(Token& t)
|
Chris@16
|
55 { return current_state ? (this->*state)(t) : t; }
|
Chris@16
|
56 bool detected(std::string& guard_name_) const
|
Chris@16
|
57 {
|
Chris@16
|
58 if (detected_guards) {
|
Chris@16
|
59 guard_name_ = guard_name.c_str();
|
Chris@16
|
60 return true;
|
Chris@16
|
61 }
|
Chris@16
|
62 return false;
|
Chris@16
|
63 }
|
Chris@16
|
64
|
Chris@16
|
65 private:
|
Chris@16
|
66 typedef Token& state_type(Token& t);
|
Chris@16
|
67 state_type include_guards::* state;
|
Chris@16
|
68
|
Chris@16
|
69 bool detected_guards;
|
Chris@16
|
70 bool current_state;
|
Chris@16
|
71 typename Token::string_type guard_name;
|
Chris@16
|
72 int if_depth;
|
Chris@16
|
73
|
Chris@16
|
74 state_type state_0, state_1, state_2, state_3, state_4, state_5;
|
Chris@16
|
75 state_type state_1a, state_1b, state_1c, state_1d, state_1e;
|
Chris@16
|
76
|
Chris@16
|
77 bool is_skippable(token_id id) const
|
Chris@16
|
78 {
|
Chris@16
|
79 return (T_POUND == BASE_TOKEN(id) ||
|
Chris@16
|
80 IS_CATEGORY(id, WhiteSpaceTokenType) ||
|
Chris@16
|
81 IS_CATEGORY(id, EOLTokenType));
|
Chris@16
|
82 }
|
Chris@16
|
83 };
|
Chris@16
|
84
|
Chris@16
|
85 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
86 // state 0: beginning of a file, tries to recognize #ifndef or #if tokens
|
Chris@16
|
87 template <typename Token>
|
Chris@16
|
88 inline Token&
|
Chris@16
|
89 include_guards<Token>::state_0(Token& t)
|
Chris@16
|
90 {
|
Chris@16
|
91 token_id id = token_id(t);
|
Chris@16
|
92 if (T_PP_IFNDEF == id)
|
Chris@16
|
93 state = &include_guards::state_1;
|
Chris@16
|
94 else if (T_PP_IF == id)
|
Chris@16
|
95 state = &include_guards::state_1a;
|
Chris@16
|
96 else if (!is_skippable(id))
|
Chris@16
|
97 current_state = false;
|
Chris@16
|
98 return t;
|
Chris@16
|
99 }
|
Chris@16
|
100
|
Chris@16
|
101 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
102 // state 1: found #ifndef, looking for T_IDENTIFIER
|
Chris@16
|
103 template <typename Token>
|
Chris@16
|
104 inline Token&
|
Chris@16
|
105 include_guards<Token>::state_1(Token& t)
|
Chris@16
|
106 {
|
Chris@16
|
107 token_id id = token_id(t);
|
Chris@16
|
108 if (T_IDENTIFIER == id) {
|
Chris@16
|
109 guard_name = t.get_value();
|
Chris@16
|
110 state = &include_guards::state_2;
|
Chris@16
|
111 }
|
Chris@16
|
112 else if (!is_skippable(id))
|
Chris@16
|
113 current_state = false;
|
Chris@16
|
114 return t;
|
Chris@16
|
115 }
|
Chris@16
|
116
|
Chris@16
|
117 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
118 // state 1a: found T_PP_IF, looking for T_NOT ("!")
|
Chris@16
|
119 template <typename Token>
|
Chris@16
|
120 inline Token&
|
Chris@16
|
121 include_guards<Token>::state_1a(Token& t)
|
Chris@16
|
122 {
|
Chris@16
|
123 token_id id = token_id(t);
|
Chris@16
|
124 if (T_NOT == BASE_TOKEN(id))
|
Chris@16
|
125 state = &include_guards::state_1b;
|
Chris@16
|
126 else if (!is_skippable(id))
|
Chris@16
|
127 current_state = false;
|
Chris@16
|
128 return t;
|
Chris@16
|
129 }
|
Chris@16
|
130
|
Chris@16
|
131 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
132 // state 1b: found T_NOT, looking for 'defined'
|
Chris@16
|
133 template <typename Token>
|
Chris@16
|
134 inline Token&
|
Chris@16
|
135 include_guards<Token>::state_1b(Token& t)
|
Chris@16
|
136 {
|
Chris@16
|
137 token_id id = token_id(t);
|
Chris@16
|
138 if (T_IDENTIFIER == id && t.get_value() == "defined")
|
Chris@16
|
139 state = &include_guards::state_1c;
|
Chris@16
|
140 else if (!is_skippable(id))
|
Chris@16
|
141 current_state = false;
|
Chris@16
|
142 return t;
|
Chris@16
|
143 }
|
Chris@16
|
144
|
Chris@16
|
145 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
146 // state 1c: found 'defined', looking for (optional) T_LEFTPAREN
|
Chris@16
|
147 template <typename Token>
|
Chris@16
|
148 inline Token&
|
Chris@16
|
149 include_guards<Token>::state_1c(Token& t)
|
Chris@16
|
150 {
|
Chris@16
|
151 token_id id = token_id(t);
|
Chris@16
|
152 if (T_LEFTPAREN == id)
|
Chris@16
|
153 state = &include_guards::state_1d;
|
Chris@16
|
154 else if (T_IDENTIFIER == id) {
|
Chris@16
|
155 guard_name = t.get_value();
|
Chris@16
|
156 state = &include_guards::state_2;
|
Chris@16
|
157 }
|
Chris@16
|
158 else if (!is_skippable(id))
|
Chris@16
|
159 current_state = false;
|
Chris@16
|
160 return t;
|
Chris@16
|
161 }
|
Chris@16
|
162
|
Chris@16
|
163 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
164 // state 1d: found T_LEFTPAREN, looking for T_IDENTIFIER guard
|
Chris@16
|
165 template <typename Token>
|
Chris@16
|
166 inline Token&
|
Chris@16
|
167 include_guards<Token>::state_1d(Token& t)
|
Chris@16
|
168 {
|
Chris@16
|
169 token_id id = token_id(t);
|
Chris@16
|
170 if (T_IDENTIFIER == id) {
|
Chris@16
|
171 guard_name = t.get_value();
|
Chris@16
|
172 state = &include_guards::state_1e;
|
Chris@16
|
173 }
|
Chris@16
|
174 else if (!is_skippable(id))
|
Chris@16
|
175 current_state = false;
|
Chris@16
|
176 return t;
|
Chris@16
|
177 }
|
Chris@16
|
178
|
Chris@16
|
179 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
180 // state 1e: found T_IDENTIFIER guard, looking for T_RIGHTPAREN
|
Chris@16
|
181 template <typename Token>
|
Chris@16
|
182 inline Token&
|
Chris@16
|
183 include_guards<Token>::state_1e(Token& t)
|
Chris@16
|
184 {
|
Chris@16
|
185 token_id id = token_id(t);
|
Chris@16
|
186 if (T_RIGHTPAREN == id)
|
Chris@16
|
187 state = &include_guards::state_2;
|
Chris@16
|
188 else if (!is_skippable(id))
|
Chris@16
|
189 current_state = false;
|
Chris@16
|
190 return t;
|
Chris@16
|
191 }
|
Chris@16
|
192
|
Chris@16
|
193 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
194 // state 2: found T_IDENTIFIER, looking for #define
|
Chris@16
|
195 template <typename Token>
|
Chris@16
|
196 inline Token&
|
Chris@16
|
197 include_guards<Token>::state_2(Token& t)
|
Chris@16
|
198 {
|
Chris@16
|
199 token_id id = token_id(t);
|
Chris@16
|
200 if (T_PP_DEFINE == id)
|
Chris@16
|
201 state = &include_guards::state_3;
|
Chris@16
|
202 else if (!is_skippable(id))
|
Chris@16
|
203 current_state = false;
|
Chris@16
|
204 return t;
|
Chris@16
|
205 }
|
Chris@16
|
206
|
Chris@16
|
207 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
208 // state 3: found #define, looking for T_IDENTIFIER as recognized by state 1
|
Chris@16
|
209 template <typename Token>
|
Chris@16
|
210 inline Token&
|
Chris@16
|
211 include_guards<Token>::state_3(Token& t)
|
Chris@16
|
212 {
|
Chris@16
|
213 token_id id = token_id(t);
|
Chris@16
|
214 if (T_IDENTIFIER == id && t.get_value() == guard_name)
|
Chris@16
|
215 state = &include_guards::state_4;
|
Chris@16
|
216 else if (!is_skippable(id))
|
Chris@16
|
217 current_state = false;
|
Chris@16
|
218 return t;
|
Chris@16
|
219 }
|
Chris@16
|
220
|
Chris@16
|
221 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
222 // state 4: found guard T_IDENTIFIER, looking for #endif
|
Chris@16
|
223 template <typename Token>
|
Chris@16
|
224 inline Token&
|
Chris@16
|
225 include_guards<Token>::state_4(Token& t)
|
Chris@16
|
226 {
|
Chris@16
|
227 token_id id = token_id(t);
|
Chris@16
|
228 if (T_PP_IF == id || T_PP_IFDEF == id || T_PP_IFNDEF == id)
|
Chris@16
|
229 ++if_depth;
|
Chris@16
|
230 else if (T_PP_ENDIF == id) {
|
Chris@16
|
231 if (if_depth > 0)
|
Chris@16
|
232 --if_depth;
|
Chris@16
|
233 else
|
Chris@16
|
234 state = &include_guards::state_5;
|
Chris@16
|
235 }
|
Chris@16
|
236 return t;
|
Chris@16
|
237 }
|
Chris@16
|
238
|
Chris@16
|
239 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
240 // state 5: found final #endif, looking for T_EOF
|
Chris@16
|
241 template <typename Token>
|
Chris@16
|
242 inline Token&
|
Chris@16
|
243 include_guards<Token>::state_5(Token& t)
|
Chris@16
|
244 {
|
Chris@16
|
245 token_id id = token_id(t);
|
Chris@16
|
246 if (T_EOF == id)
|
Chris@16
|
247 detected_guards = current_state;
|
Chris@16
|
248 else if (!is_skippable(id))
|
Chris@16
|
249 current_state = false;
|
Chris@16
|
250 return t;
|
Chris@16
|
251 }
|
Chris@16
|
252
|
Chris@16
|
253 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
254 } // namespace cpplexer
|
Chris@16
|
255 } // namespace wave
|
Chris@16
|
256 } // namespace boost
|
Chris@16
|
257
|
Chris@16
|
258 // the suffix header occurs after all of the code
|
Chris@16
|
259 #ifdef BOOST_HAS_ABI_HEADERS
|
Chris@16
|
260 #include BOOST_ABI_SUFFIX
|
Chris@16
|
261 #endif
|
Chris@16
|
262
|
Chris@16
|
263 #endif // !DETECT_INCLUDE_GUARDS_HK060304_INCLUDED
|