• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(BOOST_DETECT_INCLUDE_GUARDS_HK060304_INCLUDED)
30 #define BOOST_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:
include_guards()49     include_guards()
50     :   state(&include_guards::state_0), detected_guards(false),
51         current_state(true), if_depth(0)
52     {}
53 
detect_guard(Token & t)54     Token& detect_guard(Token& t)
55         { return current_state ? (this->*state)(t) : t; }
detected(std::string & guard_name_) const56     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 
is_skippable(token_id id) const77     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&
state_0(Token & t)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&
state_1(Token & t)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&
state_1a(Token & t)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&
state_1b(Token & t)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&
state_1c(Token & t)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&
state_1d(Token & t)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&
state_1e(Token & t)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&
state_2(Token & t)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&
state_3(Token & t)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&
state_4(Token & t)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&
state_5(Token & t)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 // !BOOST_DETECT_INCLUDE_GUARDS_HK060304_INCLUDED
264