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-2007 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 const& detect_guard(Token const& 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 const& state_type(Token const& 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 const& |
---|
89 | include_guards<Token>::state_0(Token const& 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 const& |
---|
105 | include_guards<Token>::state_1(Token const& 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 const& |
---|
121 | include_guards<Token>::state_1a(Token const& 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 const& |
---|
135 | include_guards<Token>::state_1b(Token const& 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 const& |
---|
149 | include_guards<Token>::state_1c(Token const& 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 const& |
---|
167 | include_guards<Token>::state_1d(Token const& 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 const& |
---|
183 | include_guards<Token>::state_1e(Token const& 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 const& |
---|
197 | include_guards<Token>::state_2(Token const& 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 const& |
---|
211 | include_guards<Token>::state_3(Token const& 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 const& |
---|
225 | include_guards<Token>::state_4(Token const& 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 const& |
---|
243 | include_guards<Token>::state_5(Token const& 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 |
---|