Skip to main content
summaryrefslogtreecommitdiffstats
blob: 1a49b4ef6c13a8a7cf6728c94a09460c47c10976 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package org.eclipse.cdt.internal.core.parser;

import java.util.EmptyStackException;
import java.util.Stack;

/**
 * @author jcamelon
 *
 * To change this generated comment edit the template variable 
"typecomment":
 * Window>Preferences>Java>Templates.
 * To enable and disable the creation of type comments go to
 * Window>Preferences>Java>Code Generation.
 */
public class BranchTracker {
	
	private static final int IGNORE_SENTINEL = -1;
	
	/**
	 * Default constructor.  
	 * 
	 * @see java.lang.Object#Object()
	 */
	public BranchTracker()
	{
	}
	
	private Stack branches = new Stack();
	
	private int ignore = IGNORE_SENTINEL;
	private static final Boolean FALSE = new Boolean( false );
	private static final Boolean TRUE = new Boolean( true );
	
	/**
	 * Method poundif. 
	 * 
	 * This method is called whenever one encounters a #if, #ifndef
	 * or #ifdef preprocessor directive.
	 * 
	 * @param	 taken		- boolean indicates whether or not the condition
	 * evaluates to true or false
	 * @return boolean		- are we set to continue scanning or not? 
	 */
	public boolean poundif( boolean taken )
	{
		if( ignore == IGNORE_SENTINEL )
		{	
			// we are entering an if
			// push the taken value onto the stack
			branches.push( new Boolean( taken ) );
			
			if( taken == false )
			{					
				ignore = branches.size();  
			}
			
			return taken;
		}
		else
		{
			branches.push( FALSE ); 
			return false; 
		}
	}	
	
	public boolean poundelif( boolean taken ) throws EmptyStackException 
	{
		if( ignore != IGNORE_SENTINEL && ignore < branches.size() )
		{
			branches.pop(); 
			branches.push( FALSE ); 
			return false; 
		}
		
		// so at this point we are either 
		//		--> ignore == IGNORE_SENTINEL
		//		--> ignore >= branches.size()
		// check the branch queue to see whether or not the branch has already been taken 
		Boolean branchAlreadyTaken;
		branchAlreadyTaken = (Boolean) branches.peek();
		
		if( ignore == IGNORE_SENTINEL )
		{	
			if( ! branchAlreadyTaken.booleanValue() )
			{
				branches.pop(); 
				branches.push( new Boolean( taken ) );
				if( ! taken )
					ignore = branches.size();
					
				return taken;
			}
			
			// otherwise this section is to be ignored as well
			ignore = branches.size(); 
			return false;
		}
		
		// if we have gotten this far then ignore == branches.size()
		if( ! branchAlreadyTaken.booleanValue() )
		{
			branches.pop(); 
			branches.push( new Boolean( taken ) );
			if( taken )
				ignore = IGNORE_SENTINEL;
			
			return taken; 
		}
		ignore = branches.size(); 
		return false;
	}
	
	public boolean poundelse() throws EmptyStackException
	{
		if( ignore != IGNORE_SENTINEL && ignore < branches.size() )
		{
			branches.pop(); 
			branches.push( FALSE ); 
			return false; 
		}
				
		Boolean branchAlreadyTaken;
		branchAlreadyTaken = (Boolean) branches.peek();
				
		if( ignore == IGNORE_SENTINEL )
		{
			if( branchAlreadyTaken.booleanValue() )
			{
				ignore = branches.size();
				return false; 
			}
			
			branches.pop(); 
			branches.push( TRUE );
			return true;
			
		}
		
		// now ignore >= branches.size()
		if( branchAlreadyTaken.booleanValue() )
		{
			ignore = branches.size(); 
			return false;
		}
		
		branches.pop(); 
		branches.push( TRUE ); 
		ignore = IGNORE_SENTINEL; 
		return true;
		
	}
	
	// taken only on an #endif 
	public boolean poundendif( )
	{
		if( ignore == branches.size() )
			ignore = IGNORE_SENTINEL;
		branches.pop();
		return ( ignore == IGNORE_SENTINEL );
	}
		
	public int getDepth()
	{
		return branches.size(); 
	}
}

Back to the top