detect_include_guards.hpp 7.5 KB

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