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