Skip to main content
summaryrefslogblamecommitdiffstats
blob: 1a49b4ef6c13a8a7cf6728c94a09460c47c10976 (plain) (tree)
































































                                                                                        
                                                                             












                                                                                                  
                                                               































                                                                            
                                                             








                                                                           

                                                               









































                                                               
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