diff --git a/jode/jode/Decompiler.java b/jode/jode/Decompiler.java index a803336..eceb144 100644 --- a/jode/jode/Decompiler.java +++ b/jode/jode/Decompiler.java @@ -18,8 +18,6 @@ */ package jode; -import sun.tools.java.*; -import java.lang.reflect.Modifier; public class Decompiler { public static boolean isVerbose = false; @@ -29,6 +27,8 @@ public class Decompiler { public static boolean debugInOut = false; public static boolean showLVT = false; public static boolean doChecks = false; + public static int importPackageLimit = 3; + public static int importClassLimit = 3; public static void main(String[] params) { JodeEnvironment env = new JodeEnvironment(); @@ -47,7 +47,10 @@ public class Decompiler { showLVT = true; else if (params[i].equals("-check")) doChecks = true; - else + else if (params[i].equals("-import")) { + importPackageLimit = Integer.parseInt(params[++i]); + importClassLimit = Integer.parseInt(params[++i]); + } else env.doClass(params[i]); } } diff --git a/jode/jode/bytecode/Opcodes.java b/jode/jode/bytecode/Opcodes.java index 6b4bd73..e13fde7 100644 --- a/jode/jode/bytecode/Opcodes.java +++ b/jode/jode/bytecode/Opcodes.java @@ -20,13 +20,14 @@ package jode; import jode.flow.*; import java.io.*; -import sun.tools.java.*; +import gnu.bytecode.CpoolRef; +import gnu.bytecode.CpoolClass; /** * This is an abstract class which creates flow blocks for the * opcodes in a byte stream. */ -public abstract class Opcodes implements RuntimeConstants { +public abstract class Opcodes { public final static Type ALL_INT_TYPE = Type.tUInt; public final static Type BOOL_INT_TYPE = Type.tBoolInt; @@ -42,6 +43,210 @@ public abstract class Opcodes implements RuntimeConstants { public final static Type SHORT_TYPE = Type.tShort; public final static Type VOID_TYPE = Type.tVoid; + public static final int opc_nop = 0; + public static final int opc_aconst_null = 1; + public static final int opc_iconst_m1 = 2; + public static final int opc_iconst_0 = 3; + public static final int opc_iconst_1 = 4; + public static final int opc_iconst_2 = 5; + public static final int opc_iconst_3 = 6; + public static final int opc_iconst_4 = 7; + public static final int opc_iconst_5 = 8; + public static final int opc_lconst_0 = 9; + public static final int opc_lconst_1 = 10; + public static final int opc_fconst_0 = 11; + public static final int opc_fconst_1 = 12; + public static final int opc_fconst_2 = 13; + public static final int opc_dconst_0 = 14; + public static final int opc_dconst_1 = 15; + public static final int opc_bipush = 16; + public static final int opc_sipush = 17; + public static final int opc_ldc = 18; + public static final int opc_ldc_w = 19; + public static final int opc_ldc2_w = 20; + public static final int opc_iload = 21; + public static final int opc_lload = 22; + public static final int opc_fload = 23; + public static final int opc_dload = 24; + public static final int opc_aload = 25; + public static final int opc_iload_0 = 26; + public static final int opc_iload_1 = 27; + public static final int opc_iload_2 = 28; + public static final int opc_iload_3 = 29; + public static final int opc_lload_0 = 30; + public static final int opc_lload_1 = 31; + public static final int opc_lload_2 = 32; + public static final int opc_lload_3 = 33; + public static final int opc_fload_0 = 34; + public static final int opc_fload_1 = 35; + public static final int opc_fload_2 = 36; + public static final int opc_fload_3 = 37; + public static final int opc_dload_0 = 38; + public static final int opc_dload_1 = 39; + public static final int opc_dload_2 = 40; + public static final int opc_dload_3 = 41; + public static final int opc_aload_0 = 42; + public static final int opc_aload_1 = 43; + public static final int opc_aload_2 = 44; + public static final int opc_aload_3 = 45; + public static final int opc_iaload = 46; + public static final int opc_laload = 47; + public static final int opc_faload = 48; + public static final int opc_daload = 49; + public static final int opc_aaload = 50; + public static final int opc_baload = 51; + public static final int opc_caload = 52; + public static final int opc_saload = 53; + public static final int opc_istore = 54; + public static final int opc_lstore = 55; + public static final int opc_fstore = 56; + public static final int opc_dstore = 57; + public static final int opc_astore = 58; + public static final int opc_istore_0 = 59; + public static final int opc_istore_1 = 60; + public static final int opc_istore_2 = 61; + public static final int opc_istore_3 = 62; + public static final int opc_lstore_0 = 63; + public static final int opc_lstore_1 = 64; + public static final int opc_lstore_2 = 65; + public static final int opc_lstore_3 = 66; + public static final int opc_fstore_0 = 67; + public static final int opc_fstore_1 = 68; + public static final int opc_fstore_2 = 69; + public static final int opc_fstore_3 = 70; + public static final int opc_dstore_0 = 71; + public static final int opc_dstore_1 = 72; + public static final int opc_dstore_2 = 73; + public static final int opc_dstore_3 = 74; + public static final int opc_astore_0 = 75; + public static final int opc_astore_1 = 76; + public static final int opc_astore_2 = 77; + public static final int opc_astore_3 = 78; + public static final int opc_iastore = 79; + public static final int opc_lastore = 80; + public static final int opc_fastore = 81; + public static final int opc_dastore = 82; + public static final int opc_aastore = 83; + public static final int opc_bastore = 84; + public static final int opc_castore = 85; + public static final int opc_sastore = 86; + public static final int opc_pop = 87; + public static final int opc_pop2 = 88; + public static final int opc_dup = 89; + public static final int opc_dup_x1 = 90; + public static final int opc_dup_x2 = 91; + public static final int opc_dup2 = 92; + public static final int opc_dup2_x1 = 93; + public static final int opc_dup2_x2 = 94; + public static final int opc_swap = 95; + public static final int opc_iadd = 96; + public static final int opc_ladd = 97; + public static final int opc_fadd = 98; + public static final int opc_dadd = 99; + public static final int opc_isub = 100; + public static final int opc_lsub = 101; + public static final int opc_fsub = 102; + public static final int opc_dsub = 103; + public static final int opc_imul = 104; + public static final int opc_lmul = 105; + public static final int opc_fmul = 106; + public static final int opc_dmul = 107; + public static final int opc_idiv = 108; + public static final int opc_ldiv = 109; + public static final int opc_fdiv = 110; + public static final int opc_ddiv = 111; + public static final int opc_irem = 112; + public static final int opc_lrem = 113; + public static final int opc_frem = 114; + public static final int opc_drem = 115; + public static final int opc_ineg = 116; + public static final int opc_lneg = 117; + public static final int opc_fneg = 118; + public static final int opc_dneg = 119; + public static final int opc_ishl = 120; + public static final int opc_lshl = 121; + public static final int opc_ishr = 122; + public static final int opc_lshr = 123; + public static final int opc_iushr = 124; + public static final int opc_lushr = 125; + public static final int opc_iand = 126; + public static final int opc_land = 127; + public static final int opc_ior = 128; + public static final int opc_lor = 129; + public static final int opc_ixor = 130; + public static final int opc_lxor = 131; + public static final int opc_iinc = 132; + public static final int opc_i2l = 133; + public static final int opc_i2f = 134; + public static final int opc_i2d = 135; + public static final int opc_l2i = 136; + public static final int opc_l2f = 137; + public static final int opc_l2d = 138; + public static final int opc_f2i = 139; + public static final int opc_f2l = 140; + public static final int opc_f2d = 141; + public static final int opc_d2i = 142; + public static final int opc_d2l = 143; + public static final int opc_d2f = 144; + public static final int opc_i2b = 145; + public static final int opc_i2c = 146; + public static final int opc_i2s = 147; + public static final int opc_lcmp = 148; + public static final int opc_fcmpl = 149; + public static final int opc_fcmpg = 150; + public static final int opc_dcmpl = 151; + public static final int opc_dcmpg = 152; + public static final int opc_ifeq = 153; + public static final int opc_ifne = 154; + public static final int opc_iflt = 155; + public static final int opc_ifge = 156; + public static final int opc_ifgt = 157; + public static final int opc_ifle = 158; + public static final int opc_if_icmpeq = 159; + public static final int opc_if_icmpne = 160; + public static final int opc_if_icmplt = 161; + public static final int opc_if_icmpge = 162; + public static final int opc_if_icmpgt = 163; + public static final int opc_if_icmple = 164; + public static final int opc_if_acmpeq = 165; + public static final int opc_if_acmpne = 166; + public static final int opc_goto = 167; + public static final int opc_jsr = 168; + public static final int opc_ret = 169; + public static final int opc_tableswitch = 170; + public static final int opc_lookupswitch = 171; + public static final int opc_ireturn = 172; + public static final int opc_lreturn = 173; + public static final int opc_freturn = 174; + public static final int opc_dreturn = 175; + public static final int opc_areturn = 176; + public static final int opc_return = 177; + public static final int opc_getstatic = 178; + public static final int opc_putstatic = 179; + public static final int opc_getfield = 180; + public static final int opc_putfield = 181; + public static final int opc_invokevirtual = 182; + public static final int opc_invokespecial = 183; + public static final int opc_invokestatic = 184; + public static final int opc_invokeinterface = 185; + public static final int opc_xxxunusedxxx = 186; + public static final int opc_new = 187; + public static final int opc_newarray = 188; + public static final int opc_anewarray = 189; + public static final int opc_arraylength = 190; + public static final int opc_athrow = 191; + public static final int opc_checkcast = 192; + public static final int opc_instanceof = 193; + public static final int opc_monitorenter = 194; + public static final int opc_monitorexit = 195; + public static final int opc_wide = 196; + public static final int opc_multianewarray = 197; + public static final int opc_ifnull = 198; + public static final int opc_ifnonnull = 199; + public static final int opc_goto_w = 200; + public static final int opc_jsr_w = 201; + public static final int opc_breakpoint = 202; + public final static Type types[][] = { {BOOL_INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE, OBJECT_TYPE }, @@ -173,16 +378,16 @@ public abstract class Opcodes implements RuntimeConstants { int index = stream.readUnsignedByte(); return createNormal (ca, addr, 2, new ConstOperator - (ca.env.getConstantType(index), - ca.env.getConstant(index).toString())); + (ca.method.classAnalyzer.getConstantType(index), + ca.method.classAnalyzer.getConstantString(index))); } case opc_ldc_w: case opc_ldc2_w: { int index = stream.readUnsignedShort(); return createNormal (ca, addr, 3, new ConstOperator - (ca.env.getConstantType(index), - ca.env.getConstant(index).toString())); + (ca.method.classAnalyzer.getConstantType(index), + ca.method.classAnalyzer.getConstantString(index))); } case opc_iload: case opc_lload: case opc_fload: case opc_dload: case opc_aload: @@ -381,9 +586,7 @@ public abstract class Opcodes implements RuntimeConstants { } case opc_ireturn: case opc_lreturn: case opc_freturn: case opc_dreturn: case opc_areturn: { - Type retType = - Type.tSubType(Type.tType(ca.getMethod().mdef.getType() - .getReturnType())); + Type retType = Type.tSubType(ca.getMethod().getReturnType()); return createBlock (ca, addr, 1, new ReturnBlock(new NopOperator(retType))); } @@ -396,14 +599,14 @@ public abstract class Opcodes implements RuntimeConstants { return createNormal (ca, addr, 3, new GetFieldOperator (ca, opcode == opc_getstatic, - (FieldDefinition)ca.env.getConstant + (CpoolRef)ca.method.classAnalyzer.getConstant (stream.readUnsignedShort()))); case opc_putstatic: case opc_putfield: return createNormal (ca, addr, 3, new PutFieldOperator (ca, opcode == opc_putstatic, - (FieldDefinition)ca.env.getConstant + (CpoolRef)ca.method.classAnalyzer.getConstant (stream.readUnsignedShort()))); case opc_invokevirtual: case opc_invokespecial: @@ -412,23 +615,23 @@ public abstract class Opcodes implements RuntimeConstants { (ca, addr, 3, new InvokeOperator (ca, opcode == opc_invokestatic, opcode == opc_invokespecial, - (FieldDefinition)ca.env.getConstant + (CpoolRef)ca.method.classAnalyzer.getConstant (stream.readUnsignedShort()))); case opc_invokeinterface: { FlowBlock fb = createNormal (ca, addr, 5, new InvokeOperator (ca, false, false, - (FieldDefinition)ca.env.getConstant + (CpoolRef)ca.method.classAnalyzer.getConstant (stream.readUnsignedShort()))); int reserved = stream.readUnsignedShort(); return fb; } case opc_new: { - ClassDeclaration cldec = (ClassDeclaration) - ca.env.getConstant(stream.readUnsignedShort()); - Type type = Type.tClassOrArray(cldec.getName()); + CpoolClass cpcls = (CpoolClass) + ca.method.classAnalyzer.getConstant(stream.readUnsignedShort()); + Type type = Type.tClassOrArray(cpcls.getName().getString()); return createNormal - (ca, addr, 3, new NewOperator(type, ca.env.getTypeString(type))); + (ca, addr, 3, new NewOperator(type, type.toString())); } case opc_newarray: { Type type; @@ -445,18 +648,15 @@ public abstract class Opcodes implements RuntimeConstants { throw new ClassFormatError("Invalid newarray operand"); } return createNormal - (ca, addr, 2, - new NewArrayOperator(Type.tArray(type), - type.toString(), 1)); + (ca, addr, 2, new NewArrayOperator(Type.tArray(type), 1)); } case opc_anewarray: { - ClassDeclaration cldec = (ClassDeclaration) ca.env.getConstant + CpoolClass cpcls = (CpoolClass) + ca.method.classAnalyzer.getConstant (stream.readUnsignedShort()); - Identifier ident = cldec.getName(); - Type type = Type.tClassOrArray(cldec.getName()); + Type type = Type.tClassOrArray(cpcls.getName().getString()); return createNormal - (ca, addr, 3, new NewArrayOperator - (Type.tArray(type), ca.env.getTypeString(type),1)); + (ca, addr, 3, new NewArrayOperator(Type.tArray(type), 1)); } case opc_arraylength: return createNormal @@ -466,20 +666,22 @@ public abstract class Opcodes implements RuntimeConstants { (ca, addr, 1, new ThrowBlock(new NopOperator(Type.tUObject))); case opc_checkcast: { - ClassDeclaration cldec = (ClassDeclaration) ca.env.getConstant + CpoolClass cpcls = (CpoolClass) + ca.method.classAnalyzer.getConstant (stream.readUnsignedShort()); - Type type = Type.tClassOrArray(cldec.getName()); + Type type = Type.tClassOrArray(cpcls.getName().getString()); return createNormal (ca, addr, 3, new CheckCastOperator - (type, ca.env.getTypeString(type))); + (type, type.toString())); } case opc_instanceof: { - ClassDeclaration cldec = (ClassDeclaration) ca.env.getConstant + CpoolClass cpcls = (CpoolClass) + ca.method.classAnalyzer.getConstant (stream.readUnsignedShort()); - Type type = Type.tClassOrArray(cldec.getName()); + Type type = Type.tClassOrArray(cpcls.getName().getString()); return createNormal (ca, addr, 3, - new InstanceOfOperator(type, ca.env.getTypeString(type))); + new InstanceOfOperator(type, type.toString())); } case opc_monitorenter: return createNormal(ca, addr, 1, @@ -528,17 +730,14 @@ public abstract class Opcodes implements RuntimeConstants { } } case opc_multianewarray: { - ClassDeclaration cldec = (ClassDeclaration) ca.env.getConstant + CpoolClass cpcls = (CpoolClass) + ca.method.classAnalyzer.getConstant (stream.readUnsignedShort()); - Type type = Type.tClassOrArray(cldec.getName()); + Type type = Type.tClassOrArray(cpcls.getName().getString()); int dimension = stream.readUnsignedByte(); - Type baseType = type; - for (int i=0; i 0) writer.print(modif + " "); - writer.print((cdef.isInterface())?"interface ":"class "); - writer.println(cdef.getName().getName().toString()); + writer.print((clazz.isInterface())?"interface ":"class "); + writer.println(env.classString(clazz)); writer.tab(); - if (cdef.getSuperClass() != null) - writer.println("extends "+cdef.getSuperClass().getName().toString()); - ClassDeclaration interfaces[] = cdef.getInterfaces(); + Class superClazz = clazz.getSuperclass(); + if (superClazz != null && + superClazz != new Object().getClass()) { + writer.println("extends "+env.classString(superClazz)); + } + Class interfaces[] = clazz.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.print(env.classString(interfaces[i])); } writer.println(""); } @@ -89,11 +109,86 @@ public class ClassAnalyzer implements Analyzer { writer.println("{"); writer.tab(); - for (int i=0; i< fields.length; i++) - fields[i].dumpSource(writer); + for (int i=0; i< analyzers.length; i++) + analyzers[i].dumpSource(writer); writer.untab(); writer.println("}"); } + + + public ConstantPool getConstantPool() { + return classType.getConstants(); + } + + public CpoolEntry getConstant(int i) { + return classType.getConstant(i); + } + + public Type getConstantType(int i) + throws ClassFormatError + { + int t = classType.getConstant(i).getTag(); + switch(t) { + case ConstantPool.INTEGER: return Type.tInt ; + case ConstantPool.FLOAT : return Type.tFloat ; + case ConstantPool.LONG : return Type.tLong ; + case ConstantPool.DOUBLE : return Type.tDouble; + case ConstantPool.STRING : return Type.tString; + default: + throw new ClassFormatError("invalid constant type: "+t); + } + } + + private static String quoted(String str) { + StringBuffer result = new StringBuffer("\""); + for (int i=0; i< str.length(); i++) { + switch (str.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(str.charAt(i)); + } + } + return result.append("\"").toString(); + } + + public String getConstantString(int i) + { + CpoolEntry constant = classType.getConstant(i); + switch (constant.getTag()) { + case ConstantPool.INTEGER: + return Integer.toString(((CpoolValue1)constant).getValue()); + case ConstantPool.FLOAT: + return Float.toString + (Float.intBitsToFloat(((CpoolValue1)constant).getValue())); + case ConstantPool.LONG: + return Long.toString(((CpoolValue2)constant).getValue()); + case ConstantPool.DOUBLE: + return Double.toString + (Double.longBitsToDouble(((CpoolValue2)constant).getValue())); + case ConstantPool.STRING: + return quoted(((CpoolString)constant).getString().getString()); + } + throw new AssertError("unknown constant type"); + } + + public String getTypeString(Type type) { + return type.toString(); + } + + public String getTypeString(Type type, String name) { + return type.toString() + " " + name; + } } diff --git a/jode/jode/decompiler/CodeAnalyzer.java b/jode/jode/decompiler/CodeAnalyzer.java index 9b7bd03..2acad76 100644 --- a/jode/jode/decompiler/CodeAnalyzer.java +++ b/jode/jode/decompiler/CodeAnalyzer.java @@ -18,18 +18,23 @@ */ package jode; -import sun.tools.java.*; -import java.util.Stack; -import java.io.*; import jode.flow.FlowBlock; import jode.flow.Jump; import jode.flow.StructuredBlock; import jode.flow.RawTryCatchBlock; -public class CodeAnalyzer implements Analyzer, Constants { - - BinaryCode bincode; +import java.util.Stack; +import java.io.DataInputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import gnu.bytecode.CodeAttr; +import gnu.bytecode.Attribute; +import gnu.bytecode.LocalVarsAttr; +import gnu.bytecode.CpoolClass; + +public class CodeAnalyzer implements Analyzer { + FlowBlock methodHeader; MethodAnalyzer method; public JodeEnvironment env; @@ -43,25 +48,15 @@ public class CodeAnalyzer implements Analyzer, Constants { */ public MethodAnalyzer getMethod() {return method;} - void readCode() + void readCode(CodeAttr bincode) throws ClassFormatError { - BinaryAttribute attr = bincode.getAttributes(); - while (attr != null) { - if (attr.getName() == Constants.idLocalVariableTable) { - DataInputStream stream = - new DataInputStream - (new ByteArrayInputStream(attr.getData())); - try { - lvt = new LocalVariableTable(bincode.getMaxLocals()); - lvt.read(env, stream); - } catch (IOException ex) { - throw new ClassFormatError(ex.toString()); - } - } - attr = attr.getNextAttribute(); - } + LocalVarsAttr attr = + (LocalVarsAttr) Attribute.get(bincode, "LocalVariableTable"); + if (attr != null) + lvt = new LocalVariableTable(bincode.getMaxLocals(), + method.classAnalyzer, attr); byte[] code = bincode.getCode(); FlowBlock[] instr = new FlowBlock[code.length]; @@ -84,27 +79,30 @@ public class CodeAnalyzer implements Analyzer, Constants { methodHeader = instr[0]; methodHeader.makeStartBlock(); - BinaryExceptionHandler[] handlers = bincode.getExceptionHandlers(); - for (int i=0; i handlers[i].handlerPC)) { + > handlers[i + 2])) { tryBlock = ((RawTryCatchBlock)tryBlock).getTryBlock(); } - Type type = - (handlers[i].exceptionClass != null)? - Type.tClass(handlers[i].exceptionClass.getName().toString()) : null; + Type type = null; + + if (handlers[i + 3 ] != 0) { + CpoolClass cpcls = (CpoolClass) + method.classAnalyzer.getConstant(handlers[i + 3]); + type = Type.tClass(cpcls.getName().getString()); + } new RawTryCatchBlock(type, tryBlock, - new Jump(instr[handlers[i].endPC]), - new Jump(instr[handlers[i].handlerPC])); + new Jump(instr[handlers[i + 1]]), + new Jump(instr[handlers[i + 2]])); } - int paramCount = method.mdef.getType().getArgumentTypes().length - + (method.mdef.isStatic() ? 0 : 1); + int paramCount = method.getParamCount(); param = new jode.flow.VariableSet(); for (int i=0; i 0) writer.print(modif+" "); - writer.print(env.getTypeString(Type.tType(fdef.getType()), - fdef.getName())); - byte[] attrib = - ((BinaryField) fdef).getAttribute(Constants.idConstantValue); - if (attrib != null) { - int index = (unsigned(attrib[0]) << 8) | unsigned(attrib[1]); - writer.print(" = "+env.getConstant(index).toString()); + writer.print(Type.tType(field.getType()).toString() + + " " + field.getName()); + if (constantValue != 0) { + writer.print(" = "+clazz.getConstantString(constantValue)); } writer.println(";"); } } - - diff --git a/jode/jode/decompiler/ImportHandler.java b/jode/jode/decompiler/ImportHandler.java index 6e39e08..49ee8ff 100644 --- a/jode/jode/decompiler/ImportHandler.java +++ b/jode/jode/decompiler/ImportHandler.java @@ -18,72 +18,45 @@ */ package jode; -import sun.tools.java.*; -import sun.tools.util.*; import java.util.*; -public class JodeEnvironment extends LoadEnvironment { +public class JodeEnvironment { Hashtable imports = new Hashtable(); - BinaryClass main; - Identifier pkg; + ClassAnalyzer main; + String className; + String pkg; + + SearchPath classPath; JodeEnvironment() { - super(null); Type.setEnvironment(this); - 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 getTypeString(Type type) { - return type.toString(); - } - - public String getTypeString(Identifier clazz) { - return clazz.toString(); - } - - public String getTypeString(Type type, Identifier name) { - return type.toString() + " " + name.toString(); + classPath = new SearchPath(System.getProperty("java.class.path")); } - public ClassDefinition getClassDefinition() { - return main; + public java.io.InputStream getClassStream(Class clazz) + throws java.io.IOException { + return classPath.getFile(clazz.getName(). + replace('.', java.io.File.separatorChar) + +".class"); + } 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("/* "+ className + " - Decompiled by JoDe (Jochen's Decompiler)\n * Send comments or bug reports to Jochen Hoenicke \n */"); + if (pkg.length() != 0) 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+";"); + String importName = (String) enum.nextElement(); + Integer vote = (Integer) imports.get(importName); + if (vote.intValue() >= + (importName.endsWith(".*") + ? Decompiler.importPackageLimit + : Decompiler.importClassLimit)) + writer.println("import "+importName+";"); } writer.println(""); } @@ -94,25 +67,85 @@ public class JodeEnvironment extends LoadEnvironment { public void doClass(String className) { + Class clazz; try { - Identifier ident = Identifier.lookup(className); - error(ident.toString()); - if (!classExists(ident)) { - error("`"+ident+"' not found"); + clazz = Class.forName(className); + } catch (ClassNotFoundException ex) { + System.err.println("Class `"+className+"' not found"); + return; + } catch (IllegalArgumentException ex) { + System.err.println("`"+className+"' is not a class name"); + return; + } + + System.err.println(className); + + int pkgdelim = className.lastIndexOf('.'); + pkg = (pkgdelim == -1)? "" : className.substring(0, pkgdelim); + this.className = (pkgdelim == -1) ? className + : className.substring(pkgdelim+1); + + main = new ClassAnalyzer(null, clazz, this); + main.analyze(); + + TabbedPrintWriter writer = + new TabbedPrintWriter(System.out, " "); + try { + dumpHeader(writer); + main.dumpSource(writer); + } catch (java.io.IOException e) { + e.printStackTrace(); + } + } + + /* Marks the clazz as used, so that it will be imported if used often + * enough. + */ + public void useClass(Class clazz) { + String name = clazz.getName(); + int pkgdelim = name.lastIndexOf('.'); + if (pkgdelim != -1) { + String pkgName = name.substring(0, pkgdelim); + if (pkgName.equals(pkg) + || pkgName.equals("java.lang")) + return; + Integer i = (Integer) imports.get(pkgName+".*"); + i = (i == null)? new Integer(1): new Integer(i.intValue()+1); + imports.put(pkgName+".*", i); + if (i.intValue() >= Decompiler.importPackageLimit) return; + + i = (Integer) imports.get(name); + i = (i == null)? new Integer(1): new Integer(i.intValue()+1); + imports.put(name, i); + } + } + + /** + * Check if clazz is imported and maybe remove package delimiter from + * full qualified class name. + *

+ * Known Bug: If the same class name is in more than one imported package + * the name should be qualified, but isn't. + * @return a legal string representation of clazz. + */ + public String classString(Class clazz) { + String name = clazz.getName(); + int pkgdelim = name.lastIndexOf('.'); + if (pkgdelim != -1) { + String pkgName = name.substring(0, pkgdelim); + + Integer i; + if (pkgName.equals(pkg) + || pkgName.equals("java.lang") + || ( (i = (Integer)imports.get(pkgName+".*")) != null + && i.intValue() >= Decompiler.importPackageLimit ) + || ( (i = (Integer)imports.get(name)) != null + && i.intValue() >= Decompiler.importClassLimit )) { + return name.substring(pkgdelim+1); } - 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()); } + return name; } protected int loadFileFlags() diff --git a/jode/jode/decompiler/LocalInfo.java b/jode/jode/decompiler/LocalInfo.java index c427038..662967f 100644 --- a/jode/jode/decompiler/LocalInfo.java +++ b/jode/jode/decompiler/LocalInfo.java @@ -18,7 +18,6 @@ */ package jode; -import sun.tools.java.Identifier; import java.util.Enumeration; import java.util.Vector; @@ -36,7 +35,7 @@ import java.util.Vector; public class LocalInfo { private static int serialnr = 0; private int slot; - private Identifier name; + private String name; private Type type; private LocalInfo shadow; private Vector operators = new Vector(); @@ -46,9 +45,7 @@ public class LocalInfo { */ /** - * Create a new local info. The name will be an identifier - * of the form local_x__yyy, where x is the slot number and - * yyy a unique number. + * Create a new local info. The name will be a string * @param slot The slot of this variable. */ public LocalInfo(int slot) { @@ -108,7 +105,7 @@ public class LocalInfo { /** * Get the name of this local. */ - public Identifier getName() { + public String getName() { if (shadow != null) { while (shadow.shadow != null) { shadow = shadow.shadow; @@ -116,7 +113,7 @@ public class LocalInfo { return shadow.getName(); } if (name == null) - name = Identifier.lookup("local_"+slot+"__"+serialnr++); + name = "local_"+slot+"__"+serialnr++; return name; } @@ -131,7 +128,7 @@ public class LocalInfo { /** * Set the name of this local. */ - public void setName(Identifier name) { + public void setName(String name) { if (shadow != null) shadow.setName(name); else diff --git a/jode/jode/decompiler/LocalVariableRangeList.java b/jode/jode/decompiler/LocalVariableRangeList.java index 1c740c4..e381a5c 100644 --- a/jode/jode/decompiler/LocalVariableRangeList.java +++ b/jode/jode/decompiler/LocalVariableRangeList.java @@ -18,7 +18,6 @@ */ package jode; -import sun.tools.java.*; public class LocalVariableRangeList { @@ -27,7 +26,7 @@ public class LocalVariableRangeList { int length; MyLocalInfo next; - MyLocalInfo(int slot, int s, int l, Identifier n, Type t) { + MyLocalInfo(int slot, int s, int l, String n, Type t) { super (slot); start = s; length = l; @@ -72,7 +71,7 @@ public class LocalVariableRangeList { } public void addLocal(int start, int length, - Identifier name, Type type) { + String name, Type type) { MyLocalInfo li = new MyLocalInfo(slot,start,length,name,type); add (li); } diff --git a/jode/jode/decompiler/LocalVariableTable.java b/jode/jode/decompiler/LocalVariableTable.java index fe874e2..af7a422 100644 --- a/jode/jode/decompiler/LocalVariableTable.java +++ b/jode/jode/decompiler/LocalVariableTable.java @@ -18,61 +18,42 @@ */ package jode; -import sun.tools.java.Identifier; -import java.io.*; +import java.util.Enumeration; +import gnu.bytecode.CpoolUtf8; +import gnu.bytecode.LocalVarsAttr; +import gnu.bytecode.Variable; +import gnu.bytecode.Spy; public class LocalVariableTable { LocalVariableRangeList[] locals; - boolean readfromclass; - public LocalVariableTable(int size) { - locals = new LocalVariableRangeList[size]; - readfromclass = false; - } - - public int getSize() { - return locals.length; - } + public LocalVariableTable(int size, + ClassAnalyzer cla, LocalVarsAttr attr) { - public boolean isReadFromClass() { - return readfromclass; - } - - public void read(JodeEnvironment env, DataInputStream stream) - throws IOException - { - int count = stream.readUnsignedShort(); - for (int i=0; i" : m.getName(); + Class[] paramTypes = (isConstructor + ? c.getParameterTypes() + : m.getParameterTypes()); + + gnu.bytecode.Method mdef = cla.classType.getMethods(); + while (mdef != null) { + if (mdef.getName().equals(name)) { + gnu.bytecode.Type[] argtypes = mdef.getParameterTypes(); + if (argtypes.length == paramTypes.length) { + int i; + for (i=0; i" : method.getName())+": "); code.analyze(); if (Decompiler.isVerbose) System.err.println(""); } writer.println(""); - String modif = Modifier.toString(mdef.getModifiers()); + String modif = Modifier.toString(isConstructor + ? constr.getModifiers() + : method.getModifiers()); if (modif.length() > 0) writer.print(modif+" "); - if (mdef.isInitializer()) { + if (isConstructor && Modifier.isStatic(constr.getModifiers())) writer.print(""); /* static block */ - } else { - if (mdef.isConstructor()) - writer.print(mdef.getClassDeclaration().getName().toString()); + else { + if (isConstructor) + writer.print(env.classString(classAnalyzer.clazz)); else - writer.print(env.getTypeString - (Type.tType(mdef.getType().getReturnType())) - + " " + mdef.getName().toString()); + writer.print(Type.tType(method.getReturnType()).toString() + + " " + method.getName()); writer.print("("); - sun.tools.java.Type[] paramTypes = - mdef.getType().getArgumentTypes(); - int offset = mdef.isStatic()?0:1; + Class[] paramTypes = isConstructor + ? constr.getParameterTypes() : method.getParameterTypes(); + int offset = (!isConstructor + && Modifier.isStatic(method.getModifiers()))?0:1; for (int i=0; i0) writer.print(", "); - writer.print - ((code == null)? - env.getTypeString(Type.tType(paramTypes[i])): - env.getTypeString(Type.tType(paramTypes[i]), - code.getParamInfo(i+offset).getName())); + if (code == null) { + writer.print(classAnalyzer.getTypeString + (Type.tType(paramTypes[i]))); + } else { + LocalInfo li = code.getParamInfo(i+offset); + writer.print(li.getType().toString()+" "+li.getName()); + } } writer.print(")"); } - IdentifierToken[] exceptions = mdef.getExceptionIds(); + Class[] exceptions = isConstructor + ? constr.getExceptionTypes() : method.getExceptionTypes(); if (exceptions != null && exceptions.length > 0) { writer.println(""); writer.print("throws "); @@ -116,7 +165,7 @@ public class MethodAnalyzer implements Analyzer, Constants { if (exceptions[i] != null) { if (i > 0) writer.print(", "); - writer.print(env.getTypeString(exceptions[i].getName())); + writer.print(env.classString(exceptions[i])); } } } @@ -129,13 +178,4 @@ public class MethodAnalyzer implements Analyzer, Constants { } else writer.println(";"); } - - /* - public byte[] getAttribute(Identifier identifier) - { - if (mdef instanceof BinaryField) - return ((BinaryField)mdef).getAttribute(identifier); - return null; - } - */ } diff --git a/jode/jode/expr/ComplexExpression.java b/jode/jode/expr/ComplexExpression.java index 1c8cccf..053889d 100644 --- a/jode/jode/expr/ComplexExpression.java +++ b/jode/jode/expr/ComplexExpression.java @@ -18,7 +18,6 @@ */ package jode; -import sun.tools.java.Constants; public class ComplexExpression extends Expression { Operator operator; @@ -181,14 +180,14 @@ public class ComplexExpression extends Expression { new EmptyStringOperator(); Expression simplifyStringBuffer() { - sun.tools.java.FieldDefinition field; - if (operator instanceof InvokeOperator && - (field = ((InvokeOperator)operator).getField()) - .getClassDefinition().getName() - == Constants.idJavaLangStringBuffer + gnu.bytecode.CpoolRef field; + if (operator instanceof InvokeOperator + && ((field = ((InvokeOperator)operator).getField()) + .getCpoolClass().getName().getString() + .equals("java.lang.StringBuffer")) && !((InvokeOperator)operator).isStatic() && - field.getName() == Constants.idAppend && - field.getType().getArgumentTypes().length == 1) { + field.getNameAndType().getName().getString().equals("append") && + ((InvokeOperator)operator).getMethodType().getArgumentTypes().length == 1) { Expression e = subExpressions[0].simplifyStringBuffer(); if (e == null) @@ -286,26 +285,26 @@ public class ComplexExpression extends Expression { return subExpressions[0].simplify(); } - if (operator instanceof InvokeOperator && - ((InvokeOperator)operator).getField() - .getName() == Constants.idToString && - !((InvokeOperator)operator).isStatic() && - ((InvokeOperator)operator).getField() - .getClassDefinition().getName() - == Constants.idJavaLangStringBuffer && - subExpressions.length == 1) { + if (operator instanceof InvokeOperator + && (((InvokeOperator)operator).getField() + .getNameAndType().getName().getString().equals("toString")) + && !((InvokeOperator)operator).isStatic() + && (((InvokeOperator)operator).getField() + .getCpoolClass().getName().getString() + .equals("java.lang.StringBuffer")) + && 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).isStatic() && - ((InvokeOperator)operator).getField() - .getClassDefinition().getName() - == Constants.idJavaLangString && - subExpressions.length == 1) { + if (operator instanceof InvokeOperator + && (((InvokeOperator)operator).getField() + .getNameAndType().getName().getString().equals("valueOf")) + && ((InvokeOperator)operator).isStatic() + && (((InvokeOperator)operator).getField() + .getCpoolClass().getName().getString() + .equals("java.lang.String")) + && subExpressions.length == 1) { if (subExpressions[0].getType() == Type.tString) return subExpressions[0].simplify(); else { diff --git a/jode/jode/expr/ConstOperator.java b/jode/jode/expr/ConstOperator.java index d0405a1..ed280d5 100644 --- a/jode/jode/expr/ConstOperator.java +++ b/jode/jode/expr/ConstOperator.java @@ -24,8 +24,6 @@ public class ConstOperator extends NoArgOperator { public ConstOperator(Type type, String value) { super(type); - if (type == Type.tString) - value = quoted(value); this.value = value; } @@ -37,29 +35,6 @@ public class ConstOperator extends NoArgOperator { return 1000; } - public static String quoted(String str) { - StringBuffer result = new StringBuffer("\""); - for (int i=0; i< str.length(); i++) { - switch (str.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(str.charAt(i)); - } - } - return result.append("\"").toString(); - } - public boolean equals(Object o) { return (o instanceof ConstOperator) && ((ConstOperator)o).value.equals(value); diff --git a/jode/jode/expr/ConstructorOperator.java b/jode/jode/expr/ConstructorOperator.java index 074a482..980ef61 100644 --- a/jode/jode/expr/ConstructorOperator.java +++ b/jode/jode/expr/ConstructorOperator.java @@ -18,13 +18,17 @@ */ package jode; -import sun.tools.java.FieldDefinition; +import gnu.bytecode.CpoolRef; public class ConstructorOperator extends Operator { - FieldDefinition field; + CpoolRef field; + MethodType methodType; + Type classType; - public ConstructorOperator(Type type, FieldDefinition field) { + public ConstructorOperator(Type type, CpoolRef field) { super(type, 0); + methodType = new MethodType(field.getNameAndType(). + getType().getString()); this.field = field; } @@ -33,7 +37,7 @@ public class ConstructorOperator extends Operator { } public int getOperandCount() { - return 1 + field.getType().getArgumentTypes().length; + return 1 + methodType.getArgumentTypes().length; } public int getOperandPriority(int i) { @@ -44,10 +48,8 @@ public class ConstructorOperator extends Operator { public Type getOperandType(int i) { if (i == 0) - return Type.tSubType(Type.tClass(field.getClassDeclaration() - .getName().toString())); - return Type.tSubType(Type.tType(field.getType() - .getArgumentTypes()[i-1])); + return Type.tSubType(type); + return Type.tSubType(methodType.getArgumentTypes()[i-1]); } public void setOperandType(Type types[]) { @@ -55,7 +57,7 @@ public class ConstructorOperator extends Operator { public String toString(String[] operands) { StringBuffer result = new StringBuffer(operands[0]).append("("); - for (int i=0; i < field.getType().getArgumentTypes().length; i++) { + for (int i=0; i < methodType.getArgumentTypes().length; i++) { if (i>0) result.append(", "); result.append(operands[i+1]); diff --git a/jode/jode/expr/GetFieldOperator.java b/jode/jode/expr/GetFieldOperator.java index 46f60c5..614df64 100644 --- a/jode/jode/expr/GetFieldOperator.java +++ b/jode/jode/expr/GetFieldOperator.java @@ -18,16 +18,16 @@ */ package jode; -import sun.tools.java.*; +import gnu.bytecode.CpoolRef; public class GetFieldOperator extends Operator { boolean staticFlag; - FieldDefinition field; + CpoolRef field; CodeAnalyzer codeAnalyzer; public GetFieldOperator(CodeAnalyzer codeAnalyzer, boolean staticFlag, - FieldDefinition field) { - super(Type.tType(field.getType()), 0); + CpoolRef field) { + super(Type.tType(field.getNameAndType().getType().getString()), 0); this.codeAnalyzer = codeAnalyzer; this.staticFlag = staticFlag; this.field = field; @@ -54,8 +54,8 @@ public class GetFieldOperator extends Operator { /* shouldn't be called */ throw new RuntimeException("Field is static"); } - return Type.tSubType(Type.tClass(field.getClassDeclaration() - .getName().toString())); + return Type.tSubType(Type.tClass(field.getCpoolClass() + .getName().getString())); } public void setOperandType(Type types[]) { @@ -64,18 +64,19 @@ public class GetFieldOperator extends Operator { public String toString(String[] operands) { String object; if (staticFlag) { - if (field.getClassDefinition() == codeAnalyzer.getClassDefinition()) - return field.getName().toString(); + if (field.getCpoolClass().getName().getString() + .equals(codeAnalyzer.getClazz().getName())) + return field.getNameAndType().getName().getString(); object = codeAnalyzer.getTypeString - (Type.tClass(field.getClassDeclaration() - .getName().toString())); + (Type.tClass(field.getCpoolClass() + .getName().getString())); } else { if (operands[0].equals("this")) - return field.getName().toString(); + return field.getNameAndType().getName().getString(); object = operands[0]; } - return object + "." + field.getName(); + return object + "." + field.getNameAndType().getName().getString(); } public boolean equals(Object o) { diff --git a/jode/jode/expr/InvokeOperator.java b/jode/jode/expr/InvokeOperator.java index 6146457..341c07a 100644 --- a/jode/jode/expr/InvokeOperator.java +++ b/jode/jode/expr/InvokeOperator.java @@ -18,19 +18,24 @@ */ package jode; -import sun.tools.java.*; +import gnu.bytecode.CpoolRef; -public class InvokeOperator extends Operator { +public final class InvokeOperator extends Operator { CodeAnalyzer codeAnalyzer; boolean staticFlag; boolean specialFlag; - FieldDefinition field; + MethodType methodType; + Type classType; + CpoolRef field; public InvokeOperator(CodeAnalyzer codeAnalyzer, boolean staticFlag, boolean specialFlag, - FieldDefinition field) { - super(Type.tType(field.getType().getReturnType().getTypeSignature()), - 0); + CpoolRef field) { + super(Type.tError, 0); + methodType = new MethodType(field.getNameAndType(). + getType().getString()); + classType = Type.tClass(field.getCpoolClass().getName().getString()); + setType(methodType.getReturnType()); this.codeAnalyzer = codeAnalyzer; this.staticFlag = staticFlag; this.specialFlag = specialFlag; @@ -41,12 +46,16 @@ public class InvokeOperator extends Operator { return staticFlag; } - public FieldDefinition getField() { + public CpoolRef getField() { return field; } + public MethodType getMethodType() { + return methodType; + } + public Type getClassType() { - return Type.tClass(field.getClassDeclaration().getName().toString()); + return classType; } public int getPriority() { @@ -54,7 +63,7 @@ public class InvokeOperator extends Operator { } public int getOperandCount() { - return (staticFlag?0:1) + field.getType().getArgumentTypes().length; + return (staticFlag?0:1) + methodType.getArgumentTypes().length; } public int getOperandPriority(int i) { @@ -69,65 +78,49 @@ public class InvokeOperator extends Operator { return Type.tSubType(getClassType()); i--; } - return Type.tSubType(Type.tType(field.getType(). - getArgumentTypes()[i]. - getTypeSignature())); + return Type.tSubType(methodType.getArgumentTypes()[i]); } public void setOperandType(Type types[]) { } public boolean isConstructor() { - return field.isConstructor(); + return field.getNameAndType().getName().getString().equals(""); } public String toString(String[] operands) { - String object; - int arg = 0; - if (staticFlag) { - if (field.getClassDefinition() == codeAnalyzer.getClassDefinition()) - object = ""; - else - object = codeAnalyzer. - getTypeString(getClassType()); - } else { - if (operands[arg].equals("this")) { - if (specialFlag - && (field.getClassDeclaration() - == codeAnalyzer.getClassDefinition().getSuperClass())) -// || (field.getClassDeclaration().getName() -// == Constants.idJavaLangObject -// && codeAnalyzer.getClassDefinition() -// .getSuperClass() == null))) - object = "super"; - else if (specialFlag) - object = "(("+codeAnalyzer.getTypeString(getClassType()) - + ") this)"; - else - object = ""; - } else { - if (specialFlag) - object = "((" + codeAnalyzer.getTypeString(getClassType()) - + ") " + operands[arg]+")"; - else - object = operands[arg]; - } - arg++; - } + String object = + staticFlag + ? ((field.getCpoolClass().getName().getString() + .replace(java.io.File.separatorChar, '.') + .equals(codeAnalyzer.getClazz().getName())) + ? "" + : codeAnalyzer.getTypeString(getClassType())) + : (operands[0].equals("this") + ? (specialFlag + ? ( (field.getCpoolClass().getName().getString() + .replace(java.io.File.separatorChar, '.') + .equals(codeAnalyzer.getClazz() + .getSuperclass().getName())) + ? "super" + : "((" + codeAnalyzer.getTypeString(getClassType()) + + ") this)" ) + : "") + : (specialFlag + ? "((" + codeAnalyzer.getTypeString(getClassType()) + + ") " + operands[0]+")" + : operands[0] )); + + int arg = staticFlag ? 0 : 1; 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(); - } + if (isConstructor()) + method = (object.length() == 0 ? "this" : object); + else + method = (object.length() == 0 ? "" : object + ".") + + field.getNameAndType().getName().getString(); + StringBuffer params = new StringBuffer(); - for (int i=0; i < field.getType().getArgumentTypes().length; i++) { + for (int i=0; i < methodType.getArgumentTypes().length; i++) { if (i>0) params.append(", "); params.append(operands[arg++]); diff --git a/jode/jode/expr/NewArrayOperator.java b/jode/jode/expr/NewArrayOperator.java index 0c3654f..c35b4ae 100644 --- a/jode/jode/expr/NewArrayOperator.java +++ b/jode/jode/expr/NewArrayOperator.java @@ -22,13 +22,11 @@ package jode; public class NewArrayOperator extends SimpleOperator { String baseTypeString; - public NewArrayOperator(Type arrayType, String baseTypeString, - int dimensions) { + public NewArrayOperator(Type arrayType, int dimensions) { super(arrayType, 0, dimensions); for (int i=0; i< dimensions; i++) { operandTypes[i] = Type.tInt; } - this.baseTypeString = baseTypeString; } public int getPriority() { @@ -40,11 +38,16 @@ public class NewArrayOperator extends SimpleOperator { } public String toString(String[] operands) { - StringBuffer result - = new StringBuffer("new ").append(baseTypeString); - for (int i=0; i< getOperandCount(); i++) { - result.append("[").append(operands[i]).append("]"); + StringBuffer arrays = new StringBuffer(); + Type flat = type; + int i = 0; + while (flat instanceof ArrayType) { + flat = ((ArrayType)flat).getElementType(); + if (i < getOperandCount()) + arrays.append("[").append(operands[i++]).append("]"); + else + arrays.append("[]"); } - return result.toString(); + return "new "+flat.toString()+arrays; } } diff --git a/jode/jode/expr/Operator.java b/jode/jode/expr/Operator.java index 9405b8b..1deb0c2 100644 --- a/jode/jode/expr/Operator.java +++ b/jode/jode/expr/Operator.java @@ -69,13 +69,6 @@ public abstract class Operator extends Expression { operator = op; } - /** - * Sets the return type of this operator. - */ - public void setType(Type type) { - this.type = type; - } - public String getOperatorString() { return opString[operator]; } diff --git a/jode/jode/expr/PutFieldOperator.java b/jode/jode/expr/PutFieldOperator.java index 1ee8c45..97c6743 100644 --- a/jode/jode/expr/PutFieldOperator.java +++ b/jode/jode/expr/PutFieldOperator.java @@ -18,16 +18,16 @@ */ package jode; -import sun.tools.java.*; +import gnu.bytecode.CpoolRef; public class PutFieldOperator extends StoreInstruction { CodeAnalyzer codeAnalyzer; boolean staticFlag; - FieldDefinition field; + CpoolRef field; public PutFieldOperator(CodeAnalyzer codeAnalyzer, boolean staticFlag, - FieldDefinition field) { - super(Type.tType(field.getType()), ASSIGN_OP); + CpoolRef field) { + super(Type.tType(field.getNameAndType().getType().getString()), ASSIGN_OP); this.codeAnalyzer = codeAnalyzer; this.staticFlag = staticFlag; this.field = field; @@ -55,8 +55,8 @@ public class PutFieldOperator extends StoreInstruction { /* shouldn't be called */ throw new AssertError("Field is static"); } - return Type.tSubType(Type.tClass(field.getClassDefinition() - .getName().toString())); + return Type.tSubType(Type.tClass(field.getCpoolClass() + .getName().getString())); } public void setLValueOperandType(Type[] t) { @@ -70,18 +70,17 @@ public class PutFieldOperator extends StoreInstruction { public String getLValueString(String[] operands) { String object; if (staticFlag) { - if (field.getClassDefinition() - == codeAnalyzer.getClassDefinition()) - return field.getName().toString(); + if (field.getCpoolClass().getName().getString() + .equals(codeAnalyzer.getClazz().getName())) + return field.getNameAndType().getName().getString(); object = codeAnalyzer.getTypeString - (Type.tClass(field.getClassDeclaration() - .getName().toString()))+"."; + (Type.tClass(field.getCpoolClass().getName().getString())); } else { if (operands[0].equals("this")) - return field.getName().toString(); + return field.getNameAndType().getName().getString(); object = operands[0]; } - return object + "." + field.getName(); + return object + "." + field.getNameAndType().getName().getString(); } public boolean equals(Object o) { diff --git a/jode/jode/flow/CatchBlock.java b/jode/jode/flow/CatchBlock.java index acc73bc..2d59682 100644 --- a/jode/jode/flow/CatchBlock.java +++ b/jode/jode/flow/CatchBlock.java @@ -19,7 +19,6 @@ package jode.flow; import jode.Type; import jode.LocalInfo; -import sun.tools.java.Identifier; /** * @@ -72,8 +71,7 @@ public class CatchBlock extends StructuredBlock { if (instr instanceof jode.PopOperator) { exceptionLocal = new LocalInfo(-1); - exceptionLocal.setName - (Identifier.lookup("exception_"+(serialno++)+"_")); + exceptionLocal.setName("exception_"+(serialno++)+"_"); exceptionLocal.setType(exceptionType); } else if (instr instanceof jode.LocalStoreOperator) { exceptionLocal = @@ -92,7 +90,7 @@ public class CatchBlock extends StructuredBlock { } if (exceptionLocal == null) { exceptionLocal = new LocalInfo(-1); - exceptionLocal.setName(Identifier.lookup("ERROR!!!")); + exceptionLocal.setName("ERROR!!!"); exceptionLocal.setType(exceptionType); } used.addElement(exceptionLocal); diff --git a/jode/jode/type/ClassInterfacesType.java b/jode/jode/type/ClassInterfacesType.java index 224bd99..242eca5 100644 --- a/jode/jode/type/ClassInterfacesType.java +++ b/jode/jode/type/ClassInterfacesType.java @@ -17,7 +17,6 @@ * $Id$ */ package jode; -import sun.tools.java.*; import java.util.Vector; import java.util.Stack; @@ -370,9 +369,9 @@ public class ClassInterfacesType extends Type { return sb.append("}").toString(); } else { if (clazz != null) - return clazz.getName(); + return env.classString(clazz); else if (ifaces.length > 0) - return ifaces[0].getName(); + return env.classString(ifaces[0]); else return "{}"; } diff --git a/jode/jode/type/MethodType.java b/jode/jode/type/MethodType.java new file mode 100644 index 0000000..91d397a --- /dev/null +++ b/jode/jode/type/MethodType.java @@ -0,0 +1,65 @@ +/* MethodType Copyright (C) 1997-1998 Jochen Hoenicke. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ +package jode; + +/** + * This type represents an method type. + * + * @author Jochen Hoenicke + */ +public class MethodType { + Type[] argumentTypes; + Type returnType; + Type elementType; + + public MethodType(String signature) { + int index = 1, types = 0; + while (signature.charAt(index) != ')') { + types++; + while (signature.charAt(index) == '[') + index++; + if (signature.charAt(index) == 'L') + index = signature.indexOf(';', index); + index++; + } + argumentTypes = new Type[types]; + + index = 1; + types = 0; + while (signature.charAt(index) != ')') { + int lastindex = index; + while (signature.charAt(index) == '[') + index++; + if (signature.charAt(index) == 'L') + index = signature.indexOf(';', index); + index++; + argumentTypes[types++] + = Type.tType(signature.substring(lastindex,index)); + } + returnType = Type.tType(signature.substring(index+1)); + } + + public Type[] getArgumentTypes() { + return argumentTypes; + } + + public Type getReturnType() { + return returnType; + } +} diff --git a/jode/jode/type/Type.java b/jode/jode/type/Type.java index 6f6170d..c237333 100644 --- a/jode/jode/type/Type.java +++ b/jode/jode/type/Type.java @@ -21,7 +21,7 @@ package jode; import java.util.Hashtable; /** - * This is my type class. It differs from sun.tools.java.Type, in + * This is my type class. It differs from java.lang.class, in * that it maintains a type range. This type range may be implicit or * explicit.

* @@ -138,16 +138,31 @@ public class Type { int index = type.indexOf(';'); if (index != type.length()-1) return tError; - return tClass(type.substring(1, index).replace('/', '.')); + return tClass(type.substring(1, index)); } throw new AssertError("Unknown type signature: "+type); } - public static final Type tType(sun.tools.java.Type type) { - return tType(type.getTypeSignature()); + public static final Type tType(Class clazz) { + if (clazz.isArray()) + return tArray(tType(clazz.getComponentType())); + if (clazz.isPrimitive()) { + return clazz == Boolean.TYPE ? tBoolean + : clazz == Byte.TYPE ? tByte + : clazz == Character.TYPE ? tChar + : clazz == Short.TYPE ? tShort + : clazz == Integer.TYPE ? tInt + : clazz == Float.TYPE ? tFloat + : clazz == Long.TYPE ? tLong + : clazz == Double.TYPE ? tDouble + : clazz == Void.TYPE ? tVoid + : tError; + } + return tClass(clazz.getName()); } public static final Type tClass(String clazzname) { + clazzname = clazzname.replace(java.io.File.separatorChar, '.'); Object result = classHash.get(clazzname); if (result == null) { result = new ClassInterfacesType(clazzname); @@ -184,11 +199,11 @@ public class Type { return tUnknown.createRangeType(type.getBottom()); } - public static Type tClassOrArray(sun.tools.java.Identifier ident) { - if (ident.toString().charAt(0) == '[') - return Type.tType(ident.toString()); + public static Type tClassOrArray(String ident) { + if (ident.charAt(0) == '[') + return Type.tType(ident); else - return Type.tClass(ident.toString()); + return Type.tClass(ident); } public static void setEnvironment(JodeEnvironment e) {