Initial revision

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@2 379699f6-c40d-0410-875b-85095c16579e
stable
delwi 26 years ago
parent 1be1aaff37
commit 55a5ea33d9
  1. 18
      jode/Block.java
  2. 10
      jode/jode/AssertError.java
  3. 12
      jode/jode/Decompiler.java
  4. 225
      jode/jode/bytecode/Opcodes.java
  5. 6
      jode/jode/decompiler/Analyzer.java
  6. 75
      jode/jode/decompiler/ClassAnalyzer.java
  7. 1016
      jode/jode/decompiler/CodeAnalyzer.java
  8. 37
      jode/jode/decompiler/FieldAnalyzer.java
  9. 96
      jode/jode/decompiler/ImportHandler.java
  10. 15
      jode/jode/decompiler/LocalInfo.java
  11. 10
      jode/jode/decompiler/LocalVariable.java
  12. 44
      jode/jode/decompiler/LocalVariableHash.java
  13. 82
      jode/jode/decompiler/LocalVariableRangeList.java
  14. 55
      jode/jode/decompiler/LocalVariableTable.java
  15. 135
      jode/jode/decompiler/MethodAnalyzer.java
  16. 42
      jode/jode/decompiler/TabbedPrintWriter.java
  17. 36
      jode/jode/expr/ArrayLengthOperator.java
  18. 46
      jode/jode/expr/ArrayLoadOperator.java
  19. 57
      jode/jode/expr/ArrayStoreOperator.java
  20. 46
      jode/jode/expr/AssignOperator.java
  21. 72
      jode/jode/expr/BinaryOperator.java
  22. 21
      jode/jode/expr/CheckCastOperator.java
  23. 38
      jode/jode/expr/CompareBinaryOperator.java
  24. 27
      jode/jode/expr/CompareToIntOperator.java
  25. 39
      jode/jode/expr/CompareUnaryOperator.java
  26. 55
      jode/jode/expr/ConstOperator.java
  27. 45
      jode/jode/expr/ConstructorOperator.java
  28. 36
      jode/jode/expr/ConvertOperator.java
  29. 25
      jode/jode/expr/DupOperator.java
  30. 128
      jode/jode/expr/Expression.java
  31. 56
      jode/jode/expr/GetFieldOperator.java
  32. 40
      jode/jode/expr/GotoOperator.java
  33. 39
      jode/jode/expr/IfGotoOperator.java
  34. 55
      jode/jode/expr/IfThenElseOperator.java
  35. 27
      jode/jode/expr/InstanceOfOperator.java
  36. 34
      jode/jode/expr/Instruction.java
  37. 110
      jode/jode/expr/InvokeOperator.java
  38. 16
      jode/jode/expr/JsrOperator.java
  39. 12
      jode/jode/expr/JumpInstruction.java
  40. 25
      jode/jode/expr/LoadOperator.java
  41. 21
      jode/jode/expr/MonitorEnterOperator.java
  42. 25
      jode/jode/expr/MonitorExitOperator.java
  43. 37
      jode/jode/expr/NewArrayOperator.java
  44. 20
      jode/jode/expr/NewConstructorOperator.java
  45. 17
      jode/jode/expr/NewOperator.java
  46. 26
      jode/jode/expr/NoArgOperator.java
  47. 13
      jode/jode/expr/NopOperator.java
  48. 111
      jode/jode/expr/Operator.java
  49. 24
      jode/jode/expr/PopOperator.java
  50. 34
      jode/jode/expr/PostFixOperator.java
  51. 62
      jode/jode/expr/PutFieldOperator.java
  52. 20
      jode/jode/expr/RetOperator.java
  53. 29
      jode/jode/expr/ReturnOperator.java
  54. 23
      jode/jode/expr/ShiftOperator.java
  55. 31
      jode/jode/expr/SimpleOperator.java
  56. 80
      jode/jode/expr/StoreInstruction.java
  57. 46
      jode/jode/expr/StoreOperator.java
  58. 13
      jode/jode/expr/SwapOperator.java
  59. 70
      jode/jode/expr/SwitchOperator.java
  60. 13
      jode/jode/expr/ThrowOperator.java
  61. 34
      jode/jode/expr/UnaryOperator.java
  62. 22
      jode/jode/type/UnknownSubType.java
  63. 204
      jode/jode/type/UnknownType.java

@ -0,0 +1,18 @@
package jode;
public class Block extends Instruction {
Expression[] exprs;
public Block(int addr, int length, Expression[] exprs) {
super(addr,length);
this.exprs = exprs;
}
public void dumpSource(TabbedPrintWriter writer, CodeAnalyzer ca)
throws java.io.IOException
{
for (int i=0; i< exprs.length; i++)
exprs[i].dumpSource(writer,ca);
}
}

@ -0,0 +1,10 @@
package jode;
public class AssertError extends Error {
public AssertError() {
}
public AssertError(String detail) {
super(detail);
}
}

@ -0,0 +1,12 @@
package jode;
import sun.tools.java.*;
import java.lang.reflect.Modifier;
public class Decompiler {
public static void main(String[] params) {
JodeEnvironment env = new JodeEnvironment();
for (int i=0; i<params.length; i++) {
env.doClass(params[i]);
}
}
}

@ -0,0 +1,225 @@
package jode;
import java.io.*;
import sun.tools.java.Type;
public interface Opcodes {
public final static int NOP_OP = 0;
public final static int ACONST_NULL_OP = 1;
public final static int ICONST_M1_OP = 2;
public final static int ICONST_0_OP = 3;
public final static int ICONST_1_OP = 4;
public final static int ICONST_2_OP = 5;
public final static int ICONST_3_OP = 6;
public final static int ICONST_4_OP = 7;
public final static int ICONST_5_OP = 8;
public final static int LCONST_0_OP = 9;
public final static int LCONST_1_OP = 10;
public final static int FCONST_0_OP = 11;
public final static int FCONST_1_OP = 12;
public final static int FCONST_2_OP = 13;
public final static int DCONST_0_OP = 14;
public final static int DCONST_1_OP = 15;
public final static int BIPUSH_OP = 16;
public final static int SIPUSH_OP = 17;
public final static int LDC_OP = 18;
public final static int LDC_W_OP = 19;
public final static int LDC2_W_OP = 20;
public final static int ILOAD_OP = 21;
public final static int LLOAD_OP = 22;
public final static int FLOAD_OP = 23;
public final static int DLOAD_OP = 24;
public final static int ALOAD_OP = 25;
public final static int ILOAD_0_OP = 26;
public final static int ILOAD_1_OP = 27;
public final static int ILOAD_2_OP = 28;
public final static int ILOAD_3_OP = 29;
public final static int LLOAD_0_OP = 30;
public final static int LLOAD_1_OP = 31;
public final static int LLOAD_2_OP = 32;
public final static int LLOAD_3_OP = 33;
public final static int FLOAD_0_OP = 34;
public final static int FLOAD_1_OP = 35;
public final static int FLOAD_2_OP = 36;
public final static int FLOAD_3_OP = 37;
public final static int DLOAD_0_OP = 38;
public final static int DLOAD_1_OP = 39;
public final static int DLOAD_2_OP = 40;
public final static int DLOAD_3_OP = 41;
public final static int ALOAD_0_OP = 42;
public final static int ALOAD_1_OP = 43;
public final static int ALOAD_2_OP = 44;
public final static int ALOAD_3_OP = 45;
public final static int IALOAD_OP = 46;
public final static int LALOAD_OP = 47;
public final static int FALOAD_OP = 48;
public final static int DALOAD_OP = 49;
public final static int AALOAD_OP = 50;
public final static int BALOAD_OP = 51;
public final static int CALOAD_OP = 52;
public final static int SALOAD_OP = 53;
public final static int ISTORE_OP = 54;
public final static int LSTORE_OP = 55;
public final static int FSTORE_OP = 56;
public final static int DSTORE_OP = 57;
public final static int ASTORE_OP = 58;
public final static int ISTORE_0_OP = 59;
public final static int ISTORE_1_OP = 60;
public final static int ISTORE_2_OP = 61;
public final static int ISTORE_3_OP = 62;
public final static int LSTORE_0_OP = 63;
public final static int LSTORE_1_OP = 64;
public final static int LSTORE_2_OP = 65;
public final static int LSTORE_3_OP = 66;
public final static int FSTORE_0_OP = 67;
public final static int FSTORE_1_OP = 68;
public final static int FSTORE_2_OP = 69;
public final static int FSTORE_3_OP = 70;
public final static int DSTORE_0_OP = 71;
public final static int DSTORE_1_OP = 72;
public final static int DSTORE_2_OP = 73;
public final static int DSTORE_3_OP = 74;
public final static int ASTORE_0_OP = 75;
public final static int ASTORE_1_OP = 76;
public final static int ASTORE_2_OP = 77;
public final static int ASTORE_3_OP = 78;
public final static int IASTORE_OP = 79;
public final static int LASTORE_OP = 80;
public final static int FASTORE_OP = 81;
public final static int DASTORE_OP = 82;
public final static int AASTORE_OP = 83;
public final static int BASTORE_OP = 84;
public final static int CASTORE_OP = 85;
public final static int SASTORE_OP = 86;
public final static int POP_OP = 87;
public final static int POP2_OP = 88;
public final static int DUP_OP = 89;
public final static int DUP_X1_OP = 90;
public final static int DUP_X2_OP = 91;
public final static int DUP2_OP = 92;
public final static int DUP2_X1_OP = 93;
public final static int DUP2_X2_OP = 94;
public final static int SWAP_OP = 95;
public final static int IADD_OP = 96;
public final static int LADD_OP = 97;
public final static int FADD_OP = 98;
public final static int DADD_OP = 99;
public final static int ISUB_OP = 100;
public final static int LSUB_OP = 101;
public final static int FSUB_OP = 102;
public final static int DSUB_OP = 103;
public final static int IMUL_OP = 104;
public final static int LMUL_OP = 105;
public final static int FMUL_OP = 106;
public final static int DMUL_OP = 107;
public final static int IDIV_OP = 108;
public final static int LDIV_OP = 109;
public final static int FDIV_OP = 110;
public final static int DDIV_OP = 111;
public final static int IREM_OP = 112;
public final static int LREM_OP = 113;
public final static int FREM_OP = 114;
public final static int DREM_OP = 115;
public final static int INEG_OP = 116;
public final static int LNEG_OP = 117;
public final static int FNEG_OP = 118;
public final static int DNEG_OP = 119;
public final static int ISHL_OP = 120;
public final static int LSHL_OP = 121;
public final static int ISHR_OP = 122;
public final static int LSHR_OP = 123;
public final static int IUSHR_OP = 124;
public final static int LUSHR_OP = 125;
public final static int IAND_OP = 126;
public final static int LAND_OP = 127;
public final static int IOR_OP = 128;
public final static int LOR_OP = 129;
public final static int IXOR_OP = 130;
public final static int LXOR_OP = 131;
public final static int IINC_OP = 132;
public final static int I2L_OP = 133;
public final static int I2F_OP = 134;
public final static int I2D_OP = 135;
public final static int L2I_OP = 136;
public final static int L2F_OP = 137;
public final static int L2D_OP = 138;
public final static int F2I_OP = 139;
public final static int F2L_OP = 140;
public final static int F2D_OP = 141;
public final static int D2I_OP = 142;
public final static int D2L_OP = 143;
public final static int D2F_OP = 144;
public final static int I2B_OP = 145;
public final static int I2C_OP = 146;
public final static int I2S_OP = 147;
public final static int LCMP_OP = 148;
public final static int FCMPL_OP = 149;
public final static int FCMPG_OP = 150;
public final static int DCMPL_OP = 151;
public final static int DCMPG_OP = 152;
public final static int IFEQ_OP = 153;
public final static int IFNE_OP = 154;
public final static int IFLT_OP = 155;
public final static int IFGE_OP = 156;
public final static int IFGT_OP = 157;
public final static int IFLE_OP = 158;
public final static int IF_ICMPEQ_OP = 159;
public final static int IF_ICMPNE_OP = 160;
public final static int IF_ICMPLT_OP = 161;
public final static int IF_ICMPGE_OP = 162;
public final static int IF_ICMPGT_OP = 163;
public final static int IF_ICMPLE_OP = 164;
public final static int IF_ACMPEQ_OP = 165;
public final static int IF_ACMPNE_OP = 166;
public final static int GOTO_OP = 167;
public final static int JSR_OP = 168;
public final static int RET_OP = 169;
public final static int TABLESWITCH_OP = 170;
public final static int LOOKUPSWITCH_OP = 171;
public final static int IRETURN_OP = 172;
public final static int LRETURN_OP = 173;
public final static int FRETURN_OP = 174;
public final static int DRETURN_OP = 175;
public final static int ARETURN_OP = 176;
public final static int RETURN_OP = 177;
public final static int GETSTATIC_OP = 178;
public final static int PUTSTATIC_OP = 179;
public final static int GETFIELD_OP = 180;
public final static int PUTFIELD_OP = 181;
public final static int INVOKEVIRTUAL_OP = 182;
public final static int INVOKESPECIAL_OP = 183;
public final static int INVOKESTATIC_OP = 184;
public final static int INVOKEINTERFACE_OP = 185;
public final static int NEW_OP = 187;
public final static int NEWARRAY_OP = 188;
public final static int ANEWARRAY_OP = 189;
public final static int ARRAYLENGTH_OP = 190;
public final static int ATHROW_OP = 191;
public final static int CHECKCAST_OP = 192;
public final static int INSTANCEOF_OP = 193;
public final static int MONITORENTER_OP = 194;
public final static int MONITOREXIT_OP = 195;
public final static int WIDE_OP = 196;
public final static int MULTIANEWARRAY_OP = 197;
public final static int IFNULL_OP = 198;
public final static int IFNONNULL_OP = 199;
public final static int GOTO_W_OP = 200;
public final static int JSR_W_OP = 201;
public final static Type ALL_INT_TYPE = UnknownType.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 = UnknownType.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 types[][] = {
{ ALL_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 }
};
}

@ -0,0 +1,6 @@
package jode;
public interface Analyzer {
public void analyze();
public void dumpSource(TabbedPrintWriter writer) throws java.io.IOException;
}

@ -0,0 +1,75 @@
package jode;
import java.lang.reflect.Modifier;
import java.io.IOException;
import sun.tools.java.*;
public class ClassAnalyzer implements Analyzer {
BinaryClass cdef;
JodeEnvironment env;
Analyzer fields[];
public ClassAnalyzer(BinaryClass bc, JodeEnvironment e)
{
cdef = bc;
env = e;
}
public void analyze() {
int numFields = 0, i=0;
FieldDefinition f;
for (f= cdef.getInnerClassField(); f != null; f = f.getNextField())
numFields++;
for (f= cdef.getFirstField(); f != null; f = f.getNextField())
numFields++;
fields = new Analyzer[numFields];
for (f= cdef.getInnerClassField(); f != null; f = f.getNextField()) {
System.err.println("analyzing inner: "+f.getName());
fields[i] = new ClassAnalyzer((BinaryClass) f.getInnerClass(), env);
fields[i++].analyze();
}
for (f= cdef.getFirstField(); f != null; f = f.getNextField()) {
if (f.getType().getTypeCode() == Constants.TC_METHOD) {
System.err.println("analyzing method: "+f.getName());
fields[i] = new MethodAnalyzer(f, env);
} else {
System.err.println("analyzing field: "+f.getName());
fields[i] = new FieldAnalyzer(f, env);
}
fields[i++].analyze();
}
}
public void dumpSource(TabbedPrintWriter writer) throws IOException
{
if (cdef.getSource() != null)
writer.println("/* Original source: "+cdef.getSource()+" */");
String modif = Modifier.toString(cdef.getModifiers());
if (modif.length() > 0)
writer.print(modif + " ");
writer.print((cdef.isInterface())?"interface ":"class ");
writer.println(env.getNickName(cdef.getName().toString()));
writer.tab();
if (cdef.getSuperClass() != null)
writer.println("extends "+cdef.getSuperClass().getName().toString());
ClassDeclaration interfaces[] = cdef.getInterfaces();
if (interfaces.length > 0) {
writer.print("implements ");
for (int i=0; i < interfaces.length; i++) {
if (i > 0)
writer.print(", ");
writer.print(interfaces[i].getName().toString());
}
}
writer.untab();
writer.println(" {");
writer.tab();
for (int i=0; i< fields.length; i++)
fields[i].dumpSource(writer);
writer.untab();
writer.println("}");
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,37 @@
package jode;
import sun.tools.java.*;
import java.lang.reflect.Modifier;
public class FieldAnalyzer implements Analyzer {
FieldDefinition fdef;
JodeEnvironment env;
public FieldAnalyzer(FieldDefinition fd, JodeEnvironment e)
{
fdef = fd;
env = e;
}
public void analyze() {
}
public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException
{
String modif = Modifier.toString(fdef.getModifiers());
if (modif.length() > 0)
writer.print(modif+" ");
writer.println(fdef.getType().
typeString(fdef.getName().toString(), false, false)+";");
// writer.tab();
// if (attributes.length > 0) {
// writer.println("/* Attributes: "+attributes.length+" */");
// for (int i=0; i < attributes.length; i++)
// attributes[i].dumpSource(writer);
// }
// writer.untab();
}
}

@ -0,0 +1,96 @@
package jode;
import sun.tools.java.*;
import sun.tools.util.*;
import java.util.*;
public class JodeEnvironment extends LoadEnvironment {
Hashtable imports = new Hashtable();
BinaryClass main;
Identifier pkg;
boolean isVerbose = true;
JodeEnvironment() {
super(null);
path = new ClassPath(System.getProperty("java.class.path"));
}
public BinaryConstantPool getConstantPool() {
return main.getConstants();
}
public Object getConstant(int i) {
return main.getConstants().getConstant(i, this);
}
public Type getConstantType(int i)
throws ClassFormatError
{
int t = main.getConstants().getConstantType(i);
switch(t) {
case 3: return Type.tInt ;
case 4: return Type.tFloat ;
case 5: return Type.tLong ;
case 6: return Type.tDouble;
case 8: return Type.tString;
default:
throw new ClassFormatError("invalid constant type: "+t);
}
}
public String getNickName(String string) {
return string;
}
public ClassDefinition getClassDefinition() {
return main;
}
public void dumpHeader(TabbedPrintWriter writer)
throws java.io.IOException
{
writer.println("/* Decompiled by JoDe (Jochen's Decompiler) */");
if (pkg != null && pkg != Constants.idNull)
writer.println("package "+pkg+";");
Enumeration enum = imports.keys();
while (enum.hasMoreElements()) {
Identifier packageName = (Identifier) enum.nextElement();
Integer vote = (Integer) imports.get(packageName);
if (vote.intValue() > 3)
writer.println("import "+packageName+";");
}
writer.println("");
}
public void error(String message) {
System.err.println(message);
}
public void doClass(String className)
{
try {
Identifier ident = Identifier.lookup(className);
error(ident.toString());
if (!classExists(ident)) {
error("`"+ident+"' not found");
return;
}
pkg = ident.getQualifier();
main = (BinaryClass)getClassDefinition(ident);
ClassAnalyzer a = new ClassAnalyzer(main, this);
a.analyze();
TabbedPrintWriter writer =
new TabbedPrintWriter(System.out, " ");
a.dumpSource(writer);
} catch (ClassNotFound e) {
error(e.toString());
} catch (java.io.IOException e) {
error(e.toString());
}
}
protected int loadFileFlags()
{
return 1;
}
}

@ -0,0 +1,15 @@
package jode;
import sun.tools.java.*;
public class LocalInfo {
static int serialnr = 0;
Identifier name;
Type type;
public LocalInfo() {
name = Identifier.lookup("__"+serialnr);
type = Type.tUnknown;
serialnr++;
}
}

@ -0,0 +1,10 @@
package jode;
import sun.tools.java.Type;
import sun.tools.java.Identifier;
public interface LocalVariable {
public Identifier getName(int addr);
public Type getType(int addr);
public Type setType(int addr, Type type);
public void combine(int addr1, int addr2);
}

@ -0,0 +1,44 @@
package jode;
import sun.tools.java.Type;
import sun.tools.java.Identifier;
public class LocalVariableHash implements LocalVariable {
Hashtable locals;
private find(int addr) {
LocalInfo li = (LocalInfo) locals.get(new Integer(addr));
if (li == null) {
li = new LocalInfo();
locals.put(new Integer(addr), li);
}
return li;
}
public Identifier getName(int addr) {
LocalInfo li = find(addr);
return li.name;
}
public Type getType(int addr) {
LocalInfo li = find(addr);
return li.type;
}
public Type setType(int addr, Type type) {
LocalInfo li = find(addr);
li.type = UnknownType.commonType(li.type, type);
return li.type;
}
public void combine(int addr1, int addr2) {
LocalInfo li1 = find(addr1);
LocalInfo li2 = find(addr2);
li1.type = UnknownType.commonType(li1.type, li2.type);
Enumeration keys = locals.keys();
while (keys.hasMoreElements()) {
Object key = keys.nextElement();
if (locals.get(key) == li2)
locals.put(key, li1);
}
}
}

@ -0,0 +1,82 @@
package jode;
import sun.tools.java.*;
public class LocalVariableRangeList implements LocalVariable {
class MyLocalInfo extends LocalInfo {
int start;
int length;
MyLocalInfo next;
MyLocalInfo(int s, int l, Identifier n, Type t) {
start = s;
length = l;
name = n;
type = t;
next = null;
}
}
MyLocalInfo list = null;
int slot;
LocalVariableRangeList(int slot) {
this.slot = slot;
}
private void add(MyLocalInfo li) {
MyLocalInfo before = null;
MyLocalInfo after = list;
while (after != null && after.start < li.start) {
before = after;
after = after.next;
}
if (after != null && li.start + li.length > after.start)
throw new AssertError("non disjoint locals");
li.next = after;
if (before == null)
list = li;
else
before.next = li;
}
private LocalInfo find(int addr) {
MyLocalInfo li = list;
while (li != null && addr > li.start+li.length)
li = li.next;
if (li == null || li.start > addr) {
LocalInfo temp =new LocalInfo();
return temp;
}
return li;
}
public void addLocal(int start, int length,
Identifier name, Type type) {
MyLocalInfo li = new MyLocalInfo(start,length,name,type);
add (li);
}
public Identifier getName(int addr) {
LocalInfo li = find(addr);
return li.name;
}
public Type getType(int addr) {
LocalInfo li = find(addr);
return li.type;
}
public LocalInfo getInfo(int addr) {
return find(addr);
}
public Type setType(int addr, Type newType) {
LocalInfo li = find(addr);
return commonType(newType, li.type);
}
public void combine(int addr1, int addr2) {
throw AssertError("combine called on RangeList");
}
}

@ -0,0 +1,55 @@
package jode;
import sun.tools.java.*;
import java.io.*;
import java.util.Vector;
public class LocalVariableTable {
Vector locals;
boolean readfromclass;
public LocalVariableTable(int size) {
locals = new Vector();
locals.setSize(size);
readfromclass = false;
}
public boolean isReadFromClass() {
return readfromclass;
}
public void read(JodeEnvironment env, DataInputStream stream)
throws IOException
{
int count = stream.readUnsignedShort();
for (int i=0; i<count; i++) {
int start = stream.readUnsignedShort();
int length = stream.readUnsignedShort();
int name_i = stream.readUnsignedShort();
int desc_i = stream.readUnsignedShort();
int slot = stream.readUnsignedShort();
LocalVariableRangeList lv =
(LocalVariableRangeList)locals.elementAt(slot);
if (lv == null) {
lv = new LocalVariableRangeList(slot);
locals.setElementAt(lv, slot);
}
lv.addLocal(start, length,
Identifier.lookup((String)
env.getConstantPool().
getValue(name_i)),
env.getConstantPool().getType(desc_i));
}
readfromclass = true;
}
public LocalVariable getLocal(int slot)
throws ArrayOutOfBoundsException
{
LocalVariable lv = (LocalVariable)locals.elementAt(slot);
if (lv == null) {
lv = new LocalVariable(slot);
locals.setElementAt(lv, slot);
}
return lv;
}
}

@ -0,0 +1,135 @@
package jode;
import sun.tools.java.*;
import java.lang.reflect.Modifier;
import java.io.*;
public class MethodAnalyzer implements Analyzer, Constants {
FieldDefinition mdef;
JodeEnvironment env;
CodeAnalyzer code = null;
LocalVariableTable lvt;
public MethodAnalyzer(FieldDefinition fd, JodeEnvironment e)
{
mdef = fd;
env = e;
byte bytecode[] = ((BinaryField) mdef).getAttribute(Constants.idCode);
if (bytecode != null) {
BinaryCode bc =
new BinaryCode(bytecode,
env.getConstantPool(),
env);
lvt = new LocalVariableTable(bc.getMaxLocals());
readLVT(bc);
code = new CodeAnalyzer(this, bc, env);
}
}
public void readLVT(BinaryCode bc) {
BinaryAttribute attr = bc.getAttributes();
while (attr != null) {
if (attr.getName() == idLocalVariableTable) {
DataInputStream stream =
new DataInputStream
(new ByteArrayInputStream(attr.getData()));
try {
lvt.read(env, stream);
} catch (IOException ex) {
throw new ClassFormatError(ex.toString());
}
}
attr = attr.getNextAttribute();
}
if (!lvt.isReadFromClass()) {
int offset = 0;
if (!mdef.isStatic()) {
LocalInfo li = lvt.getLocal(0);
li.name = "this";
li.type = mdef.getClassDefinition().getType();
offset++;
}
Type[] paramTypes = mdef.getType().getArgumentTypes();
for (int i=0; i< paramTypes.length; i++) {
LocalInfo li = lvt.getLocal(offset+i);
li.type = paramTypes[i];
}
}
}
public void analyze()
throws ClassFormatError
{
code.analyze();
}
public LocalVariable getLocal(int i) {
return lvt.getLocal(i);
}
public Identifier getLocalName(int i, int addr) {
Identifier name = lvt.getLocal(i).getName(addr);
if (name != null)
return name;
if (!mdef.isStatic() && i == 0)
return idThis;
return Identifier.lookup("local_"+i+"@"+addr);
}
public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException
{
writer.println("");
String modif = Modifier.toString(mdef.getModifiers());
if (modif.length() > 0)
writer.print(modif+" ");
if (mdef.isInitializer()) {
writer.print(""); /* static block */
} else {
if (mdef.isConstructor())
writer.print(mdef.getClassDeclaration().getName().toString());
else
writer.print(mdef.getType().getReturnType().toString()+" "+
mdef.getName().toString());
writer.print("(");
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(paramTypes[i].
typeString(getLocalName(i+offset, 0).toString(),
false, false));
}
writer.print(")");
}
IdentifierToken[] exceptions = mdef.getExceptionIds();
if (exceptions != null && exceptions.length > 0) {
writer.println("");
writer.print("throws ");
for (int i= 0; i< exceptions.length; i++) {
if (exceptions[i] != null) {
if (i > 0)
writer.print(", ");
writer.print(exceptions[i].getName().toString());
}
}
}
if (code != null) {
writer.println(" {");
writer.tab();
code.dumpSource(writer);
writer.untab();
writer.println("}");
} else
writer.println(";");
}
/*
public byte[] getAttribute(Identifier identifier)
{
if (mdef instanceof BinaryField)
return ((BinaryField)mdef).getAttribute(identifier);
return null;
}
*/
}

@ -0,0 +1,42 @@
package jode;
import java.io.*;
public class TabbedPrintWriter {
boolean atbol;
String tabstr;
StringBuffer indent;
PrintWriter pw;
int verbosity=100;
public TabbedPrintWriter (OutputStream os, String tabstr) {
pw = new PrintWriter(os);
this.tabstr=tabstr;
indent = new StringBuffer();
atbol = true;
}
public void tab() {
indent.append(tabstr);
}
public void untab() {
indent.setLength(indent.length()-tabstr.length());
}
public void println(String str) throws java.io.IOException {
if (atbol) {
pw.print(indent);
}
pw.println(str);
pw.flush();
atbol = true;
}
public void print(String str) throws java.io.IOException {
if (atbol) {
pw.print(indent);
}
pw.print(str);
atbol = false;
}
}

@ -0,0 +1,36 @@
package jode;
import sun.tools.java.*;
public class ArrayLengthOperator extends Operator {
Type arrayType;
public ArrayLengthOperator(int addr, int length) {
super(addr,length, Type.tInt, 0);
arrayType = Type.tArray(UnknownType.tUnknown);
}
public int getPriority() {
return 950;
}
public int getOperandCount() {
return 1;
}
public int getOperandPriority(int i) {
return 900;
}
public Type getOperandType(int i) {
return arrayType;
}
public void setOperandType(Type[] types) {
arrayType = UnknownType.commonType(arrayType,types[0]);
}
public String toString(CodeAnalyzer ca, String[] operands) {
return operands[0] + ".length";
}
}

@ -0,0 +1,46 @@
package jode;
import sun.tools.java.Type;
import sun.tools.java.ArrayType;
public class ArrayLoadOperator extends SimpleOperator {
String value;
public ArrayLoadOperator(int addr, int length, Type type) {
super(addr,length, type, 0, 2);
operandTypes[0] = Type.tArray(type);
operandTypes[1] = UnknownType.tUIndex;
}
public int getPriority() {
return 950;
}
public int getOperandPriority(int i) {
return (i==0)?950:0;
}
/**
* Sets the return type of this operator.
* @return true if the operand types changed
*/
public boolean setType(Type type) {
if (type != this.type) {
super.setType(type);
operandTypes[0] = Type.tArray(type);
return true;
}
return false;
}
public void setOperandType(Type[] t) {
super.setOperandType(t);
if (operandTypes[0] instanceof ArrayType)
type = operandTypes[0].getElementType();
else
type = Type.tError;
}
public String toString(CodeAnalyzer ca, String[] operands) {
return operands[0]+"["+operands[1]+"]";
}
}

@ -0,0 +1,57 @@
package jode;
import sun.tools.java.Type;
import sun.tools.java.ArrayType;
public class ArrayStoreOperator extends StoreInstruction {
Type indexType;
public ArrayStoreOperator(int addr, int length, Type type) {
super(addr,length, type);
indexType = UnknownType.tUIndex;
}
public ArrayStoreOperator(int addr, int length, Type type, int operator) {
super(addr,length, type, operator);
indexType = UnknownType.tUIndex;
}
public boolean matches(Operator loadop) {
return loadop instanceof ArrayLoadOperator;
}
public int getLValueOperandCount() {
return 2;
}
public int getLValueOperandPriority(int i) {
if (i == 0)
return 950;
else
return 0;
}
public Type getLValueOperandType(int i) {
if (i == 0)
return Type.tArray(lvalueType);
else
return indexType;
}
public void setLValueOperandType(Type[] t) {
indexType = UnknownType.commonType(indexType, t[1]);
Type arraytype =
UnknownType.commonType(t[0], Type.tArray(lvalueType));
System.err.println("lvot: "+t[0]+","+Type.tArray(lvalueType)+
" -> "+arraytype);
if (arraytype instanceof ArrayType)
lvalueType = arraytype.getElementType();
else {
System.err.println("no array: "+arraytype);
lvalueType = Type.tError;
}
}
public String getLValueString(CodeAnalyzer ca, String[] operands) {
return operands[0]+"["+operands[1]+"]";
}
}

@ -0,0 +1,46 @@
package jode;
import sun.tools.java.Type;
public class AssignOperator extends BinaryOperator {
StoreInstruction store;
public AssignOperator(int addr, int length, int op,
StoreInstruction store) {
super(addr,length, store.getLValueType(), op);
this.store = store;
}
public int getOperandCount() {
return store.getOperandCount();
}
public int getOperandPriority(int i) {
return store.getOperandPriority(i);
}
public Type getOperandType(int i) {
return store.getOperandType(i);
}
/**
* Sets the return type of this operator.
* @return true if the operand types changed
*/
public boolean setType(Type type) {
boolean result = store.setLValueType(type);
super.setType(store.getLValueType());
return result;
}
/**
* Overload this method if the resulting type depends on the input types
*/
public void setOperandType(Type[] inputTypes) {
store.setOperandType(inputTypes);
this.type = store.getLValueType();
}
public String toString(CodeAnalyzer ca, String[] operands) {
return store.toString(ca, operands);
}
}

@ -0,0 +1,72 @@
package jode;
import sun.tools.java.Type;
public class BinaryOperator extends Operator {
protected Type operandType;
public BinaryOperator(int addr, int length, Type type, int op) {
super(addr,length, type, op);
operandType = type;
}
public int getOperandCount() {
return 2;
}
public int getPriority() {
switch (operator) {
case 1: case 2:
return 610;
case 3: case 4: case 5:
return 650;
case 6: case 7: case 8:
return 600;
case 9:
return 450;
case 10:
return 410;
case 11:
return 420;
case 12: case 13: case 14: case 15: case 16: case 17:
case 18: case 19: case 20: case 21: case 22: case 23:
return 100;
case LOG_OR_OP:
return 310;
case LOG_AND_OP:
return 350;
}
throw new RuntimeException("Illegal operator");
}
public int getOperandPriority(int i) {
return getPriority() + i;
}
public Type getOperandType(int i) {
return operandType;
}
public void setOperandType(Type[] inputTypes) {
operandType = UnknownType.commonType
(operandType, UnknownType.commonType(inputTypes[0],
inputTypes[1]));
type = operandType;
}
/**
* Sets the return type of this operator.
* @return true if the operand types changed
*/
public boolean setType(Type newType) {
operandType = UnknownType.commonType(operandType, newType);
if (type != operandType) {
type = operandType;
return true;
}
return false;
}
public String toString(CodeAnalyzer ca, String[] operands) {
return operands[0] + " "+getOperatorString()+" "+ operands[1];
}
}

@ -0,0 +1,21 @@
package jode;
import sun.tools.java.Type;
public class CheckCastOperator extends SimpleOperator {
public CheckCastOperator(int addr, int length, Type type) {
super(addr,length, type, 0, 1);
operandTypes[0] = UnknownType.tSubClass(type);
}
public int getPriority() {
return 700;
}
public int getOperandPriority(int i) {
return getPriority();
}
public String toString(CodeAnalyzer ca, String[] operands) {
return "("+ca.getTypeString(type) + ")" + operands[0];
}
}

@ -0,0 +1,38 @@
package jode;
import sun.tools.java.Type;
public class CompareBinaryOperator extends SimpleOperator {
public CompareBinaryOperator(int addr, int length, Type type, int op) {
super(addr,length, Type.tBoolean, op, 2);
operandTypes[0] = operandTypes[1] = type;
}
public int getPriority() {
switch (getOperator()) {
case 26:
case 27:
return 500;
case 28:
case 29:
case 30:
case 31:
return 550;
}
throw new RuntimeException("Illegal operator");
}
public int getOperandPriority(int i) {
return getPriority()+i;
}
public void setOperandType(Type[] inputTypes) {
super.setOperandType(inputTypes);
Type operandType =
UnknownType.commonType(operandTypes[0],operandTypes[1]);
operandTypes[0] = operandTypes[1] = operandType;
}
public String toString(CodeAnalyzer ca, String[] operands) {
return operands[0] + " "+opString[operator]+" "+operands[1];
}
}

@ -0,0 +1,27 @@
package jode;
import sun.tools.java.Type;
public class CompareToIntOperator extends BinaryOperator {
public CompareToIntOperator(int addr, int length, Type type, int op) {
super(addr,length, Type.tInt, op);
operandType = type;
}
public int getPriority() {
switch (getOperator()) {
case 25:
case 26:
return 500;
case 27:
case 28:
case 29:
case 30:
return 550;
}
throw new RuntimeException("Illegal operator");
}
public String toString(CodeAnalyzer ca, String[] operands) {
return operands[0] + " "+opString[operator]+" "+operands[1];
}
}

@ -0,0 +1,39 @@
package jode;
import sun.tools.java.Type;
public class CompareUnaryOperator extends SimpleOperator {
public CompareUnaryOperator(int addr, int length, Type type, int op) {
super(addr,length, Type.tBoolean, op, 1);
operandTypes[0] = type;
}
public int getPriority() {
switch (getOperator()) {
case 26:
case 27:
return 500;
case 28:
case 29:
case 30:
case 31:
return 550;
}
throw new RuntimeException("Illegal operator");
}
public int getOperandPriority(int i) {
return getPriority();
}
public String toString(CodeAnalyzer ca, String[] operands) {
if (operandTypes[0] == Type.tBoolean) {
if (operator == 26) /* xx == false */
return "! ("+operands[0]+")"; /*XXX Make operators */
else if (operator == 27) /* xx != false */
return operands[0];
}
return operands[0] + " "+opString[operator]+" "+
(UnknownType.isOfType(operandTypes[0],
UnknownType.tObject)?"null":"0");
}
}

@ -0,0 +1,55 @@
package jode;
import sun.tools.java.Type;
public class ConstOperator extends NoArgOperator {
String value;
public ConstOperator(int addr, int length, Type type, String value) {
super(addr, length, type);
this.value = value;
}
public String getValue() {
return value;
}
public int getPriority() {
return 1000;
}
public String quoted(String str) {
StringBuffer result = new StringBuffer("\"");
for (int i=0; i< value.length(); i++) {
switch (value.charAt(i)) {
case '\t':
result.append("\\t");
break;
case '\n':
result.append("\\n");
break;
case '\\':
result.append("\\\\");
break;
case '\"':
result.append("\\\"");
break;
default:
result.append(value.charAt(i));
}
}
return result.append("\"").toString();
}
public String toString(CodeAnalyzer ca, String[] operands) {
if (type == Type.tString)
return quoted(value);
if (type == Type.tBoolean) {
if (value.equals("0"))
return "false";
else if (value.equals("1"))
return "true";
}
return value;
}
}

@ -0,0 +1,45 @@
package jode;
import sun.tools.java.*;
public class ConstructorOperator extends Operator {
FieldDefinition field;
public ConstructorOperator(int addr, int length, Type type,
FieldDefinition field) {
super(addr,length, type, 0);
this.field = field;
}
public int getPriority() {
return 950;
}
public int getOperandCount() {
return 1 + field.getType().getArgumentTypes().length;
}
public int getOperandPriority(int i) {
if (i == 0)
return 950;
return 0;
}
public Type getOperandType(int i) {
if (i == 0)
return type;
return field.getType().getArgumentTypes()[i-1];
}
public void setOperandType(Type types[]) {
}
public String toString(CodeAnalyzer ca, String[] operands) {
StringBuffer result = new StringBuffer(operands[0]).append("(");
for (int i=0; i < field.getType().getArgumentTypes().length; i++) {
if (i>0)
result.append(", ");
result.append(operands[i+1]);
}
return result.append(")").toString();
}
}

@ -0,0 +1,36 @@
package jode;
import sun.tools.java.Type;
public class ConvertOperator extends Operator {
Type from;
public ConvertOperator(int addr, int length, Type from, Type to) {
super(addr,length, to, 0);
this.from = from;
}
public int getPriority() {
return 700;
}
public int getOperandPriority(int i) {
return 700;
}
public int getOperandCount() {
return 1;
}
public Type getOperandType(int i) {
return from;
}
public void setOperandType(Type[] inputTypes) {
from = UnknownType.commonType(from, inputTypes[0]);
}
public String toString(CodeAnalyzer ca, String[] operands)
{
return "("+ca.getTypeString(type)+") "+operands[0];
}
}

@ -0,0 +1,25 @@
package jode;
public class DupOperator extends Instruction {
int count, depth;
public DupOperator(int a, int l, int depth, int count) {
super(a,l);
this.count = count;
this.depth = depth;
}
public int getCount(){
return count;
}
public int getDepth(){
return depth;
}
public void dumpSource(TabbedPrintWriter tpw, CodeAnalyzer ca)
throws java.io.IOException
{
tpw.println("dup"+count+"_x"+depth+";");
}
}

@ -0,0 +1,128 @@
package jode;
import sun.tools.java.Type;
public class Expression extends Instruction {
Operator operator;
Expression[] subExpressions;
protected Expression(int addr, int length) {
super(addr, length);
}
public Expression(int addr, int length, Operator op, Expression[] sub) {
super(addr, length);
operator = op;
subExpressions = sub;
if (op.getOperandCount() > 0) {
Type types[] = new Type[subExpressions.length];
for (int i=0; i < types.length; i++) {
types[i] = subExpressions[i].getType();
}
operator.setOperandType(types);
updateSubTypes();
}
}
public Expression negate() {
if (operator.operator >= operator.COMPARE_OP &&
operator.operator < operator.COMPARE_OP+6) {
operator.setOperator(operator.getOperator() ^ 1);
return this;
} else if (operator.operator == operator.LOG_AND_OP ||
operator.operator == operator.LOG_OR_OP) {
operator.setOperator(operator.getOperator() ^ 1);
for (int i=0; i< subExpressions.length; i++) {
subExpressions[i] = subExpressions[i].negate();
}
return this;
} else if (operator.operator == operator.LOG_NOT_OP) {
return subExpressions[0];
}
Operator negop =
new UnaryOperator(getAddr(), getLength(),
Type.tBoolean, Operator.LOG_NOT_OP);
Expression[] e = { this };
return new Expression(getAddr(), getLength(), negop, e);
}
public Operator getOperator() {
return operator;
}
public Expression[] getSubExpressions() {
return subExpressions;
}
public Type getType() {
return operator.getType();
}
public void updateSubTypes() {
for (int i=0; i < subExpressions.length; i++) {
subExpressions[i].setType(operator.getOperandType(i));
}
}
public void setType(Type type) {
if (operator.setType(type))
updateSubTypes();
}
public int[] getSuccessors() {
return operator.getSuccessors();
}
public boolean isVoid() {
return operator.getType() == Type.tVoid;
}
String toString(CodeAnalyzer ca, int minPriority) {
String[] expr = new String[subExpressions.length];
for (int i=0; i<subExpressions.length; i++) {
expr[i] = subExpressions[i].
toString(ca, operator.getOperandPriority(i));
}
String result = operator.toString(ca, expr);
if (operator.getPriority() < minPriority) {
result = "("+result+")";
}
if (operator.casts.indexOf("/*",0) >= 0 ||
operator.casts.indexOf("<-",0) >= 0 && false)
result = "<"+operator.casts+" "+result+">";
return result;
}
public boolean equals(Expression expr) {
if (this == expr)
return true;
if (!operator.equals(expr.operator) ||
subExpressions.length != expr.subExpressions.length)
return false;
for (int i=0; i<subExpressions.length; i++) {
if (subExpressions[i] != expr.subExpressions[i])
return false;
}
return true;
}
public void dumpSource(TabbedPrintWriter writer, CodeAnalyzer ca)
throws java.io.IOException
{
if (writer.verbosity > 6) {
writer.print("< "+
ca.getTypeString(operator.getType())+" "+
operator.getClass().getName()+"(");
for (int i=0; i< subExpressions.length; i++) {
if (i>0)
writer.print(", ");
writer.print("("+ca.getTypeString(operator.getOperandType(i))+
") "+ca.getTypeString(subExpressions[i].getType()));
}
writer.println(") >");
}
if (!isVoid())
writer.print("push ");
writer.println(toString(ca, 0)+";");
}
}

@ -0,0 +1,56 @@
package jode;
import sun.tools.java.*;
public class GetFieldOperator extends Operator {
boolean staticFlag;
FieldDefinition field;
public GetFieldOperator(int addr, int length, boolean staticFlag,
FieldDefinition field) {
super(addr, length, field.getType(), 0);
this.staticFlag = staticFlag;
this.field = field;
}
public int getPriority() {
return 950;
}
public int getOperandCount() {
return staticFlag?0:1;
}
public int getOperandPriority(int i) {
if (staticFlag) {
/* shouldn't be called */
throw new RuntimeException("Field is static");
}
return 900;
}
public Type getOperandType(int i) {
if (staticFlag) {
/* shouldn't be called */
throw new RuntimeException("Field is static");
}
return field.getClassDeclaration().getType();
}
public void setOperandType(Type types[]) {
}
public String toString(CodeAnalyzer ca, String[] operands) {
String object;
if (staticFlag) {
if (field.getClassDefinition() == ca.getClassDefinition())
return field.getName().toString();
object =
ca.getTypeString(field.getClassDeclaration().getType());
} else {
if (operands[0].equals("this"))
return field.getName().toString();
object = operands[0];
}
return object + "." + field.getName();
}
}

@ -0,0 +1,40 @@
package jode;
import sun.tools.java.Type;
public class GotoOperator extends JumpInstruction {
protected int destination;
public GotoOperator(int addr, int length, int dest) {
super(addr,length);
this.destination = dest;
}
public int getDestination() {
return destination;
}
public int getOperandCount() {
return 0;
}
public int getOperandPriority(int i) {
throw new AssertError("This operator has no operands");
}
public Type getOperandType(int i) {
throw new AssertError("This operator has no operands");
}
public void setOperandType(Type types[]) {
throw new AssertError("This operator has no operands");
}
public int[] getSuccessors() {
int [] result = { destination };
return result;
}
public String toString(CodeAnalyzer ca, String[] operands) {
return "goto addr_" + destination;
}
}

@ -0,0 +1,39 @@
package jode;
import sun.tools.java.Type;
public class IfGotoOperator extends JumpInstruction {
protected int destination;
public IfGotoOperator(int addr, int length, int dest) {
super(addr,length);
destination = dest;
}
public int getDestination() {
return destination;
}
public int getOperandCount() {
return 1;
}
public int getOperandPriority(int i) {
return 200; /* force parentheses around assignments */
}
public Type getOperandType(int i) {
return Type.tBoolean;
}
public void setOperandType(Type types[]) {
}
public int[] getSuccessors() {
int [] result = { destination, getAddr() + getLength() };
return result;
}
public String toString(CodeAnalyzer ca, String[] operands) {
return "if ("+operands[0]+") goto addr_" + destination;
}
}

@ -0,0 +1,55 @@
package jode;
import sun.tools.java.Type;
public class IfThenElseOperator extends SimpleOperator {
public IfThenElseOperator(int addr, int length, Type type) {
super(addr,length, type, 0, 3);
operandTypes[0] = Type.tBoolean;
}
public int getOperandCount() {
return 3;
}
public int getPriority() {
return 200;
}
public int getOperandPriority(int i) {
switch (i) {
case 0:
return 201;
case 1:
return 0;
case 2:
return 200;
default:
throw new AssertError("ifthenelse with operand "+i);
}
}
public void setOperandType(Type[] inputTypes) {
super.setOperandType(inputTypes);
Type operandType =
UnknownType.commonType(operandTypes[1],operandTypes[2]);
type = operandTypes[1] = operandTypes[2] = operandType;
}
/**
* Sets the return type of this operator.
* @return true if the operand types changed
*/
public boolean setType(Type newType) {
Type operandType =
UnknownType.commonType(operandTypes[1], newType);
if (type != operandType) {
type = operandTypes[1] = operandTypes[2] = operandType;
return true;
}
return false;
}
public String toString(CodeAnalyzer ca, String[] operands) {
return operands[0] + " ? "+operands[1]+" : "+ operands[2];
}
}

@ -0,0 +1,27 @@
package jode;
import sun.tools.java.Type;
public class InstanceOfOperator extends SimpleOperator {
Type classType;
public InstanceOfOperator(int addr, int length, Type type) {
super(addr, length, Type.tBoolean, 0, 1);
this.operandTypes[0] = UnknownType.tSubClass(type);
this.classType = type;
}
public int getOperandCount() {
return 1;
}
public int getPriority() {
return 550;
}
public int getOperandPriority(int i) {
return getPriority();
}
public String toString(CodeAnalyzer ca, String[] operands) {
return operands[0] + " instanceof "+ca.getTypeString(classType);
}
}

@ -0,0 +1,34 @@
package jode;
public abstract class Instruction {
int addr,length;
Instruction(int a, int l) {
addr = a;
length = l;
}
public int getAddr() {
return addr;
}
public void setAddr(int addr) {
this.addr = addr;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public int[] getSuccessors() {
int[] result = { addr + length };
return result;
}
public abstract void dumpSource(TabbedPrintWriter tpw, CodeAnalyzer ca)
throws java.io.IOException;
}

@ -0,0 +1,110 @@
package jode;
import sun.tools.java.*;
public class InvokeOperator extends Operator {
boolean staticFlag;
boolean specialFlag;
FieldDefinition field;
public InvokeOperator(int addr, int length,
boolean staticFlag, boolean specialFlag,
FieldDefinition field) {
super(addr,length, field.getType().getReturnType(), 0);
this.staticFlag = staticFlag;
this.specialFlag = specialFlag;
this.field = field;
}
public FieldDefinition getField() {
return field;
}
public Type getClassType() {
return field.getClassDeclaration().getType();
}
public int getPriority() {
return 950;
}
public int getOperandCount() {
return (staticFlag?0:1) + field.getType().getArgumentTypes().length;
}
public int getOperandPriority(int i) {
if (!staticFlag && i == 0)
return 950;
return 0;
}
public Type getOperandType(int i) {
if (!staticFlag) {
if (i == 0)
return field.getClassDeclaration().getType();
i--;
}
return field.getType().getArgumentTypes()[i];
}
public void setOperandType(Type types[]) {
}
public boolean isConstructor() {
return field.isConstructor();
}
public String toString(CodeAnalyzer ca, String[] operands) {
String object;
int arg = 0;
if (staticFlag) {
if (field.getClassDefinition() == ca.getClassDefinition())
object = "";
else
object = ca.
getTypeString(field.getClassDeclaration().getType());
} else {
if (operands[arg].equals("this")) {
if (specialFlag &&
(field.getClassDeclaration() ==
ca.getClassDefinition().getSuperClass() ||
(field.getClassDeclaration().getName() ==
Constants.idJavaLangObject &&
ca.getClassDefinition().getSuperClass() == null)))
object = "super";
else if (specialFlag)
object = "(("+ca.getTypeString
(field.getClassDeclaration().getType())+
") this)";
else
object = "";
} else {
if (specialFlag)
object = "(("+ca.getTypeString
(field.getClassDeclaration().getType())+
") "+operands[arg]+")";
else
object = operands[arg];
}
arg++;
}
String method;
if (isConstructor()) {
if (object.length() == 0)
method = "this";
else
method = object;
} else {
if (object.length() == 0)
method = field.getName().toString();
else
method = object+"."+field.getName().toString();
}
StringBuffer params = new StringBuffer();
for (int i=0; i < field.getType().getArgumentTypes().length; i++) {
if (i>0)
params.append(", ");
params.append(operands[arg++]);
}
return method+"("+params+")";
}
}

@ -0,0 +1,16 @@
package jode;
public class JsrOperator extends Instruction {
int destination;
public JsrOperator(int addr, int length, int dest) {
super(addr,length);
this.destination = dest;
}
public void dumpSource(TabbedPrintWriter writer, CodeAnalyzer ca)
throws java.io.IOException
{
writer.println("jsr addr_"+destination+";");
}
}

@ -0,0 +1,12 @@
package jode;
import sun.tools.java.Type;
public abstract class JumpInstruction extends Operator {
public JumpInstruction(int addr, int length) {
super(addr, length, Type.tVoid, 0);
}
public int getPriority() {
return 0;
}
}

@ -0,0 +1,25 @@
package jode;
import sun.tools.java.Type;
public class LoadOperator extends ConstOperator {
LocalVariable slot;
public LoadOperator(int addr, int length, Type type, LocalVariable slot) {
super(addr,length,
UnknownType.commonType(type,slot.getType(addr)), "");
this.slot = slot;
}
public LocalVariable getSlot() {
return slot;
}
public String toString(CodeAnalyzer ca, String[] operands) {
return slot.getName(getAddr()).toString();
}
public boolean equals(Object o) {
return (o instanceof LoadOperator &&
((LoadOperator) o).slot == slot);
}
}

@ -0,0 +1,21 @@
package jode;
import sun.tools.java.Type;
public class MonitorEnterOperator extends SimpleOperator {
public MonitorEnterOperator(int a, int l) {
super(a,l, Type.tVoid, 0, 1);
operandTypes[0] = Type.tObject;
}
public int getPriority() {
return 0;
}
public int getOperandPriority(int i) {
return 0;
}
public String toString(CodeAnalyzer ca, String[] operands) {
return "monitorenter "+operands[0];
}
}

@ -0,0 +1,25 @@
package jode;
import sun.tools.java.Type;
public class MonitorExitOperator extends SimpleOperator {
public MonitorExitOperator(int a, int l) {
super(a,l,Type.tVoid, 0, 1);
operandTypes[0] = Type.tObject;
}
public int getPriority() {
return 0;
}
public int getOperandPriority(int i) {
return 0;
}
public Type getOperandType(int i) {
return UnknownType.tObject;
}
public String toString(CodeAnalyzer ca, String[] operands) {
return "monitorexit "+operands[0];
}
}

@ -0,0 +1,37 @@
package jode;
import sun.tools.java.Type;
public class NewArrayOperator extends SimpleOperator {
Type baseType;
public NewArrayOperator(int addr, int length,
Type baseType, int dimensions) {
super(addr, length, baseType, 0, dimensions);
this.baseType = baseType;
for (int i=0; i< dimensions; i++) {
this.type = Type.tArray(this.type);
operandTypes[i] = UnknownType.tUIndex;
}
}
public NewArrayOperator(int addr, int length, Type baseType) {
this(addr, length, baseType, 1);
}
public int getPriority() {
return 900;
}
public int getOperandPriority(int i) {
return 0;
}
public String toString(CodeAnalyzer ca, String[] operands) {
StringBuffer result
= new StringBuffer("new ").append(ca.getTypeString(baseType));
for (int i=0; i< getOperandCount(); i++) {
result.append("[").append(operands[i]).append("]");
}
return result.toString();
}
}

@ -0,0 +1,20 @@
package jode;
import sun.tools.java.Type;
public class NewConstructorOperator extends NoArgOperator {
Expression constructor;
public NewConstructorOperator(int addr, int length, Type type,
Expression expr) {
super(addr,length, type);
this.constructor = expr;
}
public int getPriority() {
return 950;
}
public String toString(CodeAnalyzer ca, String[] operands) {
return "new "+constructor.toString(ca, 0);
}
}

@ -0,0 +1,17 @@
package jode;
import sun.tools.java.Type;
public class NewOperator extends NoArgOperator {
public NewOperator(int addr, int length, Type type) {
super(addr,length, type);
}
public int getPriority() {
return 950;
}
public String toString(CodeAnalyzer ca, String[] operands) {
return "new "+getType().toString();
}
}

@ -0,0 +1,26 @@
package jode;
import sun.tools.java.Type;
public abstract class NoArgOperator extends Operator {
public NoArgOperator(int addr, int length, Type type) {
super(addr, length, type, 0);
}
public int getOperandCount() {
return 0;
}
public int getOperandPriority(int i) {
throw new AssertError("This operator has no operands");
}
public Type getOperandType(int i) {
throw new AssertError("This operator has no operands");
}
public void setOperandType(Type[] types) {
throw new AssertError("This operator has no operands");
}
}

@ -0,0 +1,13 @@
package jode;
public class NopOperator extends Instruction {
public NopOperator(int a, int l) {
super(a,l);
}
public void dumpSource(TabbedPrintWriter tpw, CodeAnalyzer ca)
throws java.io.IOException
{
tpw.println("nop;");
}
}

@ -0,0 +1,111 @@
package jode;
import sun.tools.java.Type;
public abstract class Operator extends Instruction {
public final static int ADD_OP = 1;
public final static int NEG_OP = 2;
public final static int SHIFT_OP = 6;
public final static int ASSIGN_OP = 12;
public final static int OPASSIGN_OP= 12;
public final static int INC_OP = 24;
public final static int COMPARE_OP = 26; /* must be even! */
public final static int LOG_AND_OP = 32; /* must be even! */
public final static int LOG_OR_OP = 33;
public final static int LOG_NOT_OP = 34;
static String opString[] = {
"", "+","-","*","/","%", "<<", ">>", ">>>", "&", "|", "^",
"=","+=","-=","*=","/=","%=", "<<=", ">>=", ">>>=", "&=", "|=", "^=",
"++", "--",
"==","!=","<",">=",">", "<=", "&&", "||",
"~", "!"
};
protected Type type;
protected int operator;
String casts;
Operator (int addr, int length, Type type, int op) {
super(addr,length);
this.type = type;
this.operator = op;
if (type == null)
throw new AssertError("type == null");
casts = type.toString();
}
public int getOperator() {
return operator;
}
public void setOperator(int op) {
operator = op;
}
/**
* Sets the return type of this operator.
* @return true if the operand types changed
*/
public boolean setType(Type type) {
if (!UnknownType.isOfType(type, this.type)) {
casts = type.toString()+"/*invalid*/ <- " + casts;
} else if (type != this.type) {
casts = type.toString()+" <- " + casts;
}
this.type = type;
return false;
}
public final Type getType() {
return type;
}
public String getOperatorString() {
return opString[operator];
}
/**
* Get priority of the operator.
* Currently this priorities are known:
* <ul><li> 1000 constant
* </li><li> 950 new, .(field access), []
* </li><li> 900 new[]
* </li><li> 800 ++,-- (post)
* </li><li> 700 ++,--(pre), +,-(unary), ~, !, cast
* </li><li> 650 *,/, %
* </li><li> 610 +,-
* </li><li> 600 <<, >>, >>>
* </li><li> 550 >, <, >=, <=, instanceof
* </li><li> 500 ==, !=
* </li><li> 450 &
* </li><li> 420 ^
* </li><li> 410 |
* </li><li> 350 &&
* </li><li> 310 ||
* </li><li> 200 ?:
* </li><li> 100 =, +=, -=, etc.
* </li></ul>
*/
public abstract int getPriority();
/**
* Get minimum priority of the nth operand.
* @see getPriority
*/
public abstract int getOperandPriority(int i);
public abstract Type getOperandType(int i);
public abstract int getOperandCount();
public abstract void setOperandType(Type[] inputTypes);
public abstract String toString(CodeAnalyzer ca, String[] operands);
public void dumpSource(TabbedPrintWriter writer, CodeAnalyzer ca)
throws java.io.IOException
{
if (type == null)
throw new AssertError("type == null");
String[] operands = new String[getOperandCount()];
for (int i=0; i< operands.length; i++) {
operands[i] = "stack_"+(operands.length-i-1);
}
writer.println(toString(ca, operands));
}
}

@ -0,0 +1,24 @@
package jode;
import sun.tools.java.Type;
public class PopOperator extends SimpleOperator {
int count;
public PopOperator(int a, int l, int count) {
super(a,l, Type.tVoid, 0, 1);
operandTypes[0] = UnknownType.tUnknown;
this.count = count;
}
public int getPriority() {
return 0;
}
public int getOperandPriority(int i) {
return 0;
}
public String toString(CodeAnalyzer ca, String[] operands) {
return operands[0];
}
}

@ -0,0 +1,34 @@
package jode;
import sun.tools.java.Type;
public class PostFixOperator extends SimpleOperator {
public PostFixOperator(int addr, int length, Type type, int op) {
super(addr,length, type, op, 1);
}
public int getPriority() {
return 800;
}
public int getOperandPriority(int i) {
return getPriority();
}
/**
* Sets the return type of this operator.
* @return true if the operand types changed
*/
public boolean setType(Type type) {
super.setType(type);
Type newOpType = UnknownType.commonType(type, operandTypes[0]);
if (newOpType != operandTypes[0]) {
operandTypes[0] = newOpType;
return true;
}
return false;
}
public String toString(CodeAnalyzer ca, String[] operands) {
return operands[0] + getOperatorString();
}
}

@ -0,0 +1,62 @@
package jode;
import sun.tools.java.*;
public class PutFieldOperator extends StoreInstruction {
boolean staticFlag;
FieldDefinition field;
public PutFieldOperator(int addr, int length, boolean staticFlag,
FieldDefinition field) {
super(addr, length, field.getType());
this.staticFlag = staticFlag;
this.field = field;
}
public boolean matches(Operator loadop) {
return loadop instanceof GetFieldOperator &&
((GetFieldOperator)loadop).field == field;
}
public int getLValueOperandCount() {
return staticFlag?0:1;
}
public int getLValueOperandPriority(int i) {
if (staticFlag) {
/* shouldn't be called */
throw new RuntimeException("Field is static");
}
return 900;
}
public Type getLValueOperandType(int i) {
if (staticFlag) {
/* shouldn't be called */
throw new AssertError("Field is static");
}
return field.getClassDefinition().getType();
}
public void setLValueOperandType(Type[] t) {
if (staticFlag) {
/* shouldn't be called */
throw new AssertError("Field is static");
}
return;
}
public String getLValueString(CodeAnalyzer ca, String[] operands) {
String object;
if (staticFlag) {
if (field.getClassDefinition() == ca.getClassDefinition())
return field.getName().toString();
object =
ca.getTypeString(field.getClassDeclaration().getType())+".";
} else {
if (operands[0].equals("this"))
return field.getName().toString();
object = operands[0];
}
return object + "." + field.getName();
}
}

@ -0,0 +1,20 @@
package jode;
public class RetOperator extends Instruction {
int slot;
public RetOperator(int addr, int length, int slot) {
super(addr,length);
this.slot = slot;
}
public int[] getSuccessors() {
return new int[0];
}
public void dumpSource(TabbedPrintWriter writer, CodeAnalyzer ca)
throws java.io.IOException
{
writer.println("ret;");
}
}

@ -0,0 +1,29 @@
package jode;
import sun.tools.java.Type;
public class ReturnOperator extends SimpleOperator {
public ReturnOperator(int addr, int length, Type type) {
super(addr,length, Type.tVoid, 0, (type == Type.tVoid)?0:1);
if (type != Type.tVoid)
operandTypes[0] = type;
}
public int[] getSuccessors() {
return new int[0];
}
public int getPriority() {
return 0;
}
public int getOperandPriority(int i) {
return 0;
}
public String toString(CodeAnalyzer ca, String[] operands) {
StringBuffer result = new StringBuffer("return");
if (getOperandCount() != 0)
result.append(" ").append(operands[0]);
return result.toString();
}
}

@ -0,0 +1,23 @@
package jode;
import sun.tools.java.Type;
/**
* ShiftOpcodes are special, because their second operand is an UIndex
*/
public class ShiftOperator extends BinaryOperator {
protected Type shiftType;
public ShiftOperator(int addr, int length, Type type, int op) {
super(addr,length, type, op);
shiftType = UnknownType.tUIndex;
}
public Type getOperandType(int i) {
return (i==0)?operandType:shiftType;
}
public void setOperandType(Type[] inputTypes) {
operandType = UnknownType.commonType(operandType, inputTypes[0]);
shiftType = UnknownType.commonType(shiftType, inputTypes[1]);
}
}

@ -0,0 +1,31 @@
package jode;
import sun.tools.java.Type;
public abstract class SimpleOperator extends Operator {
protected Type[] operandTypes;
public SimpleOperator(int addr, int length, Type type, int operator,
int operandCount) {
super(addr, length, type, operator);
operandTypes = new Type[operandCount];
for (int i=0; i< operandCount; i++) {
operandTypes[i] = type;
}
}
public int getOperandCount() {
return operandTypes.length;
}
public Type getOperandType(int i) {
return operandTypes[i];
}
public void setOperandType(Type[] t) {
for (int i=0; i< operandTypes.length; i++) {
if (UnknownType.commonType(operandTypes[i], t[i]) == Type.tError)
System.err.println("Error: "+operandTypes[i]+","+t[i]);
operandTypes[i] = UnknownType.commonType(operandTypes[i], t[i]);
}
}
}

@ -0,0 +1,80 @@
package jode;
import sun.tools.java.Type;
public abstract class StoreInstruction extends Operator {
public String lvCasts;
Type lvalueType;
public StoreInstruction(int addr, int length, Type type) {
this (addr,length, type, ASSIGN_OP);
}
public StoreInstruction(int addr, int length, Type type, int operator) {
super(addr,length, Type.tVoid, operator);
lvalueType = type;
lvCasts = lvalueType.toString();
}
public Type getLValueType() {
return lvalueType;
}
public abstract boolean matches(Operator loadop);
public abstract int getLValueOperandCount();
public abstract int getLValueOperandPriority(int i);
public abstract Type getLValueOperandType(int i);
public abstract void setLValueOperandType(Type [] t);
/**
* Sets the type of the lvalue (and rvalue).
* @return true if the operand types changed
*/
public boolean setLValueType(Type type) {
if (!UnknownType.isOfType(type, this.lvalueType)) {
lvCasts = type.toString()+"/*invalid*/ <- " + lvCasts;
} else if (type != this.lvalueType) {
lvCasts = type.toString()+" <- " + lvCasts;
}
this.lvalueType = type;
return false;
}
public abstract String getLValueString(CodeAnalyzer ca, String[] operands);
public int getPriority() {
return 100;
}
public int getOperandPriority(int i) {
if (i == getLValueOperandCount())
return 100;
else
return getLValueOperandPriority(i);
}
public Type getOperandType(int i) {
if (i == getLValueOperandCount())
return getLValueType();
else
return getLValueOperandType(i);
}
public void setOperandType(Type[] t) {
if (getLValueOperandCount() > 0)
setLValueOperandType(t);
setLValueType
(UnknownType.commonType(lvalueType, t[getLValueOperandCount()]));
}
public int getOperandCount() {
return 1 + getLValueOperandCount();
}
public String toString(CodeAnalyzer ca, String[] operands)
{
return "{"+lvCasts+" "+getLValueString(ca, operands) + "} "+
getOperatorString() +" "+
operands[getLValueOperandCount()];
}
}

@ -0,0 +1,46 @@
package jode;
import sun.tools.java.Type;
public class StoreOperator extends StoreInstruction {
LocalVariable slot;
public StoreOperator(int addr, int length, Type type,
LocalVariable slot, int operator) {
super(addr,length,
UnknownType.commonType(type,slot.getType(addr+length)),
operator);
this.slot = slot;
}
public LocalVariable getSlot() {
return slot;
}
public boolean matches(Operator loadop) {
return loadop instanceof LoadOperator &&
((LoadOperator)loadop).getSlot() == slot;
}
public int getLValueOperandCount() {
return 0;
}
public int getLValueOperandPriority(int i) {
/* shouldn't be called */
throw new RuntimeException("StoreOperator has no operands");
}
public Type getLValueOperandType(int i) {
/* shouldn't be called */
throw new RuntimeException("StoreOperator has no operands");
}
public void setLValueOperandType(Type []t) {
/* shouldn't be called */
throw new RuntimeException("StoreOperator has no operands");
}
public String getLValueString(CodeAnalyzer ca, String[] operands) {
return slot.getName(getAddr()+getLength()).toString();
}
}

@ -0,0 +1,13 @@
package jode;
public class SwapOperator extends Instruction {
public SwapOperator(int a, int l) {
super(a,l);
}
public void dumpSource(TabbedPrintWriter writer, CodeAnalyzer ca)
throws java.io.IOException
{
writer.println("swap;");
}
}

@ -0,0 +1,70 @@
package jode;
import sun.tools.java.Type;
public class SwitchOperator extends JumpInstruction {
int[] cases;
int[] destinations;
Type operandType;
public SwitchOperator(int addr, int length, int[] cases, int[] dests) {
super(addr,length);
this.cases = cases;
this.destinations = dests;
this.operandType = UnknownType.tUInt;
}
public int[] getCases() {
return cases;
}
public int[] getSuccessors() {
return destinations;
}
public int getPriority() {
return 0;
}
public int getOperandCount() {
return 1;
}
public int getOperandPriority(int i) {
return 0;
}
public Type getOperandType(int i) {
return operandType;
}
public void setOperandType(Type types[]) {
operandType = UnknownType.commonType(operandType, types[0]);
}
public boolean setType(Type t) {
super.setType(type);
if (type != operandType) {
operandType = type;
return true;
}
return false;
}
public String toString(CodeAnalyzer ca, String[] operands) {
return "switch ("+operands[0]+") ";
}
public void dumpSource(TabbedPrintWriter writer, CodeAnalyzer ca)
throws java.io.IOException
{
writer.println("switch(stack_0) {");
writer.tab();
for (int i=0; i< cases.length; i++) {
writer.println("case "+cases[i]+
": goto addr_"+destinations[i]+";");
}
writer.println("default: goto addr_"+destinations[cases.length]);
writer.untab();
writer.println("}");
}
}

@ -0,0 +1,13 @@
package jode;
import sun.tools.java.Type;
public class ThrowOperator extends ReturnOperator {
public ThrowOperator(int addr, int length) {
super(addr,length, UnknownType.tUObject);
}
public String toString(CodeAnalyzer ca, String[] operands) {
return "throw " + operands[0];
}
}

@ -0,0 +1,34 @@
package jode;
import sun.tools.java.Type;
public class UnaryOperator extends SimpleOperator {
public UnaryOperator(int addr, int length, Type type, int op) {
super(addr,length, type, op, 1);
}
public int getPriority() {
return 700;
}
public int getOperandPriority(int i) {
return getPriority();
}
/**
* Sets the return type of this operator.
* @return true if the operand types changed
*/
public boolean setType(Type type) {
super.setType(type);
Type newOpType = UnknownType.commonType(type, operandTypes[0]);
if (newOpType != operandTypes[0]) {
operandTypes[0] = newOpType;
return true;
}
return false;
}
public String toString(CodeAnalyzer ca, String[] operands) {
return getOperatorString() + operands[0];
}
}

@ -0,0 +1,22 @@
package jode;
import sun.tools.java.Type;
public class UnknownSubType extends UnknownType {
Type elemType;
public UnknownSubType(Type type) {
super(103, "<");
elemType = type;
}
public Type getElementType()
{
return elemType;
}
public String typeString(String string, boolean flag1, boolean flag2)
{
return "<superclass of "+
String.valueOf(elemType.typeString(string, flag1, flag2))+">";
}
}

@ -0,0 +1,204 @@
package jode;
import sun.tools.java.Type;
import java.util.Hashtable;
public class UnknownType extends Type {
static Hashtable subclasses = new Hashtable();
public static Type tUnknown = new UnknownType(100, "x");
public static Type tUInt = new UnknownType(101, "i");
public static Type tUIndex = new UnknownType(104, "[");
public static Type tUObject = new UnknownType(102, "*");
public static Type tSubClass(Type type) {
Type subtype = (Type) subclasses.get(type);
if (subtype == null) {
subtype = new UnknownSubType(type);
subclasses.put(type, subtype);
}
return subtype;
}
protected UnknownType(int i, String str) {
super (i, str);
}
public int stackSize()
{
return 1;
}
public String typeString(String var, boolean flag1, boolean flag2)
{
String typeStr;
switch (typeCode) {
case 100: typeStr="<unknown>"; break;
case 101: typeStr="<int>"; break; /*XXX*/
case 102: typeStr="<Object>"; break;
case 104: typeStr="<arrindex>"; break; /*XXX*/
default:
throw new RuntimeException("Wrong typeCode "+typeCode);
}
if (var.length() > 0)
return typeStr+" "+var;
return typeStr;
}
public static Type commonType(Type t1, Type t2) {
if (t1 == t2 || t2 == tUnknown)
return t1;
switch (t1.getTypeCode()) {
case 0: /* boolean*/
case 1: /* byte */
case 2: /* char */
case 3: /* short */
case 4: /* int */
if (t2.getTypeCode() <= 4) {
if (t2.getTypeCode() > t1.getTypeCode())
return t2;
else
return t1;
}
if (t2 == tUInt || t2 == tUIndex)
return t1;
break;
case 5: /* long */
case 6: /* float */
case 7: /* double */
case 8: /* null? */
case 11: /* void */
case 12: /* method */
case 13: /* error */
break;
case 9: /* array */
if (t2 == tUObject)
return t1;
if (t2.getTypeCode() == 9) /* array, array case */
return tArray(commonType(t1.getElementType(),
t2.getElementType()));
break;
case 10: /* class */
if (t2 == tUObject)
return t1;
if (t2.getTypeCode() == 103) {
/* find suitable subclass of t2 */
return t2; /*XXX*/
}
if (t2.getTypeCode() == 10) {
return t1; /*XXX*/
}
break;
case 100: /* unknown */
return t2;
case 101: /* unknown int */
if ((t2.getTypeCode() >= 0 && t2.getTypeCode() <= 4) ||
t2 == tUIndex)
return t2;
break;
case 104: /* unknown index */
if (t2.getTypeCode() >= 1 && t2.getTypeCode() <= 4)
return t2;
if (t2 == tUInt)
return t1;
break;
case 102: /* unknown object */
if (t2.getTypeCode() == 9 || t2.getTypeCode() == 10 ||
t2.getTypeCode() == 103)
return t2;
break;
case 103: /* unknown super class */
if (t2.getTypeCode() == 10 || t2.getTypeCode() == 103)
return t2; /*XXX*/
if (t2 == tUObject)
return t1;
break;
default:
throw new AssertError("Wrong typeCode "+t1.getTypeCode());
}
return tError;
}
/**
* Check if t1 is a t2.
* @return true if t1 is a more specific type than t2, e.g.
* if t2 is a superclass of t1
*/
public static boolean isOfType(Type t1, Type t2) {
if ((t1 == t2 || t2 == tUnknown) && t1 != tError)
return true;
switch (t1.getTypeCode()) {
case 0: /* boolean*/
case 1: /* byte */
case 2: /* char */
case 3: /* short */
case 4: /* int */
/* JavaC thinks, that this is okay. */
if (t2.getTypeCode() >= 0 && t2.getTypeCode() <=4)
return true;
/* fallthrough */
case 104: /* unknown index */
if (t2 == tUInt || t2 == tUIndex)
return true;
break;
case 5: /* long */
case 6: /* float */
case 7: /* double */
case 8: /* null? */
case 11: /* void */
case 12: /* method */
case 13: /* error */
case 100: /* unknown */
case 101: /* unknown int */
case 102: /* unknown object */
break;
case 9: /* array */
if (t2 == tUObject)
return true;
if (t2.getTypeCode() == 9) /* array,array case */
return isOfType(t1.getElementType(), t2.getElementType());
break;
case 10: /* class */
if (t2 == tUObject)
return true;
if (t2.getTypeCode() == 103)
/* Always true because t2 may be an Object XXX I think not*/
return true;
if (t2.getTypeCode() == 10)
/* true if t2 is a superclass of t1 */
return true; /*XXX*/
break;
case 103: /* unknown super class */
if (t2.getTypeCode() == 103)
/* Always true because t2 may be an Object XXX I think not*/
return true;
if (t2.getTypeCode() == 10) {
/* true if t2 is a real super class
(or interface) of t1.getElementType() */
return true; /*XXX*/
}
if (t2 == tUObject)
return true;
break;
default:
throw new AssertError("Wrong typeCode "+t1.getTypeCode());
}
return false;
}
}
Loading…
Cancel
Save