/*
 * FindBugs - Find bugs in Java programs
 * Copyright (C) 2005, University of Maryland
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package edu.umd.cs.findbugs.ba.constant;

import org.apache.bcel.classfile.Method;

import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.MethodGen;

import edu.umd.cs.findbugs.ba.BasicBlock;
import edu.umd.cs.findbugs.ba.CFG;
import edu.umd.cs.findbugs.ba.CFGBuilderException;
import edu.umd.cs.findbugs.ba.ClassContext;
import edu.umd.cs.findbugs.ba.Dataflow;
import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
import edu.umd.cs.findbugs.ba.DataflowTestDriver;
import edu.umd.cs.findbugs.ba.DepthFirstSearch;
import edu.umd.cs.findbugs.ba.Edge;
import edu.umd.cs.findbugs.ba.FrameDataflowAnalysis;

/**
 * Dataflow analysis to find constant values.
 * 
 * @see edu.umd.cs.findbugs.ba.constant.Constant
 * @author David Hovemeyer
 */
public class ConstantAnalysis extends FrameDataflowAnalysis<Constant, ConstantFrame> {
	private MethodGen methodGen;
	private DepthFirstSearch dfs;
	private ConstantFrameModelingVisitor visitor;
	
	public ConstantAnalysis(MethodGen methodGen, DepthFirstSearch dfs) {
		super(dfs);
		this.methodGen = methodGen;
		this.visitor = new ConstantFrameModelingVisitor(methodGen.getConstantPool());
	}
	
	public ConstantFrame createFact() {
		return new ConstantFrame(methodGen.getMaxLocals());
	}
	
	public void initEntryFact(ConstantFrame frame) {
		frame.setValid();
		frame.clearStack();
		int numSlots = frame.getNumSlots();
		for (int i = 0; i < numSlots; ++i) {
			frame.setValue(i, Constant.NOT_CONSTANT);
		}
	}
	
	public void transferInstruction(
			InstructionHandle handle,
			BasicBlock basicBlock,
			ConstantFrame frame) throws DataflowAnalysisException {
		visitor.setFrame(frame);
		handle.getInstruction().accept(visitor);
	}
	
	public void meetInto(
			ConstantFrame fact,
			Edge edge,
			ConstantFrame result) throws DataflowAnalysisException {
		
		ConstantFrame tmpFact = null;
		
		if (edge.isExceptionEdge()) {
			tmpFact = modifyFrame(fact, tmpFact);
			tmpFact.clearStack();
			tmpFact.pushValue(Constant.NOT_CONSTANT);
		}
		
		if (tmpFact != null) {
			fact = tmpFact;
		}
		
		mergeInto(fact, result);
	}
	
	protected Constant mergeValues(
			ConstantFrame frame,
			int slot,
			Constant a,
			Constant b) throws DataflowAnalysisException {
		return Constant.merge(a, b);
	}
	
	public static void main(String[] argv) throws Exception {
		if (argv.length != 1) {
			System.err.println("Usage: " + ConstantAnalysis.class.getName() + " <class file>");
			System.exit(1);
		}
		
		DataflowTestDriver<ConstantFrame, ConstantAnalysis> driver =
			new DataflowTestDriver<ConstantFrame, ConstantAnalysis>() {
				public Dataflow<ConstantFrame, ConstantAnalysis> createDataflow(
						ClassContext classContext,
						Method method) throws CFGBuilderException, DataflowAnalysisException {
					
					CFG cfg = classContext.getCFG(method);
					
					ConstantAnalysis analysis = new ConstantAnalysis(
							classContext.getMethodGen(method),
							classContext.getDepthFirstSearch(method));
					
					Dataflow<ConstantFrame, ConstantAnalysis> dataflow =
						new Dataflow<ConstantFrame, ConstantAnalysis>(cfg, analysis);
					dataflow.execute();
					
					return dataflow;
				}
			};
			
		driver.execute(argv[0]);
	}
}

@@ -3,45 +3,35 @@
 %0A * 
-FindBugs - Find bugs in Java programs
+Bytecode Analysis Framework
 %0A * 
@@ -1042,43 +1042,8 @@
 ck;%0A
-import edu.umd.cs.findbugs.ba.CFG;%0A
 impo
@@ -3044,32 +3044,58 @@
 rge(a, b);%0A%09%7D%0A%09%0A
+%09/*%0A%09 * Test driver.%0A%09 */%0A
 %09public static v
@@ -3590,389 +3590,55 @@
 %09%09%09%09
-%0A%09%09%09%09%09CFG cfg = classContext.getCFG(method);%0A%09%09%09%09%09%0A%09%09%09%09%09ConstantAnalysis analysis = new ConstantAnalysis(%0A%09%09%09%09%09%09%09classContext.getMethodGen(method),%0A%09%09%09%09%09%09%09classContext.getDepthFirstSearch(method));%0A%09%09%09%09%09%0A%09%09%09%09%09Dataflow%3CConstantFrame, ConstantAnalysis%3E dataflow =%0A%09%09%09%09%09%09new Dataflow%3CConstantFrame, ConstantAnalysis%3E(cfg, analysis);%0A%09%09%09%09%09dataflow.execute();%0A%09%09%09%09%09%0A%09%09%09%09%09return dataflow
+return classContext.getConstantDataflow(method)
 ;%0A%09%09

Use ClassContext to create the ConstantDataflow.