*** empty log message ***

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@52 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 4f6e9bf4b5
commit 94846b8034
  1. 108
      jode/jode/bytecode/Opcodes.java
  2. 3
      jode/jode/decompiler/ClassAnalyzer.java
  3. 4
      jode/jode/decompiler/CodeAnalyzer.java
  4. 3
      jode/jode/decompiler/FieldAnalyzer.java
  5. 4
      jode/jode/decompiler/ImportHandler.java
  6. 32
      jode/jode/decompiler/LocalInfo.java
  7. 6
      jode/jode/decompiler/LocalVariableRangeList.java
  8. 4
      jode/jode/decompiler/LocalVariableTable.java
  9. 26
      jode/jode/decompiler/MethodAnalyzer.java
  10. 5
      jode/jode/expr/ArrayLengthOperator.java
  11. 17
      jode/jode/expr/ArrayLoadOperator.java
  12. 19
      jode/jode/expr/ArrayStoreOperator.java
  13. 1
      jode/jode/expr/AssignOperator.java
  14. 9
      jode/jode/expr/BinaryOperator.java
  15. 3
      jode/jode/expr/CheckCastOperator.java
  16. 6
      jode/jode/expr/CompareBinaryOperator.java
  17. 4
      jode/jode/expr/CompareToIntOperator.java
  18. 3
      jode/jode/expr/CompareUnaryOperator.java
  19. 75
      jode/jode/expr/ComplexExpression.java
  20. 5
      jode/jode/expr/ConstOperator.java
  21. 3
      jode/jode/expr/ConstantArrayOperator.java
  22. 8
      jode/jode/expr/ConstructorOperator.java
  23. 3
      jode/jode/expr/ConvertOperator.java
  24. 3
      jode/jode/expr/DupOperator.java
  25. 1
      jode/jode/expr/EmptyStringOperator.java
  26. 1
      jode/jode/expr/Expression.java
  27. 9
      jode/jode/expr/GetFieldOperator.java
  28. 16
      jode/jode/expr/IIncOperator.java
  29. 7
      jode/jode/expr/IfThenElseOperator.java
  30. 5
      jode/jode/expr/InstanceOfOperator.java
  31. 1
      jode/jode/expr/Instruction.java
  32. 36
      jode/jode/expr/InvokeOperator.java
  33. 8
      jode/jode/expr/LocalLoadOperator.java
  34. 1
      jode/jode/expr/LocalPostFixOperator.java
  35. 9
      jode/jode/expr/LocalStoreOperator.java
  36. 7
      jode/jode/expr/LocalVarOperator.java
  37. 1
      jode/jode/expr/MonitorEnterOperator.java
  38. 3
      jode/jode/expr/MonitorExitOperator.java
  39. 3
      jode/jode/expr/NewArrayOperator.java
  40. 1
      jode/jode/expr/NewOperator.java
  41. 1
      jode/jode/expr/NoArgOperator.java
  42. 3
      jode/jode/expr/NopOperator.java
  43. 1
      jode/jode/expr/Operator.java
  44. 3
      jode/jode/expr/PopOperator.java
  45. 1
      jode/jode/expr/PostFixOperator.java
  46. 11
      jode/jode/expr/PutFieldOperator.java
  47. 7
      jode/jode/expr/ShiftOperator.java
  48. 3
      jode/jode/expr/SimpleOperator.java
  49. 15
      jode/jode/expr/StoreInstruction.java
  50. 5
      jode/jode/expr/StringAddOperator.java
  51. 2
      jode/jode/expr/SwapOperator.java
  52. 3
      jode/jode/expr/UnaryOperator.java
  53. 7
      jode/jode/flow/BreakBlock.java
  54. 2
      jode/jode/flow/CaseBlock.java
  55. 7
      jode/jode/flow/CatchBlock.java
  56. 4
      jode/jode/flow/CombineIfGotoExpressions.java
  57. 7
      jode/jode/flow/ContinueBlock.java
  58. 24
      jode/jode/flow/CreateAssignExpression.java
  59. 13
      jode/jode/flow/CreateConstantArray.java
  60. 5
      jode/jode/flow/CreateIfThenElseOperator.java
  61. 5
      jode/jode/flow/CreatePostIncExpression.java
  62. 7
      jode/jode/flow/EmptyBlock.java
  63. 30
      jode/jode/flow/FlowBlock.java
  64. 3
      jode/jode/flow/IfThenElseBlock.java
  65. 2
      jode/jode/flow/InstructionBlock.java
  66. 4
      jode/jode/flow/LoopBlock.java
  67. 4
      jode/jode/flow/RawTryCatchBlock.java
  68. 3
      jode/jode/flow/RemoveEmpty.java
  69. 16
      jode/jode/flow/SequentialBlock.java
  70. 11
      jode/jode/flow/StructuredBlock.java
  71. 2
      jode/jode/flow/SwitchBlock.java
  72. 258
      jode/jode/type/ClassInterfacesType.java

@ -28,23 +28,27 @@ import sun.tools.java.*;
*/ */
public abstract class Opcodes implements RuntimeConstants { public abstract class Opcodes implements RuntimeConstants {
public final static Type ALL_INT_TYPE = MyType.tUInt; public final static Type ALL_INT_TYPE = Type.tUInt;
public final static Type INT_TYPE = Type.tInt; public final static Type BOOL_INT_TYPE = Type.tBoolInt;
public final static Type LONG_TYPE = Type.tLong; public final static Type INT_TYPE = Type.tInt;
public final static Type FLOAT_TYPE = Type.tFloat; public final static Type LONG_TYPE = Type.tLong;
public final static Type DOUBLE_TYPE = Type.tDouble; public final static Type FLOAT_TYPE = Type.tFloat;
public final static Type OBJECT_TYPE = MyType.tUObject; public final static Type DOUBLE_TYPE = Type.tDouble;
public final static Type BOOLEAN_TYPE = Type.tBoolean; public final static Type OBJECT_TYPE = Type.tUObject;
public final static Type BYTE_TYPE = Type.tByte; public final static Type BOOLEAN_TYPE = Type.tBoolean;
public final static Type CHAR_TYPE = Type.tChar; public final static Type BYTEBOOL_TYPE = Type.tBoolByte;
public final static Type SHORT_TYPE = Type.tShort; public final static Type BYTE_TYPE = Type.tByte;
public final static Type VOID_TYPE = Type.tVoid; public final static Type CHAR_TYPE = Type.tChar;
public final static Type SHORT_TYPE = Type.tShort;
public final static Type VOID_TYPE = Type.tVoid;
public final static Type types[][] = { public final static Type types[][] = {
{ ALL_INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE, OBJECT_TYPE }, {BOOL_INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE, OBJECT_TYPE },
{ INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE, OBJECT_TYPE, { INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE, OBJECT_TYPE,
BYTE_TYPE, CHAR_TYPE, SHORT_TYPE } BYTEBOOL_TYPE, CHAR_TYPE, SHORT_TYPE },
{ BYTE_TYPE, CHAR_TYPE, SHORT_TYPE },
{ ALL_INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE, OBJECT_TYPE }
}; };
@ -90,7 +94,7 @@ public abstract class Opcodes implements RuntimeConstants {
int[] cases, int[] dests) int[] cases, int[] dests)
{ {
return new FlowBlock(ca, addr, length, return new FlowBlock(ca, addr, length,
new SwitchBlock(new NopOperator(MyType.tInt), new SwitchBlock(new NopOperator(Type.tInt),
cases, dests)); cases, dests));
} }
@ -132,8 +136,11 @@ public abstract class Opcodes implements RuntimeConstants {
case opc_aconst_null: case opc_aconst_null:
return createNormal return createNormal
(ca, addr, 1, new ConstOperator(OBJECT_TYPE, "null")); (ca, addr, 1, new ConstOperator(OBJECT_TYPE, "null"));
case opc_iconst_m1: case opc_iconst_0: case opc_iconst_1:
case opc_iconst_0: case opc_iconst_1: case opc_iconst_2: return createNormal
(ca, addr, 1, new ConstOperator
(Type.tBoolInt, Integer.toString(opcode - opc_iconst_0)));
case opc_iconst_m1: case opc_iconst_2:
case opc_iconst_3: case opc_iconst_4: case opc_iconst_5: case opc_iconst_3: case opc_iconst_4: case opc_iconst_5:
return createNormal return createNormal
(ca, addr, 1, new ConstOperator (ca, addr, 1, new ConstOperator
@ -160,7 +167,8 @@ public abstract class Opcodes implements RuntimeConstants {
case opc_sipush: case opc_sipush:
return createNormal return createNormal
(ca, addr, 3, new ConstOperator (ca, addr, 3, new ConstOperator
(ALL_INT_TYPE, Integer.toString(stream.readShort()))); (Type.tRange(Type.tInt, Type.tShort),
Integer.toString(stream.readShort())));
case opc_ldc: { case opc_ldc: {
int index = stream.readUnsignedByte(); int index = stream.readUnsignedByte();
return createNormal return createNormal
@ -242,25 +250,25 @@ public abstract class Opcodes implements RuntimeConstants {
case opc_irem: case opc_lrem: case opc_frem: case opc_drem: case opc_irem: case opc_lrem: case opc_frem: case opc_drem:
return createNormal return createNormal
(ca, addr, 1, new BinaryOperator (ca, addr, 1, new BinaryOperator
(types[0][(opcode - opc_iadd)%4], (types[3][(opcode - opc_iadd)%4],
(opcode - opc_iadd)/4+Operator.ADD_OP)); (opcode - opc_iadd)/4+Operator.ADD_OP));
case opc_ineg: case opc_lneg: case opc_fneg: case opc_dneg: case opc_ineg: case opc_lneg: case opc_fneg: case opc_dneg:
return createNormal return createNormal
(ca, addr, 1, new UnaryOperator (ca, addr, 1, new UnaryOperator
(types[0][opcode - opc_ineg], Operator.NEG_OP)); (types[3][opcode - opc_ineg], Operator.NEG_OP));
case opc_ishl: case opc_lshl: case opc_ishl: case opc_lshl:
case opc_ishr: case opc_lshr: case opc_ishr: case opc_lshr:
case opc_iushr: case opc_lushr: case opc_iushr: case opc_lushr:
return createNormal return createNormal
(ca, addr, 1, new ShiftOperator (ca, addr, 1, new ShiftOperator
(types[0][(opcode - opc_ishl)%2], (types[3][(opcode - opc_ishl)%2],
(opcode - opc_ishl)/2 + Operator.SHIFT_OP)); (opcode - opc_ishl)/2 + Operator.SHIFT_OP));
case opc_iand: case opc_land: case opc_iand: case opc_land:
case opc_ior : case opc_lor : case opc_ior : case opc_lor :
case opc_ixor: case opc_lxor: case opc_ixor: case opc_lxor:
return createNormal return createNormal
(ca, addr, 1, new BinaryOperator (ca, addr, 1, new BinaryOperator
(types[0][(opcode - opc_iand)%2], (types[3][(opcode - opc_iand)%2],
(opcode - opc_iand)/2 + Operator.AND_OP)); (opcode - opc_iand)/2 + Operator.AND_OP));
case opc_iinc: { case opc_iinc: {
int local = stream.readUnsignedByte(); int local = stream.readUnsignedByte();
@ -271,6 +279,7 @@ public abstract class Opcodes implements RuntimeConstants {
operation = Operator.NEG_OP; operation = Operator.NEG_OP;
} }
LocalInfo li = ca.getLocalInfo(addr, local); LocalInfo li = ca.getLocalInfo(addr, local);
li.setType(ALL_INT_TYPE);
return createNormal return createNormal
(ca, addr, 3, new IIncOperator (ca, addr, 3, new IIncOperator
(li, Integer.toString(value), (li, Integer.toString(value),
@ -285,36 +294,48 @@ public abstract class Opcodes implements RuntimeConstants {
if (to >= from) if (to >= from)
to++; to++;
return createNormal return createNormal
(ca, addr, 1, new ConvertOperator(types[0][from], (ca, addr, 1, new ConvertOperator(types[3][from],
types[0][to])); types[3][to]));
} }
case opc_i2b: case opc_i2c: case opc_i2s: case opc_i2b: case opc_i2c: case opc_i2s:
return createNormal return createNormal
(ca, addr, 1, new ConvertOperator (ca, addr, 1, new ConvertOperator
(ALL_INT_TYPE, types[1][(opcode-opc_i2b)+5])); (ALL_INT_TYPE, types[2][opcode-opc_i2b]));
case opc_lcmp: case opc_lcmp:
case opc_fcmpl: case opc_fcmpg: case opc_fcmpl: case opc_fcmpg:
case opc_dcmpl: case opc_dcmpg: case opc_dcmpl: case opc_dcmpg:
return createNormal return createNormal
(ca, addr, 1, new CompareToIntOperator (ca, addr, 1, new CompareToIntOperator
(types[0][(opcode-opc_lcmp+3)/2], (opcode-opc_lcmp+3)%2)); (types[3][(opcode-opc_lcmp+3)/2], (opcode-opc_lcmp+3)%2));
case opc_ifeq: case opc_ifne: case opc_ifeq: case opc_ifne:
return createIfGoto
(ca, addr, 3, addr+stream.readShort(),
new CompareUnaryOperator
(BOOL_INT_TYPE, opcode - opc_ifeq+Operator.COMPARE_OP));
case opc_iflt: case opc_ifge: case opc_ifgt: case opc_ifle: case opc_iflt: case opc_ifge: case opc_ifgt: case opc_ifle:
return createIfGoto return createIfGoto
(ca, addr, 3, addr+stream.readShort(), (ca, addr, 3, addr+stream.readShort(),
new CompareUnaryOperator new CompareUnaryOperator
(ALL_INT_TYPE, opcode - opc_ifeq+Operator.COMPARE_OP)); (ALL_INT_TYPE, opcode - opc_ifeq+Operator.COMPARE_OP));
case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmplt: case opc_if_icmpeq: case opc_if_icmpne:
case opc_if_icmpge: case opc_if_icmpgt: case opc_if_icmple: return createIfGoto
(ca, addr, 3, addr+stream.readShort(),
new CompareBinaryOperator
(Type.tBoolInt,
opcode - opc_if_icmpeq+Operator.COMPARE_OP));
case opc_if_icmplt: case opc_if_icmpge:
case opc_if_icmpgt: case opc_if_icmple:
return createIfGoto return createIfGoto
(ca, addr, 3, addr+stream.readShort(), (ca, addr, 3, addr+stream.readShort(),
new CompareBinaryOperator new CompareBinaryOperator
(ALL_INT_TYPE, opcode - opc_if_icmpeq+Operator.COMPARE_OP)); (ALL_INT_TYPE,
opcode - opc_if_icmpeq+Operator.COMPARE_OP));
case opc_if_acmpeq: case opc_if_acmpne: case opc_if_acmpeq: case opc_if_acmpne:
return createIfGoto return createIfGoto
(ca, addr, 3, addr+stream.readShort(), (ca, addr, 3, addr+stream.readShort(),
new CompareBinaryOperator new CompareBinaryOperator
(OBJECT_TYPE, opcode - opc_if_acmpeq+Operator.COMPARE_OP)); (OBJECT_TYPE,
opcode - opc_if_acmpeq+Operator.COMPARE_OP));
case opc_goto: case opc_goto:
return createGoto return createGoto
(ca, addr, 3, addr+stream.readShort()); (ca, addr, 3, addr+stream.readShort());
@ -360,9 +381,9 @@ public abstract class Opcodes implements RuntimeConstants {
} }
case opc_ireturn: case opc_lreturn: case opc_ireturn: case opc_lreturn:
case opc_freturn: case opc_dreturn: case opc_areturn: { case opc_freturn: case opc_dreturn: case opc_areturn: {
Type retType = MyType.tSubType(MyType.intersection Type retType =
(ca.getMethod().mdef.getType().getReturnType(), Type.tSubType(Type.tType(ca.getMethod().mdef.getType()
types[0][opcode-opc_ireturn])); .getReturnType()));
return createBlock return createBlock
(ca, addr, 1, new ReturnBlock(new NopOperator(retType))); (ca, addr, 1, new ReturnBlock(new NopOperator(retType)));
} }
@ -405,7 +426,7 @@ public abstract class Opcodes implements RuntimeConstants {
case opc_new: { case opc_new: {
ClassDeclaration cldec = (ClassDeclaration) ClassDeclaration cldec = (ClassDeclaration)
ca.env.getConstant(stream.readUnsignedShort()); ca.env.getConstant(stream.readUnsignedShort());
Type type = MyType.tClassOrArray(cldec.getName()); Type type = Type.tClassOrArray(cldec.getName());
return createNormal return createNormal
(ca, addr, 3, new NewOperator(type, ca.env.getTypeString(type))); (ca, addr, 3, new NewOperator(type, ca.env.getTypeString(type)));
} }
@ -425,17 +446,17 @@ public abstract class Opcodes implements RuntimeConstants {
} }
return createNormal return createNormal
(ca, addr, 2, (ca, addr, 2,
new NewArrayOperator(MyType.tArray(type), new NewArrayOperator(Type.tArray(type),
type.toString(), 1)); type.toString(), 1));
} }
case opc_anewarray: { case opc_anewarray: {
ClassDeclaration cldec = (ClassDeclaration) ca.env.getConstant ClassDeclaration cldec = (ClassDeclaration) ca.env.getConstant
(stream.readUnsignedShort()); (stream.readUnsignedShort());
Identifier ident = cldec.getName(); Identifier ident = cldec.getName();
Type type = MyType.tClassOrArray(cldec.getName()); Type type = Type.tClassOrArray(cldec.getName());
return createNormal return createNormal
(ca, addr, 3, new NewArrayOperator (ca, addr, 3, new NewArrayOperator
(MyType.tArray(type), ca.env.getTypeString(type),1)); (Type.tArray(type), ca.env.getTypeString(type),1));
} }
case opc_arraylength: case opc_arraylength:
return createNormal return createNormal
@ -443,11 +464,11 @@ public abstract class Opcodes implements RuntimeConstants {
case opc_athrow: case opc_athrow:
return createBlock return createBlock
(ca, addr, 1, (ca, addr, 1,
new ThrowBlock(new NopOperator(MyType.tUObject))); new ThrowBlock(new NopOperator(Type.tUObject)));
case opc_checkcast: { case opc_checkcast: {
ClassDeclaration cldec = (ClassDeclaration) ca.env.getConstant ClassDeclaration cldec = (ClassDeclaration) ca.env.getConstant
(stream.readUnsignedShort()); (stream.readUnsignedShort());
Type type = MyType.tClassOrArray(cldec.getName()); Type type = Type.tClassOrArray(cldec.getName());
return createNormal return createNormal
(ca, addr, 3, new CheckCastOperator (ca, addr, 3, new CheckCastOperator
(type, ca.env.getTypeString(type))); (type, ca.env.getTypeString(type)));
@ -455,17 +476,17 @@ public abstract class Opcodes implements RuntimeConstants {
case opc_instanceof: { case opc_instanceof: {
ClassDeclaration cldec = (ClassDeclaration) ca.env.getConstant ClassDeclaration cldec = (ClassDeclaration) ca.env.getConstant
(stream.readUnsignedShort()); (stream.readUnsignedShort());
Type type = MyType.tClassOrArray(cldec.getName()); Type type = Type.tClassOrArray(cldec.getName());
return createNormal return createNormal
(ca, addr, 3, (ca, addr, 3,
new InstanceOfOperator(type, ca.env.getTypeString(type))); new InstanceOfOperator(type, ca.env.getTypeString(type)));
} }
case opc_monitorenter: case opc_monitorenter:
return createNormal(ca, addr, 1, return createNormal(ca, addr, 1,
new MonitorEnterOperator()); new MonitorEnterOperator());
case opc_monitorexit: case opc_monitorexit:
return createNormal(ca, addr, 1, return createNormal(ca, addr, 1,
new MonitorExitOperator()); new MonitorExitOperator());
case opc_wide: { case opc_wide: {
switch (opcode=stream.readUnsignedByte()) { switch (opcode=stream.readUnsignedByte()) {
case opc_iload: case opc_lload: case opc_iload: case opc_lload:
@ -492,6 +513,7 @@ public abstract class Opcodes implements RuntimeConstants {
operation = Operator.NEG_OP; operation = Operator.NEG_OP;
} }
LocalInfo li = ca.getLocalInfo(addr, local); LocalInfo li = ca.getLocalInfo(addr, local);
li.setType(ALL_INT_TYPE);
return createNormal return createNormal
(ca, addr, 6, new IIncOperator (ca, addr, 6, new IIncOperator
(li, Integer.toString(value), (li, Integer.toString(value),
@ -508,11 +530,11 @@ public abstract class Opcodes implements RuntimeConstants {
case opc_multianewarray: { case opc_multianewarray: {
ClassDeclaration cldec = (ClassDeclaration) ca.env.getConstant ClassDeclaration cldec = (ClassDeclaration) ca.env.getConstant
(stream.readUnsignedShort()); (stream.readUnsignedShort());
Type type = MyType.tClassOrArray(cldec.getName()); Type type = Type.tClassOrArray(cldec.getName());
int dimension = stream.readUnsignedByte(); int dimension = stream.readUnsignedByte();
Type baseType = type; Type baseType = type;
for (int i=0; i<dimension; i++) for (int i=0; i<dimension; i++)
baseType = baseType.getElementType(); baseType = ((ArrayType)baseType).getElementType();
return createNormal return createNormal
(ca, addr, 4, (ca, addr, 4,
new NewArrayOperator new NewArrayOperator

@ -62,7 +62,8 @@ public class ClassAnalyzer implements Analyzer {
if (cdef.getSource() != null) if (cdef.getSource() != null)
writer.println("/* Original source: "+cdef.getSource()+" */"); writer.println("/* Original source: "+cdef.getSource()+" */");
writer.println("package " + cdef.getName().getQualifier() + ";"); if (cdef.getName().isQualified())
writer.println("package " + cdef.getName().getQualifier() + ";");
/* XXX imports */ /* XXX imports */
writer.println(""); writer.println("");

@ -94,9 +94,9 @@ public class CodeAnalyzer implements Analyzer, Constants {
tryBlock = ((RawTryCatchBlock)tryBlock).getTryBlock(); tryBlock = ((RawTryCatchBlock)tryBlock).getTryBlock();
} }
Type type = Type type =
(handlers[i].exceptionClass != null)? (handlers[i].exceptionClass != null)?
handlers[i].exceptionClass.getType() : null; Type.tClass(handlers[i].exceptionClass.getName().toString()) : null;
new RawTryCatchBlock(type, tryBlock, new RawTryCatchBlock(type, tryBlock,
new Jump(instr[handlers[i].endPC]), new Jump(instr[handlers[i].endPC]),

@ -48,7 +48,8 @@ public class FieldAnalyzer implements Analyzer {
if (modif.length() > 0) if (modif.length() > 0)
writer.print(modif+" "); writer.print(modif+" ");
writer.print(env.getTypeString(fdef.getType(), fdef.getName())); writer.print(env.getTypeString(Type.tType(fdef.getType()),
fdef.getName()));
byte[] attrib = byte[] attrib =
((BinaryField) fdef).getAttribute(Constants.idConstantValue); ((BinaryField) fdef).getAttribute(Constants.idConstantValue);
if (attrib != null) { if (attrib != null) {

@ -29,7 +29,7 @@ public class JodeEnvironment extends LoadEnvironment {
JodeEnvironment() { JodeEnvironment() {
super(null); super(null);
MyType.setEnvironment(this); Type.setEnvironment(this);
path = new ClassPath(System.getProperty("java.class.path")); path = new ClassPath(System.getProperty("java.class.path"));
} }
@ -65,7 +65,7 @@ public class JodeEnvironment extends LoadEnvironment {
} }
public String getTypeString(Type type, Identifier name) { public String getTypeString(Type type, Identifier name) {
return type.typeString(name.toString(), false, false); return type.toString() + " " + name.toString();
} }
public ClassDefinition getClassDefinition() { public ClassDefinition getClassDefinition() {

@ -18,7 +18,9 @@
*/ */
package jode; package jode;
import sun.tools.java.*; import sun.tools.java.Identifier;
import java.util.Enumeration;
import java.util.Vector;
/** /**
* The LocalInfo represents a local variable of a method. * The LocalInfo represents a local variable of a method.
@ -37,6 +39,7 @@ public class LocalInfo {
private Identifier name; private Identifier name;
private Type type; private Type type;
private LocalInfo shadow; private LocalInfo shadow;
private Vector operators = new Vector();
/* The current implementation may use very much stack. This /* The current implementation may use very much stack. This
* should be changed someday. * should be changed someday.
@ -50,10 +53,14 @@ public class LocalInfo {
*/ */
public LocalInfo(int slot) { public LocalInfo(int slot) {
name = null; name = null;
type = MyType.tUnknown; type = Type.tUnknown;
this.slot = slot; this.slot = slot;
} }
public void setOperator(LocalVarOperator operator) {
getLocalInfo().operators.addElement(operator);
}
/** /**
* Combines the LocalInfo with another. This will make this * Combines the LocalInfo with another. This will make this
* a shadow object to the other local info. That is all member * a shadow object to the other local info. That is all member
@ -70,10 +77,16 @@ public class LocalInfo {
if (this != li) { if (this != li) {
shadow = li; shadow = li;
li.setType(type); li.setType(type);
java.util.Enumeration enum = operators.elements();
while (enum.hasMoreElements()) {
shadow.operators.addElement(enum.nextElement());
}
/* Clear unused fields, to allow garbage collection. /* Clear unused fields, to allow garbage collection.
*/ */
type = null; type = null;
name = null; name = null;
operators = null;
} }
} }
} }
@ -139,15 +152,14 @@ public class LocalInfo {
* @return The new type of the local. * @return The new type of the local.
*/ */
public Type setType(Type newType) { public Type setType(Type newType) {
if (shadow != null) { LocalInfo li = getLocalInfo();
while (shadow.shadow != null) { newType = li.type.intersection(newType);
shadow = shadow.shadow; if (!li.type.equals(newType)) {
} li.type = newType;
return shadow.setType(newType); java.util.Enumeration enum = li.operators.elements();
while (enum.hasMoreElements())
((LocalVarOperator)enum.nextElement()).updateType();
} }
this.type = MyType.intersection(this.type, newType);
if (this.type == MyType.tError)
System.err.println("Type error in "+getName());
return this.type; return this.type;
} }

@ -20,7 +20,7 @@
package jode; package jode;
import sun.tools.java.*; import sun.tools.java.*;
public class LocalVariableRangeList implements LocalVariable { public class LocalVariableRangeList {
class MyLocalInfo extends LocalInfo { class MyLocalInfo extends LocalInfo {
int start; int start;
@ -80,8 +80,4 @@ public class LocalVariableRangeList implements LocalVariable {
public LocalInfo getInfo(int addr) { public LocalInfo getInfo(int addr) {
return find(addr); return find(addr);
} }
public void combine(int addr1, int addr2) {
throw new AssertError("combine called on RangeList");
}
} }

@ -18,7 +18,7 @@
*/ */
package jode; package jode;
import sun.tools.java.*; import sun.tools.java.Identifier;
import java.io.*; import java.io.*;
public class LocalVariableTable { public class LocalVariableTable {
@ -57,7 +57,7 @@ public class LocalVariableTable {
Identifier.lookup((String) Identifier.lookup((String)
env.getConstantPool(). env.getConstantPool().
getValue(name_i)), getValue(name_i)),
env.getConstantPool().getType(desc_i)); Type.tType(env.getConstantPool().getType(desc_i)));
if (Decompiler.showLVT) if (Decompiler.showLVT)
System.err.println(""+env.getConstantPool().getValue(name_i) System.err.println(""+env.getConstantPool().getValue(name_i)
+": "+env.getConstantPool().getType(desc_i) +": "+env.getConstantPool().getType(desc_i)

@ -26,7 +26,6 @@ public class MethodAnalyzer implements Analyzer, Constants {
FieldDefinition mdef; FieldDefinition mdef;
JodeEnvironment env; JodeEnvironment env;
CodeAnalyzer code = null; CodeAnalyzer code = null;
LocalVariableAnalyzer lva;
public MethodAnalyzer(FieldDefinition fd, JodeEnvironment e) public MethodAnalyzer(FieldDefinition fd, JodeEnvironment e)
{ {
@ -38,8 +37,6 @@ public class MethodAnalyzer implements Analyzer, Constants {
new BinaryCode(bytecode, new BinaryCode(bytecode,
env.getConstantPool(), env.getConstantPool(),
env); env);
// lva = new LocalVariableAnalyzer(env, mdef, bc.getMaxLocals());
// lva.read(bc);
code = new CodeAnalyzer(this, bc, env); code = new CodeAnalyzer(this, bc, env);
} }
} }
@ -58,13 +55,15 @@ public class MethodAnalyzer implements Analyzer, Constants {
int offset = 0; int offset = 0;
if (!mdef.isStatic()) { if (!mdef.isStatic()) {
LocalInfo clazz = code.getParamInfo(0); LocalInfo clazz = code.getParamInfo(0);
clazz.setType(mdef.getClassDefinition().getType()); clazz.setType(Type.tClass(mdef.getClassDefinition()
.getName().toString()));
clazz.setName(Constants.idThis); clazz.setName(Constants.idThis);
offset++; offset++;
} }
Type[] paramTypes = mdef.getType().getArgumentTypes(); sun.tools.java.Type[] paramTypes = mdef.getType().getArgumentTypes();
for (int i=0; i< paramTypes.length; i++) for (int i=0; i< paramTypes.length; i++)
code.getParamInfo(offset+i).setType(paramTypes[i]); code.getParamInfo(offset+i).setType
(Type.tType(paramTypes[i].getTypeSignature()));
// We do the code.analyze() in dumpSource, to get // We do the code.analyze() in dumpSource, to get
// immediate output. // immediate output.
@ -91,20 +90,21 @@ public class MethodAnalyzer implements Analyzer, Constants {
if (mdef.isConstructor()) if (mdef.isConstructor())
writer.print(mdef.getClassDeclaration().getName().toString()); writer.print(mdef.getClassDeclaration().getName().toString());
else else
writer.print(env.getTypeString(mdef.getType().getReturnType())+ writer.print(env.getTypeString
" "+ mdef.getName().toString()); (Type.tType(mdef.getType().getReturnType()))
+ " " + mdef.getName().toString());
writer.print("("); writer.print("(");
Type[] paramTypes = mdef.getType().getArgumentTypes(); sun.tools.java.Type[] paramTypes =
mdef.getType().getArgumentTypes();
int offset = mdef.isStatic()?0:1; int offset = mdef.isStatic()?0:1;
for (int i=0; i<paramTypes.length; i++) { for (int i=0; i<paramTypes.length; i++) {
if (i>0) if (i>0)
writer.print(", "); writer.print(", ");
writer.print writer.print
((code == null)? ((code == null)?
env.getTypeString(paramTypes[i]): env.getTypeString(Type.tType(paramTypes[i])):
env.getTypeString env.getTypeString(Type.tType(paramTypes[i]),
(paramTypes[i], code.getParamInfo(i+offset).getName()));
code.getParamInfo(i+offset).getName()));
} }
writer.print(")"); writer.print(")");
} }

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.*;
public class ArrayLengthOperator extends Operator { public class ArrayLengthOperator extends Operator {
@ -26,7 +25,7 @@ public class ArrayLengthOperator extends Operator {
public ArrayLengthOperator() { public ArrayLengthOperator() {
super(Type.tInt, 0); super(Type.tInt, 0);
arrayType = Type.tArray(MyType.tUnknown); arrayType = Type.tArray(Type.tUnknown);
} }
public int getPriority() { public int getPriority() {
@ -46,7 +45,7 @@ public class ArrayLengthOperator extends Operator {
} }
public void setOperandType(Type[] types) { public void setOperandType(Type[] types) {
arrayType = MyType.intersection(arrayType,types[0]); arrayType = arrayType.intersection(types[0]);
} }
public String toString(String[] operands) { public String toString(String[] operands) {

@ -18,8 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
import sun.tools.java.ArrayType;
public class ArrayLoadOperator extends SimpleOperator { public class ArrayLoadOperator extends SimpleOperator {
String value; String value;
@ -27,7 +25,7 @@ public class ArrayLoadOperator extends SimpleOperator {
public ArrayLoadOperator(Type type) { public ArrayLoadOperator(Type type) {
super(type, 0, 2); super(type, 0, 2);
operandTypes[0] = Type.tArray(type); operandTypes[0] = Type.tArray(type);
operandTypes[1] = MyType.tUIndex; operandTypes[1] = Type.tInt;
} }
public int getPriority() { public int getPriority() {
@ -42,7 +40,7 @@ public class ArrayLoadOperator extends SimpleOperator {
* Sets the return type of this operator. * Sets the return type of this operator.
*/ */
public void setType(Type type) { public void setType(Type type) {
if (type != this.type) { if (!type.equals(this.type)) {
super.setType(type); super.setType(type);
operandTypes[0] = Type.tArray(type); operandTypes[0] = Type.tArray(type);
} }
@ -50,12 +48,11 @@ public class ArrayLoadOperator extends SimpleOperator {
public void setOperandType(Type[] t) { public void setOperandType(Type[] t) {
super.setOperandType(t); super.setOperandType(t);
try { if (operandTypes[0] instanceof ArrayType)
type = operandTypes[0].getElementType(); type = type.intersection
} catch (sun.tools.java.CompilerError err) { (((ArrayType)operandTypes[0]).getElementType());
System.err.println("No Array type: "+operandTypes[0]); else
type = Type.tError; throw new AssertError("No Array type: "+operandTypes[0]);
}
} }
public String toString(String[] operands) { public String toString(String[] operands) {

@ -18,15 +18,13 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
import sun.tools.java.ArrayType;
public class ArrayStoreOperator extends StoreInstruction { public class ArrayStoreOperator extends StoreInstruction {
Type indexType; Type indexType;
public ArrayStoreOperator(Type type, int operator) { public ArrayStoreOperator(Type type, int operator) {
super(type, operator); super(type, operator);
indexType = MyType.tUIndex; indexType = Type.tInt;
} }
public ArrayStoreOperator(Type type) { public ArrayStoreOperator(Type type) {
@ -66,15 +64,12 @@ public class ArrayStoreOperator extends StoreInstruction {
} }
public void setLValueOperandType(Type[] t) { public void setLValueOperandType(Type[] t) {
indexType = MyType.intersection(indexType, t[1]); indexType = indexType.intersection(t[1]);
Type arrayType = Type arrayType = t[0].intersection(Type.tArray(lvalueType));
MyType.intersection(t[0], Type.tArray(lvalueType)); if (arrayType instanceof ArrayType)
try { lvalueType = ((ArrayType)arrayType).getElementType();
lvalueType = arrayType.getElementType(); else
} catch (sun.tools.java.CompilerError err) { throw new AssertError("No Array type: "+arrayType);
System.err.println("No Array type: "+arrayType);
lvalueType = Type.tError;
}
} }
public String getLValueString(String[] operands) { public String getLValueString(String[] operands) {

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class AssignOperator extends Operator { public class AssignOperator extends Operator {
StoreInstruction store; StoreInstruction store;

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class BinaryOperator extends Operator { public class BinaryOperator extends Operator {
protected Type operandType; protected Type operandType;
@ -66,9 +65,9 @@ public class BinaryOperator extends Operator {
} }
public void setOperandType(Type[] inputTypes) { public void setOperandType(Type[] inputTypes) {
operandType = MyType.intersection operandType = operandType
(operandType, MyType.intersection(inputTypes[0], .intersection(inputTypes[0])
inputTypes[1])); .intersection(inputTypes[1]);
type = operandType; type = operandType;
} }
@ -76,7 +75,7 @@ public class BinaryOperator extends Operator {
* Sets the return type of this operator. * Sets the return type of this operator.
*/ */
public void setType(Type newType) { public void setType(Type newType) {
type = operandType = MyType.intersection(operandType, newType); type = operandType = operandType.intersection(newType);
} }
public boolean equals(Object o) { public boolean equals(Object o) {

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class CheckCastOperator extends SimpleOperator { public class CheckCastOperator extends SimpleOperator {
String typeString; String typeString;
@ -37,7 +36,7 @@ public class CheckCastOperator extends SimpleOperator {
* *
* The forgiving solution: * The forgiving solution:
*/ */
operandTypes[0] = MyType.tUnknown; operandTypes[0] = Type.tUnknown;
} }
public int getPriority() { public int getPriority() {

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class CompareBinaryOperator extends SimpleOperator { public class CompareBinaryOperator extends SimpleOperator {
public CompareBinaryOperator(Type type, int op) { public CompareBinaryOperator(Type type, int op) {
@ -47,9 +46,8 @@ public class CompareBinaryOperator extends SimpleOperator {
public void setOperandType(Type[] inputTypes) { public void setOperandType(Type[] inputTypes) {
super.setOperandType(inputTypes); super.setOperandType(inputTypes);
Type operandType = Type operandType =
MyType.tSubType(MyType.intersection Type.tSubType(Type.tSuperType(operandTypes[0])
(MyType.tSuperType(operandTypes[0]), .intersection(Type.tSuperType(operandTypes[1])));
MyType.tSuperType(operandTypes[1])));
operandTypes[0] = operandTypes[1] = operandType; operandTypes[0] = operandTypes[1] = operandType;
} }

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class CompareToIntOperator extends SimpleOperator { public class CompareToIntOperator extends SimpleOperator {
public CompareToIntOperator(Type type, int lessGreater) { public CompareToIntOperator(Type type, int lessGreater) {
@ -36,8 +35,7 @@ public class CompareToIntOperator extends SimpleOperator {
public void setOperandType(Type[] inputTypes) { public void setOperandType(Type[] inputTypes) {
super.setOperandType(inputTypes); super.setOperandType(inputTypes);
Type operandType = Type operandType = operandTypes[0].intersection(operandTypes[1]);
MyType.intersection(operandTypes[0],operandTypes[1]);
operandTypes[0] = operandTypes[1] = operandType; operandTypes[0] = operandTypes[1] = operandType;
} }

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class CompareUnaryOperator extends SimpleOperator { public class CompareUnaryOperator extends SimpleOperator {
boolean objectType; boolean objectType;
@ -26,7 +25,7 @@ public class CompareUnaryOperator extends SimpleOperator {
public CompareUnaryOperator(Type type, int op) { public CompareUnaryOperator(Type type, int op) {
super(Type.tBoolean, op, 1); super(Type.tBoolean, op, 1);
operandTypes[0] = type; operandTypes[0] = type;
objectType = (type == MyType.tUObject); objectType = (type == Type.tUObject);
} }
public int getPriority() { public int getPriority() {

@ -18,17 +18,16 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
import sun.tools.java.Constants; import sun.tools.java.Constants;
import sun.tools.java.FieldDefinition;
public class ComplexExpression extends Expression { public class ComplexExpression extends Expression {
Operator operator; Operator operator;
Expression[] subExpressions; Expression[] subExpressions;
public ComplexExpression(Operator op, Expression[] sub) { public ComplexExpression(Operator op, Expression[] sub) {
super(MyType.tUnknown); super(Type.tUnknown);
operator = op; operator = op;
operator.parent = this;
subExpressions = sub; subExpressions = sub;
operator.setExpression(this); operator.setExpression(this);
if (subExpressions.length != op.getOperandCount()) if (subExpressions.length != op.getOperandCount())
@ -122,9 +121,21 @@ public class ComplexExpression extends Expression {
} }
} }
public void updateType() {
updateSubTypes();
if (subExpressions.length > 0) {
Type types[] = new Type[subExpressions.length];
for (int i=0; i < types.length; i++) {
types[i] = subExpressions[i].getType();
}
operator.setOperandType(types);
}
setType(operator.getType());
}
public void setType(Type newType) { public void setType(Type newType) {
newType = MyType.intersection(type, newType); newType = type.intersection(newType);
if (newType != type) { if (!newType.equals(type)) {
type = newType; type = newType;
operator.setType(type); operator.setType(type);
updateSubTypes(); updateSubTypes();
@ -143,8 +154,8 @@ public class ComplexExpression extends Expression {
} }
String result = operator.toString(expr); String result = operator.toString(expr);
if (Decompiler.isTypeDebugging) if (Decompiler.isTypeDebugging)
result = "(("+operator.getType()+")"+result+")"; result = "("+operator.getType()+") ("+result+")";
else if (operator.getType() == MyType.tError) else if (operator.getType() == Type.tError)
result = "(/*type error */" + result+")"; result = "(/*type error */" + result+")";
return result; return result;
} }
@ -170,12 +181,12 @@ public class ComplexExpression extends Expression {
new EmptyStringOperator(); new EmptyStringOperator();
Expression simplifyStringBuffer() { Expression simplifyStringBuffer() {
FieldDefinition field; sun.tools.java.FieldDefinition field;
if (operator instanceof InvokeOperator && if (operator instanceof InvokeOperator &&
(field = ((InvokeOperator)operator).getField()) (field = ((InvokeOperator)operator).getField())
.getClassDefinition().getName() == .getClassDefinition().getName()
Constants.idJavaLangStringBuffer && == Constants.idJavaLangStringBuffer
!((InvokeOperator)operator).isStatic() && && !((InvokeOperator)operator).isStatic() &&
field.getName() == Constants.idAppend && field.getName() == Constants.idAppend &&
field.getType().getArgumentTypes().length == 1) { field.getType().getArgumentTypes().length == 1) {
@ -184,7 +195,7 @@ public class ComplexExpression extends Expression {
return null; return null;
if (e.getOperator() instanceof EmptyStringOperator && if (e.getOperator() instanceof EmptyStringOperator &&
MyType.isOfType(subExpressions[1].getType(), Type.tString)) subExpressions[1].getType().isOfType(Type.tString))
return subExpressions[1]; return subExpressions[1];
Expression[] exprs = { e, Expression[] exprs = { e,
@ -192,13 +203,12 @@ public class ComplexExpression extends Expression {
return new ComplexExpression(new StringAddOperator(), exprs); return new ComplexExpression(new StringAddOperator(), exprs);
} }
if (operator instanceof ConstructorOperator && if (operator instanceof ConstructorOperator &&
MyType.isOfType(operator.getType(), MyType.tStringBuffer)) { operator.getType().isOfType(Type.tStringBuffer)) {
/* subExpressions[0] is always a "new StringBuffer" */ /* subExpressions[0] is always a "new StringBuffer" */
if (subExpressions.length == 1) if (subExpressions.length == 1)
return emptyString; return emptyString;
else if (subExpressions.length == 2 && else if (subExpressions.length == 2 &&
MyType.isOfType(subExpressions[1].getType(), subExpressions[1].getType().isOfType(Type.tString))
MyType.tString))
return (Expression) subExpressions[1].simplify(); return (Expression) subExpressions[1].simplify();
} }
return null; return null;
@ -206,7 +216,7 @@ public class ComplexExpression extends Expression {
public Instruction simplify() { public Instruction simplify() {
if (operator instanceof IfThenElseOperator && if (operator instanceof IfThenElseOperator &&
operator.getType() == Type.tBoolean) { operator.getType().isOfType(Type.tBoolean)) {
if (subExpressions[1].getOperator() instanceof ConstOperator && if (subExpressions[1].getOperator() instanceof ConstOperator &&
subExpressions[2].getOperator() instanceof ConstOperator) { subExpressions[2].getOperator() instanceof ConstOperator) {
ConstOperator c1 = ConstOperator c1 =
@ -267,18 +277,7 @@ public class ComplexExpression extends Expression {
return newOp.simplify(); return newOp.simplify();
} }
if (operator instanceof CompareUnaryOperator && if (operator instanceof CompareUnaryOperator &&
operator.getOperandType(0) != Type.tBoolean) { operator.getOperandType(0).isOfType(Type.tBoolean)) {
if (subExpressions[0].getOperator() instanceof ConstOperator) {
ConstOperator c =
(ConstOperator) subExpressions[0].getOperator();
if (c.getValue().equals("0") || c.getValue().equals("1")) {
Type[] newType = {Type.tBoolean};
operator.setOperandType(newType);
}
}
}
if (operator instanceof CompareUnaryOperator &&
operator.getOperandType(0) == Type.tBoolean) {
/* xx == false */ /* xx == false */
if (operator.getOperatorIndex() == operator.EQUALS_OP) if (operator.getOperatorIndex() == operator.EQUALS_OP)
return subExpressions[0].negate().simplify(); return subExpressions[0].negate().simplify();
@ -288,24 +287,26 @@ public class ComplexExpression extends Expression {
} }
if (operator instanceof InvokeOperator && if (operator instanceof InvokeOperator &&
((InvokeOperator)operator).getField(). ((InvokeOperator)operator).getField()
getName() == Constants.idToString && .getName() == Constants.idToString &&
!((InvokeOperator)operator).isStatic() && !((InvokeOperator)operator).isStatic() &&
((InvokeOperator)operator).getField(). ((InvokeOperator)operator).getField()
getClassDefinition().getType() == MyType.tStringBuffer && .getClassDefinition().getName()
== Constants.idJavaLangStringBuffer &&
subExpressions.length == 1) { subExpressions.length == 1) {
Instruction simple = subExpressions[0].simplifyStringBuffer(); Instruction simple = subExpressions[0].simplifyStringBuffer();
if (simple != null) if (simple != null)
return simple; return simple;
} }
if (operator instanceof InvokeOperator && if (operator instanceof InvokeOperator &&
((InvokeOperator)operator).getField(). ((InvokeOperator)operator).getField()
getName() == Constants.idValueOf && .getName() == Constants.idValueOf &&
((InvokeOperator)operator).isStatic() && ((InvokeOperator)operator).isStatic() &&
((InvokeOperator)operator).getField(). ((InvokeOperator)operator).getField()
getClassDefinition().getType() == MyType.tString && .getClassDefinition().getName()
== Constants.idJavaLangString &&
subExpressions.length == 1) { subExpressions.length == 1) {
if (subExpressions[0].getType() == MyType.tString) if (subExpressions[0].getType() == Type.tString)
return subExpressions[0].simplify(); return subExpressions[0].simplify();
else { else {
Expression[] exprs = { Expression[] exprs = {

@ -18,14 +18,13 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class ConstOperator extends NoArgOperator { public class ConstOperator extends NoArgOperator {
String value; String value;
public ConstOperator(Type type, String value) { public ConstOperator(Type type, String value) {
super(type); super(type);
if (type == MyType.tString) if (type == Type.tString)
value = quoted(value); value = quoted(value);
this.value = value; this.value = value;
} }
@ -67,7 +66,7 @@ public class ConstOperator extends NoArgOperator {
} }
public String toString(String[] operands) { public String toString(String[] operands) {
if (type == Type.tBoolean) { if (type.isOfType(Type.tBoolean)) {
if (value.equals("0")) if (value.equals("0"))
return "false"; return "false";
else if (value.equals("1")) else if (value.equals("1"))

@ -18,14 +18,13 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class ConstantArrayOperator extends SimpleOperator { public class ConstantArrayOperator extends SimpleOperator {
public ConstantArrayOperator(Type type, int size) { public ConstantArrayOperator(Type type, int size) {
super(type, 0, size); super(type, 0, size);
for (int i=0; i< size; i++) for (int i=0; i< size; i++)
operandTypes[i] = MyType.tSubType(type.getElementType()); operandTypes[i] = Type.tSubType(((ArrayType)type).getElementType());
} }
public int getPriority() { public int getPriority() {

@ -18,7 +18,7 @@
*/ */
package jode; package jode;
import sun.tools.java.*; import sun.tools.java.FieldDefinition;
public class ConstructorOperator extends Operator { public class ConstructorOperator extends Operator {
FieldDefinition field; FieldDefinition field;
@ -44,8 +44,10 @@ public class ConstructorOperator extends Operator {
public Type getOperandType(int i) { public Type getOperandType(int i) {
if (i == 0) if (i == 0)
return field.getClassDeclaration().getType(); // or subtype? XXX return Type.tSubType(Type.tClass(field.getClassDeclaration()
return MyType.tSubType(field.getType().getArgumentTypes()[i-1]); .getName().toString()));
return Type.tSubType(Type.tType(field.getType()
.getArgumentTypes()[i-1]));
} }
public void setOperandType(Type types[]) { public void setOperandType(Type types[]) {

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class ConvertOperator extends Operator { public class ConvertOperator extends Operator {
Type from; Type from;
@ -45,7 +44,7 @@ public class ConvertOperator extends Operator {
} }
public void setOperandType(Type[] inputTypes) { public void setOperandType(Type[] inputTypes) {
from = MyType.intersection(from, inputTypes[0]); from = from.intersection(inputTypes[0]);
} }
public String toString(String[] operands) public String toString(String[] operands)

@ -18,13 +18,12 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class DupOperator extends Instruction { public class DupOperator extends Instruction {
int count, depth; int count, depth;
public DupOperator(int depth, int count) { public DupOperator(int depth, int count) {
super(MyType.tUnknown); super(Type.tUnknown);
this.count = count; this.count = count;
this.depth = depth; this.depth = depth;
} }

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class EmptyStringOperator extends NoArgOperator { public class EmptyStringOperator extends NoArgOperator {

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public abstract class Expression extends Instruction { public abstract class Expression extends Instruction {

@ -27,7 +27,7 @@ public class GetFieldOperator extends Operator {
public GetFieldOperator(CodeAnalyzer codeAnalyzer, boolean staticFlag, public GetFieldOperator(CodeAnalyzer codeAnalyzer, boolean staticFlag,
FieldDefinition field) { FieldDefinition field) {
super(field.getType(), 0); super(Type.tType(field.getType()), 0);
this.codeAnalyzer = codeAnalyzer; this.codeAnalyzer = codeAnalyzer;
this.staticFlag = staticFlag; this.staticFlag = staticFlag;
this.field = field; this.field = field;
@ -54,7 +54,8 @@ public class GetFieldOperator extends Operator {
/* shouldn't be called */ /* shouldn't be called */
throw new RuntimeException("Field is static"); throw new RuntimeException("Field is static");
} }
return MyType.tSubType(field.getClassDeclaration().getType()); return Type.tSubType(Type.tClass(field.getClassDeclaration()
.getName().toString()));
} }
public void setOperandType(Type types[]) { public void setOperandType(Type types[]) {
@ -66,7 +67,9 @@ public class GetFieldOperator extends Operator {
if (field.getClassDefinition() == codeAnalyzer.getClassDefinition()) if (field.getClassDefinition() == codeAnalyzer.getClassDefinition())
return field.getName().toString(); return field.getName().toString();
object = object =
codeAnalyzer.getTypeString(field.getClassDeclaration().getType()); codeAnalyzer.getTypeString
(Type.tClass(field.getClassDeclaration()
.getName().toString()));
} else { } else {
if (operands[0].equals("this")) if (operands[0].equals("this"))
return field.getName().toString(); return field.getName().toString();

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class IIncOperator extends NoArgOperator public class IIncOperator extends NoArgOperator
implements LocalVarOperator { implements LocalVarOperator {
@ -26,9 +25,10 @@ implements LocalVarOperator {
LocalInfo local; LocalInfo local;
public IIncOperator(LocalInfo local, String value, int operator) { public IIncOperator(LocalInfo local, String value, int operator) {
super(MyType.tVoid, operator); super(Type.tVoid, operator);
this.local = local; this.local = local;
this.value = value; this.value = value;
local.setOperator(this);
} }
public String getValue() { public String getValue() {
@ -43,19 +43,15 @@ implements LocalVarOperator {
return true; return true;
} }
// public void setLocalInfo(LocalInfo local) { public void updateType() {
// local.setType(MyType.tUIndex); if (parent != null)
// this.local = local; parent.updateType();
// } }
public LocalInfo getLocalInfo() { public LocalInfo getLocalInfo() {
return local; return local;
} }
// public int getSlot() {
// return slot;
// }
public int getPriority() { public int getPriority() {
return 100; return 100;
} }

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class IfThenElseOperator extends SimpleOperator { public class IfThenElseOperator extends SimpleOperator {
public IfThenElseOperator(Type type) { public IfThenElseOperator(Type type) {
@ -50,7 +49,7 @@ public class IfThenElseOperator extends SimpleOperator {
public void setOperandType(Type[] inputTypes) { public void setOperandType(Type[] inputTypes) {
super.setOperandType(inputTypes); super.setOperandType(inputTypes);
Type operandType = Type operandType =
MyType.intersection(operandTypes[1],operandTypes[2]); type.intersection(operandTypes[1]).intersection(operandTypes[2]);
type = operandTypes[1] = operandTypes[2] = operandType; type = operandTypes[1] = operandTypes[2] = operandType;
} }
@ -60,8 +59,8 @@ public class IfThenElseOperator extends SimpleOperator {
*/ */
public void setType(Type newType) { public void setType(Type newType) {
Type operandType = Type operandType =
MyType.intersection(operandTypes[1], newType); type.intersection(operandTypes[1]).intersection(newType);
if (type != operandType) { if (!type.equals(operandType)) {
type = operandTypes[1] = operandTypes[2] = operandType; type = operandTypes[1] = operandTypes[2] = operandType;
} }
} }

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class InstanceOfOperator extends SimpleOperator { public class InstanceOfOperator extends SimpleOperator {
String typeString; String typeString;
@ -32,11 +31,11 @@ public class InstanceOfOperator extends SimpleOperator {
* If operand is of class type, it is probably a * If operand is of class type, it is probably a
* super type, but who knows? * super type, but who knows?
* *
* this.operandTypes[0] = MyType.tSuperType(type); * this.operandTypes[0] = Type.tSuperType(type);
* *
* The forgiving solution: * The forgiving solution:
*/ */
this.operandTypes[0] = MyType.tUnknown; this.operandTypes[0] = Type.tUnknown;
this.typeString = typeString; this.typeString = typeString;
} }
public int getOperandCount() { public int getOperandCount() {

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public abstract class Instruction { public abstract class Instruction {
protected Type type; protected Type type;

@ -29,7 +29,8 @@ public class InvokeOperator extends Operator {
public InvokeOperator(CodeAnalyzer codeAnalyzer, public InvokeOperator(CodeAnalyzer codeAnalyzer,
boolean staticFlag, boolean specialFlag, boolean staticFlag, boolean specialFlag,
FieldDefinition field) { FieldDefinition field) {
super(field.getType().getReturnType(), 0); super(Type.tType(field.getType().getReturnType().getTypeSignature()),
0);
this.codeAnalyzer = codeAnalyzer; this.codeAnalyzer = codeAnalyzer;
this.staticFlag = staticFlag; this.staticFlag = staticFlag;
this.specialFlag = specialFlag; this.specialFlag = specialFlag;
@ -45,7 +46,7 @@ public class InvokeOperator extends Operator {
} }
public Type getClassType() { public Type getClassType() {
return field.getClassDeclaration().getType(); return Type.tClass(field.getClassDeclaration().getName().toString());
} }
public int getPriority() { public int getPriority() {
@ -65,10 +66,12 @@ public class InvokeOperator extends Operator {
public Type getOperandType(int i) { public Type getOperandType(int i) {
if (!staticFlag) { if (!staticFlag) {
if (i == 0) if (i == 0)
return MyType.tSubType(field.getClassDeclaration().getType()); return Type.tSubType(getClassType());
i--; i--;
} }
return MyType.tSubType(field.getType().getArgumentTypes()[i]); return Type.tSubType(Type.tType(field.getType().
getArgumentTypes()[i].
getTypeSignature()));
} }
public void setOperandType(Type types[]) { public void setOperandType(Type types[]) {
@ -86,27 +89,26 @@ public class InvokeOperator extends Operator {
object = ""; object = "";
else else
object = codeAnalyzer. object = codeAnalyzer.
getTypeString(field.getClassDeclaration().getType()); getTypeString(getClassType());
} else { } else {
if (operands[arg].equals("this")) { if (operands[arg].equals("this")) {
if (specialFlag && if (specialFlag
(field.getClassDeclaration() == && (field.getClassDeclaration()
codeAnalyzer.getClassDefinition().getSuperClass() || == codeAnalyzer.getClassDefinition().getSuperClass()))
(field.getClassDeclaration().getName() == // || (field.getClassDeclaration().getName()
Constants.idJavaLangObject && // == Constants.idJavaLangObject
codeAnalyzer.getClassDefinition().getSuperClass() == null))) // && codeAnalyzer.getClassDefinition()
// .getSuperClass() == null)))
object = "super"; object = "super";
else if (specialFlag) else if (specialFlag)
object = "(("+codeAnalyzer.getTypeString object = "(("+codeAnalyzer.getTypeString(getClassType())
(field.getClassDeclaration().getType())+ + ") this)";
") this)";
else else
object = ""; object = "";
} else { } else {
if (specialFlag) if (specialFlag)
object = "(("+codeAnalyzer.getTypeString object = "((" + codeAnalyzer.getTypeString(getClassType())
(field.getClassDeclaration().getType())+ + ") " + operands[arg]+")";
") "+operands[arg]+")";
else else
object = operands[arg]; object = operands[arg];
} }

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class LocalLoadOperator extends ConstOperator public class LocalLoadOperator extends ConstOperator
implements LocalVarOperator { implements LocalVarOperator {
@ -27,6 +26,7 @@ implements LocalVarOperator {
public LocalLoadOperator(Type type, LocalInfo local) { public LocalLoadOperator(Type type, LocalInfo local) {
super(type, ""); super(type, "");
this.local = local; this.local = local;
local.setOperator(this);
} }
public boolean isRead() { public boolean isRead() {
@ -46,6 +46,12 @@ implements LocalVarOperator {
return local.getLocalInfo(); return local.getLocalInfo();
} }
public void updateType() {
super.setType(local.getType());
if (parent != null)
parent.updateType();
}
public Type getType() { public Type getType() {
// System.err.println("LocalLoad.getType of "+local.getName()+": "+local.getType()); // System.err.println("LocalLoad.getType of "+local.getName()+": "+local.getType());
return local.getType(); return local.getType();

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class LocalPostFixOperator extends NoArgOperator { public class LocalPostFixOperator extends NoArgOperator {
IIncOperator iinc; IIncOperator iinc;

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class LocalStoreOperator extends StoreInstruction public class LocalStoreOperator extends StoreInstruction
implements LocalVarOperator { implements LocalVarOperator {
@ -27,6 +26,7 @@ implements LocalVarOperator {
public LocalStoreOperator(Type lvalueType, LocalInfo local, int operator) { public LocalStoreOperator(Type lvalueType, LocalInfo local, int operator) {
super(lvalueType, operator); super(lvalueType, operator);
this.local = local; this.local = local;
local.setOperator(this);
} }
public boolean isRead() { public boolean isRead() {
@ -37,6 +37,11 @@ implements LocalVarOperator {
return true; return true;
} }
public void updateType() {
if (parent != null)
parent.updateType();
}
public LocalInfo getLocalInfo() { public LocalInfo getLocalInfo() {
return local.getLocalInfo(); return local.getLocalInfo();
} }
@ -49,7 +54,7 @@ implements LocalVarOperator {
public boolean setLValueType(Type type) { public boolean setLValueType(Type type) {
// System.err.println("LocalStore.setType of "+local.getName()+": "+local.getType()); // System.err.println("LocalStore.setType of "+local.getName()+": "+local.getType());
return super.setLValueType return super.setLValueType
(local.setType(MyType.tSuperType(type))); (local.setType(Type.tSuperType(type)));
} }
// public int getSlot() { // public int getSlot() {

@ -22,9 +22,12 @@ package jode;
public interface LocalVarOperator { public interface LocalVarOperator {
public boolean isRead(); public boolean isRead();
public boolean isWrite(); public boolean isWrite();
// public int getSlot();
public LocalInfo getLocalInfo(); public LocalInfo getLocalInfo();
// public void setLocalInfo(LocalInfo li); /**
* This is called by the local info when the type
* of it changed
*/
public void updateType();
} }

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class MonitorEnterOperator extends SimpleOperator { public class MonitorEnterOperator extends SimpleOperator {
public MonitorEnterOperator() { public MonitorEnterOperator() {

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class MonitorExitOperator extends SimpleOperator { public class MonitorExitOperator extends SimpleOperator {
public MonitorExitOperator() { public MonitorExitOperator() {
@ -35,7 +34,7 @@ public class MonitorExitOperator extends SimpleOperator {
} }
public Type getOperandType(int i) { public Type getOperandType(int i) {
return MyType.tObject; return Type.tObject;
} }
public String toString(String[] operands) { public String toString(String[] operands) {

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class NewArrayOperator extends SimpleOperator { public class NewArrayOperator extends SimpleOperator {
String baseTypeString; String baseTypeString;
@ -27,7 +26,7 @@ public class NewArrayOperator extends SimpleOperator {
int dimensions) { int dimensions) {
super(arrayType, 0, dimensions); super(arrayType, 0, dimensions);
for (int i=0; i< dimensions; i++) { for (int i=0; i< dimensions; i++) {
operandTypes[i] = MyType.tUIndex; operandTypes[i] = Type.tInt;
} }
this.baseTypeString = baseTypeString; this.baseTypeString = baseTypeString;
} }

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class NewOperator extends NoArgOperator { public class NewOperator extends NoArgOperator {
String typeString; String typeString;

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public abstract class NoArgOperator extends Operator { public abstract class NoArgOperator extends Operator {

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class NopOperator extends Instruction { public class NopOperator extends Instruction {
public NopOperator(Type type) { public NopOperator(Type type) {
@ -26,7 +25,7 @@ public class NopOperator extends Instruction {
} }
public NopOperator() { public NopOperator() {
this(MyType.tVoid); this(Type.tVoid);
} }
public boolean equals(Object o) { public boolean equals(Object o) {

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public abstract class Operator extends Expression { public abstract class Operator extends Expression {
public final static int ADD_OP = 1; public final static int ADD_OP = 1;

@ -18,14 +18,13 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class PopOperator extends SimpleOperator { public class PopOperator extends SimpleOperator {
int count; int count;
public PopOperator(int count) { public PopOperator(int count) {
super(Type.tVoid, 0, 1); super(Type.tVoid, 0, 1);
operandTypes[0] = MyType.tUnknown; operandTypes[0] = Type.tUnknown;
this.count = count; this.count = count;
} }

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class PostFixOperator extends Operator { public class PostFixOperator extends Operator {
StoreInstruction store; StoreInstruction store;

@ -27,7 +27,7 @@ public class PutFieldOperator extends StoreInstruction {
public PutFieldOperator(CodeAnalyzer codeAnalyzer, boolean staticFlag, public PutFieldOperator(CodeAnalyzer codeAnalyzer, boolean staticFlag,
FieldDefinition field) { FieldDefinition field) {
super(field.getType(), ASSIGN_OP); super(Type.tType(field.getType()), ASSIGN_OP);
this.codeAnalyzer = codeAnalyzer; this.codeAnalyzer = codeAnalyzer;
this.staticFlag = staticFlag; this.staticFlag = staticFlag;
this.field = field; this.field = field;
@ -55,7 +55,8 @@ public class PutFieldOperator extends StoreInstruction {
/* shouldn't be called */ /* shouldn't be called */
throw new AssertError("Field is static"); throw new AssertError("Field is static");
} }
return MyType.tSubType(field.getClassDefinition().getType()); return Type.tSubType(Type.tClass(field.getClassDefinition()
.getName().toString()));
} }
public void setLValueOperandType(Type[] t) { public void setLValueOperandType(Type[] t) {
@ -72,9 +73,9 @@ public class PutFieldOperator extends StoreInstruction {
if (field.getClassDefinition() if (field.getClassDefinition()
== codeAnalyzer.getClassDefinition()) == codeAnalyzer.getClassDefinition())
return field.getName().toString(); return field.getName().toString();
object = object = codeAnalyzer.getTypeString
codeAnalyzer.getTypeString (Type.tClass(field.getClassDeclaration()
(field.getClassDeclaration().getType())+"."; .getName().toString()))+".";
} else { } else {
if (operands[0].equals("this")) if (operands[0].equals("this"))
return field.getName().toString(); return field.getName().toString();

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
/** /**
* ShiftOpcodes are special, because their second operand is an UIndex * ShiftOpcodes are special, because their second operand is an UIndex
@ -28,7 +27,7 @@ public class ShiftOperator extends BinaryOperator {
public ShiftOperator(Type type, int op) { public ShiftOperator(Type type, int op) {
super(type, op); super(type, op);
shiftType = MyType.tUIndex; shiftType = Type.tInt;
} }
public Type getOperandType(int i) { public Type getOperandType(int i) {
@ -36,7 +35,7 @@ public class ShiftOperator extends BinaryOperator {
} }
public void setOperandType(Type[] inputTypes) { public void setOperandType(Type[] inputTypes) {
operandType = MyType.intersection(operandType, inputTypes[0]); operandType = operandType.intersection(inputTypes[0]);
shiftType = MyType.intersection(shiftType, inputTypes[1]); shiftType = shiftType .intersection(inputTypes[1]);
} }
} }

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public abstract class SimpleOperator extends Operator { public abstract class SimpleOperator extends Operator {
protected Type[] operandTypes; protected Type[] operandTypes;
@ -42,7 +41,7 @@ public abstract class SimpleOperator extends Operator {
public void setOperandType(Type[] t) { public void setOperandType(Type[] t) {
for (int i=0; i< operandTypes.length; i++) { for (int i=0; i< operandTypes.length; i++) {
operandTypes[i] = MyType.intersection(operandTypes[i], t[i]); operandTypes[i] = operandTypes[i].intersection(t[i]);
} }
} }
} }

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public abstract class StoreInstruction extends Operator { public abstract class StoreInstruction extends Operator {
@ -27,7 +26,7 @@ public abstract class StoreInstruction extends Operator {
public StoreInstruction(Type type, int operator) { public StoreInstruction(Type type, int operator) {
super(Type.tVoid, operator); super(Type.tVoid, operator);
lvalueType = MyType.tSubType(type); lvalueType = Type.tSubType(type);
lvCasts = lvalueType.toString(); lvCasts = lvalueType.toString();
} }
@ -46,11 +45,6 @@ public abstract class StoreInstruction extends Operator {
* @return true if the operand types changed * @return true if the operand types changed
*/ */
public boolean setLValueType(Type type) { public boolean setLValueType(Type type) {
// if (!MyType.isOfType(type, this.lvalueType)) {
// lvCasts = type.toString()+"/*invalid*/ <- " + lvCasts;
// } else if (type != this.lvalueType) {
// lvCasts = type.toString()+" <- " + lvCasts;
// }
this.lvalueType = type; this.lvalueType = type;
return false; return false;
} }
@ -70,7 +64,7 @@ public abstract class StoreInstruction extends Operator {
public Type getOperandType(int i) { public Type getOperandType(int i) {
if (i == getLValueOperandCount()) if (i == getLValueOperandCount())
return MyType.tSubType(getLValueType()); return Type.tSubType(getLValueType());
else else
return getLValueOperandType(i); return getLValueOperandType(i);
} }
@ -78,9 +72,8 @@ public abstract class StoreInstruction extends Operator {
public void setOperandType(Type[] t) { public void setOperandType(Type[] t) {
if (getLValueOperandCount() > 0) if (getLValueOperandCount() > 0)
setLValueOperandType(t); setLValueOperandType(t);
setLValueType(MyType.intersection setLValueType(lvalueType.intersection
(lvalueType, (Type.tSuperType(t[getLValueOperandCount()])));
MyType.tSuperType(t[getLValueOperandCount()])));
} }
public int getOperandCount() { public int getOperandCount() {

@ -18,14 +18,13 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class StringAddOperator extends SimpleOperator { public class StringAddOperator extends SimpleOperator {
protected Type operandType; protected Type operandType;
public StringAddOperator() { public StringAddOperator() {
super(MyType.tString, ADD_OP, 2); super(Type.tString, ADD_OP, 2);
operandTypes[1] = MyType.tUnknown; operandTypes[1] = Type.tUnknown;
} }
public int getPriority() { public int getPriority() {

@ -21,7 +21,7 @@ package jode;
public class SwapOperator extends Instruction { public class SwapOperator extends Instruction {
public SwapOperator() { public SwapOperator() {
super(MyType.tVoid); super(Type.tVoid);
} }
public String toString() public String toString()

@ -18,7 +18,6 @@
*/ */
package jode; package jode;
import sun.tools.java.Type;
public class UnaryOperator extends SimpleOperator { public class UnaryOperator extends SimpleOperator {
public UnaryOperator(Type type, int op) { public UnaryOperator(Type type, int op) {
@ -38,7 +37,7 @@ public class UnaryOperator extends SimpleOperator {
*/ */
public void setType(Type type) { public void setType(Type type) {
super.setType(type); super.setType(type);
Type newOpType = MyType.intersection(type, operandTypes[0]); Type newOpType = type.intersection(operandTypes[0]);
operandTypes[0] = newOpType; operandTypes[0] = newOpType;
} }

@ -44,6 +44,13 @@ public class BreakBlock extends StructuredBlock {
} }
} }
/**
* Tells if this block is empty and only changes control flow.
*/
public boolean isEmpty() {
return true;
}
/** /**
* Returns the block where the control will normally flow to, when * Returns the block where the control will normally flow to, when
* this block is finished. * this block is finished.

@ -49,7 +49,7 @@ public class CaseBlock extends StructuredBlock {
/** /**
* The type of the switch value. * The type of the switch value.
*/ */
sun.tools.java.Type type; jode.Type type;
public CaseBlock(int value) { public CaseBlock(int value) {
this.value = value; this.value = value;

@ -17,6 +17,7 @@
* $Id$ * $Id$
*/ */
package jode.flow; package jode.flow;
import jode.Type;
import jode.LocalInfo; import jode.LocalInfo;
import sun.tools.java.Identifier; import sun.tools.java.Identifier;
@ -39,7 +40,7 @@ public class CatchBlock extends StructuredBlock {
/** /**
* The type of the exception. * The type of the exception.
*/ */
sun.tools.java.Type exceptionType; Type exceptionType;
/** /**
* The local containing the exception. * The local containing the exception.
@ -166,8 +167,8 @@ public class CatchBlock extends StructuredBlock {
} }
tryBlock.dumpSource(writer); tryBlock.dumpSource(writer);
writer.untab(); writer.untab();
writer.println("} catch ("+/*XXX*/exceptionType.typeString writer.println("} catch ("+/*XXX*/exceptionType.toString() + " "
(exceptionLocal.getName().toString())+") {"); + exceptionLocal.getName().toString()+ ") {");
writer.tab(); writer.tab();
catchBlock.dumpSource(writer); catchBlock.dumpSource(writer);
if (!(outer instanceof CatchBlock if (!(outer instanceof CatchBlock

@ -21,7 +21,7 @@ package jode.flow;
import java.util.Vector; import java.util.Vector;
import jode.Expression; import jode.Expression;
import jode.ComplexExpression; import jode.ComplexExpression;
import jode.MyType; import jode.Type;
import jode.BinaryOperator; import jode.BinaryOperator;
public class CombineIfGotoExpressions implements Transformation{ public class CombineIfGotoExpressions implements Transformation{
@ -83,7 +83,7 @@ public class CombineIfGotoExpressions implements Transformation{
prevJump.prev.removeJump(); prevJump.prev.removeJump();
Expression cond = Expression cond =
new ComplexExpression new ComplexExpression
(new BinaryOperator(MyType.tBoolean, operator), e); (new BinaryOperator(Type.tBoolean, operator), e);
cb.setInstruction(cond); cb.setInstruction(cond);
cb.replace(cb.outer, cb); cb.replace(cb.outer, cb);
return true; return true;

@ -43,6 +43,13 @@ public class ContinueBlock extends StructuredBlock {
} }
} }
/**
* Tells if this block is empty and only changes control flow.
*/
public boolean isEmpty() {
return true;
}
/** /**
* Returns the block where the control will normally flow to, when * Returns the block where the control will normally flow to, when
* this block is finished (not ignoring the jump after this block). * this block is finished (not ignoring the jump after this block).

@ -33,6 +33,7 @@ public class CreateAssignExpression implements Transformation{
InstructionContainer lastBlock; InstructionContainer lastBlock;
SequentialBlock opBlock; SequentialBlock opBlock;
SequentialBlock sequBlock; SequentialBlock sequBlock;
boolean isExpression = false;
try { try {
InstructionBlock ib; InstructionBlock ib;
lastBlock = (InstructionContainer) flow.lastModified; lastBlock = (InstructionContainer) flow.lastModified;
@ -43,6 +44,16 @@ public class CreateAssignExpression implements Transformation{
return false; return false;
ib = (InstructionBlock) opBlock.subBlocks[0]; ib = (InstructionBlock) opBlock.subBlocks[0];
if (ib.getInstruction() instanceof DupOperator) {
DupOperator dup = (DupOperator) ib.getInstruction();
if (dup.getDepth() != store.getLValueOperandCount() &&
dup.getCount() != store.getLValueType().stackSize())
return false;
opBlock = (SequentialBlock) lastBlock.outer;
ib = (InstructionBlock) opBlock.subBlocks[0];
isExpression = true;
}
ComplexExpression binopExpr = ComplexExpression binopExpr =
(ComplexExpression) ib.getInstruction(); (ComplexExpression) ib.getInstruction();
binop = (BinaryOperator) binopExpr.getOperator(); binop = (BinaryOperator) binopExpr.getOperator();
@ -75,9 +86,14 @@ public class CreateAssignExpression implements Transformation{
opBlock.replace(sequBlock, opBlock); opBlock.replace(sequBlock, opBlock);
store.setOperatorIndex(store.OPASSIGN_OP+binop.getOperatorIndex()); store.setOperatorIndex(store.OPASSIGN_OP+binop.getOperatorIndex());
store.setLValueType(MyType.intersection(binop.getType(), store.setLValueType(binop.getType()
store.getLValueType())); .intersection(store.getLValueType()));
lastBlock.setInstruction(store);
if (isExpression)
lastBlock.setInstruction
(new AssignOperator(store.getOperatorIndex(), store));
else
lastBlock.setInstruction(store);
lastBlock.replace(opBlock.subBlocks[1], lastBlock); lastBlock.replace(opBlock.subBlocks[1], lastBlock);
return true; return true;
} }
@ -103,7 +119,7 @@ public class CreateAssignExpression implements Transformation{
return false; return false;
} }
lastBlock.setInstruction lastBlock.setInstruction
(new AssignOperator(Operator.ASSIGN_OP, store)); (new AssignOperator(store.getOperatorIndex(), store));
lastBlock.replace(sequBlock, lastBlock); lastBlock.replace(sequBlock, lastBlock);
return true; return true;

@ -25,8 +25,7 @@ import jode.ArrayStoreOperator;
import jode.NewArrayOperator; import jode.NewArrayOperator;
import jode.ConstantArrayOperator; import jode.ConstantArrayOperator;
import jode.ConstOperator; import jode.ConstOperator;
import jode.MyType; import jode.Type;
import sun.tools.java.Type;
public class CreateConstantArray implements Transformation { public class CreateConstantArray implements Transformation {
@ -60,7 +59,7 @@ public class CreateConstantArray implements Transformation {
Expression indexexpr = (Expression) ib.getInstruction(); Expression indexexpr = (Expression) ib.getInstruction();
ConstOperator indexop = ConstOperator indexop =
(ConstOperator) indexexpr.getOperator(); (ConstOperator) indexexpr.getOperator();
if (!MyType.isOfType(indexop.getType(), MyType.tUInt)) if (!indexop.getType().isOfType(Type.tUInt))
return false; return false;
int index = Integer.parseInt(indexop.getValue()); int index = Integer.parseInt(indexop.getValue());
if (index >= 0 && consts == null) { if (index >= 0 && consts == null) {
@ -71,7 +70,7 @@ public class CreateConstantArray implements Transformation {
else { else {
while (index < lastindex) { while (index < lastindex) {
consts[lastindex--] = consts[lastindex--] =
new ConstOperator(MyType.tUnknown, "0"); new ConstOperator(Type.tUnknown, "0");
} }
} }
consts[lastindex--] = lastconst; consts[lastindex--] = lastconst;
@ -89,7 +88,7 @@ public class CreateConstantArray implements Transformation {
return false; return false;
while (lastindex >= 0) { while (lastindex >= 0) {
consts[lastindex--] = consts[lastindex--] =
new ConstOperator(MyType.tUnknown, "0"); new ConstOperator(Type.tUnknown, "0");
} }
ComplexExpression newArrayExpr = ComplexExpression newArrayExpr =
(ComplexExpression) ib.getInstruction(); (ComplexExpression) ib.getInstruction();
@ -102,7 +101,7 @@ public class CreateConstantArray implements Transformation {
(Expression) newArrayExpr.getSubExpressions()[0]; (Expression) newArrayExpr.getSubExpressions()[0];
ConstOperator countop = ConstOperator countop =
(ConstOperator) countexpr.getOperator(); (ConstOperator) countexpr.getOperator();
if (!MyType.isOfType(countop.getType(), MyType.tUInt)) if (!countop.getType().isOfType(Type.tUInt))
return false; return false;
int arraylength = Integer.parseInt(countop.getValue()); int arraylength = Integer.parseInt(countop.getValue());
if (arraylength != consts.length) { if (arraylength != consts.length) {
@ -111,7 +110,7 @@ public class CreateConstantArray implements Transformation {
Expression[] newConsts = new Expression[arraylength]; Expression[] newConsts = new Expression[arraylength];
System.arraycopy(consts, 0, newConsts, 0, consts.length); System.arraycopy(consts, 0, newConsts, 0, consts.length);
for (int i=consts.length; i<arraylength; i++) for (int i=consts.length; i<arraylength; i++)
newConsts[i] = new ConstOperator(MyType.tUnknown, "0"); newConsts[i] = new ConstOperator(Type.tUnknown, "0");
consts = newConsts; consts = newConsts;
} }
} catch (NullPointerException ex) { } catch (NullPointerException ex) {

@ -21,7 +21,6 @@ package jode.flow;
import jode.Expression; import jode.Expression;
import jode.ComplexExpression; import jode.ComplexExpression;
import jode.IfThenElseOperator; import jode.IfThenElseOperator;
import jode.MyType;
import jode.CompareUnaryOperator; import jode.CompareUnaryOperator;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Vector; import java.util.Vector;
@ -145,7 +144,7 @@ public class CreateIfThenElseOperator implements Transformation {
System.err.print("?"); System.err.print("?");
IfThenElseOperator iteo = new IfThenElseOperator IfThenElseOperator iteo = new IfThenElseOperator
(MyType.intersection(e[1].getType(),e[2].getType())); (e[1].getType().intersection(e[2].getType()));
((InstructionBlock)ifBlock.thenBlock). ((InstructionBlock)ifBlock.thenBlock).
setInstruction(new ComplexExpression(iteo, e)); setInstruction(new ComplexExpression(iteo, e));
@ -206,7 +205,7 @@ public class CreateIfThenElseOperator implements Transformation {
System.err.print("?"); System.err.print("?");
IfThenElseOperator iteo = new IfThenElseOperator IfThenElseOperator iteo = new IfThenElseOperator
(MyType.intersection(e[1].getType(),e[2].getType())); (e[1].getType().intersection(e[2].getType()));
((InstructionBlock)flow.lastModified). ((InstructionBlock)flow.lastModified).
setInstruction(new ComplexExpression(iteo, e)); setInstruction(new ComplexExpression(iteo, e));

@ -18,7 +18,6 @@
*/ */
package jode.flow; package jode.flow;
import sun.tools.java.Type;
import jode.*; import jode.*;
public class CreatePostIncExpression implements Transformation { public class CreatePostIncExpression implements Transformation {
@ -57,7 +56,7 @@ public class CreatePostIncExpression implements Transformation {
if (!iinc.matches(load)) if (!iinc.matches(load))
return false; return false;
type = MyType.intersection(load.getType(), MyType.tUInt); type = load.getType().intersection(Type.tUInt);
} catch (NullPointerException ex) { } catch (NullPointerException ex) {
return false; return false;
} catch (ClassCastException ex) { } catch (ClassCastException ex) {
@ -135,7 +134,7 @@ public class CreatePostIncExpression implements Transformation {
dup2.getDepth() != 0) dup2.getDepth() != 0)
return false; return false;
} }
type = MyType.intersection(load.getType(), store.getLValueType()); type = load.getType().intersection(store.getLValueType());
} catch (NullPointerException ex) { } catch (NullPointerException ex) {
return false; return false;
} catch (ClassCastException ex) { } catch (ClassCastException ex) {

@ -31,6 +31,13 @@ public class EmptyBlock extends StructuredBlock {
setJump(jump); setJump(jump);
} }
/**
* Tells if this block is empty and only changes control flow.
*/
public boolean isEmpty() {
return true;
}
/** /**
* Appends a block to this block. * Appends a block to this block.
* @return the new combined block. * @return the new combined block.

@ -443,7 +443,6 @@ public class FlowBlock {
doWhileFalse = new LoopBlock(LoopBlock.DOWHILE, doWhileFalse = new LoopBlock(LoopBlock.DOWHILE,
LoopBlock.FALSE); LoopBlock.FALSE);
doWhileFalse.setJump(new Jump(succ)); doWhileFalse.setJump(new Jump(succ));
successors.addElement(doWhileFalse.jump);
} }
prevBlock.appendBlock prevBlock.appendBlock
(new BreakBlock(doWhileFalse, breaklevel > 0)); (new BreakBlock(doWhileFalse, breaklevel > 0));
@ -455,7 +454,7 @@ public class FlowBlock {
if (doWhileFalse != null) { if (doWhileFalse != null) {
doWhileFalse.replace(appendBlock, appendBlock); doWhileFalse.replace(appendBlock, appendBlock);
doWhileFalse.setBody(appendBlock); doWhileFalse.setBody(appendBlock);
doWhileFalse.removeJump(); doWhileFalse.jump = null;
} }
/* Now remove the jump of the appendBlock if it points to /* Now remove the jump of the appendBlock if it points to
@ -757,6 +756,13 @@ public class FlowBlock {
checkConsistent(); checkConsistent();
// TabbedPrintWriter writer = new jode.TabbedPrintWriter(System.err, " ");
// try {
// writer.println("XXXXXXXXXXXXXXXX");
// writer.tab();
// dumpSource(writer);
// } catch(java.io.IOException ex) {}
appendBlock = resolveRemaining(succ, appendBlock); appendBlock = resolveRemaining(succ, appendBlock);
} }
@ -1110,6 +1116,11 @@ public class FlowBlock {
/* the Block has no successor where t1 is applicable. /* the Block has no successor where t1 is applicable.
* Finish this analyzation. * Finish this analyzation.
*/ */
if (Decompiler.isFlowDebugging) {
writer.println("No more successors applicable: "
+ start + " - " + end + "; "
+ addr + " - " + (addr+length));
}
return changed; return changed;
} else { } else {
/* Only do T1 transformation if the blocks are /* Only do T1 transformation if the blocks are
@ -1190,8 +1201,15 @@ public class FlowBlock {
return changed; return changed;
else if (next.addr >= start) { else if (next.addr >= start) {
/* First analyze the next block. */ /* First analyze the next block. It may
changed = next.analyze(next.addr, end) || changed; * return early after a T2 trafo so call it
* until nothing more is possible.
*/
while (next.analyze(addr + length, end))
changed = changed || true;
if (next.addr != addr + length)
return changed;
/* Check if next has only the previous case /* Check if next has only the previous case
* and this case as predecessor. Otherwise * and this case as predecessor. Otherwise
@ -1227,9 +1245,7 @@ public class FlowBlock {
lastBlock = resolveRemaining(next, lastBlock); lastBlock = resolveRemaining(next, lastBlock);
} }
/* Set addr+length to (semi-)correct value */ /* Set length to correct value */
if (next.addr < addr)
addr = next.addr;
length += next.length; length += next.length;
lastBlock = next.block; lastBlock = next.block;

@ -104,7 +104,8 @@ public class IfThenElseBlock extends StructuredBlock {
if (elseBlock != null) { if (elseBlock != null) {
writer.print(needBrace ? "} " : ""); writer.print(needBrace ? "} " : "");
if (elseBlock instanceof IfThenElseBlock if (elseBlock instanceof IfThenElseBlock
/* XXX && No variables are declared XXX*/) { && (elseBlock.declare == null
|| elseBlock.declare.isEmpty())) {
needBrace = false; needBrace = false;
writer.print("else "); writer.print("else ");
elseBlock.dumpSource(writer); elseBlock.dumpSource(writer);

@ -72,7 +72,7 @@ public class InstructionBlock extends InstructionContainer {
.getLocalInfo().getType().toString()/*XXX*/ .getLocalInfo().getType().toString()/*XXX*/
+ " " + instr.toString() + ";"); + " " + instr.toString() + ";");
} else { } else {
if (instr.getType() != MyType.tVoid) if (instr.getType() != Type.tVoid)
writer.print("push "); writer.print("push ");
writer.println(instr.toString()+";"); writer.println(instr.toString()+";");
} }

@ -30,9 +30,9 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
public static final int FOR = 2; public static final int FOR = 2;
public static final Instruction TRUE = public static final Instruction TRUE =
new ConstOperator(MyType.tBoolean, "1"); new ConstOperator(Type.tBoolean, "1");
public static final Instruction FALSE = public static final Instruction FALSE =
new ConstOperator(MyType.tBoolean, "0"); new ConstOperator(Type.tBoolean, "0");
/** /**
* The condition. Must be of boolean type. * The condition. Must be of boolean type.

@ -42,7 +42,7 @@ import jode.TabbedPrintWriter;
public class RawTryCatchBlock extends StructuredBlock { public class RawTryCatchBlock extends StructuredBlock {
public RawTryCatchBlock(sun.tools.java.Type type, public RawTryCatchBlock(jode.Type type,
StructuredBlock tryBlock, StructuredBlock tryBlock,
Jump endDest, Jump catchDest) { Jump endDest, Jump catchDest) {
this.type = type; this.type = type;
@ -89,7 +89,7 @@ public class RawTryCatchBlock extends StructuredBlock {
* The type of the exception that is catched. This is null for a * The type of the exception that is catched. This is null for a
* synchronized/finally block * synchronized/finally block
*/ */
sun.tools.java.Type type; jode.Type type;
/** /**
* Replaces the given sub block with a new block. * Replaces the given sub block with a new block.

@ -47,8 +47,7 @@ public class RemoveEmpty implements Transformation {
if (prev.jump != null) if (prev.jump != null)
return false; return false;
instr = (Instruction) prev.getInstruction(); instr = (Instruction) prev.getInstruction();
instr.setType(jode.MyType.intersection instr.setType(instr.getType().intersection(prevInstr.getType()));
(instr.getType(), prevInstr.getType()));
} catch (NullPointerException ex) { } catch (NullPointerException ex) {
return false; return false;
} catch (ClassCastException ex) { } catch (ClassCastException ex) {

@ -52,14 +52,22 @@ public class SequentialBlock extends StructuredBlock {
* the behaviour is undefined, so take care. * the behaviour is undefined, so take care.
* @return null, if the control flows to another FlowBlock. */ * @return null, if the control flows to another FlowBlock. */
public StructuredBlock getNextBlock(StructuredBlock subBlock) { public StructuredBlock getNextBlock(StructuredBlock subBlock) {
if (subBlock == subBlocks[0]) if (subBlock == subBlocks[0]) {
return subBlocks[1]; if (subBlocks[1].isEmpty())
return subBlocks[1].getNextBlock();
else
return subBlocks[1];
}
return getNextBlock(); return getNextBlock();
} }
public FlowBlock getNextFlowBlock(StructuredBlock subBlock) { public FlowBlock getNextFlowBlock(StructuredBlock subBlock) {
if (subBlock == subBlocks[0]) if (subBlock == subBlocks[0]) {
return null; if (subBlocks[1].isEmpty())
return subBlocks[1].getNextFlowBlock();
else
return null;
}
return getNextFlowBlock(); return getNextFlowBlock();
} }

@ -150,6 +150,13 @@ public abstract class StructuredBlock {
return getNextFlowBlock(); return getNextFlowBlock();
} }
/**
* Tells if this block is empty and only changes control flow.
*/
public boolean isEmpty() {
return false;
}
/** /**
* Tells if the sub block is the single exit point of the current block. * Tells if the sub block is the single exit point of the current block.
* @param subBlock the sub block. * @param subBlock the sub block.
@ -441,8 +448,8 @@ public abstract class StructuredBlock {
public void dumpDeclaration(jode.TabbedPrintWriter writer, LocalInfo local) public void dumpDeclaration(jode.TabbedPrintWriter writer, LocalInfo local)
throws java.io.IOException throws java.io.IOException
{ {
writer.println(local.getType().typeString(local.getName().toString()) writer.println(local.getType().toString() + " "
+ ";"); + local.getName().toString() + ";");
} }
/** /**

@ -141,7 +141,7 @@ implements BreakableBlock {
public void setInstruction(jode.Instruction instr) { public void setInstruction(jode.Instruction instr) {
super.setInstruction(instr); super.setInstruction(instr);
sun.tools.java.Type type = instr.getType(); jode.Type type = instr.getType();
if (type != caseBlocks[0].type) { if (type != caseBlocks[0].type) {
for (int i=0; i < caseBlocks.length; i++) for (int i=0; i < caseBlocks.length; i++)
caseBlocks[i].type = type; caseBlocks[i].type = type;

@ -33,24 +33,23 @@ import java.util.Stack;
* interfaces or the class type or any of their super types. * interfaces or the class type or any of their super types.
* *
* @author Jochen Hoenicke */ * @author Jochen Hoenicke */
public class ClassInterfacesType extends MyType { public class ClassInterfacesType extends Type {
Class clazz; Class clazz;
Class ifaces[]; Class ifaces[];
public final static Class cObject = new Object().getClass(); public final static Class cObject = new Object().getClass();
public ClassInterfacesType(Type clazzType) { public ClassInterfacesType(String clazzName) {
super(104, "{"+clazzType.getTypeSignature()+"}"); super(TC_CLASS);
try { try {
Class cdecl = Class clazz = Class.forName(clazzName);
Class.forName(clazzType.getClassName().toString()); if (clazz.isInterface()) {
if (cdecl.isInterface()) { this.clazz = cObject;
clazz = cObject;
ifaces = new Class[1]; ifaces = new Class[1];
ifaces[0] = cdecl; ifaces[0] = clazz;
} else { } else {
clazz = cdecl; this.clazz = clazz;
ifaces = new Class[0]; ifaces = new Class[0];
} }
} catch (ClassNotFoundException ex) { } catch (ClassNotFoundException ex) {
@ -58,20 +57,31 @@ public class ClassInterfacesType extends MyType {
} }
} }
public ClassInterfacesType(Class clazz, public ClassInterfacesType(Class clazz) {
Class[] ifaces) { super(TC_CLASS);
super(104, "{}"); if (clazz.isInterface()) {
StringBuffer sig = new StringBuffer("{"); this.clazz = cObject;
if (clazz != null) ifaces = new Class[1];
sig.append("L").append(clazz.getName()).append(";"); ifaces[0] = clazz;
for (int i=0;i < ifaces.length; i++) } else {
sig.append("L").append(ifaces[i].getName()).append(";"); this.clazz = clazz;
sig.append("}"); ifaces = new Class[0];
typeSig = sig.toString(); }
}
public ClassInterfacesType(Class clazz, Class[] ifaces) {
super(TC_CLASS);
this.clazz = clazz; this.clazz = clazz;
this.ifaces = ifaces; this.ifaces = ifaces;
} }
private static Type create(Class clazz, Class[] ifaces) {
/* Make sure that every {java.lang.Object} equals tObject */
if (ifaces.length == 0 && (clazz == cObject || clazz == null))
return tObject;
return new ClassInterfacesType(clazz, ifaces);
}
public final static boolean superClassOf(Class parent, Class clazz) { public final static boolean superClassOf(Class parent, Class clazz) {
while (clazz != parent && clazz != null) { while (clazz != parent && clazz != null) {
clazz = clazz.getSuperclass(); clazz = clazz.getSuperclass();
@ -92,40 +102,51 @@ public class ClassInterfacesType extends MyType {
} }
/** /**
* Checks if the given type range may be not empty. * Create the type corresponding to the range from bottomType to
* This means, that bottom.clazz is extended by top.clazz * this. Checks if the given type range may be not empty. This
* and that all interfaces in bottom are implemented by an * means, that bottom.clazz is extended by this.clazz and that all
* interface or by top.clazz. <p> * interfaces in bottom are implemented by an interface or by
* * clazz.
* if that is true, a class range type is created, otherwise * @param bottom the start point of the range
* tError is returned. * @return the range type, or tError if range is empty.
*/ */
public final static Type createRangeType(ClassInterfacesType bottom, public Type createRangeType(Type bottomType) {
ClassInterfacesType top) {
if (bottomType == tUnknown || bottomType == tObject)
return (this == tObject) ? tObject : tRange(tObject, this);
if (bottomType.typecode != TC_CLASS)
return tError;
ClassInterfacesType bottom = (ClassInterfacesType) bottomType;
if (bottom.clazz != null if (bottom.clazz != null
&& bottom.clazz != cObject) { && bottom.clazz != cObject) {
/* The searched type must be a class type. /* The searched type must be a class type.
*/ */
if (top.ifaces.length != 0 if (this.ifaces.length != 0
|| !superClassOf(bottom.clazz,top.clazz)) || !superClassOf(bottom.clazz,this.clazz))
return tError; return tError;
/* All interfaces must be implemented by top.clazz /* All interfaces must be implemented by this.clazz
*/ */
for (int i=0; i < bottom.ifaces.length; i++) { for (int i=0; i < bottom.ifaces.length; i++) {
if (!implementedBy(bottom.ifaces[i], top.clazz)) if (!implementedBy(bottom.ifaces[i], this.clazz))
return tError; return tError;
} }
return new ClassRangeType
(bottom, new ClassInterfacesType(top.clazz, if (bottom.clazz == this.clazz
new Class[0])); && bottom.ifaces.length == 0)
return bottom;
return tRange(bottom, create(this.clazz, new Class[0]));
} else { } else {
/* Now bottom.clazz is null, find all top.class/interfaces /* Now bottom.clazz is null (or tObject), find all
* that implement all bottom.ifaces. * classes/interfaces that implement all bottom.ifaces.
*/ */
Class clazz = top.clazz; Class clazz = this.clazz;
if (clazz != null) { if (clazz != null) {
for (int i=0; i < bottom.ifaces.length; i++) { for (int i=0; i < bottom.ifaces.length; i++) {
if (!implementedBy(bottom.ifaces[i], clazz)) { if (!implementedBy(bottom.ifaces[i], clazz)) {
@ -136,46 +157,60 @@ public class ClassInterfacesType extends MyType {
} }
Vector ifaces = new Vector(); Vector ifaces = new Vector();
big_loop: big_loop:
for (int j=0; j < top.ifaces.length; j++) { for (int j=0; j < this.ifaces.length; j++) {
for (int i=0; i < bottom.ifaces.length; i++) { for (int i=0; i < bottom.ifaces.length; i++) {
if (!implementedBy(bottom.ifaces[i], top.ifaces[j])) if (!implementedBy(bottom.ifaces[i], this.ifaces[j]))
continue big_loop; continue big_loop;
} }
ifaces.addElement(top.ifaces[j]); ifaces.addElement(this.ifaces[j]);
} }
/* If bottom and the new top are the same single interface
* return it.
*/
if (clazz == null
&& bottom.ifaces.length == 1 && ifaces.size() == 1
&& bottom.ifaces[0] == ifaces.elementAt(0))
return bottom;
Class[] ifaceArray = Class[] ifaceArray =
new Class[ifaces.size()]; new Class[ifaces.size()];
ifaces.copyInto(ifaceArray); ifaces.copyInto(ifaceArray);
return new ClassRangeType return tRange(bottom, create(clazz, ifaceArray));
(bottom, new ClassInterfacesType(clazz, ifaceArray));
} }
} }
/** /**
* Returns the specialized type of t1 and t2. * Returns the specialized type of this and type.
* We have two classes and multiple interfaces. The result * We have two classes and multiple interfaces. The result
* should be the object that is the the child of both objects * should be the object that is the the child of both objects
* and the union of all interfaces. * and the union of all interfaces.
*/ */
public static Type getSpecializedType(ClassInterfacesType t1, public Type getSpecializedType(Type type) {
ClassInterfacesType t2) {
if (type.getTypeCode() == TC_UNKNOWN)
return this;
if (type.getTypeCode() == TC_ARRAY && this == tObject)
return type;
if (type.getTypeCode() != TC_CLASS)
return tError;
ClassInterfacesType other = (ClassInterfacesType) type;
Class clazz = null; Class clazz = null;
Vector ifaces = new Vector(); Vector ifaces = new Vector();
/* First determine the clazz, one of the two classes must be a sub /* First determine the clazz, one of the two classes must be a sub
* class of the other or null. * class of the other or null.
*/ */
if (t1.clazz == null) if (this.clazz == null)
clazz = t2.clazz; clazz = other.clazz;
else if (t2.clazz == null) else if (other.clazz == null)
clazz = t1.clazz; clazz = this.clazz;
else if (superClassOf(t1.clazz, t2.clazz)) else if (superClassOf(this.clazz, other.clazz))
clazz = t2.clazz; clazz = other.clazz;
else if (superClassOf(t2.clazz, t1.clazz)) else if (superClassOf(other.clazz, this.clazz))
clazz = t1.clazz; clazz = this.clazz;
else else
return tError; return tError;
@ -183,15 +218,15 @@ public class ClassInterfacesType extends MyType {
* But we can simplify this, if an interface is implemented by * But we can simplify this, if an interface is implemented by
* another or by the class, we can omit it. * another or by the class, we can omit it.
*/ */
big_loop_t1: big_loop_this:
for (int i=0; i< t1.ifaces.length; i++) { for (int i=0; i< this.ifaces.length; i++) {
Class iface = t1.ifaces[i]; Class iface = this.ifaces[i];
if (clazz != null && implementedBy(iface, clazz)) { if (clazz != null && implementedBy(iface, clazz)) {
continue big_loop_t1; continue big_loop_this;
} }
for (int j=0; j<t2.ifaces.length; j++) { for (int j=0; j<other.ifaces.length; j++) {
if (implementedBy(iface, t2.ifaces[j])) { if (implementedBy(iface, other.ifaces[j])) {
continue big_loop_t1; continue big_loop_this;
} }
} }
@ -200,15 +235,15 @@ public class ClassInterfacesType extends MyType {
*/ */
ifaces.addElement(iface); ifaces.addElement(iface);
} }
big_loop_t2: big_loop_other:
for (int i=0; i< t2.ifaces.length; i++) { for (int i=0; i< other.ifaces.length; i++) {
Class iface = t2.ifaces[i]; Class iface = other.ifaces[i];
if (clazz != null && implementedBy(iface, clazz)) { if (clazz != null && implementedBy(iface, clazz)) {
continue big_loop_t2; continue big_loop_other;
} }
for (int j=0; j<ifaces.size(); j++) { for (int j=0; j<ifaces.size(); j++) {
if (implementedBy(iface, (Class) ifaces.elementAt(j))) { if (implementedBy(iface, (Class) ifaces.elementAt(j))) {
continue big_loop_t2; continue big_loop_other;
} }
} }
@ -223,32 +258,38 @@ public class ClassInterfacesType extends MyType {
Class[] ifaceArray = new Class[ifaces.size()]; Class[] ifaceArray = new Class[ifaces.size()];
ifaces.copyInto(ifaceArray); ifaces.copyInto(ifaceArray);
return new ClassInterfacesType(clazz, ifaceArray); return create(clazz, ifaceArray);
} }
/** /**
* Returns the generalized type of t1 and t2. * Returns the generalized type of this and type.
* We have two classes and multiple interfaces. The result * We have two classes and multiple interfaces. The result
* should be the object that is the the parent of both objects and * should be the object that is the the parent of both objects and
* all interfaces, that one class or interface of t1 and of t2 * all interfaces, that one class or interface of this and of type
* implements. * implements.
*/ */
public static Type getGeneralizedType(ClassInterfacesType t1, public Type getGeneralizedType(Type type) {
ClassInterfacesType t2) {
Class clazz; Class clazz;
Vector ifaces = new Vector(); Vector ifaces = new Vector();
if (type.getTypeCode() == TC_UNKNOWN)
return this;
if (type.getTypeCode() == TC_ARRAY)
return tObject;
if (type.getTypeCode() != TC_CLASS)
return tError;
ClassInterfacesType other = (ClassInterfacesType) type;
/* First the easy part, determine the clazz */ /* First the easy part, determine the clazz */
if (t1.clazz == null) if (this.clazz == null || other.clazz == null)
clazz = t2.clazz; clazz = null;
else if (t2.clazz == null)
clazz = t1.clazz;
else { else {
clazz = t1.clazz; clazz = this.clazz;
while(clazz != null) { while(clazz != null) {
if (superClassOf(clazz, t2.clazz)) if (superClassOf(clazz, other.clazz))
break; break;
clazz = clazz.getSuperclass(); clazz = clazz.getSuperclass();
} }
@ -257,14 +298,14 @@ public class ClassInterfacesType extends MyType {
} }
/* Now the more complicated part: find all interfaces, that are /* Now the more complicated part: find all interfaces, that are
* implemented by one interface or class in each group. * implemented by one interface or class in each group.
* *
* First get all interfaces of t1.clazz and t1.ifaces. * First get all interfaces of this.clazz and this.ifaces.
*/ */
Stack allIfaces = new Stack(); Stack allIfaces = new Stack();
if (t1.clazz != null) { if (this.clazz != null) {
Class c = t1.clazz; Class c = this.clazz;
while (clazz != c) { while (clazz != c) {
Class clazzIfaces[] = c.getInterfaces(); Class clazzIfaces[] = c.getInterfaces();
for (int i=0; i<clazzIfaces.length; i++) for (int i=0; i<clazzIfaces.length; i++)
@ -272,11 +313,11 @@ public class ClassInterfacesType extends MyType {
c = c.getSuperclass(); c = c.getSuperclass();
} }
} }
for (int i=0; i<t1.ifaces.length; i++) for (int i=0; i<this.ifaces.length; i++)
allIfaces.push(t1.ifaces[i]); allIfaces.push(this.ifaces[i]);
/* Now consider each interface. If any clazz or interface /* Now consider each interface. If any clazz or interface
* in t2 implements it, add it to the ifaces vector. * in other implements it, add it to the ifaces vector.
* Otherwise consider all sub interfaces. * Otherwise consider all sub interfaces.
*/ */
iface_loop: iface_loop:
@ -287,12 +328,12 @@ public class ClassInterfacesType extends MyType {
*/ */
continue iface_loop; continue iface_loop;
if (t2.clazz != null && implementedBy(iface, t2.clazz)) { if (other.clazz != null && implementedBy(iface, other.clazz)) {
ifaces.addElement(iface); ifaces.addElement(iface);
continue iface_loop; continue iface_loop;
} }
for (int i=0; i<t2.ifaces.length; i++) { for (int i=0; i<other.ifaces.length; i++) {
if (implementedBy(iface, t2.ifaces[i])) { if (implementedBy(iface, other.ifaces[i])) {
ifaces.addElement(iface); ifaces.addElement(iface);
continue iface_loop; continue iface_loop;
} }
@ -308,12 +349,14 @@ public class ClassInterfacesType extends MyType {
Class[] ifaceArray = new Class[ifaces.size()]; Class[] ifaceArray = new Class[ifaces.size()];
ifaces.copyInto(ifaceArray); ifaces.copyInto(ifaceArray);
return new ClassInterfacesType(clazz, ifaceArray); return create(clazz, ifaceArray);
} }
public String typeString(String string, boolean flag1, boolean flag2) public String toString()
{ {
if (jode.Decompiler.isTypeDebugging) { if (jode.Decompiler.isTypeDebugging) {
if (this == tObject)
return "<tObject>";
StringBuffer sb = new StringBuffer("{"); StringBuffer sb = new StringBuffer("{");
String comma = ""; String comma = "";
if (clazz != null) { if (clazz != null) {
@ -324,14 +367,35 @@ public class ClassInterfacesType extends MyType {
sb.append(comma).append(ifaces[i].getName()); sb.append(comma).append(ifaces[i].getName());
comma = ", "; comma = ", ";
} }
return sb.append("}").append(string).toString(); return sb.append("}").toString();
} else { } else {
if (clazz != null) if (clazz != null)
return clazz.toString() + string; return clazz.getName();
else if (ifaces.length > 0) else if (ifaces.length > 0)
return ifaces[0].toString() + string; return ifaces[0].getName();
else else
return tError.toString() + string; return "{<error>}";
}
}
public boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof ClassInterfacesType) {
ClassInterfacesType type = (ClassInterfacesType) o;
if (type.clazz == clazz
&& type.ifaces.length == ifaces.length) {
big_loop:
for (int i=0; i< type.ifaces.length; i++) {
for (int j=0; j<ifaces.length; j++) {
if (type.ifaces[i] == ifaces[j])
continue big_loop;
}
return false;
}
return true;
}
} }
return false;
} }
} }

Loading…
Cancel
Save