Chris@16: /*============================================================================= Chris@16: Boost.Wave: A Standard compliant C++ preprocessor library Chris@16: Chris@16: http://www.boost.org/ Chris@16: Chris@16: State machine detecting include guards in an included file. Chris@16: This detects two forms of include guards: Chris@16: Chris@16: #ifndef INCLUDE_GUARD_MACRO Chris@16: #define INCLUDE_GUARD_MACRO Chris@16: ... Chris@16: #endif Chris@16: Chris@16: or Chris@16: Chris@16: if !defined(INCLUDE_GUARD_MACRO) Chris@16: #define INCLUDE_GUARD_MACRO Chris@16: ... Chris@16: #endif Chris@16: Chris@16: note, that the parenthesis are optional (i.e. !defined INCLUDE_GUARD_MACRO Chris@16: will work as well). The code allows for any whitespace, newline and single Chris@16: '#' tokens before the #if/#ifndef and after the final #endif. Chris@16: Chris@16: Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost Chris@16: Software License, Version 1.0. (See accompanying file Chris@16: LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: =============================================================================*/ Chris@16: #if !defined(DETECT_INCLUDE_GUARDS_HK060304_INCLUDED) Chris@16: #define DETECT_INCLUDE_GUARDS_HK060304_INCLUDED Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: // this must occur after all of the includes and before any code appears Chris@16: #ifdef BOOST_HAS_ABI_HEADERS Chris@16: #include BOOST_ABI_PREFIX Chris@16: #endif Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: namespace boost { Chris@16: namespace wave { Chris@16: namespace cpplexer { Chris@16: Chris@16: template Chris@16: class include_guards Chris@16: { Chris@16: public: Chris@16: include_guards() Chris@16: : state(&include_guards::state_0), detected_guards(false), Chris@16: current_state(true), if_depth(0) Chris@16: {} Chris@16: Chris@16: Token& detect_guard(Token& t) Chris@16: { return current_state ? (this->*state)(t) : t; } Chris@16: bool detected(std::string& guard_name_) const Chris@16: { Chris@16: if (detected_guards) { Chris@16: guard_name_ = guard_name.c_str(); Chris@16: return true; Chris@16: } Chris@16: return false; Chris@16: } Chris@16: Chris@16: private: Chris@16: typedef Token& state_type(Token& t); Chris@16: state_type include_guards::* state; Chris@16: Chris@16: bool detected_guards; Chris@16: bool current_state; Chris@16: typename Token::string_type guard_name; Chris@16: int if_depth; Chris@16: Chris@16: state_type state_0, state_1, state_2, state_3, state_4, state_5; Chris@16: state_type state_1a, state_1b, state_1c, state_1d, state_1e; Chris@16: Chris@16: bool is_skippable(token_id id) const Chris@16: { Chris@16: return (T_POUND == BASE_TOKEN(id) || Chris@16: IS_CATEGORY(id, WhiteSpaceTokenType) || Chris@16: IS_CATEGORY(id, EOLTokenType)); Chris@16: } Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // state 0: beginning of a file, tries to recognize #ifndef or #if tokens Chris@16: template Chris@16: inline Token& Chris@16: include_guards::state_0(Token& t) Chris@16: { Chris@16: token_id id = token_id(t); Chris@16: if (T_PP_IFNDEF == id) Chris@16: state = &include_guards::state_1; Chris@16: else if (T_PP_IF == id) Chris@16: state = &include_guards::state_1a; Chris@16: else if (!is_skippable(id)) Chris@16: current_state = false; Chris@16: return t; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // state 1: found #ifndef, looking for T_IDENTIFIER Chris@16: template Chris@16: inline Token& Chris@16: include_guards::state_1(Token& t) Chris@16: { Chris@16: token_id id = token_id(t); Chris@16: if (T_IDENTIFIER == id) { Chris@16: guard_name = t.get_value(); Chris@16: state = &include_guards::state_2; Chris@16: } Chris@16: else if (!is_skippable(id)) Chris@16: current_state = false; Chris@16: return t; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // state 1a: found T_PP_IF, looking for T_NOT ("!") Chris@16: template Chris@16: inline Token& Chris@16: include_guards::state_1a(Token& t) Chris@16: { Chris@16: token_id id = token_id(t); Chris@16: if (T_NOT == BASE_TOKEN(id)) Chris@16: state = &include_guards::state_1b; Chris@16: else if (!is_skippable(id)) Chris@16: current_state = false; Chris@16: return t; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // state 1b: found T_NOT, looking for 'defined' Chris@16: template Chris@16: inline Token& Chris@16: include_guards::state_1b(Token& t) Chris@16: { Chris@16: token_id id = token_id(t); Chris@16: if (T_IDENTIFIER == id && t.get_value() == "defined") Chris@16: state = &include_guards::state_1c; Chris@16: else if (!is_skippable(id)) Chris@16: current_state = false; Chris@16: return t; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // state 1c: found 'defined', looking for (optional) T_LEFTPAREN Chris@16: template Chris@16: inline Token& Chris@16: include_guards::state_1c(Token& t) Chris@16: { Chris@16: token_id id = token_id(t); Chris@16: if (T_LEFTPAREN == id) Chris@16: state = &include_guards::state_1d; Chris@16: else if (T_IDENTIFIER == id) { Chris@16: guard_name = t.get_value(); Chris@16: state = &include_guards::state_2; Chris@16: } Chris@16: else if (!is_skippable(id)) Chris@16: current_state = false; Chris@16: return t; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // state 1d: found T_LEFTPAREN, looking for T_IDENTIFIER guard Chris@16: template Chris@16: inline Token& Chris@16: include_guards::state_1d(Token& t) Chris@16: { Chris@16: token_id id = token_id(t); Chris@16: if (T_IDENTIFIER == id) { Chris@16: guard_name = t.get_value(); Chris@16: state = &include_guards::state_1e; Chris@16: } Chris@16: else if (!is_skippable(id)) Chris@16: current_state = false; Chris@16: return t; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // state 1e: found T_IDENTIFIER guard, looking for T_RIGHTPAREN Chris@16: template Chris@16: inline Token& Chris@16: include_guards::state_1e(Token& t) Chris@16: { Chris@16: token_id id = token_id(t); Chris@16: if (T_RIGHTPAREN == id) Chris@16: state = &include_guards::state_2; Chris@16: else if (!is_skippable(id)) Chris@16: current_state = false; Chris@16: return t; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // state 2: found T_IDENTIFIER, looking for #define Chris@16: template Chris@16: inline Token& Chris@16: include_guards::state_2(Token& t) Chris@16: { Chris@16: token_id id = token_id(t); Chris@16: if (T_PP_DEFINE == id) Chris@16: state = &include_guards::state_3; Chris@16: else if (!is_skippable(id)) Chris@16: current_state = false; Chris@16: return t; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // state 3: found #define, looking for T_IDENTIFIER as recognized by state 1 Chris@16: template Chris@16: inline Token& Chris@16: include_guards::state_3(Token& t) Chris@16: { Chris@16: token_id id = token_id(t); Chris@16: if (T_IDENTIFIER == id && t.get_value() == guard_name) Chris@16: state = &include_guards::state_4; Chris@16: else if (!is_skippable(id)) Chris@16: current_state = false; Chris@16: return t; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // state 4: found guard T_IDENTIFIER, looking for #endif Chris@16: template Chris@16: inline Token& Chris@16: include_guards::state_4(Token& t) Chris@16: { Chris@16: token_id id = token_id(t); Chris@16: if (T_PP_IF == id || T_PP_IFDEF == id || T_PP_IFNDEF == id) Chris@16: ++if_depth; Chris@16: else if (T_PP_ENDIF == id) { Chris@16: if (if_depth > 0) Chris@16: --if_depth; Chris@16: else Chris@16: state = &include_guards::state_5; Chris@16: } Chris@16: return t; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // state 5: found final #endif, looking for T_EOF Chris@16: template Chris@16: inline Token& Chris@16: include_guards::state_5(Token& t) Chris@16: { Chris@16: token_id id = token_id(t); Chris@16: if (T_EOF == id) Chris@16: detected_guards = current_state; Chris@16: else if (!is_skippable(id)) Chris@16: current_state = false; Chris@16: return t; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: } // namespace cpplexer Chris@16: } // namespace wave Chris@16: } // namespace boost Chris@16: Chris@16: // the suffix header occurs after all of the code Chris@16: #ifdef BOOST_HAS_ABI_HEADERS Chris@16: #include BOOST_ABI_SUFFIX Chris@16: #endif Chris@16: Chris@16: #endif // !DETECT_INCLUDE_GUARDS_HK060304_INCLUDED