cpp_ifblock.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*=============================================================================
  2. Boost.Wave: A Standard compliant C++ preprocessor library
  3. http://www.boost.org/
  4. Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
  5. Software License, Version 1.0. (See accompanying file
  6. LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. #if !defined(CPP_IFBLOCK_HPP_D4676B36_00C5_41F4_BC9F_9CBBAE3B8006_INCLUDED)
  9. #define CPP_IFBLOCK_HPP_D4676B36_00C5_41F4_BC9F_9CBBAE3B8006_INCLUDED
  10. #include <stack>
  11. #include <boost/wave/wave_config.hpp>
  12. // this must occur after all of the includes and before any code appears
  13. #ifdef BOOST_HAS_ABI_HEADERS
  14. #include BOOST_ABI_PREFIX
  15. #endif
  16. ///////////////////////////////////////////////////////////////////////////////
  17. namespace boost {
  18. namespace wave {
  19. namespace util {
  20. ///////////////////////////////////////////////////////////////////////////////
  21. // the class if_blocks handles recursive conditional compilation contexts
  22. class if_block
  23. {
  24. public:
  25. if_block() :
  26. status(true), some_part_status(true),
  27. enclosing_status(true), is_in_else(false)
  28. {
  29. }
  30. if_block(bool status_, bool enclosing_status_) :
  31. status(status_),
  32. some_part_status(status_),
  33. enclosing_status(enclosing_status_),
  34. is_in_else(false)
  35. {
  36. }
  37. void set_status(bool status_)
  38. {
  39. status = status_;
  40. if (status_)
  41. some_part_status = true;
  42. }
  43. bool get_status() const { return status; }
  44. bool get_some_part_status() const { return some_part_status; }
  45. bool get_enclosing_status() const { return enclosing_status; }
  46. bool get_in_else() const { return is_in_else; }
  47. void set_in_else() { is_in_else = true; }
  48. private:
  49. bool status; // Current block is true
  50. bool some_part_status; // One of the preceding or current #if/#elif was true
  51. bool enclosing_status; // Enclosing #if block is true
  52. bool is_in_else; // Inside the #else part
  53. };
  54. ///////////////////////////////////////////////////////////////////////////////
  55. // stack of conditional compilation contexts
  56. class if_block_stack
  57. : private std::stack<if_block>
  58. {
  59. public:
  60. typedef std::stack<if_block>::size_type size_type;
  61. void enter_if_block(bool new_status)
  62. {
  63. // If enclosing block is false, then this block is also false
  64. bool enclosing_status = get_status();
  65. this->push (value_type (new_status && enclosing_status, enclosing_status));
  66. }
  67. bool enter_elif_block(bool new_status)
  68. {
  69. if (!is_inside_ifpart())
  70. return false; // #elif without matching #if
  71. if (get_enclosing_status()) {
  72. if (get_status()) {
  73. // entered a (false) #elif block from a true block
  74. this->top().set_status(false);
  75. }
  76. else if (new_status && !this->top().get_some_part_status()) {
  77. // Entered true #elif block and no previous block was true
  78. this->top().set_status(new_status);
  79. }
  80. }
  81. return true;
  82. }
  83. bool enter_else_block()
  84. {
  85. if (!is_inside_ifpart())
  86. return false; // #else without matching #if
  87. if (get_enclosing_status()) {
  88. if (!this->top().get_some_part_status()) {
  89. // Entered (true) #else block and no previous block was true
  90. this->top().set_status(true);
  91. }
  92. else if (get_status()) {
  93. // Entered (false) #else block from true block
  94. this->top().set_status(false);
  95. }
  96. // Set else flag
  97. this->top().set_in_else();
  98. }
  99. return true;
  100. }
  101. bool exit_if_block()
  102. {
  103. if (0 == this->size())
  104. return false; // #endif without matching #if
  105. this->pop();
  106. return true;
  107. }
  108. // return, whether the top (innermost) condition is true or false
  109. bool get_status() const
  110. {
  111. return 0 == this->size() || this->top().get_status();
  112. }
  113. bool get_some_part_status() const
  114. {
  115. return 0 == this->size() || this->top().get_some_part_status();
  116. }
  117. bool get_enclosing_status() const
  118. {
  119. return 0 == this->size() || this->top().get_enclosing_status();
  120. }
  121. size_type get_if_block_depth() const { return this->size(); }
  122. protected:
  123. bool is_inside_ifpart() const
  124. {
  125. return 0 != this->size() && !this->top().get_in_else();
  126. }
  127. bool is_inside_elsepart() const
  128. {
  129. return 0 != this->size() && this->top().get_in_else();
  130. }
  131. };
  132. ///////////////////////////////////////////////////////////////////////////////
  133. } // namespace util
  134. } // namespace wave
  135. } // namespace boost
  136. // the suffix header occurs after all of the code
  137. #ifdef BOOST_HAS_ABI_HEADERS
  138. #include BOOST_ABI_SUFFIX
  139. #endif
  140. #endif // !defined(CPP_IFBLOCK_HPP_D4676B36_00C5_41F4_BC9F_9CBBAE3B8006_INCLUDED)