ConstOperator.getValue() returns Object not String.

IIncOperator.getValue() returns int not String.
ACCESSCONSTRUCTOR handling added
InvokeOperator has new constructor syntax
InvokeOperator reworked


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1183 379699f6-c40d-0410-875b-85095c16579e
branch_1_1
jochen 25 years ago
parent 6885078d96
commit 75f42b3167
  1. 4
      jode/jode/expr/ConstOperator.java
  2. 4
      jode/jode/expr/IIncOperator.java
  3. 10
      jode/jode/expr/IfThenElseOperator.java
  4. 333
      jode/jode/expr/InvokeOperator.java.in
  5. 7
      jode/jode/expr/StoreInstruction.java

@ -69,8 +69,8 @@ public class ConstOperator extends NoArgOperator {
value = constant;
}
public String getValue() {
return String.valueOf(value);
public Object getValue() {
return value;
}
public int getPriority() {

@ -38,8 +38,8 @@ public class IIncOperator extends Operator
return (LValueExpression) subExpressions[0];
}
public String getValue() {
return Integer.toString(value);
public int getValue() {
return value;
}
public int getPriority() {

@ -50,11 +50,11 @@ public class IfThenElseOperator extends Operator {
&& subExpressions[2] instanceof ConstOperator) {
ConstOperator c1 = (ConstOperator) subExpressions[1];
ConstOperator c2 = (ConstOperator) subExpressions[2];
if (c1.getValue().equals("1") &&
c2.getValue().equals("0"))
if (c1.getValue().equals(new Integer(1)) &&
c2.getValue().equals(new Integer(0)))
return subExpressions[0].simplify();
if (c2.getValue().equals("1") &&
c1.getValue().equals("0"))
if (c2.getValue().equals(new Integer(1)) &&
c1.getValue().equals(new Integer(0)))
return subExpressions[0].negate().simplify();
}
}
@ -84,7 +84,7 @@ public class IfThenElseOperator extends Operator {
&& invoke.subExpressions[0] instanceof ConstOperator
&& (invoke.subExpressions[0].getType()
.equals(Type.tString))) {
String clazz =
String clazz = (String)
((ConstOperator)invoke.subExpressions[0]).getValue();
if (field.setClassConstant(clazz))
return new ClassFieldOperator(clazz.charAt(0) == '['

@ -41,11 +41,22 @@ import @COLLECTIONS@.Iterator;
public final class InvokeOperator extends Operator
implements MatchableOperator {
public final static int VIRTUAL = 0;
public final static int SPECIAL = 1;
public final static int STATIC = 2;
public final static int CONSTRUCTOR = 3;
public final static int ACCESSSPECIAL = 4;
/**
* The methodAnalyzer of the method, that contains this invocation.
* This is not the method that we should call.
*/
MethodAnalyzer methodAnalyzer;
boolean staticFlag;
boolean specialFlag;
int methodFlag;
MethodType methodType;
String methodName;
int skippedArgs;
Type classType;
Type[] hints;
@ -112,8 +123,7 @@ public final class InvokeOperator extends Operator
public InvokeOperator(MethodAnalyzer methodAnalyzer,
boolean staticFlag, boolean specialFlag,
Reference reference) {
int methodFlag, Reference reference) {
super(Type.tUnknown, 0);
this.methodType = Type.tMethod(reference.getType());
this.methodName = reference.getName();
@ -134,17 +144,16 @@ public final class InvokeOperator extends Operator
else
this.type = methodType.getReturnType();
this.methodAnalyzer = methodAnalyzer;
this.staticFlag = staticFlag;
this.specialFlag = specialFlag;
if (staticFlag)
this.methodFlag = methodFlag;
if (methodFlag == STATIC)
methodAnalyzer.useType(classType);
initOperands((staticFlag ? 0 : 1)
+ methodType.getParameterTypes().length);
skippedArgs = (methodFlag == STATIC ? 0 : 1);
initOperands(skippedArgs + methodType.getParameterTypes().length);
checkAnonymousClasses();
}
public final boolean isStatic() {
return staticFlag;
return methodFlag == STATIC;
}
public MethodType getMethodType() {
@ -166,7 +175,7 @@ public final class InvokeOperator extends Operator
public void checkAnonymousClasses() {
if ((Decompiler.options & Decompiler.OPTION_ANON) == 0)
return;
if (!isConstructor())
if (methodFlag != CONSTRUCTOR)
return;
ClassInfo clazz = getClassInfo();
InnerClassInfo outer = getOuterClassInfo(clazz);
@ -210,7 +219,7 @@ public final class InvokeOperator extends Operator
}
public boolean isConstructor() {
return methodName.equals("<init>");
return methodFlag == CONSTRUCTOR;
}
public ClassInfo getClassInfo() {
@ -221,8 +230,6 @@ public final class InvokeOperator extends Operator
/**
* Checks, whether this is a call of a method from this class.
* @XXX check, if this class implements the method and if not
* allow super class
*/
public boolean isThis() {
return getClassInfo() == methodAnalyzer.getClazz();
@ -237,6 +244,69 @@ public final class InvokeOperator extends Operator
return null;
}
/**
* Tries to locate the class analyzer for the callee class. This
* is mainly useful for inner and anonymous classes.
*
* @return The class analyzer, if the callee class is declared
* inside the same base class as the caller class, null otherwise.
*/
public ClassAnalyzer getClassAnalyzer() {
if ((Decompiler.options &
(Decompiler.OPTION_ANON | Decompiler.OPTION_INNER)) == 0)
return null;
ClassInfo callee = getClassInfo();
if (callee == null)
return null;
int nested = 0;
InnerClassInfo[] outers = callee.getOuterClasses();
if ((Decompiler.options & Decompiler.OPTION_INNER) != 0
&& outers != null) {
/* If the callee class is an inner class we take its
* (outermost) parent instead. This will assure that we
* find the callee class with one inner -> outer pass.
*/
nested = outers.length;
if (outers[nested - 1].outer == null
|| outers[nested - 1].name == null)
nested--;
if (nested > 0)
callee = ClassInfo.forName(outers[nested - 1].outer);
}
/* Now we iterate the caller analyzer queue to find the class
* analyzer for callee
*/
ClassAnalyzer ana = methodAnalyzer.getClassAnalyzer();
while (callee != ana.getClazz()) {
if (ana.getParent() == null)
return null;
if (ana.getParent() instanceof MethodAnalyzer
&& (Decompiler.options & Decompiler.OPTION_ANON) != 0)
ana = ((MethodAnalyzer) ana.getParent())
.getClassAnalyzer();
else if (ana.getParent() instanceof ClassAnalyzer
&& (Decompiler.options
& Decompiler.OPTION_INNER) != 0)
ana = (ClassAnalyzer) ana.getParent();
else
throw new jode.AssertError
("Unknown parent: "+ana+": "+ana.getParent());
}
/* Now get the ClassAnalyzer of the real callee */
while (nested > 0) {
nested--;
ana = ana.getInnerClassAnalyzer(outers[nested].name);
if (ana == null)
return null;
}
return ana;
}
/**
* Checks, whether this is a call of a method from this class or an
* outer instance.
@ -266,26 +336,18 @@ public final class InvokeOperator extends Operator
return false;
}
/**
* Tries to locate the method analyzer for the callee. This
* is mainly useful for inner and anonymous classes.
*
* @return The method analyzer, if the callee is declared
* inside the same base class as the caller class, null otherwise.
*/
public MethodAnalyzer getMethodAnalyzer() {
ClassInfo clazz = getClassInfo();
if (clazz != null) {
ClassAnalyzer ana = methodAnalyzer.getClassAnalyzer();
while (true) {
if (clazz == ana.getClazz()) {
return ana.getMethod(methodName, methodType);
}
if (ana.getParent() == null)
return null;
if (ana.getParent() instanceof MethodAnalyzer)
ana = ((MethodAnalyzer) ana.getParent())
.getClassAnalyzer();
else if (ana.getParent() instanceof ClassAnalyzer)
ana = (ClassAnalyzer) ana.getParent();
else
throw new jode.AssertError("Unknown parent");
}
}
return null;
ClassAnalyzer ana = getClassAnalyzer();
if (ana == null)
return null;
return ana.getMethod(methodName, methodType);
}
/**
@ -378,7 +440,7 @@ public final class InvokeOperator extends Operator
String result;
try {
result = (String) interpreter.interpretMethod
(ma.getBytecodeInfo(), null, new String[] { op.getValue() });
(ma.getBytecodeInfo(), null, new Object[] { op.getValue() });
} catch (InterpreterException ex) {
GlobalOptions.err.println("Warning: Can't interpret method "
+methodName);
@ -520,18 +582,30 @@ public final class InvokeOperator extends Operator
synth.getReference()));
break;
case SyntheticAnalyzer.ACCESSMETHOD:
op = new InvokeOperator(methodAnalyzer, false,
false, synth.getReference());
op = new InvokeOperator(methodAnalyzer, ACCESSSPECIAL,
synth.getReference());
break;
case SyntheticAnalyzer.ACCESSSTATICMETHOD:
op = new InvokeOperator(methodAnalyzer, true,
false, synth.getReference());
op = new InvokeOperator(methodAnalyzer, STATIC,
synth.getReference());
break;
case SyntheticAnalyzer.ACCESSCONSTRUCTOR:
if (subExpressions[1] instanceof ConstOperator
&& ((ConstOperator)
subExpressions[1]).getValue() == null) {
op = new InvokeOperator(methodAnalyzer, CONSTRUCTOR,
synth.getReference());
}
break;
}
if (op != null) {
if (subExpressions != null) {
for (int i=subExpressions.length; i-- > 0; ) {
if (i == 1 && synth.getKind()
== SyntheticAnalyzer.ACCESSCONSTRUCTOR)
// skip the null param.
continue;
op = op.addOperand(subExpressions[i]);
if (subExpressions[i].getFreeOperandCount() > 0)
break;
@ -546,7 +620,7 @@ public final class InvokeOperator extends Operator
public boolean needsCast(int param, Type[] paramTypes) {
Type realClassType;
if (staticFlag)
if (methodFlag == STATIC)
realClassType = classType;
else {
if (param == 0)
@ -559,7 +633,7 @@ public final class InvokeOperator extends Operator
return false;
}
ClassInfo clazz = ((ClassInterfacesType) realClassType).getClassInfo();
int offset = staticFlag ? 0 : 1;
int offset = skippedArgs;
Type[] myParamTypes = methodType.getParameterTypes();
if (myParamTypes[param-offset].equals(paramTypes[param])) {
@ -658,7 +732,7 @@ public final class InvokeOperator extends Operator
clazz = interfaces[0];
} else {
clazz = (superClazz != null
? superClazz : ClassInfo.javaLangObject);
? superClazz : ClassInfo.javaLangObject);
}
outer = getOuterClassInfo(clazz);
}
@ -685,14 +759,10 @@ public final class InvokeOperator extends Operator
*/
public void dumpExpression(TabbedPrintWriter writer)
throws java.io.IOException {
boolean opIsThis = !staticFlag
&& subExpressions[0] instanceof ThisOperator;
int arg = 1;
int length = subExpressions.length;
/* true, if this is the constructor of an anonymous class and we
* must therefore dump the class.
*/
boolean dumpBlock = false;
boolean anonymousNew = false;
ClassInfo clazz = getClassInfo();
ClassAnalyzer clazzAna = null;
@ -700,17 +770,28 @@ public final class InvokeOperator extends Operator
for (int i=0; i< subExpressions.length; i++)
paramTypes[i] = subExpressions[i].getType().getCanonic();
if (isConstructor()) {
switch (methodFlag) {
case CONSTRUCTOR: {
boolean qualifiedNew = false;
boolean jikesAnonymousInner = false;
/* Check if this is an anonymous constructor. In this case
* clazz and outer will be changed to point to the
* super class and anonymousNew will be set.
*/
InnerClassInfo outer = getOuterClassInfo(clazz);
if (outer != null && outer.name == null)
anonymousNew = true;
clazzAna = methodAnalyzer.getClassAnalyzer(clazz);
if ((Decompiler.options &
(Decompiler.OPTION_ANON | Decompiler.OPTION_CONTRAFO)) != 0
if ((~Decompiler.options &
(Decompiler.OPTION_ANON | Decompiler.OPTION_CONTRAFO)) == 0
&& clazzAna != null
&& outer != null
&& (outer.outer == null || outer.name == null)) {
/* This is a method scoped class, skip the outerValues */
arg += clazzAna.getOuterValues().length;
jikesAnonymousInner = clazzAna.isJikesAnonymousInner();
@ -730,7 +811,6 @@ public final class InvokeOperator extends Operator
? superClazz : ClassInfo.javaLangObject);
}
outer = getOuterClassInfo(clazz);
dumpBlock = true;
if (jikesAnonymousInner
&& outer.outer == null && outer.name != null) {
Expression thisExpr = subExpressions[--length];
@ -746,12 +826,16 @@ public final class InvokeOperator extends Operator
}
}
}
/* Check if this is an inner class. It will dump the outer
* class expression, except if its default.
*/
if (outer != null && outer.outer != null && outer.name != null
&& !Modifier.isStatic(outer.modifiers)
&& (Decompiler.options &
&& (~Decompiler.options &
(Decompiler.OPTION_INNER
| Decompiler.OPTION_CONTRAFO)) != 0) {
| Decompiler.OPTION_CONTRAFO)) == 0) {
Expression outerExpr = jikesAnonymousInner
? subExpressions[--length]
: subExpressions[arg++];
@ -770,10 +854,12 @@ public final class InvokeOperator extends Operator
(((ThisOperator) outerExpr).getClassInfo(),
Scope.CLASSSCOPE);
if (writer.conflicts(outer.name, scope, Scope.CLASSNAME)) {
qualifiedNew = true;
outerExpr.dumpExpression(writer, 950);
writer.print(".");
}
} else {
qualifiedNew = true;
if (outerExpr.getType() instanceof NullType) {
writer.print("((");
writer.printType(Type.tClass
@ -786,52 +872,94 @@ public final class InvokeOperator extends Operator
writer.print(".");
}
}
if (subExpressions[0] instanceof NewOperator
&& paramTypes[0].equals(classType)) {
writer.print("new ");
if (qualifiedNew)
writer.print(outer.name);
else
writer.printType(Type.tClass(clazz));
break;
}
if (subExpressions[0] instanceof ThisOperator
&& (((ThisOperator)subExpressions[0]).getClassInfo()
== methodAnalyzer.getClazz())) {
if (isThis())
writer.print("this");
else
writer.print("super");
break;
}
writer.print("((UNCONSTRUCTED)");
subExpressions[0].dumpExpression(writer, 950);
writer.print(").");
writer.printType(Type.tClass(clazz));
break;
}
if (specialFlag) {
if (opIsThis
case SPECIAL:
if (subExpressions[0] instanceof ThisOperator
&& (((ThisOperator)subExpressions[0]).getClassInfo()
== methodAnalyzer.getClazz())) {
if (isThis()) {
/* XXX check if this is a private or final method. */
} else {
/* XXX check that this is the first defined
* super method. */
if (!isThis()) {
/* We don't have to check if this is the real super
* class, as long as ACC_SUPER is set.
*/
writer.print("super");
ClassInfo superClazz = getClassInfo().getSuperclass();
paramTypes[0] = superClazz == null
? Type.tObject : Type.tClass(superClazz);
opIsThis = false;
writer.print(".");
} else {
/* XXX check if this is a private method. */
}
} else if (isConstructor()
&& subExpressions[0] instanceof NewOperator) {
writer.print("new ");
writer.printType(Type.tClass(clazz));
} else {
/* XXX check if this is a private or final method. */
int minPriority = 950; /* field access */
if (!isThis()) {
writer.print("(NON VIRTUAL ");
writer.printType(classType);
writer.print(")");
paramTypes[0] = classType;
minPriority = 700;
}
subExpressions[0].dumpExpression(writer, minPriority);
writer.print("((NON VIRTUAL ");
writer.printType(classType);
writer.print(")");
paramTypes[0] = classType;
subExpressions[0].dumpExpression(writer, 700);
writer.print(").");
}
writer.print(methodName);
break;
case ACCESSSPECIAL:
/* Calling a private method in another class. (This is
* allowed for inner classes.)
*/
if (paramTypes[0].equals(classType))
subExpressions[0].dumpExpression(writer, 950);
else {
writer.print("((");
writer.printType(classType);
writer.print(")");
paramTypes[0] = classType;
subExpressions[0].dumpExpression(writer, 700);
writer.print(")");
}
} else if (staticFlag) {
writer.print(".");
writer.print(methodName);
break;
case STATIC: {
arg = 0;
Scope scope = writer.getScope(getClassInfo(),
Scope.CLASSSCOPE);
if (scope != null
&& !writer.conflicts(methodName, scope, Scope.METHODNAME))
opIsThis = true;
else
if (scope == null
||writer.conflicts(methodName, scope, Scope.METHODNAME)) {
writer.printType(classType);
} else {
if (opIsThis) {
writer.print(".");
}
writer.print(methodName);
break;
}
case VIRTUAL:
if (subExpressions[0] instanceof ThisOperator) {
ThisOperator thisOp = (ThisOperator) subExpressions[0];
Scope scope = writer.getScope(thisOp.getClassInfo(),
Scope.CLASSSCOPE);
@ -868,20 +996,14 @@ public final class InvokeOperator extends Operator
paramTypes[0] = classType;
} else
subExpressions[0].dumpExpression(writer, 950);
}
}
if (isConstructor()) {
if (opIsThis)
writer.print("this");
} else {
if (!opIsThis)
writer.print(".");
}
writer.print(methodName);
}
writer.print("(");
boolean first = true;
int offset = staticFlag ? 0 : 1;
int offset = skippedArgs;
while (arg < length) {
if (!first)
writer.print(", ");
@ -899,7 +1021,11 @@ public final class InvokeOperator extends Operator
subExpressions[arg++].dumpExpression(writer, priority);
}
writer.print(")");
if (dumpBlock) {
if (anonymousNew) {
/* If this was an anonymous constructor call, we must now
* dump the source code of the anonymous class.
*/
writer.openBrace();
writer.tab();
clazzAna.dumpBlock(writer);
@ -907,4 +1033,15 @@ public final class InvokeOperator extends Operator
writer.closeBraceNoSpace();
}
}
public boolean opEquals(Operator o) {
if (o instanceof InvokeOperator) {
InvokeOperator i = (InvokeOperator)o;
return classType.equals(i.classType)
&& methodName.equals(i.methodName)
&& methodType.equals(i.methodType)
&& methodFlag == i.methodFlag;
}
return false;
}
}

@ -90,12 +90,11 @@ public class StoreInstruction extends Operator
if ((getOperatorIndex() == OPASSIGN_OP+ADD_OP ||
getOperatorIndex() == OPASSIGN_OP+SUB_OP) &&
(one.getValue().equals("1")
|| one.getValue().equals("1.0"))) {
((Number)one.getValue()).doubleValue() == 1.0) {
int op = (getOperatorIndex() == OPASSIGN_OP+ADD_OP)
? INC_OP : DEC_OP;
return new PrePostFixOperator
(getType(), op, getLValue(), isVoid()).simplify();
}

Loading…
Cancel
Save