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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -27,7 +27,7 @@ public class GetFieldOperator extends Operator {
public GetFieldOperator(CodeAnalyzer codeAnalyzer, boolean staticFlag,
FieldDefinition field) {
super(field.getType(), 0);
super(Type.tType(field.getType()), 0);
this.codeAnalyzer = codeAnalyzer;
this.staticFlag = staticFlag;
this.field = field;
@ -54,7 +54,8 @@ public class GetFieldOperator extends Operator {
/* shouldn't be called */
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[]) {
@ -66,7 +67,9 @@ public class GetFieldOperator extends Operator {
if (field.getClassDefinition() == codeAnalyzer.getClassDefinition())
return field.getName().toString();
object =
codeAnalyzer.getTypeString(field.getClassDeclaration().getType());
codeAnalyzer.getTypeString
(Type.tClass(field.getClassDeclaration()
.getName().toString()));
} else {
if (operands[0].equals("this"))
return field.getName().toString();

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

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

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

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

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

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

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

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

@ -22,9 +22,12 @@ package jode;
public interface LocalVarOperator {
public boolean isRead();
public boolean isWrite();
// public int getSlot();
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;
import sun.tools.java.Type;
public class MonitorEnterOperator extends SimpleOperator {
public MonitorEnterOperator() {

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

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

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

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

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

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

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

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

@ -27,7 +27,7 @@ public class PutFieldOperator extends StoreInstruction {
public PutFieldOperator(CodeAnalyzer codeAnalyzer, boolean staticFlag,
FieldDefinition field) {
super(field.getType(), ASSIGN_OP);
super(Type.tType(field.getType()), ASSIGN_OP);
this.codeAnalyzer = codeAnalyzer;
this.staticFlag = staticFlag;
this.field = field;
@ -55,7 +55,8 @@ public class PutFieldOperator extends StoreInstruction {
/* shouldn't be called */
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) {
@ -72,9 +73,9 @@ public class PutFieldOperator extends StoreInstruction {
if (field.getClassDefinition()
== codeAnalyzer.getClassDefinition())
return field.getName().toString();
object =
codeAnalyzer.getTypeString
(field.getClassDeclaration().getType())+".";
object = codeAnalyzer.getTypeString
(Type.tClass(field.getClassDeclaration()
.getName().toString()))+".";
} else {
if (operands[0].equals("this"))
return field.getName().toString();

@ -18,7 +18,6 @@
*/
package jode;
import sun.tools.java.Type;
/**
* 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) {
super(type, op);
shiftType = MyType.tUIndex;
shiftType = Type.tInt;
}
public Type getOperandType(int i) {
@ -36,7 +35,7 @@ public class ShiftOperator extends BinaryOperator {
}
public void setOperandType(Type[] inputTypes) {
operandType = MyType.intersection(operandType, inputTypes[0]);
shiftType = MyType.intersection(shiftType, inputTypes[1]);
operandType = operandType.intersection(inputTypes[0]);
shiftType = shiftType .intersection(inputTypes[1]);
}
}

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

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

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

@ -18,7 +18,6 @@
*/
package jode;
import sun.tools.java.Type;
public class UnaryOperator extends SimpleOperator {
public UnaryOperator(Type type, int op) {
@ -38,7 +37,7 @@ public class UnaryOperator extends SimpleOperator {
*/
public void setType(Type type) {
super.setType(type);
Type newOpType = MyType.intersection(type, operandTypes[0]);
Type newOpType = type.intersection(operandTypes[0]);
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
* this block is finished.

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

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

@ -21,7 +21,7 @@ package jode.flow;
import java.util.Vector;
import jode.Expression;
import jode.ComplexExpression;
import jode.MyType;
import jode.Type;
import jode.BinaryOperator;
public class CombineIfGotoExpressions implements Transformation{
@ -83,7 +83,7 @@ public class CombineIfGotoExpressions implements Transformation{
prevJump.prev.removeJump();
Expression cond =
new ComplexExpression
(new BinaryOperator(MyType.tBoolean, operator), e);
(new BinaryOperator(Type.tBoolean, operator), e);
cb.setInstruction(cond);
cb.replace(cb.outer, cb);
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
* this block is finished (not ignoring the jump after this block).

@ -33,6 +33,7 @@ public class CreateAssignExpression implements Transformation{
InstructionContainer lastBlock;
SequentialBlock opBlock;
SequentialBlock sequBlock;
boolean isExpression = false;
try {
InstructionBlock ib;
lastBlock = (InstructionContainer) flow.lastModified;
@ -43,6 +44,16 @@ public class CreateAssignExpression implements Transformation{
return false;
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) ib.getInstruction();
binop = (BinaryOperator) binopExpr.getOperator();
@ -75,9 +86,14 @@ public class CreateAssignExpression implements Transformation{
opBlock.replace(sequBlock, opBlock);
store.setOperatorIndex(store.OPASSIGN_OP+binop.getOperatorIndex());
store.setLValueType(MyType.intersection(binop.getType(),
store.getLValueType()));
lastBlock.setInstruction(store);
store.setLValueType(binop.getType()
.intersection(store.getLValueType()));
if (isExpression)
lastBlock.setInstruction
(new AssignOperator(store.getOperatorIndex(), store));
else
lastBlock.setInstruction(store);
lastBlock.replace(opBlock.subBlocks[1], lastBlock);
return true;
}
@ -103,7 +119,7 @@ public class CreateAssignExpression implements Transformation{
return false;
}
lastBlock.setInstruction
(new AssignOperator(Operator.ASSIGN_OP, store));
(new AssignOperator(store.getOperatorIndex(), store));
lastBlock.replace(sequBlock, lastBlock);
return true;

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

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

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

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

@ -443,7 +443,6 @@ public class FlowBlock {
doWhileFalse = new LoopBlock(LoopBlock.DOWHILE,
LoopBlock.FALSE);
doWhileFalse.setJump(new Jump(succ));
successors.addElement(doWhileFalse.jump);
}
prevBlock.appendBlock
(new BreakBlock(doWhileFalse, breaklevel > 0));
@ -455,7 +454,7 @@ public class FlowBlock {
if (doWhileFalse != null) {
doWhileFalse.replace(appendBlock, appendBlock);
doWhileFalse.setBody(appendBlock);
doWhileFalse.removeJump();
doWhileFalse.jump = null;
}
/* Now remove the jump of the appendBlock if it points to
@ -757,6 +756,13 @@ public class FlowBlock {
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);
}
@ -1110,6 +1116,11 @@ public class FlowBlock {
/* the Block has no successor where t1 is applicable.
* Finish this analyzation.
*/
if (Decompiler.isFlowDebugging) {
writer.println("No more successors applicable: "
+ start + " - " + end + "; "
+ addr + " - " + (addr+length));
}
return changed;
} else {
/* Only do T1 transformation if the blocks are
@ -1190,8 +1201,15 @@ public class FlowBlock {
return changed;
else if (next.addr >= start) {
/* First analyze the next block. */
changed = next.analyze(next.addr, end) || changed;
/* First analyze the next block. It may
* 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
* and this case as predecessor. Otherwise
@ -1227,9 +1245,7 @@ public class FlowBlock {
lastBlock = resolveRemaining(next, lastBlock);
}
/* Set addr+length to (semi-)correct value */
if (next.addr < addr)
addr = next.addr;
/* Set length to correct value */
length += next.length;
lastBlock = next.block;

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

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

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

@ -42,7 +42,7 @@ import jode.TabbedPrintWriter;
public class RawTryCatchBlock extends StructuredBlock {
public RawTryCatchBlock(sun.tools.java.Type type,
public RawTryCatchBlock(jode.Type type,
StructuredBlock tryBlock,
Jump endDest, Jump catchDest) {
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
* synchronized/finally block
*/
sun.tools.java.Type type;
jode.Type type;
/**
* Replaces the given sub block with a new block.

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

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

@ -150,6 +150,13 @@ public abstract class StructuredBlock {
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.
* @param subBlock the sub block.
@ -441,8 +448,8 @@ public abstract class StructuredBlock {
public void dumpDeclaration(jode.TabbedPrintWriter writer, LocalInfo local)
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) {
super.setInstruction(instr);
sun.tools.java.Type type = instr.getType();
jode.Type type = instr.getType();
if (type != caseBlocks[0].type) {
for (int i=0; i < caseBlocks.length; i++)
caseBlocks[i].type = type;

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