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(BOOST_CPP_IFBLOCK_HPP_D4676B36_00C5_41F4_BC9F_9CBBAE3B8006_INCLUDED) 12 #define BOOST_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: if_block()32 if_block() : 33 status(true), some_part_status(true), 34 enclosing_status(true), is_in_else(false) 35 { 36 } if_block(bool status_,bool enclosing_status_)37 if_block(bool status_, bool enclosing_status_) : 38 status(status_), 39 some_part_status(status_), 40 enclosing_status(enclosing_status_), 41 is_in_else(false) 42 { 43 } 44 set_status(bool status_)45 void set_status(bool status_) 46 { 47 status = status_; 48 if (status_) 49 some_part_status = true; 50 } get_status() const51 bool get_status() const { return status; } get_some_part_status() const52 bool get_some_part_status() const { return some_part_status; } get_enclosing_status() const53 bool get_enclosing_status() const { return enclosing_status; } get_in_else() const54 bool get_in_else() const { return is_in_else; } set_in_else()55 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 class if_block_stack 67 : private std::stack<if_block> 68 { 69 public: 70 typedef std::stack<if_block>::size_type size_type; 71 enter_if_block(bool new_status)72 void enter_if_block(bool new_status) 73 { 74 // If enclosing block is false, then this block is also false 75 bool enclosing_status = get_status(); 76 this->push (value_type (new_status && enclosing_status, enclosing_status)); 77 } enter_elif_block(bool new_status)78 bool enter_elif_block(bool new_status) 79 { 80 if (!is_inside_ifpart()) 81 return false; // #elif without matching #if 82 83 if (get_enclosing_status()) { 84 if (get_status()) { 85 // entered a (false) #elif block from a true block 86 this->top().set_status(false); 87 } 88 else if (new_status && !this->top().get_some_part_status()) { 89 // Entered true #elif block and no previous block was true 90 this->top().set_status(new_status); 91 } 92 } 93 return true; 94 } enter_else_block()95 bool enter_else_block() 96 { 97 if (!is_inside_ifpart()) 98 return false; // #else without matching #if 99 100 if (get_enclosing_status()) { 101 if (!this->top().get_some_part_status()) { 102 // Entered (true) #else block and no previous block was true 103 this->top().set_status(true); 104 } 105 else if (get_status()) { 106 // Entered (false) #else block from true block 107 this->top().set_status(false); 108 } 109 110 // Set else flag 111 this->top().set_in_else(); 112 } 113 return true; 114 } exit_if_block()115 bool exit_if_block() 116 { 117 if (0 == this->size()) 118 return false; // #endif without matching #if 119 120 this->pop(); 121 return true; 122 } 123 124 // return, whether the top (innermost) condition is true or false get_status() const125 bool get_status() const 126 { 127 return 0 == this->size() || this->top().get_status(); 128 } get_some_part_status() const129 bool get_some_part_status() const 130 { 131 return 0 == this->size() || this->top().get_some_part_status(); 132 } get_enclosing_status() const133 bool get_enclosing_status() const 134 { 135 return 0 == this->size() || this->top().get_enclosing_status(); 136 } 137 get_if_block_depth() const138 size_type get_if_block_depth() const { return this->size(); } 139 140 protected: is_inside_ifpart() const141 bool is_inside_ifpart() const 142 { 143 return 0 != this->size() && !this->top().get_in_else(); 144 } is_inside_elsepart() const145 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(BOOST_CPP_IFBLOCK_HPP_D4676B36_00C5_41F4_BC9F_9CBBAE3B8006_INCLUDED) 162