package soot.poc;

import java.util.List;

import soot.Body;
import soot.NormalUnitPrinter;
import soot.Scene;
import soot.SootClass;
import soot.SootMethod;
import soot.Unit;
import soot.poc.inter.Definition;
import soot.poc.reachingdef.ReachingDefinitions;
import soot.poc.reachingdef.SimpleReachingDefinitions;
import soot.toolkits.graph.ExceptionalUnitGraph;
import soot.toolkits.graph.UnitGraph;

public class RunReachingDefinitionsAnalysis {

	public static void main(String[] _args) {
		_args = new String[] {"br.ufpe.cin.soot.poc.testers.SimpleClass"};
		
		if (_args.length == 0) {
			System.out.println("Usage: java RunReachingDefinitionsAnalysis class_to_analyse");
			System.exit(0);
		}
		
		SootClass sClass = Scene.v().loadClassAndSupport(_args[0]);		
		sClass.setApplicationClass();
		
		List<SootMethod> methods = sClass.getMethods();
		for (SootMethod method : methods)
		{
			Body body = method.retrieveActiveBody();

			System.out.println("=======================================");			
			System.out.println("Method: " + method.getName());
			
			UnitGraph graph = new ExceptionalUnitGraph(body);
			ReachingDefinitions analysis = new SimpleReachingDefinitions(graph);

			for (Unit unit: graph)
			{
				List<Definition> in = analysis.getReachingDefinitionsBefore(unit);
				List<Definition> out = analysis.getReachingDefinitionsAfter(unit);
				NormalUnitPrinter up = new NormalUnitPrinter(body);
				up.setIndent("");

				unit.toString(up);
				System.out.println("Unit: " + up.output());

				System.out.print("RD in {");
				String sep = "";
				for (Definition definition: in)
				{
					System.out.print(sep + definition.toString());
					sep = ", ";
				}
				System.out.println("}");

				System.out.print("RD out {");
				sep = "";
				for (Definition definition: out) {
					System.out.print(sep + definition.toString());
					sep = ", ";
				}
				System.out.println("}");
				System.out.println("---------------------------------------");
			}
		}
	}

}
