diff --git a/jode/jode/expr/CheckCastOperator.java b/jode/jode/expr/CheckCastOperator.java index 0188e60..2960448 100644 --- a/jode/jode/expr/CheckCastOperator.java +++ b/jode/jode/expr/CheckCastOperator.java @@ -18,16 +18,11 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.decompiler.TabbedPrintWriter; public class CheckCastOperator extends SimpleOperator { Type castType; - /** - * There are special cases where a cast isn't allowed. We must cast - * to the common super type before. This cases always give a runtime - * error, but we want to decompile even bad programs. - */ - Type superType = null; public CheckCastOperator(Type type) { super(type, 0, 1); @@ -39,19 +34,27 @@ public class CheckCastOperator extends SimpleOperator { return 700; } - public int getOperandPriority(int i) { - return getPriority(); - } - public void setOperandType(Type[] type) { super.setOperandType(type); - superType = castType.getCastHelper(type[0]); } - public String toString(String[] operands) { - StringBuffer sb = new StringBuffer("(").append(castType).append(")"); - if (superType != null) - sb.append("(").append(superType).append(")"); - return sb.append(operands[0]).toString(); + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + writer.print("("); + writer.printType(castType); + writer.print(") "); + + /* There are special cases where a cast isn't allowed. We must cast + * to the common super type before. This cases always give a runtime + * error, but we want to decompile even bad programs. + */ + Type superType = castType.getCastHelper(operands[0].getType()); + if (superType != null) { + writer.print("("); + writer.printType(superType); + writer.print(") "); + } + operands[0].dumpExpression(writer, 700); } } diff --git a/jode/jode/expr/CheckNullOperator.java b/jode/jode/expr/CheckNullOperator.java index a2ec155..9423cd1 100644 --- a/jode/jode/expr/CheckNullOperator.java +++ b/jode/jode/expr/CheckNullOperator.java @@ -18,8 +18,9 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; import jode.decompiler.LocalInfo; +import jode.decompiler.TabbedPrintWriter; /** * This is a pseudo operator, which represents the check against null @@ -80,15 +81,11 @@ public class CheckNullOperator extends Operator { local.setType(type); } - public String toString(String[] operands) { - /* There is no way to produce exactly the same code. - * This is a good approximation. - * op.getClass will throw a null pointer exception if operands[0] - * is null, otherwise return something not equal to null. - * The bad thing is that this isn't atomar. - */ - return ("(" + local.getName() + " = " - + operands[0] + ").getClass() != null ? " - + local.getName() + " : null"); + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + writer.print("("+local.getName()+" = "); + operands[0].dumpExpression(writer, 0); + writer.print(").getClass() != null ? "+local.getName()+" : null"); } } diff --git a/jode/jode/expr/ClassFieldOperator.java b/jode/jode/expr/ClassFieldOperator.java index 488a9e7..4a9dfa0 100644 --- a/jode/jode/expr/ClassFieldOperator.java +++ b/jode/jode/expr/ClassFieldOperator.java @@ -18,8 +18,9 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; import jode.decompiler.CodeAnalyzer; +import jode.decompiler.TabbedPrintWriter; public class ClassFieldOperator extends NoArgOperator { Type classType; @@ -27,14 +28,16 @@ public class ClassFieldOperator extends NoArgOperator { public ClassFieldOperator(Type classType) { super(Type.tJavaLangClass); this.classType = classType; - classType.useType(); } public int getPriority() { return 950; } - public String toString(String[] operands) { - return classType.toString() + ".class"; + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + writer.printType(classType); + writer.print(".class"); } } diff --git a/jode/jode/expr/CompareBinaryOperator.java b/jode/jode/expr/CompareBinaryOperator.java index 8f3b31a..22f644b 100644 --- a/jode/jode/expr/CompareBinaryOperator.java +++ b/jode/jode/expr/CompareBinaryOperator.java @@ -18,7 +18,8 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.decompiler.TabbedPrintWriter; public class CompareBinaryOperator extends SimpleOperator { public CompareBinaryOperator(Type type, int op) { @@ -40,10 +41,6 @@ public class CompareBinaryOperator extends SimpleOperator { throw new RuntimeException("Illegal operator"); } - public int getOperandPriority(int i) { - return getPriority()+i; - } - public void setOperandType(Type[] inputTypes) { super.setOperandType(inputTypes); operandTypes[0] = operandTypes[1] = @@ -55,7 +52,11 @@ public class CompareBinaryOperator extends SimpleOperator { ((CompareBinaryOperator)o).operator == operator; } - public String toString(String[] operands) { - return operands[0] + getOperatorString() + operands[1]; + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + operands[0].dumpExpression(writer, getPriority()); + writer.print(getOperatorString()); + operands[1].dumpExpression(writer, getPriority()+1); } } diff --git a/jode/jode/expr/CompareToIntOperator.java b/jode/jode/expr/CompareToIntOperator.java index 48fa7fb..2f75e95 100644 --- a/jode/jode/expr/CompareToIntOperator.java +++ b/jode/jode/expr/CompareToIntOperator.java @@ -18,22 +18,22 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.decompiler.TabbedPrintWriter; public class CompareToIntOperator extends SimpleOperator { - public CompareToIntOperator(Type type, int lessGreater) { + boolean greaterOnNAN; + + public CompareToIntOperator(Type type, boolean greaterOnNAN) { super(Type.tInt, 0, 2); operandTypes[0] = operandTypes[1] = type; + this.greaterOnNAN = greaterOnNAN; } public int getPriority() { return 499; } - public int getOperandPriority(int i) { - return 550; - } - public void setOperandType(Type[] inputTypes) { super.setOperandType(inputTypes); Type operandType = operandTypes[0].intersection(operandTypes[1]); @@ -44,7 +44,12 @@ public class CompareToIntOperator extends SimpleOperator { return (o instanceof CompareToIntOperator); } - public String toString(String[] operands) { - return operands[0] + " <=> " + operands[1]; + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException + { + operands[0].dumpExpression(writer, 550); + writer.print(" <=>" + (greaterOnNAN ? 'g' : 'l') + ' '); + operands[1].dumpExpression(writer, 551); } } diff --git a/jode/jode/expr/CompareUnaryOperator.java b/jode/jode/expr/CompareUnaryOperator.java index b2d1c3e..90047b4 100644 --- a/jode/jode/expr/CompareUnaryOperator.java +++ b/jode/jode/expr/CompareUnaryOperator.java @@ -18,7 +18,8 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.decompiler.TabbedPrintWriter; public class CompareUnaryOperator extends SimpleOperator { boolean objectType; @@ -43,16 +44,16 @@ public class CompareUnaryOperator extends SimpleOperator { throw new RuntimeException("Illegal operator"); } - public int getOperandPriority(int i) { - return getPriority(); - } - public boolean equals(Object o) { return (o instanceof CompareUnaryOperator) && ((CompareUnaryOperator)o).operator == operator; } - public String toString(String[] operands) { - return operands[0] + getOperatorString() + (objectType?"null":"0"); + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + operands[0].dumpExpression(writer, getPriority()); + writer.print(getOperatorString()); + writer.print(objectType?"null":"0"); } } diff --git a/jode/jode/expr/ConstOperator.java b/jode/jode/expr/ConstOperator.java index 72255b2..b994560 100644 --- a/jode/jode/expr/ConstOperator.java +++ b/jode/jode/expr/ConstOperator.java @@ -18,8 +18,9 @@ */ package jode.expr; -import jode.Type; -import jode.IntegerType; +import jode.type.Type; +import jode.type.IntegerType; +import jode.decompiler.TabbedPrintWriter; public class ConstOperator extends NoArgOperator { Object value; @@ -129,7 +130,7 @@ public class ConstOperator extends NoArgOperator { return result.append("\"").toString(); } - public String toString(String[] operands) { + public String toString() { String strVal = String.valueOf(value); if (type.isOfType(Type.tBoolean)) { int intVal = ((Integer)value).intValue(); @@ -145,7 +146,7 @@ public class ConstOperator extends NoArgOperator { char c = (char) ((Integer) value).intValue(); switch (c) { case '\0': - return "\'\\0\'"; + return "\'\\0\'"; case '\t': return "\'\\t\'"; case '\n': @@ -215,4 +216,10 @@ public class ConstOperator extends NoArgOperator { return strVal; } + + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + writer.print(toString()); + } } diff --git a/jode/jode/expr/ConstantArrayOperator.java b/jode/jode/expr/ConstantArrayOperator.java index 599e4f3..647bc87 100644 --- a/jode/jode/expr/ConstantArrayOperator.java +++ b/jode/jode/expr/ConstantArrayOperator.java @@ -18,8 +18,9 @@ */ package jode.expr; -import jode.Type; -import jode.ArrayType; +import jode.type.Type; +import jode.type.ArrayType; +import jode.decompiler.TabbedPrintWriter; public class ConstantArrayOperator extends NoArgOperator { @@ -93,14 +94,25 @@ public class ConstantArrayOperator extends NoArgOperator { return this; } - public String toString(String[] operands) { - StringBuffer result = isInitializer ? new StringBuffer("{ ") - : new StringBuffer("new ").append(type).append(" { "); + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + writer.print("new "); + writer.printType(type); + writer.println(" {"); + writer.tab(); for (int i=0; i< values.length; i++) { - if (i>0) - result.append(", "); - result.append((values[i] != null) ? values[i] : empty); + if (i>0) { + if (i % 10 == 0) + writer.println(","); + else + writer.print(", "); + } + values[i].dumpExpression(writer, 0); } - return result.append(" }").toString(); + writer.println(); + writer.untab(); + writer.print("}"); } } + diff --git a/jode/jode/expr/ConstructorOperator.java b/jode/jode/expr/ConstructorOperator.java index 0dee47d..36283e7 100644 --- a/jode/jode/expr/ConstructorOperator.java +++ b/jode/jode/expr/ConstructorOperator.java @@ -18,8 +18,9 @@ */ package jode.expr; -import jode.Type; -import jode.MethodType; +import jode.type.Type; +import jode.type.MethodType; +import jode.decompiler.TabbedPrintWriter; public class ConstructorOperator extends Operator implements MatchableOperator { @@ -80,14 +81,19 @@ public class ConstructorOperator extends Operator ? EMPTYSTRING : null; } - public String toString(String[] operands) { - StringBuffer result = - new StringBuffer("new ").append(classType.toString()).append("("); + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + writer.print("new "); + writer.printType(classType); + writer.print("("); for (int i=0; i < methodType.getParameterTypes().length; i++) { if (i>0) - result.append(", "); - result.append(operands[i]); + writer.print(", "); + operands[i].dumpExpression(writer, 0); } - return result.append(")").toString(); + writer.print(")"); } } + + diff --git a/jode/jode/expr/ConvertOperator.java b/jode/jode/expr/ConvertOperator.java index fa86ac0..0556fdc 100644 --- a/jode/jode/expr/ConvertOperator.java +++ b/jode/jode/expr/ConvertOperator.java @@ -18,7 +18,8 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.decompiler.TabbedPrintWriter; public class ConvertOperator extends Operator { Type from; @@ -32,10 +33,6 @@ public class ConvertOperator extends Operator { return 700; } - public int getOperandPriority(int i) { - return 700; - } - public int getOperandCount() { return 1; } @@ -48,8 +45,11 @@ public class ConvertOperator extends Operator { from = from.intersection(inputTypes[0]); } - public String toString(String[] operands) - { - return "("+type.toString()+") "+operands[0]; + public void dumpExpression(TabbedPrintWriter writer, + Expression[] ops) throws java.io.IOException { + writer.print("("); + writer.printType(type); + writer.print(")"); + ops[0].dumpExpression(writer, 700); } } diff --git a/jode/jode/expr/Expression.java b/jode/jode/expr/Expression.java index 3cd3ac1..9db86f0 100644 --- a/jode/jode/expr/Expression.java +++ b/jode/jode/expr/Expression.java @@ -18,8 +18,9 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; import jode.Decompiler; +import jode.decompiler.TabbedPrintWriter; public abstract class Expression { protected Type type; @@ -166,14 +167,47 @@ public abstract class Expression { return true; } - public abstract String toString(); + public abstract void dumpExpression(TabbedPrintWriter writer) + throws java.io.IOException; + + public void dumpExpression(TabbedPrintWriter writer, int minPriority) + throws java.io.IOException { + boolean needParen1 = false, needParen2 = false; + if (Decompiler.isTypeDebugging) { + if (minPriority > 700) { + needParen1 = true; + writer.print("("); + } + writer.print("("+getType()+") "); + minPriority = 700; + } else if (getType() == Type.tError) { + writer.print("(/*type error */"); + needParen1 = true; + } + if (getOperator().getPriority() < minPriority) { + needParen2 = true; + writer.print("("); + } + + dumpExpression(writer); + + if (needParen2) + writer.print(")"); + if (needParen1) + writer.print(")"); + } + + public String toString() { + try { + java.io.StringWriter strw = new java.io.StringWriter(); + TabbedPrintWriter writer = new TabbedPrintWriter(strw); + dumpExpression(writer); + return strw.toString(); + } catch (java.io.IOException ex) { + return super.toString(); + } + } - String toString(int minPriority) { - String result = toString(); - if (getOperator().getPriority() < minPriority) - return "("+result+")"; - return result; - } public boolean isVoid() { return getType() == Type.tVoid; diff --git a/jode/jode/expr/GetFieldOperator.java b/jode/jode/expr/GetFieldOperator.java index 0cb097d..b1cbe72 100644 --- a/jode/jode/expr/GetFieldOperator.java +++ b/jode/jode/expr/GetFieldOperator.java @@ -18,9 +18,11 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.type.NullType; import jode.bytecode.Reference; import jode.decompiler.CodeAnalyzer; +import jode.decompiler.TabbedPrintWriter; public class GetFieldOperator extends Operator { boolean staticFlag; @@ -37,7 +39,7 @@ public class GetFieldOperator extends Operator { this.classType = Type.tType(ref.getClazz()); this.ref = ref; if (staticFlag) - classType.useType(); + codeAnalyzer.useType(classType); } public int getPriority() { @@ -61,19 +63,36 @@ public class GetFieldOperator extends Operator { needCast = types[0].getHint().equals(Type.tNull); } - public String toString(String[] operands) { + public void dumpExpression(TabbedPrintWriter writer, Expression[] operands) + throws java.io.IOException { + boolean opIsThis = + (!staticFlag + && operands[0] instanceof LocalLoadOperator + && (((LocalLoadOperator) operands[0]).getLocalInfo() + .equals(codeAnalyzer.getParamInfo(0))) + && !codeAnalyzer.getMethod().isStatic()); String fieldName = ref.getName(); - return staticFlag - ? (classType.equals(Type.tClass(codeAnalyzer.getClazz())) - && codeAnalyzer.findLocal(fieldName) == null - ? fieldName - : classType.toString() + "." + fieldName) - : (operands[0].equals("null") - ? "((" + classType + ") null)." + fieldName - : (operands[0].equals("this") - && codeAnalyzer.findLocal(fieldName) == null - ? fieldName - : operands[0] + "." + fieldName)); + if (staticFlag) { + if (!classType.equals(Type.tClass(codeAnalyzer.getClazz())) + || codeAnalyzer.findLocal(fieldName) != null) { + writer.printType(classType); + writer.print("."); + } + writer.print(fieldName); + } else if (operands[0].getType() instanceof NullType) { + writer.print("(("); + writer.printType(classType); + writer.print(")"); + operands[0].dumpExpression(writer, 700); + writer.print(")."); + writer.print(fieldName); + } else { + if (!opIsThis || codeAnalyzer.findLocal(fieldName) != null) { + operands[0].dumpExpression(writer, 950); + writer.print("."); + } + writer.print(fieldName); + } } public boolean equals(Object o) { diff --git a/jode/jode/expr/IIncOperator.java b/jode/jode/expr/IIncOperator.java index 5a392dd..d1619c8 100644 --- a/jode/jode/expr/IIncOperator.java +++ b/jode/jode/expr/IIncOperator.java @@ -18,11 +18,12 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; import jode.decompiler.LocalInfo; +import jode.decompiler.TabbedPrintWriter; public class IIncOperator extends NoArgOperator -implements LocalVarOperator, CombineableOperator { + implements LocalVarOperator, CombineableOperator { String value; LocalInfo local; @@ -96,8 +97,9 @@ implements LocalVarOperator, CombineableOperator { return super.simplify(); } - public String toString(String[] operands) { - return local.getName().toString() + - getOperatorString() + value; + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + writer.print(local.getName() + getOperatorString() + value); } } diff --git a/jode/jode/expr/IfThenElseOperator.java b/jode/jode/expr/IfThenElseOperator.java index c8f54ac..3792037 100644 --- a/jode/jode/expr/IfThenElseOperator.java +++ b/jode/jode/expr/IfThenElseOperator.java @@ -18,7 +18,8 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.decompiler.TabbedPrintWriter; public class IfThenElseOperator extends SimpleOperator { public IfThenElseOperator(Type type) { @@ -34,19 +35,6 @@ public class IfThenElseOperator extends SimpleOperator { return 200; } - public int getOperandPriority(int i) { - switch (i) { - case 0: - return 201; - case 1: - return 0; - case 2: - return 200; - default: - throw new jode.AssertError("ifthenelse with operand "+i); - } - } - public void setOperandType(Type[] inputTypes) { super.setOperandType(inputTypes); Type operandType = @@ -70,7 +58,13 @@ public class IfThenElseOperator extends SimpleOperator { return (o instanceof IfThenElseOperator); } - public String toString(String[] operands) { - return operands[0] + " ? "+operands[1]+" : "+ operands[2]; + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + operands[0].dumpExpression(writer, 201); + writer.print(" ? "); + operands[1].dumpExpression(writer, 0); + writer.print(" : "); + operands[2].dumpExpression(writer, 200); } } diff --git a/jode/jode/expr/InstanceOfOperator.java b/jode/jode/expr/InstanceOfOperator.java index 0ef484b..0405f38 100644 --- a/jode/jode/expr/InstanceOfOperator.java +++ b/jode/jode/expr/InstanceOfOperator.java @@ -18,7 +18,8 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.decompiler.TabbedPrintWriter; public class InstanceOfOperator extends SimpleOperator { @@ -44,22 +45,27 @@ public class InstanceOfOperator extends SimpleOperator { return 550; } - public int getOperandPriority(int i) { - return getPriority(); - } - public void setOperandType(Type[] type) { super.setOperandType(type); superType = instanceType.getCastHelper(type[0]); } - public String toString(String[] operands) { - StringBuffer sb = new StringBuffer(); - if (superType != null) - sb.append("((").append(superType).append(")"); - sb.append(operands[0]); - if (superType != null) - sb.append(")"); - return sb.append(" instanceof ").append(instanceType).toString(); + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + /* There are special cases where a cast isn't allowed. We must cast + * to the common super type before. This cases always give a runtime + * error, but we want to decompile even bad programs. + */ + Type superType = instanceType.getCastHelper(operands[0].getType()); + if (superType != null) { + writer.print("("); + writer.printType(superType); + writer.print(") "); + operands[0].dumpExpression(writer, 700); + } else + operands[0].dumpExpression(writer, 550); + writer.print(" instanceof "); + writer.printType(instanceType); } } diff --git a/jode/jode/expr/InvokeOperator.java b/jode/jode/expr/InvokeOperator.java index ecc1201..b05a8e6 100644 --- a/jode/jode/expr/InvokeOperator.java +++ b/jode/jode/expr/InvokeOperator.java @@ -20,13 +20,11 @@ package jode.expr; import jode.decompiler.CodeAnalyzer; import jode.decompiler.ClassAnalyzer; -import jode.MethodType; +import jode.decompiler.TabbedPrintWriter; import jode.Decompiler; -import jode.Type; -import jode.ArrayType; -import jode.ClassInterfacesType; import jode.bytecode.*; import jode.jvm.*; +import jode.type.*; import java.lang.reflect.InvocationTargetException; public final class InvokeOperator extends Operator @@ -50,7 +48,7 @@ public final class InvokeOperator extends Operator this.staticFlag = staticFlag; this.specialFlag = specialFlag; if (staticFlag) - clazz.useType(); + codeAnalyzer.useType(clazz); } /** @@ -97,12 +95,6 @@ public final class InvokeOperator extends Operator + methodType.getParameterTypes().length; } - public int getOperandPriority(int i) { - if (!isStatic() && i == 0) - return 950; - return 0; - } - public Type getOperandType(int i) { if (!isStatic()) { if (i == 0) @@ -144,32 +136,68 @@ public final class InvokeOperator extends Operator return false; } - public String toString(String[] operands) { - String object = specialFlag - ? (operands[0].equals("this") - ? (/* XXX check if this is a private or final method. */ - isThis() ? "" : "super") - : (/* XXX check if this is a private or final method. */ - isThis() ? operands[0] : "NON VIRTUAL " + operands[0])) - : (isStatic() - ? (isThis() ? "" : clazz.toString()) - : (operands[0].equals("this") ? "" - : operands[0].equals("null") - ? "((" + clazz.toString() + ") null)" - : operands[0])); - - int arg = isStatic() ? 0 : 1; - String method = isConstructor() - ? (object.length() == 0 ? "this" : object) - : (object.length() == 0 ? methodName : object + "." + methodName); - - StringBuffer params = new StringBuffer(); + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + boolean opIsThis = + (!staticFlag + && operands[0] instanceof LocalLoadOperator + && (((LocalLoadOperator) operands[0]).getLocalInfo() + .equals(codeAnalyzer.getParamInfo(0))) + && !codeAnalyzer.getMethod().isStatic()); + int arg = 1; + + if (specialFlag) { + if (opIsThis) { + if (isThis()) { + /* XXX check if this is a private or final method. */ + } else { + /* XXX check that this is the first defined + * super method. */ + writer.print("super"); + opIsThis = false; + } + } else { + /* XXX check if this is a private or final method. */ + if (!isThis()) { + writer.print("(NON VIRTUAL "); + writer.printType(clazz); + writer.print(")"); + } + operands[0].dumpExpression(writer, 950); + } + } else if (staticFlag) { + arg = 0; + if (!isThis()) + writer.printType(clazz); + } else { + if (!opIsThis) { + int minPriority = 950; /* field access */ + if (operands[0].getType() instanceof NullType) { + writer.print("("); + writer.printType(clazz); + writer.print(") "); + minPriority = 700; + } + operands[0].dumpExpression(writer, minPriority); + } + } + + if (isConstructor()) { + if (opIsThis) + writer.print("this"); + } else { + if (!opIsThis) + writer.print("."); + writer.print(methodName); + } + writer.print("("); for (int i=0; i < methodType.getParameterTypes().length; i++) { if (i>0) - params.append(", "); - params.append(operands[arg++]); + writer.print(", "); + operands[arg++].dumpExpression(writer, 0); } - return method+"("+params+")"; + writer.print(")"); } /** diff --git a/jode/jode/expr/LocalLoadOperator.java b/jode/jode/expr/LocalLoadOperator.java index d942fd3..6648a1a 100644 --- a/jode/jode/expr/LocalLoadOperator.java +++ b/jode/jode/expr/LocalLoadOperator.java @@ -19,11 +19,12 @@ package jode.expr; import jode.Decompiler; -import jode.Type; +import jode.type.Type; import jode.decompiler.LocalInfo; +import jode.decompiler.TabbedPrintWriter; public class LocalLoadOperator extends NoArgOperator -implements LocalVarOperator { + implements LocalVarOperator { LocalInfo local; public LocalLoadOperator(Type type, LocalInfo local) { @@ -77,7 +78,7 @@ implements LocalVarOperator { // return slot; // } - public String toString(String[] operands) { + public String toString() { return local.getName().toString(); } @@ -85,5 +86,11 @@ implements LocalVarOperator { return (o instanceof LocalLoadOperator && ((LocalLoadOperator) o).local.getSlot() == local.getSlot()); } + + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + writer.print(toString()); + } } diff --git a/jode/jode/expr/LocalPrePostFixOperator.java b/jode/jode/expr/LocalPrePostFixOperator.java index 1b3cca0..e7c234f 100644 --- a/jode/jode/expr/LocalPrePostFixOperator.java +++ b/jode/jode/expr/LocalPrePostFixOperator.java @@ -18,7 +18,8 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.decompiler.TabbedPrintWriter; public class LocalPrePostFixOperator extends NoArgOperator { IIncOperator iinc; @@ -35,10 +36,14 @@ public class LocalPrePostFixOperator extends NoArgOperator { return postfix ? 800 : 700; } - public String toString(String[] operands) { - if (postfix) - return iinc.getLocalInfo().getName() + getOperatorString(); - else - return getOperatorString() + iinc.getLocalInfo().getName(); + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + String local = iinc.getLocalInfo().getName(); + if (postfix) { + writer.print(local+getOperatorString()); + } else { + writer.print(getOperatorString()+local); + } } } diff --git a/jode/jode/expr/LocalStoreOperator.java b/jode/jode/expr/LocalStoreOperator.java index 96a3de3..7f3f514 100644 --- a/jode/jode/expr/LocalStoreOperator.java +++ b/jode/jode/expr/LocalStoreOperator.java @@ -18,11 +18,12 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; import jode.decompiler.LocalInfo; +import jode.decompiler.TabbedPrintWriter; public class LocalStoreOperator extends StoreInstruction -implements LocalVarOperator { + implements LocalVarOperator { LocalInfo local; public LocalStoreOperator(Type lvalueType, LocalInfo local, int operator) { @@ -82,8 +83,8 @@ implements LocalVarOperator { throw new RuntimeException("LocalStoreOperator has no operands"); } - public String getLValueString(String[] operands) { - return local.getName().toString(); + public void dumpLValue(TabbedPrintWriter writer, Expression[] operands) { + writer.print(local.getName()); } } diff --git a/jode/jode/expr/MonitorEnterOperator.java b/jode/jode/expr/MonitorEnterOperator.java index 5e46e0f..5509048 100644 --- a/jode/jode/expr/MonitorEnterOperator.java +++ b/jode/jode/expr/MonitorEnterOperator.java @@ -18,7 +18,8 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.decompiler.TabbedPrintWriter; public class MonitorEnterOperator extends SimpleOperator { public MonitorEnterOperator() { @@ -27,14 +28,13 @@ public class MonitorEnterOperator extends SimpleOperator { } public int getPriority() { - return 0; + return 700; } - public int getOperandPriority(int i) { - return 0; - } - - public String toString(String[] operands) { - return "MONITORENTER "+operands[0]; + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + writer.print("MONITORENTER "); + operands[0].dumpExpression(writer, 700); } } diff --git a/jode/jode/expr/MonitorExitOperator.java b/jode/jode/expr/MonitorExitOperator.java index 530dde0..8acd9a0 100644 --- a/jode/jode/expr/MonitorExitOperator.java +++ b/jode/jode/expr/MonitorExitOperator.java @@ -18,7 +18,8 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.decompiler.TabbedPrintWriter; public class MonitorExitOperator extends SimpleOperator { public MonitorExitOperator() { @@ -27,18 +28,13 @@ public class MonitorExitOperator extends SimpleOperator { } public int getPriority() { - return 0; + return 700; } - public int getOperandPriority(int i) { - return 0; - } - - public Type getOperandType(int i) { - return Type.tObject; - } - - public String toString(String[] operands) { - return "MONITOREXIT "+operands[0]; + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + writer.print("MONITOREXIT "); + operands[0].dumpExpression(writer, 700); } } diff --git a/jode/jode/expr/NewArrayOperator.java b/jode/jode/expr/NewArrayOperator.java index 7bc649e..d66124c 100644 --- a/jode/jode/expr/NewArrayOperator.java +++ b/jode/jode/expr/NewArrayOperator.java @@ -18,8 +18,9 @@ */ package jode.expr; -import jode.Type; -import jode.ArrayType; +import jode.type.Type; +import jode.type.ArrayType; +import jode.decompiler.TabbedPrintWriter; public class NewArrayOperator extends SimpleOperator { String baseTypeString; @@ -35,21 +36,22 @@ public class NewArrayOperator extends SimpleOperator { return 900; } - public int getOperandPriority(int i) { - return 0; - } - - public String toString(String[] operands) { - StringBuffer arrays = new StringBuffer(); + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { Type flat = type; - int i = 0; + int depth = 0; while (flat instanceof ArrayType) { flat = ((ArrayType)flat).getElementType(); - if (i < getOperandCount()) - arrays.append("[").append(operands[i++]).append("]"); - else - arrays.append("[]"); + depth++; } - return "new "+flat.toString()+arrays; + writer.print("new "); + writer.printType(flat); + for (int i=0; i< depth; i++) { + writer.print("["); + if (i < getOperandCount()) + operands[i].dumpExpression(writer, 0); + writer.print("]"); + } } } diff --git a/jode/jode/expr/NewOperator.java b/jode/jode/expr/NewOperator.java index 8c90056..76e3412 100644 --- a/jode/jode/expr/NewOperator.java +++ b/jode/jode/expr/NewOperator.java @@ -18,7 +18,8 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.decompiler.TabbedPrintWriter; public class NewOperator extends NoArgOperator { public NewOperator(Type type) { @@ -29,7 +30,9 @@ public class NewOperator extends NoArgOperator { return 950; } - public String toString(String[] operands) { - return "new "+type.toString(); + public void dumpExpression(TabbedPrintWriter writer, + Expression[] expr) throws java.io.IOException{ + writer.print("new "); + writer.printType(type); } } diff --git a/jode/jode/expr/NopOperator.java b/jode/jode/expr/NopOperator.java index 4efa585..54c600e 100644 --- a/jode/jode/expr/NopOperator.java +++ b/jode/jode/expr/NopOperator.java @@ -18,7 +18,8 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.decompiler.TabbedPrintWriter; /** * A NopOperator takes one or zero arguments and returns it again. It @@ -58,9 +59,15 @@ public class NopOperator extends SimpleOperator { return (o instanceof NopOperator); } - public String toString(String[] operands) { + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { if (type == Type.tVoid) - return "/* nop */"; - return operands[0]; + writer.print("/* NOP */"); + operands[0].dumpExpression(writer); + } + + public void dumpExpression(TabbedPrintWriter writer) { + writer.print("POP"); } } diff --git a/jode/jode/expr/PopOperator.java b/jode/jode/expr/PopOperator.java index 73c1775..153229f 100644 --- a/jode/jode/expr/PopOperator.java +++ b/jode/jode/expr/PopOperator.java @@ -18,7 +18,8 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.decompiler.TabbedPrintWriter; public class PopOperator extends SimpleOperator { @@ -35,7 +36,9 @@ public class PopOperator extends SimpleOperator { return 0; } - public String toString(String[] operands) { - return operands[0]; + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + operands[0].dumpExpression(writer, 0); } } diff --git a/jode/jode/expr/PrePostFixOperator.java b/jode/jode/expr/PrePostFixOperator.java index f23c83b..2c8ca43 100644 --- a/jode/jode/expr/PrePostFixOperator.java +++ b/jode/jode/expr/PrePostFixOperator.java @@ -18,7 +18,8 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.decompiler.TabbedPrintWriter; public class PrePostFixOperator extends Operator { StoreInstruction store; @@ -35,10 +36,6 @@ public class PrePostFixOperator extends Operator { return postfix ? 800 : 700; } - public int getOperandPriority(int i) { - return getPriority(); - } - public Type getOperandType(int i) { return store.getLValueOperandType(i); } @@ -69,10 +66,23 @@ public class PrePostFixOperator extends Operator { store.setLValueOperandType(inputTypes); } - public String toString(String[] operands) { - if (postfix) - return store.getLValueString(operands) + getOperatorString(); - else - return getOperatorString() + store.getLValueString(operands); + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + boolean needBrace = false; + int priority = 700; + if (postfix) { + writer.print(getOperatorString()); + priority = 800; + } + if (store.getPriority() < priority) { + needBrace = true; + writer.print("("); + } + store.dumpLValue(writer, operands); + if (needBrace) + writer.print(")"); + if (!postfix) + writer.print(getOperatorString()); } } diff --git a/jode/jode/expr/PutFieldOperator.java b/jode/jode/expr/PutFieldOperator.java index c19cc7c..d0be5f5 100644 --- a/jode/jode/expr/PutFieldOperator.java +++ b/jode/jode/expr/PutFieldOperator.java @@ -18,10 +18,12 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.type.NullType; import jode.bytecode.Reference; import jode.decompiler.CodeAnalyzer; import jode.decompiler.FieldAnalyzer; +import jode.decompiler.TabbedPrintWriter; public class PutFieldOperator extends StoreInstruction { CodeAnalyzer codeAnalyzer; @@ -37,7 +39,7 @@ public class PutFieldOperator extends StoreInstruction { this.ref = ref; this.classType = Type.tType(ref.getClazz()); if (staticFlag) - classType.useType(); + codeAnalyzer.useType(classType); } public boolean isStatic() { @@ -77,10 +79,6 @@ public class PutFieldOperator extends StoreInstruction { return staticFlag?0:1; } - public int getLValueOperandPriority(int i) { - return 900; - } - public Type getLValueOperandType(int i) { return classType; } @@ -88,19 +86,36 @@ public class PutFieldOperator extends StoreInstruction { public void setLValueOperandType(Type[] t) { } - public String getLValueString(String[] operands) { - String fieldName = getFieldName(); - return staticFlag - ? (classType.equals(Type.tClass(codeAnalyzer.getClazz())) - && codeAnalyzer.findLocal(fieldName) == null - ? fieldName - : classType.toString() + "." + fieldName) - : ((operands[0].equals("this") - && codeAnalyzer.findLocal(fieldName) == null - ? fieldName - : operands[0].equals("null") - ? "((" + classType + ") null)." + fieldName - : operands[0] + "." + fieldName)); + public void dumpLValue(TabbedPrintWriter writer, Expression[] operands) + throws java.io.IOException { + boolean opIsThis = + (!staticFlag + && operands[0] instanceof LocalLoadOperator + && (((LocalLoadOperator) operands[0]).getLocalInfo() + .equals(codeAnalyzer.getParamInfo(0))) + && !codeAnalyzer.getMethod().isStatic()); + String fieldName = ref.getName(); + if (staticFlag) { + if (!classType.equals(Type.tClass(codeAnalyzer.getClazz())) + || codeAnalyzer.findLocal(fieldName) != null) { + writer.printType(classType); + writer.print("."); + } + writer.print(fieldName); + } else if (operands[0].getType() instanceof NullType) { + writer.print("(("); + writer.printType(classType); + writer.print(")"); + operands[0].dumpExpression(writer, 700); + writer.print(")."); + writer.print(fieldName); + } else { + if (!opIsThis || codeAnalyzer.findLocal(fieldName) != null) { + operands[0].dumpExpression(writer, 950); + writer.print("."); + } + writer.print(fieldName); + } } public boolean equals(Object o) { diff --git a/jode/jode/expr/StoreInstruction.java b/jode/jode/expr/StoreInstruction.java index 752467a..0f02786 100644 --- a/jode/jode/expr/StoreInstruction.java +++ b/jode/jode/expr/StoreInstruction.java @@ -18,7 +18,8 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.decompiler.TabbedPrintWriter; public abstract class StoreInstruction extends Operator implements CombineableOperator { @@ -69,7 +70,6 @@ public abstract class StoreInstruction extends Operator public abstract boolean matches(Operator loadop); public abstract int getLValueOperandCount(); - public abstract int getLValueOperandPriority(int i); public abstract Type getLValueOperandType(int i); public abstract void setLValueOperandType(Type [] t); @@ -80,19 +80,10 @@ public abstract class StoreInstruction extends Operator lvalueType = lvalueType.intersection(type); } - public abstract String getLValueString(String[] operands); - public int getPriority() { return 100; } - public int getOperandPriority(int i) { - if (i == getLValueOperandCount()) - return 100; - else - return getLValueOperandPriority(i); - } - public Type getOperandType(int i) { if (i == getLValueOperandCount()) { if (getOperatorIndex() == ASSIGN_OP) @@ -119,9 +110,15 @@ public abstract class StoreInstruction extends Operator return 1 + getLValueOperandCount(); } - public String toString(String[] operands) + public abstract void dumpLValue(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException; + + public void dumpExpression(TabbedPrintWriter writer, Expression[] operands) + throws java.io.IOException { - return getLValueString(operands) + getOperatorString() + - operands[getLValueOperandCount()]; + dumpLValue(writer, operands); + writer.print(getOperatorString()); + operands[getLValueOperandCount()].dumpExpression(writer, 100); } } diff --git a/jode/jode/expr/StringAddOperator.java b/jode/jode/expr/StringAddOperator.java index 4e670f6..a2007c7 100644 --- a/jode/jode/expr/StringAddOperator.java +++ b/jode/jode/expr/StringAddOperator.java @@ -18,7 +18,8 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.decompiler.TabbedPrintWriter; public class StringAddOperator extends SimpleOperator { protected Type operandType; @@ -36,15 +37,15 @@ public class StringAddOperator extends SimpleOperator { return 610; } - public int getOperandPriority(int i) { - return 610 + i; - } - public boolean equals(Object o) { return (o instanceof StringAddOperator); } - public String toString(String[] operands) { - return operands[0] + getOperatorString() + operands[1]; + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + operands[0].dumpExpression(writer, 610); + writer.print(getOperatorString()); + operands[1].dumpExpression(writer, 611); } } diff --git a/jode/jode/expr/UnaryOperator.java b/jode/jode/expr/UnaryOperator.java index 2599e01..ea38967 100644 --- a/jode/jode/expr/UnaryOperator.java +++ b/jode/jode/expr/UnaryOperator.java @@ -18,7 +18,8 @@ */ package jode.expr; -import jode.Type; +import jode.type.Type; +import jode.decompiler.TabbedPrintWriter; public class UnaryOperator extends SimpleOperator { public UnaryOperator(Type type, int op) { @@ -29,10 +30,6 @@ public class UnaryOperator extends SimpleOperator { return 700; } - public int getOperandPriority(int i) { - return getPriority(); - } - /** * Sets the return type of this operator. */ @@ -47,7 +44,10 @@ public class UnaryOperator extends SimpleOperator { ((UnaryOperator)o).operator == operator; } - public String toString(String[] operands) { - return getOperatorString() + operands[0]; + public void dumpExpression(TabbedPrintWriter writer, + Expression[] operands) + throws java.io.IOException { + writer.print(getOperatorString()); + operands[0].dumpExpression(writer, 700); } }