source: NonGTP/Boost/boost/wave/util/cpp_ifblock.hpp @ 857

Revision 857, 4.7 KB checked in by igarcia, 18 years ago (diff)
Line 
1/*=============================================================================
2    Boost.Wave: A Standard compliant C++ preprocessor library
3
4    http://www.boost.org/
5
6    Copyright (c) 2001-2005 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
16///////////////////////////////////////////////////////////////////////////////
17namespace boost {
18namespace wave {
19namespace util {
20
21///////////////////////////////////////////////////////////////////////////////
22// the class if_blocks handles recursive conditional compilation contexts
23class if_block
24{
25public:
26    if_block() :
27        status(true), some_part_status(true),
28        enclosing_status(true), is_in_else(false)
29    {
30    }
31    if_block(bool status_, bool enclosing_status_) :
32        status(status_),
33        some_part_status(status_),
34        enclosing_status(enclosing_status_),
35        is_in_else(false)
36    {
37    }
38
39    void set_status(bool status_)
40    {
41        status = status_;
42        if (status_)
43            some_part_status = true;
44    }
45    bool get_status() const { return status; }
46    bool get_some_part_status() const { return some_part_status; }
47    bool get_enclosing_status() const { return enclosing_status; }
48    bool get_in_else() const { return is_in_else; }
49    void set_in_else() { is_in_else = true; }
50
51private:
52   bool status;             // Current block is true
53   bool some_part_status;   // One of the preceeding or current #if/#elif was true
54   bool enclosing_status;   // Enclosing #if block is true
55   bool is_in_else;         // Inside the #else part
56};
57
58///////////////////////////////////////////////////////////////////////////////
59// stack of conditional compilation contexts
60class if_block_stack
61:   private std::stack<if_block>
62{
63public:
64    typedef std::stack<if_block>::size_type size_type;
65   
66    void enter_if_block(bool new_status)
67    {
68    // If enclosing block is false, then this block is also false
69        bool enclosing_status = get_status();
70        this->push (value_type (new_status && enclosing_status, enclosing_status));
71    }
72    bool enter_elif_block(bool new_status)
73     {   
74        if (!is_inside_ifpart())
75            return false;       // #elif without matching #if
76
77        if (get_enclosing_status()) {
78            if (get_status()) {
79            // entered a (false) #elif block from a true block
80                this->top().set_status(false);
81            }
82            else if (new_status && !this->top().get_some_part_status()) {
83            // Entered true #elif block and no previous block was true
84                this->top().set_status(new_status);
85            }
86        }
87        return true;
88    }
89    bool enter_else_block()
90    {
91        if (!is_inside_ifpart())
92            return false;       // #else without matching #if
93
94        if (get_enclosing_status()) {
95            if (!this->top().get_some_part_status()) {
96            // Entered (true) #else block and no previous block was true
97                this->top().set_status(true);
98            }
99            else if (get_status()) {
100            // Entered (false) #else block from true block
101                this->top().set_status(false);
102            }
103
104        // Set else flag
105            this->top().set_in_else();
106        }
107        return true;
108    }
109    bool exit_if_block()
110    {
111        if (0 == this->size())
112            return false;   // #endif without matching #if
113
114        this->pop();
115        return true;
116    }
117
118// return, wether the top (innermost) condition is true or false
119    bool get_status() const
120    {
121        return 0 == this->size() || this->top().get_status();
122    }
123
124    size_type get_if_block_depth() const { return this->size(); }
125   
126protected:
127    bool get_enclosing_status() const
128    {
129       return 0 == this->size() || this->top().get_enclosing_status();
130    }
131
132    bool is_inside_ifpart() const
133    {
134       return 0 != this->size() && !this->top().get_in_else();
135    }
136    bool is_inside_elsepart() const
137    {
138       return 0 != this->size() && this->top().get_in_else();
139    }
140};
141
142///////////////////////////////////////////////////////////////////////////////
143}   // namespace util
144}   // namespace wave
145}   // namespace boost
146
147#endif // !defined(CPP_IFBLOCK_HPP_D4676B36_00C5_41F4_BC9F_9CBBAE3B8006_INCLUDED)
Note: See TracBrowser for help on using the repository browser.