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