/* Soot - a J*va Optimization Framework
* Copyright (C) 2000 Patrice Pominville
*
* 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.
*/
/*
* Modified by the Sable Research Group and others 1997-1999.
* See the 'credits' file distributed with Soot for the complete list of
* contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
*/
package soot.jimple.parser;
import soot.*;
import soot.jimple.*;
import soot.util.*;
import soot.jimple.internal.JDynamicInvokeExpr;
import soot.jimple.parser.node.*;
import soot.jimple.parser.analysis.*;
import java.util.*;
/*Modified By Marc Berndl 17th May */
public class Walker extends DepthFirstAdapter
{
boolean debug = false;
LinkedList mProductions = new LinkedList();
SootClass mSootClass = null;
Map<String, Local> mLocals = null;
Value mValue = IntConstant.v(1);
Map<Object, Unit> mLabelToStmtMap; // maps a label to the stmt following it in the jimple source
Map<String, List> mLabelToPatchList; // maps a label to the a list of stmts that refer to the label (ie goto lableX)
protected SootResolver mResolver;
public Walker(SootResolver resolver)
{
mResolver = resolver;
if(debug) {
mProductions = new LinkedList(){
public Object removeLast(){
Object o = super.removeLast();
if(debug)
G.v().out.println("popped: " + o );
return o;
}
};
}
}
public Walker(SootClass sc, SootResolver resolver)
{
mSootClass = sc;
mResolver = resolver;
}
public void outStart(Start node)
{
SootClass c = (SootClass) mProductions.removeLast();
}
public SootClass getSootClass()
{
if(mSootClass == null)
throw new RuntimeException("did not parse class yet....");
return mSootClass;
}
/*
file =
modifier* file_type class_name extends_clause? implements_clause? file_body;
*/
public void inAFile(AFile node)
{
if(debug)
G.v().out.println("reading class " + node.getClassName());
}
public void caseAFile(AFile node)
{
inAFile(node);
{
Object temp[] = node.getModifier().toArray();
for (Object element : temp) {
((PModifier) element).apply(this);
}
}
if(node.getFileType() != null)
{
node.getFileType().apply(this);
}
if(node.getClassName() != null)
{
node.getClassName().apply(this);
}
String className = (String) mProductions.removeLast();
if(mSootClass == null) {
mSootClass = new SootClass(className);
mSootClass.setResolvingLevel(SootClass.BODIES);
} else {
if(!mSootClass.getName().equals(className))
throw new RuntimeException("Invalid SootClass for this JimpleAST. The SootClass provided is of type: >" + mSootClass.getName() + "< whereas this parse tree is for type: >" + className + "<");
}
if(node.getExtendsClause() != null)
{
node.getExtendsClause().apply(this);
}
if(node.getImplementsClause() != null)
{
node.getImplementsClause().apply(this);
}
if(node.getFileBody() != null)
{
node.getFileBody().apply(this);
}
outAFile(node);
}
public void outAFile(AFile node)
{
// not not pop members; they have been taken care of.
List implementsList = null;
String superClass = null;
String classType = null;
if(node.getImplementsClause() != null) {
implementsList = (List) mProductions.removeLast();
}
if(node.getExtendsClause() != null) {
superClass = (String) mProductions.removeLast();
}
classType = (String) mProductions.removeLast();
int modifierCount = node.getModifier().size();
int modifierFlags = processModifiers(node.getModifier());
if(classType.equals("interface"))
modifierFlags |= Modifier.INTERFACE;
mSootClass.setModifiers(modifierFlags);
if(superClass != null) {
mSootClass.setSuperclass(mResolver.makeClassRef(superClass));
}
if(implementsList != null) {
Iterator implIt = implementsList.iterator();
while(implIt.hasNext()) {
SootClass interfaceClass = mResolver.makeClassRef((String) implIt.next());
mSootClass.addInterface(interfaceClass);
}
}
mProductions.addLast(mSootClass);
}
/*
member =
{field} modifier* type name semicolon |
{method} modifier* type name l_paren parameter_list? r_paren throws_clause? method_body;
*/
public void outAFieldMember(AFieldMember node)
{
int modifier = 0;
Type type = null;
String name = null;
name = (String) mProductions.removeLast();
type = (Type) mProductions.removeLast();
modifier = processModifiers(node.getModifier());
SootField f = new SootField(name, type, modifier);
mSootClass.addField(f);
}
public void outAMethodMember(AMethodMember node)
{
int modifier = 0;
Type type;
String name;
List parameterList = null;
List<SootClass> throwsClause = null;
JimpleBody methodBody = null;
if(node.getMethodBody() instanceof AFullMethodBody)
methodBody = (JimpleBody) mProductions.removeLast();
if(node.getThrowsClause() != null)
throwsClause = (List<SootClass>) mProductions.removeLast();
if(node.getParameterList() != null) {
parameterList = (List) mProductions.removeLast();
}
else {
parameterList = new ArrayList();
}
Object o = mProductions.removeLast();
name = (String) o;
type = (Type) mProductions.removeLast();
modifier = processModifiers(node.getModifier());
SootMethod method;
if(throwsClause != null)
method = new SootMethod(name, parameterList, type, modifier, throwsClause);
else
method = new SootMethod(name, parameterList, type, modifier);
mSootClass.addMethod(method);
if(method.isConcrete()) {
methodBody.setMethod(method);
method.setActiveBody(methodBody);
} else if(node.getMethodBody() instanceof AFullMethodBody)
throw new RuntimeException("Impossible: !concrete => ! instanceof");
}
/*
type =
{void} void |
{novoid} nonvoid_type;
*/
public void outAVoidType(AVoidType node)
{
mProductions.addLast(VoidType.v());
}
/*
nonvoid_type =
{base} base_type_no_name array_brackets*;
{quoted} quoted_name array_brackets* |
{ident} identifier array_brackets* |
{full_ident} full_identifier array_brackets*;
*/
public void outABaseNonvoidType(ABaseNonvoidType node)
{
Type t = (Type) mProductions.removeLast();
int dim = node.getArrayBrackets().size();
if(dim > 0)
t = ArrayType.v(t, dim);
mProductions.addLast(t);
}
public void outAQuotedNonvoidType(AQuotedNonvoidType node)
{
String typeName = (String) mProductions.removeLast();
Type t = RefType.v(typeName);
int dim = node.getArrayBrackets().size();
if(dim > 0)
t = ArrayType.v(t, dim);
mProductions.addLast(t);
}
public void outAIdentNonvoidType(AIdentNonvoidType node)
{
String typeName = (String) mProductions.removeLast();
Type t = RefType.v(typeName);
int dim = node.getArrayBrackets().size();
if(dim > 0)
t = ArrayType.v( t, dim);
mProductions.addLast(t);
}
public void outAFullIdentNonvoidType(AFullIdentNonvoidType node)
{
String typeName = (String) mProductions.removeLast();
Type t = RefType.v(typeName);
int dim = node.getArrayBrackets().size();
if(dim > 0)
t = ArrayType.v(t, dim);
mProductions.addLast(t);
}
/*
base_type_no_name =
{boolean} boolean |
{byte} byte |
{char} char |
{short} short |
{int} int |
{long} long |
{float} float |
{double} double |
{null} null_type;
*/
public void outABooleanBaseTypeNoName(ABooleanBaseTypeNoName node)
{
mProductions.addLast(BooleanType.v());
}
public void outAByteBaseTypeNoName(AByteBaseTypeNoName node)
{
mProductions.addLast(ByteType.v());
}
public void outACharBaseTypeNoName(ACharBaseTypeNoName node)
{
mProductions.addLast(CharType.v());
}
public void outAShortBaseTypeNoName(AShortBaseTypeNoName node)
{
mProductions.addLast(ShortType.v());
}
public void outAIntBaseTypeNoName(AIntBaseTypeNoName node)
{
mProductions.addLast(IntType.v());
}
public void outALongBaseTypeNoName(ALongBaseTypeNoName node)
{
mProductions.addLast(LongType.v());
}
public void outAFloatBaseTypeNoName(AFloatBaseTypeNoName node)
{
mProductions.addLast(FloatType.v());
}
public void outADoubleBaseTypeNoName(ADoubleBaseTypeNoName node)
{
mProductions.addLast(DoubleType.v());
}
public void outANullBaseTypeNoName(ANullBaseTypeNoName node)
{
mProductions.addLast(NullType.v());
}
/*
base_type =
{boolean} boolean |
{byte} byte |
{char} char |
{short} short |
{int} int |
{long} long |
{float} float |
{double} double |
{null} null_type |
{class_name} class_name;
*/
public void outABooleanBaseType(ABooleanBaseType node)
{
mProductions.addLast(BooleanType.v());
}
public void outAByteBaseType(AByteBaseType node)
{
mProductions.addLast(ByteType.v());
}
public void outACharBaseType(ACharBaseType node)
{
mProductions.addLast(CharType.v());
}
public void outAShortBaseType(AShortBaseType node)
{
mProductions.addLast(ShortType.v());
}
public void outAIntBaseType(AIntBaseType node)
{
mProductions.addLast(IntType.v());
}
public void outALongBaseType(ALongBaseType node)
{
mProductions.addLast(LongType.v());
}
public void outAFloatBaseType(AFloatBaseType node)
{
mProductions.addLast(FloatType.v());
}
public void outADoubleBaseType(ADoubleBaseType node)
{
mProductions.addLast(DoubleType.v());
}
public void outANullBaseType(ANullBaseType node)
{
mProductions.addLast(NullType.v());
}
public void outAClassNameBaseType(AClassNameBaseType node)
{
String type = (String) mProductions.removeLast();
if(type.equals("int")) throw new RuntimeException();
mProductions.addLast(RefType.v(type));
}
/*
method_body =
{empty} semicolon |
{full} l_brace declaration* statement* catch_clause* r_brace;
*/
public void inAFullMethodBody(AFullMethodBody node)
{
mLocals = new HashMap<String, Local>();
mLabelToStmtMap = new HashMap<Object, Unit>();
mLabelToPatchList = new HashMap<String, List>();
}
public void outAFullMethodBody(AFullMethodBody node)
{
JimpleBody jBody = Jimple.v().newBody();
if(node.getCatchClause() != null) {
int size = node.getCatchClause().size();
for(int i =0; i < size; i++)
jBody.getTraps().addFirst((Trap)mProductions.removeLast());
}
if(node.getStatement() != null) {
int size = node.getStatement().size();
Unit lastStmt = null;
for(int i = 0; i < size; i++) {
Object o = mProductions.removeLast();
if(o instanceof Unit) {
jBody.getUnits().addFirst((Unit) o);
lastStmt = (Unit) o;
}
else if(o instanceof String) {
if(lastStmt == null)
throw new RuntimeException("impossible");
mLabelToStmtMap.put(o, lastStmt);
}
else
throw new RuntimeException("impossible");
}
}
if(node.getDeclaration() != null) {
int size = node.getDeclaration().size();
for(int i = 0; i < size; i++) {
List<Local> localList = (List<Local>) mProductions.removeLast();
int listSize = localList.size();
for(int j = listSize-1; j>=0; j--)
jBody.getLocals().addFirst(localList.get(j));
}
}
Iterator<String> it = mLabelToPatchList.keySet().iterator();
while(it.hasNext()) {
String label = it.next();
Unit target = mLabelToStmtMap.get(label);
Iterator patchIt = mLabelToPatchList.get(label).iterator();
while(patchIt.hasNext()) {
UnitBox box = (UnitBox) patchIt.next();
box.setUnit(target);
}
}
/*
Iterator it = mLabelToStmtMap.keySet().iterator();
while(it.hasNext()) {
String label = (String) it.next();
Unit target = (Unit) mLabelToStmtMap.get(label);
List l = (List) mLabelToPatchList.get(label);
if(l != null) {
Iterator patchIt = l.iterator();
while(patchIt.hasNext()) {
UnitBox box = (UnitBox) patchIt.next();
box.setUnit(target);
}
}
}
*/
mProductions.addLast(jBody);
}
public void outANovoidType(ANovoidType node)
{
}
/*
parameter_list =
{single} parameter |
{multi} parameter comma parameter_list;
*/
public void outASingleParameterList(ASingleParameterList node)
{
List<Type> l = new ArrayList<Type>();
l.add((Type) mProductions.removeLast());
mProductions.addLast(l);
}
public void outAMultiParameterList(AMultiParameterList node)
{
List<Type> l = (List<Type>) mProductions.removeLast();
l.add(0,(Type) mProductions.removeLast());
mProductions.addLast(l);
}
/*
arg_list =
{single} immediate |
{multi} immediate comma arg_list;
*/
public void outASingleArgList(ASingleArgList node)
{
List<Value> l = new ArrayList<Value>();
l.add((Value) mProductions.removeLast());
mProductions.addLast(l);
}
public void outAMultiArgList(AMultiArgList node)
{
List<Value> l = (List<Value>) mProductions.removeLast();
l.add(0,(Value) mProductions.removeLast());
mProductions.addLast(l);
}
/*
class_name_list =
{class_name_single} class_name |
{class_name_multi} class_name comma class_name_list;
*/
public void outAClassNameSingleClassNameList(AClassNameSingleClassNameList node)
{
List<String> l = new ArrayList<String>();
l.add((String) mProductions.removeLast());
mProductions.addLast(l);
}
public void outAClassNameMultiClassNameList(AClassNameMultiClassNameList node)
{
List<String> l = (List<String>) mProductions.removeLast();
l.add(0,(String) mProductions.removeLast());
mProductions.addLast(l);
}
/*
file_type =
{class} [theclass]:class |
{interface} interface;
*/
public void outAClassFileType(AClassFileType node)
{
mProductions.addLast("class");
}
public void outAInterfaceFileType(AInterfaceFileType node)
{
mProductions.addLast("interface");
}
/*
catch_clause =
catch [name]:class_name from [from_label]:label_name to [to_label]:label_name with [with_label]:label_name semicolon;
*/
// public void caseACatchClause(ACatchClause node){}
public void outACatchClause(ACatchClause node)
{
String exceptionName;
UnitBox withUnit, fromUnit, toUnit;
withUnit = Jimple.v().newStmtBox(null);
addBoxToPatch((String) mProductions.removeLast(), withUnit);
toUnit = Jimple.v().newStmtBox(null);
addBoxToPatch((String) mProductions.removeLast(), toUnit);
fromUnit = Jimple.v().newStmtBox(null);
addBoxToPatch((String) mProductions.removeLast(), fromUnit);
exceptionName = (String) mProductions.removeLast();
Trap trap = Jimple.v().newTrap(mResolver.makeClassRef(exceptionName), fromUnit, toUnit, withUnit);
mProductions.addLast(trap);
}
/*
declaration =
jimple_type local_name_list semicolon;
*/
public void outADeclaration(ADeclaration node)
{
List localNameList = (List) mProductions.removeLast();
Type type = (Type) mProductions.removeLast();
Iterator it = localNameList.iterator();
List<Local> localList = new ArrayList<Local>();
while(it.hasNext()) {
Local l = Jimple.v().newLocal((String) it.next(),type);
mLocals.put(l.getName(), l);
localList.add(l);
}
mProductions.addLast(localList);
}
/*
jimple_type =
{unknown} unknown |
{nonvoid} nonvoid_type;
*/
public void outAUnknownJimpleType(AUnknownJimpleType node)
{
mProductions.addLast(UnknownType.v());
}
/*
local_name_list =
{single} local_name |
{multi} local_name comma local_name_list;
*/
public void outASingleLocalNameList(ASingleLocalNameList node)
{
List<String> l = new ArrayList<String>();
l.add((String) mProductions.removeLast());
mProductions.addLast(l);
}
public void outAMultiLocalNameList(AMultiLocalNameList node)
{
List<String> l = (List<String>) mProductions.removeLast();
l.add(0,(String) mProductions.removeLast());
mProductions.addLast(l);
}
/*
statement =
{label} label_name colon |
{breakpoint} breakpoint semicolon |
{entermonitor} entermonitor immediate semicolon |
{exitmonitor} exitmonitor immediate semicolon |
{switch} switch l_paren immediate r_paren l_brace case_stmt+ r_brace semicolon |
{identity} local_name colon_equals at_identifier type semicolon |
{identity_no_type} local_name colon_equals at_identifier semicolon |
{assign} variable equals expression semicolon |
{if} if bool_expr goto_stmt |
{goto} goto_stmt |
{nop} nop semicolon |
{ret} ret immediate? semicolon |
{return} return immediate? semicolon |
{throw} throw immediate semicolon |
{invoke} invoke_expr semicolon;
*/
public void outALabelStatement(ALabelStatement node)
{
}
public void outABreakpointStatement(ABreakpointStatement node)
{
Unit u = Jimple.v().newBreakpointStmt();
mProductions.addLast(u);
}
public void outAEntermonitorStatement(AEntermonitorStatement node)
{
Value op = (Value) mProductions.removeLast();
Unit u = Jimple.v().newEnterMonitorStmt(op);
mProductions.addLast(u);
}
public void outAExitmonitorStatement(AExitmonitorStatement node)
{
Value op = (Value) mProductions.removeLast();
Unit u = Jimple.v().newExitMonitorStmt(op);
mProductions.addLast(u);
}
/*
case_label =
{constant} case minus? integer_constant |
{default} default;
*/
/*
case_stmt =
case_label colon goto_stmt;
*/
public void outACaseStmt(ACaseStmt node)
{
String labelName = (String) mProductions.removeLast();
UnitBox box = Jimple.v().newStmtBox(null);
addBoxToPatch(labelName, box);
Value labelValue = null;
if(node.getCaseLabel() instanceof AConstantCaseLabel)
labelValue = (Value) mProductions.removeLast();
// if labelValue == null, this is the default label.
if(labelValue == null)
mProductions.addLast(box);
else {
Object[] valueTargetPair = new Object[2];
valueTargetPair[0] = labelValue;
valueTargetPair[1] = box;
mProductions.addLast(valueTargetPair);
}
}
public void outATableswitchStatement(ATableswitchStatement node)
{
List<Object> targets = new ArrayList<Object>();
UnitBox defaultTarget = null;
int lowIndex = 0, highIndex = 0;
if(node.getCaseStmt() != null) {
int size = node.getCaseStmt().size();
for(int i = 0; i < size; i++) {
Object valueTargetPair = mProductions.removeLast();
if(valueTargetPair instanceof UnitBox) {
if(defaultTarget != null)
throw new RuntimeException("error: can't ;have more than 1 default stmt");
defaultTarget = (UnitBox) valueTargetPair;
} else {
Object[] pair = (Object[]) valueTargetPair;
if((i == 0 && defaultTarget == null) || (i==1 && defaultTarget != null))
highIndex = ((IntConstant) pair[0]).value;
if(i == (size -1))
lowIndex = ((IntConstant) pair[0]).value;
targets.add(0, pair[1]);
}
}
} else {
throw new RuntimeException("error: switch stmt has no case stmts");
}
Value key = (Value) mProductions.removeLast();
Unit switchStmt = Jimple.v().newTableSwitchStmt(key, lowIndex, highIndex, targets, defaultTarget);
mProductions.addLast(switchStmt);
}
public void outALookupswitchStatement(ALookupswitchStatement node)
{
List<Object> lookupValues = new ArrayList<Object>();
List<Object> targets = new ArrayList<Object>();
UnitBox defaultTarget = null;
if(node.getCaseStmt() != null) {
int size = node.getCaseStmt().size();
for(int i = 0; i < size; i++) {
Object valueTargetPair = mProductions.removeLast();
if(valueTargetPair instanceof UnitBox) {
if(defaultTarget != null)
throw new RuntimeException("error: can't ;have more than 1 default stmt");
defaultTarget = (UnitBox) valueTargetPair;
} else {
Object[] pair = (Object[]) valueTargetPair;
lookupValues.add(0, pair[0]);
targets.add(0, pair[1]);
}
}
} else {
throw new RuntimeException("error: switch stmt has no case stmts");
}
Value key = (Value) mProductions.removeLast();
Unit switchStmt = Jimple.v().newLookupSwitchStmt(key, lookupValues, targets, defaultTarget);
mProductions.addLast(switchStmt);
}
public void outAIdentityStatement(AIdentityStatement node)
{
Type identityRefType = (Type) mProductions.removeLast();
String atClause = (String) mProductions.removeLast();
Value local = mLocals.get(mProductions.removeLast()); // the local ref from it's identifier
Value ref = null;
if(atClause.startsWith("@this")) {
ref = Jimple.v().newThisRef((RefType) identityRefType);
} else if(atClause.startsWith("@parameter")) {
int index = Integer.parseInt(atClause.substring(10, atClause.length() - 1));
ref = Jimple.v().newParameterRef(identityRefType, index);
} else
throw new RuntimeException("shouldn't @caughtexception be handled by outAIdentityNoTypeStatement: got" + atClause);
Unit u = Jimple.v().newIdentityStmt(local, ref);
mProductions.addLast(u);
}
public void outAIdentityNoTypeStatement(AIdentityNoTypeStatement node)
{
mProductions.removeLast(); // get rid of @caughtexception string presently on top of the stack
Value local = mLocals.get(mProductions.removeLast()); // the local ref from it's identifier
Unit u = Jimple.v().newIdentityStmt(local, Jimple.v().newCaughtExceptionRef());
mProductions.addLast(u);
}
public void outAAssignStatement(AAssignStatement node)
{
Object removeLast = mProductions.removeLast();
Value rvalue = (Value) removeLast;
Value variable =(Value)mProductions.removeLast();
Unit u = Jimple.v().newAssignStmt(variable, rvalue);
mProductions.addLast(u);
}
public void outAIfStatement(AIfStatement node)
{
String targetLabel = (String) mProductions.removeLast();
Value condition =(Value) mProductions.removeLast();
UnitBox box = Jimple.v().newStmtBox(null);
Unit u = Jimple.v().newIfStmt(condition, box);
addBoxToPatch(targetLabel, box);
mProductions.addLast(u);
}
public void outAReturnStatement(AReturnStatement node)
{
Value v;
Stmt s = null;
if(node.getImmediate() != null) {
v = (Value) mProductions.removeLast();
s = Jimple.v().newReturnStmt(v);
} else {
s = Jimple.v().newReturnVoidStmt();
}
mProductions.addLast(s);
}
public void outAGotoStatement(AGotoStatement node)
{
String targetLabel = (String) mProductions.removeLast();
UnitBox box = Jimple.v().newStmtBox(null);
Unit branch = Jimple.v().newGotoStmt(box);
addBoxToPatch(targetLabel, box);
mProductions.addLast(branch);
}
public void outANopStatement(ANopStatement node)
{
Unit u = Jimple.v().newNopStmt();
mProductions.addLast(u);
}
public void outARetStatement(ARetStatement node)
{
throw new RuntimeException("ret not yet implemented.");
}
public void outAThrowStatement(AThrowStatement node)
{
Value op = (Value) mProductions.removeLast();
Unit u = Jimple.v().newThrowStmt(op);
mProductions.addLast(u);
}
public void outAInvokeStatement(AInvokeStatement node)
{
Value op = (Value) mProductions.removeLast();
Unit u = Jimple.v().newInvokeStmt(op);
mProductions.addLast(u);
}
/*
case_label =
{constant} case minus? integer_constant |
{default} default;
*/
public void outAConstantCaseLabel(AConstantCaseLabel node)
{
String s = (String) mProductions.removeLast();
int sign = 1;
if(node.getMinus() != null)
sign = -1;
if(s.endsWith("L")) {
mProductions.addLast(LongConstant.v(sign * Long.parseLong(s.substring(0, s.length()-1))));
}
else if (s.equals("2147483648"))
mProductions.addLast(IntConstant.v(sign * Integer.MIN_VALUE));
else
mProductions.addLast(IntConstant.v(sign * Integer.parseInt(s)));
}
/*
immediate =
{local} local_name |
{constant} constant;
*/
public void outALocalImmediate(ALocalImmediate node)
{
String local = (String) mProductions.removeLast();
Local l = mLocals.get(local);
if(l == null) throw new RuntimeException("did not find local: " + local);
mProductions.addLast(l);
}
/*
constant =
{integer} minus? integer_constant |
{float} minus? float_constant |
{string} string_constant |
{null} null;
*/
public void outANullConstant(ANullConstant node)
{
mProductions.addLast(NullConstant.v());
}
public void outAIntegerConstant(AIntegerConstant node)
{
String s = (String) mProductions.removeLast();
StringBuffer buf = new StringBuffer();
if(node.getMinus() != null)
buf.append('-');
buf.append(s);
s = buf.toString();
if(s.endsWith("L")) {
mProductions.addLast(LongConstant.v(Long.parseLong(s.substring(0, s.length()-1))));
}
else if (s.equals("2147483648"))
mProductions.addLast(IntConstant.v(Integer.MIN_VALUE));
else
mProductions.addLast(IntConstant.v(Integer.parseInt(s)));
}
public void outAStringConstant(AStringConstant node)
{
String s = (String) mProductions.removeLast();
mProductions.addLast(StringConstant.v(s));
/*
try {
String t = StringTools.getUnEscapedStringOf(s);
mProductions.push(StringConstant.v(t));
} catch(RuntimeException e) {
G.v().out.println(s);
throw e;
}
*/
}
public void outAClzzConstant(AClzzConstant node)
{
String s = (String)mProductions.removeLast();
mProductions.addLast(ClassConstant.v(s));
}
/* ('#' (('-'? 'Infinity') | 'NaN') ('f' | 'F')? ) ; */
public void outAFloatConstant(AFloatConstant node)
{
String s = (String) mProductions.removeLast();
boolean isDouble = true;
float value = 0;
double dvalue = 0;
if(s.endsWith("f") || s.endsWith("F"))
isDouble = false;
if(s.charAt(0) == '#') {
if(s.charAt(1) == '-') {
if(isDouble)
dvalue = Double.NEGATIVE_INFINITY;
else
value = Float.NEGATIVE_INFINITY;
}
else if(s.charAt(1) == 'I') {
if(isDouble)
dvalue = Double.POSITIVE_INFINITY;
else
value = Float.POSITIVE_INFINITY;
}
else {
if(isDouble)
dvalue = Double.NaN;
else
value = Float.NaN;
}
}
else {
StringBuffer buf = new StringBuffer();
if(node.getMinus() != null)
buf.append('-');
buf.append(s);
s = buf.toString();
if(isDouble)
dvalue = Double.parseDouble(s);
else
value =Float.parseFloat(s);
}
Object res;
if(isDouble)
res = DoubleConstant.v(dvalue);
else
res = FloatConstant.v(value);
mProductions.addLast(res);
}
/*
binop_expr =
[left]:immediate binop [right]:immediate;
*/
public void outABinopExpr(ABinopExpr node)
{
Value right = (Value) mProductions.removeLast();
BinopExpr expr = (BinopExpr) mProductions.removeLast();
Value left = (Value) mProductions.removeLast();
expr.setOp1(left);
expr.setOp2(right);
mProductions.addLast(expr);
}
public void outABinopBoolExpr(ABinopBoolExpr node){
}
public void outAUnopExpression(AUnopExpression node)
{
}
/*
binop =
{and} and |
{or} or |
{xor} xor |
{mod} mod |
{cmp} cmp |
{cmpg} cmpg |
{cmpl} cmpl |
{cmpeq} cmpeq |
{cmpne} cmpne |
{cmpgt} cmpgt |
{cmpge} cmpge |
{cmplt} cmplt |
{cmple} cmple |
{shl} shl |
{shr} shr |
{ushr} ushr |
{plus} plus |
{minus} minus |
{mult} mult |
{div} div;
*/
public void outAAndBinop(AAndBinop node)
{
mProductions.addLast(Jimple.v().newAndExpr(mValue, mValue));
}
public void outAOrBinop(AOrBinop node)
{
mProductions.addLast(Jimple.v().newOrExpr(mValue, mValue));
}
public void outAXorBinop(AXorBinop node)
{
mProductions.addLast(Jimple.v().newXorExpr(mValue, mValue));
}
public void outAModBinop(AModBinop node)
{
mProductions.addLast(Jimple.v().newRemExpr(mValue, mValue));
}
public void outACmpBinop(ACmpBinop node)
{
mProductions.addLast(Jimple.v().newCmpExpr(mValue, mValue));
}
public void outACmpgBinop(ACmpgBinop node)
{
mProductions.addLast(Jimple.v().newCmpgExpr(mValue, mValue));
}
public void outACmplBinop(ACmplBinop node)
{
mProductions.addLast(Jimple.v().newCmplExpr(mValue, mValue));
}
public void outACmpeqBinop(ACmpeqBinop node)
{
mProductions.addLast(Jimple.v().newEqExpr(mValue, mValue));
}
public void outACmpneBinop(ACmpneBinop node)
{
mProductions.addLast(Jimple.v().newNeExpr(mValue, mValue));
}
public void outACmpgtBinop(ACmpgtBinop node)
{
mProductions.addLast(Jimple.v().newGtExpr(mValue, mValue));
}
public void outACmpgeBinop(ACmpgeBinop node)
{
mProductions.addLast(Jimple.v().newGeExpr(mValue, mValue));
}
public void outACmpltBinop(ACmpltBinop node)
{
mProductions.addLast(Jimple.v().newLtExpr(mValue, mValue));
}
public void outACmpleBinop(ACmpleBinop node)
{
mProductions.addLast(Jimple.v().newLeExpr(mValue, mValue));
}
public void outAShlBinop(AShlBinop node)
{
mProductions.addLast(Jimple.v().newShlExpr(mValue, mValue));
}
public void outAShrBinop(AShrBinop node)
{
mProductions.addLast(Jimple.v().newShrExpr(mValue, mValue));
}
public void outAUshrBinop(AUshrBinop node)
{
mProductions.addLast(Jimple.v().newUshrExpr(mValue, mValue));
}
public void outAPlusBinop(APlusBinop node)
{
mProductions.addLast(Jimple.v().newAddExpr(mValue, mValue));
}
public void outAMinusBinop(AMinusBinop node)
{
mProductions.addLast(Jimple.v().newSubExpr(mValue, mValue));
}
public void outAMultBinop(AMultBinop node)
{
mProductions.addLast(Jimple.v().newMulExpr(mValue, mValue));
}
public void outADivBinop(ADivBinop node)
{
mProductions.addLast(Jimple.v().newDivExpr(mValue, mValue));
}
/*
throws_clause =
throws class_name_list;
*/
public void outAThrowsClause(AThrowsClause node)
{
List l = (List) mProductions.removeLast();
Iterator it = l.iterator();
List<SootClass> exceptionClasses = new ArrayList<SootClass>(l.size());
while(it.hasNext()) {
String className = (String) it.next();
exceptionClasses.add(mResolver.makeClassRef(className));
}
mProductions.addLast(exceptionClasses);
}
/*
variable =
{reference} reference |
{local} local_name;
*/
public void outALocalVariable(ALocalVariable node)
{
String local = (String) mProductions.removeLast();
Local l = mLocals.get(local);
if(l == null) throw new RuntimeException("did not find local: " + local);
mProductions.addLast(l);
}
/*
public void caseAReferenceVariable(AReferenceVariable node)
{
}
*/
/*
array_ref =
identifier fixed_array_descriptor;
*/
public void outAArrayReference(AArrayReference node)
{
Value immediate = (Value) mProductions.removeLast();
String identifier = (String) mProductions.removeLast();
Local l = mLocals.get(identifier);
if(l == null) throw new RuntimeException("did not find local: " + identifier);
mProductions.addLast(Jimple.v().newArrayRef(l, immediate));
}
/*
field_ref =
{local} local_name dot field_signature |
{sig} field_signature;
*/
public void outALocalFieldRef(ALocalFieldRef node)
{
SootFieldRef field = (SootFieldRef) mProductions.removeLast();
String local = (String) mProductions.removeLast();
Local l = mLocals.get(local);
if(l == null) throw new RuntimeException("did not find local: " + local);
mProductions.addLast(Jimple.v().newInstanceFieldRef(l, field));
}
public void outASigFieldRef(ASigFieldRef node)
{
SootFieldRef field = (SootFieldRef) mProductions.removeLast();
field = Scene.v().makeFieldRef(field.declaringClass(), field.name(),
field.type(), true);
mProductions.addLast(Jimple.v().newStaticFieldRef(field));
}
/*
field_signature =
cmplt [class_name]:class_name [first]:colon type [field_name]:name cmpgt;
*/
public void outAFieldSignature(AFieldSignature node)
{
String className, fieldName;
Type t;
fieldName = (String) mProductions.removeLast();
t = (Type) mProductions.removeLast();
className = (String) mProductions.removeLast();
SootClass cl = mResolver.makeClassRef(className);
SootFieldRef field = Scene.v().makeFieldRef(cl, fieldName, t, false);
mProductions.addLast(field);
}
/*
expression =
{new} new_expr |
{cast} l_paren nonvoid_type r_paren local_name |
{instanceof} immediate instanceof nonvoid_type |
{invoke} invoke_expr |
{reference} reference |
{binop} binop_expr |
{unop} unop_expr |
{immediate} immediate;
*/
public void outACastExpression(ACastExpression node)
{
Value val = (Value) mProductions.removeLast();
Type type = (Type) mProductions.removeLast();
mProductions.addLast(Jimple.v().newCastExpr(val, type));
}
public void outAInstanceofExpression(AInstanceofExpression node)
{
Type nonvoidType = (Type) mProductions.removeLast();
Value immediate = (Value) mProductions.removeLast();
mProductions.addLast(Jimple.v().newInstanceOfExpr(immediate, nonvoidType));
}
/*
unop_expr =
unop immediate;
*/
public void outAUnopExpr(AUnopExpr node)
{
Value v = (Value) mProductions.removeLast();
UnopExpr expr = (UnopExpr) mProductions.removeLast();
expr.setOp(v);
mProductions.addLast(expr);
}
/*
unop =
{lengthof} lengthof |
{neg} neg;
*/
public void outALengthofUnop(ALengthofUnop node)
{
mProductions.addLast(Jimple.v().newLengthExpr(mValue));
}
public void outANegUnop(ANegUnop node)
{
mProductions.addLast(Jimple.v().newNegExpr(mValue));
}
/*
invoke_expr =
{nonstatic} nonstatic_invoke local_name dot method_signature l_paren arg_list? r_paren |
{static} staticinvoke method_signature l_paren arg_list? r_paren;
*/
public void outANonstaticInvokeExpr(ANonstaticInvokeExpr node)
{
List args;
if(node.getArgList() != null)
args = (List) mProductions.removeLast();
else
args = new ArrayList();
SootMethodRef method = (SootMethodRef) mProductions.removeLast();
String local = (String) mProductions.removeLast();
Local l = mLocals.get(local);
if(l == null) throw new RuntimeException("did not find local: " + local);
Node invokeType = node.getNonstaticInvoke();
Expr invokeExpr;
if(invokeType instanceof ASpecialNonstaticInvoke){
invokeExpr = Jimple.v().newSpecialInvokeExpr(l, method, args);
} else if(invokeType instanceof AVirtualNonstaticInvoke){
invokeExpr = Jimple.v().newVirtualInvokeExpr(l, method, args);
} else {
if(debug)if(!(invokeType instanceof AInterfaceNonstaticInvoke)) throw new RuntimeException("expected interface invoke.");
invokeExpr = Jimple.v().newInterfaceInvokeExpr(l, method, args);
}
mProductions.addLast(invokeExpr);
}
public void outAStaticInvokeExpr(AStaticInvokeExpr node)
{
List args;
if(node.getArgList() != null)
args = (List) mProductions.removeLast();
else
args = new ArrayList();
SootMethodRef method = (SootMethodRef) mProductions.removeLast();
method = Scene.v().makeMethodRef(method.declaringClass(),
method.name(), method.parameterTypes(), method.returnType(),
true);
mProductions.addLast(Jimple.v().newStaticInvokeExpr(method, args));
}
public void outADynamicInvokeExpr(ADynamicInvokeExpr node)
{
List<Value> bsmArgs;
if(node.getStaticargs() != null)
bsmArgs = (List) mProductions.removeLast();
else
bsmArgs = Collections.emptyList();
SootMethodRef bsmMethodRef = (SootMethodRef) mProductions.removeLast();
List<Value> dynArgs;
if(node.getDynargs() != null)
dynArgs = (List) mProductions.removeLast();
else
dynArgs = Collections.emptyList();
SootMethodRef dynMethodRef = (SootMethodRef) mProductions.removeLast();
mProductions.addLast(Jimple.v().newDynamicInvokeExpr(bsmMethodRef, bsmArgs, dynMethodRef, dynArgs));
}
public void outAUnnamedMethodSignature(AUnnamedMethodSignature node) {
String className, methodName;
List parameterList = new ArrayList();
if(node.getParameterList() != null)
parameterList = (List) mProductions.removeLast();
Type type = (Type) mProductions.removeLast();
String name = (String) mProductions.removeLast();
SootClass sootClass = mResolver.makeClassRef(SootClass.INVOKEDYNAMIC_DUMMY_CLASS_NAME);
SootMethodRef sootMethod = Scene.v().makeMethodRef(sootClass, name, parameterList, type, false);
mProductions.addLast(sootMethod);
}
/*
method_signature =
cmplt [class_name]:class_name [first]:colon type [method_name]:name l_paren parameter_list? r_paren cmpgt;
*/
public void outAMethodSignature(AMethodSignature node)
{
String className, methodName;
List parameterList = new ArrayList();
if(node.getParameterList() != null)
parameterList = (List) mProductions.removeLast();
methodName = (String) mProductions.removeLast();
Type type = (Type) mProductions.removeLast();
className = (String) mProductions.removeLast();
SootClass sootClass = mResolver.makeClassRef(className);
SootMethodRef sootMethod = Scene.v().makeMethodRef(sootClass, methodName, parameterList, type, false);
mProductions.addLast(sootMethod);
}
/*
new_expr =
{simple} new base_type |
{array} newarray l_paren nonvoid_type r_paren fixed_array_descriptor |
{multi} newmultiarray l_paren base_type r_paren array_descriptor+;
*/
public void outASimpleNewExpr(ASimpleNewExpr node)
{
mProductions.addLast(Jimple.v().newNewExpr((RefType)mProductions.removeLast()));
}
public void outAArrayNewExpr(AArrayNewExpr node)
{
Value size = (Value) mProductions.removeLast();
Type type = (Type) mProductions.removeLast();
mProductions.addLast(Jimple.v().newNewArrayExpr(type, size));
}
public void outAMultiNewExpr(AMultiNewExpr node)
{
LinkedList arrayDesc = node.getArrayDescriptor();
int descCnt = arrayDesc.size();
List sizes = new LinkedList();
Iterator it = arrayDesc.iterator();
while(it.hasNext()) {
AArrayDescriptor o = (AArrayDescriptor) it.next();
if(o.getImmediate() != null)
sizes.add(0,mProductions.removeLast());
else
break;
}
Type type = (Type) mProductions.removeLast();
ArrayType arrayType = ArrayType.v(type, descCnt);
mProductions.addLast(Jimple.v().newNewMultiArrayExpr(arrayType, sizes));
}
public void defaultCase(Node node)
{
if(node instanceof TQuotedName ||
node instanceof TFullIdentifier ||
node instanceof TIdentifier ||
node instanceof TStringConstant ||
node instanceof TIntegerConstant ||
node instanceof TFloatConstant ||
node instanceof TAtIdentifier
) {
if(debug)
G.v().out.println("Default case -pushing token:" + ((Token) node).getText());
String tokenString = ((Token) node).getText();
if(node instanceof TStringConstant || node instanceof TQuotedName) {
tokenString = tokenString.substring(1, tokenString.length() -1 );
}
if(node instanceof TIdentifier || node instanceof TFullIdentifier || node instanceof TQuotedName || node instanceof TStringConstant) {
try {
tokenString = StringTools.getUnEscapedStringOf(tokenString);
} catch(RuntimeException e) {
G.v().out.println(tokenString);
throw e;
}
}
mProductions.addLast(tokenString);
}
}
protected int processModifiers(List l)
{
int modifier = 0;
Iterator it = l.iterator();
while(it.hasNext()) {
Object t = it.next();
if(t instanceof AAbstractModifier)
modifier |= Modifier.ABSTRACT;
else if(t instanceof AFinalModifier)
modifier |= Modifier.FINAL;
else if(t instanceof ANativeModifier)
modifier |= Modifier.NATIVE;
else if(t instanceof APublicModifier)
modifier |= Modifier.PUBLIC;
else if(t instanceof AProtectedModifier)
modifier |= Modifier.PROTECTED;
else if(t instanceof APrivateModifier)
modifier |= Modifier.PRIVATE;
else if(t instanceof AStaticModifier)
modifier |= Modifier.STATIC;
else if(t instanceof ASynchronizedModifier)
modifier |= Modifier.SYNCHRONIZED;
else if(t instanceof ATransientModifier)
modifier |= Modifier.TRANSIENT;
else if(t instanceof AVolatileModifier)
modifier |= Modifier.VOLATILE;
else if(t instanceof AStrictfpModifier)
modifier |= Modifier.STRICTFP;
else if(t instanceof AEnumModifier)
modifier |= Modifier.ENUM;
else if(t instanceof AAnnotationModifier)
modifier |= Modifier.ANNOTATION;
else
throw new RuntimeException("Impossible: modifier unknown - Have you added a new modifier and not updated this file?");
}
return modifier;
}
private void addBoxToPatch(String aLabelName, UnitBox aUnitBox)
{
List<UnitBox> patchList = mLabelToPatchList.get(aLabelName);
if(patchList == null) {
patchList = new ArrayList<UnitBox>();
mLabelToPatchList.put(aLabelName, patchList);
}
patchList.add(aUnitBox);
}
}