no gnu bytecode dependencies any more

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@137 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 0b95a6ce95
commit 074140743d
  1. 94
      jode/jode/bytecode/Opcodes.java
  2. 155
      jode/jode/decompiler/ClassAnalyzer.java
  3. 79
      jode/jode/decompiler/CodeAnalyzer.java
  4. 34
      jode/jode/decompiler/FieldAnalyzer.java
  5. 20
      jode/jode/decompiler/ImportHandler.java
  6. 45
      jode/jode/decompiler/LocalVariableTable.java
  7. 51
      jode/jode/decompiler/MethodAnalyzer.java
  8. 1
      jode/jode/expr/ConstructorOperator.java
  9. 1
      jode/jode/expr/GetFieldOperator.java
  10. 3
      jode/jode/expr/InvokeOperator.java
  11. 1
      jode/jode/expr/PutFieldOperator.java
  12. 9
      jode/jode/type/ArrayType.java
  13. 68
      jode/jode/type/ClassInterfacesType.java
  14. 18
      jode/jode/type/MethodType.java

@ -20,8 +20,7 @@
package jode;
import jode.flow.*;
import java.io.*;
import gnu.bytecode.CpoolRef;
import gnu.bytecode.CpoolClass;
import jode.bytecode.ConstantPool;
/**
* This is an abstract class which creates flow blocks for the
@ -447,7 +446,8 @@ public abstract class Opcodes {
* @exception IOException if an read error occured.
* @exception ClassFormatError if an invalid opcode is detected.
*/
public static StructuredBlock readOpcode(int addr, DataInputStream stream,
public static StructuredBlock readOpcode(ConstantPool cpool,
int addr, DataInputStream stream,
CodeAnalyzer ca)
throws IOException, ClassFormatError
{
@ -499,16 +499,16 @@ public abstract class Opcodes {
int index = stream.readUnsignedByte();
return createNormal
(ca, addr, 2, new ConstOperator
(ca.method.classAnalyzer.getConstantType(index),
ca.method.classAnalyzer.getConstantString(index)));
(cpool.getConstantType(index),
cpool.getConstantString(index)));
}
case opc_ldc_w:
case opc_ldc2_w: {
int index = stream.readUnsignedShort();
return createNormal
(ca, addr, 3, new ConstOperator
(ca.method.classAnalyzer.getConstantType(index),
ca.method.classAnalyzer.getConstantString(index)));
(cpool.getConstantType(index),
cpool.getConstantString(index)));
}
case opc_iload: case opc_lload:
case opc_fload: case opc_dload: case opc_aload:
@ -719,63 +719,41 @@ public abstract class Opcodes {
(ca, addr, 1, new EmptyBlock(new Jump(-1)));
case opc_getstatic:
case opc_getfield: {
CpoolRef field = (CpoolRef)ca.method.classAnalyzer
.getConstant(stream.readUnsignedShort());
String[] ref = cpool.getRef(stream.readUnsignedShort());
return createNormal
(ca, addr, 3, new GetFieldOperator
(ca, opcode == opc_getstatic,
Type.tClass(field.getCpoolClass().getName().getString()),
Type.tType(field.getNameAndType().getType().getString()),
field.getNameAndType().getName().getString()));
Type.tClass(ref[0]), Type.tType(ref[2]), ref[1]));
}
case opc_putstatic:
case opc_putfield: {
CpoolRef field = (CpoolRef)ca.method.classAnalyzer
.getConstant(stream.readUnsignedShort());
String[] ref = cpool.getRef(stream.readUnsignedShort());
return createNormal
(ca, addr, 3, new PutFieldOperator
(ca, opcode == opc_putstatic,
Type.tClass(field.getCpoolClass().getName().getString()),
Type.tType(field.getNameAndType().getType().getString()),
field.getNameAndType().getName().getString()));
Type.tClass(ref[0]), Type.tType(ref[2]), ref[1]));
}
case opc_invokevirtual:
case opc_invokespecial:
case opc_invokestatic : {
CpoolRef field = (CpoolRef)ca.method.classAnalyzer
.getConstant(stream.readUnsignedShort());
return createNormal
(ca, addr, 3, new InvokeOperator
(ca, opcode == opc_invokespecial,
Type.tClass(field.getCpoolClass()
.getName().getString()),
new MethodType(opcode == opc_invokestatic,
field.getNameAndType()
.getType().getString()),
field.getNameAndType().getName().getString()));
}
case opc_invokestatic :
case opc_invokeinterface: {
CpoolRef field = (CpoolRef)ca.method.classAnalyzer.getConstant
(stream.readUnsignedShort());
String[] ref = cpool.getRef(stream.readUnsignedShort());
StructuredBlock block = createNormal
(ca, addr, 5, new InvokeOperator
(ca, false,
Type.tClass(field.getCpoolClass()
.getName().getString()),
new MethodType(false, field.getNameAndType()
.getType().getString()),
field.getNameAndType().getName().getString()));
int reserved = stream.readUnsignedShort();
(ca, addr, opcode == opc_invokeinterface ? 5 : 3,
new InvokeOperator
(ca, opcode == opc_invokespecial,
Type.tClass(ref[0]),
new MethodType(opcode == opc_invokestatic, ref[2]),
ref[1]));
if (opcode == opc_invokeinterface)
stream.readUnsignedShort();
return block;
}
case opc_new: {
CpoolClass cpcls = (CpoolClass)
ca.method.classAnalyzer.getConstant(stream.readUnsignedShort());
Type type = Type.tClassOrArray(cpcls.getName().getString());
Type type = Type.tClassOrArray
(cpool.getClassName(stream.readUnsignedShort()));
type.useType();
return createNormal
(ca, addr, 3, new NewOperator(type));
return createNormal(ca, addr, 3, new NewOperator(type));
}
case opc_newarray: {
Type type;
@ -796,10 +774,8 @@ public abstract class Opcodes {
(ca, addr, 2, new NewArrayOperator(Type.tArray(type), 1));
}
case opc_anewarray: {
CpoolClass cpcls = (CpoolClass)
ca.method.classAnalyzer.getConstant
(stream.readUnsignedShort());
Type type = Type.tClassOrArray(cpcls.getName().getString());
Type type = Type.tClassOrArray
(cpool.getClassName(stream.readUnsignedShort()));
type.useType();
return createNormal
(ca, addr, 3, new NewArrayOperator(Type.tArray(type), 1));
@ -813,19 +789,15 @@ public abstract class Opcodes {
new ThrowBlock(new NopOperator(Type.tUObject),
new Jump(-1)));
case opc_checkcast: {
CpoolClass cpcls = (CpoolClass)
ca.method.classAnalyzer.getConstant
(stream.readUnsignedShort());
Type type = Type.tClassOrArray(cpcls.getName().getString());
Type type = Type.tClassOrArray
(cpool.getClassName(stream.readUnsignedShort()));
type.useType();
return createNormal
(ca, addr, 3, new CheckCastOperator(type));
}
case opc_instanceof: {
CpoolClass cpcls = (CpoolClass)
ca.method.classAnalyzer.getConstant
(stream.readUnsignedShort());
Type type = Type.tClassOrArray(cpcls.getName().getString());
Type type = Type.tClassOrArray
(cpool.getClassName(stream.readUnsignedShort()));
type.useType();
return createNormal
(ca, addr, 3, new InstanceOfOperator(type));
@ -877,10 +849,8 @@ public abstract class Opcodes {
}
}
case opc_multianewarray: {
CpoolClass cpcls = (CpoolClass)
ca.method.classAnalyzer.getConstant
(stream.readUnsignedShort());
Type type = Type.tClassOrArray(cpcls.getName().getString());
Type type = Type.tClassOrArray
(cpool.getClassName(stream.readUnsignedShort()));
int dimension = stream.readUnsignedByte();
return createNormal
(ca, addr, 4,

@ -18,32 +18,31 @@
*/
package jode;
import java.lang.reflect.Modifier;
import gnu.bytecode.ConstantPool;
import gnu.bytecode.CpoolEntry;
import gnu.bytecode.CpoolValue1;
import gnu.bytecode.CpoolValue2;
import gnu.bytecode.CpoolString;
import jode.bytecode.ClassHierarchy;
import jode.bytecode.ClassInfo;
import jode.bytecode.FieldInfo;
import jode.bytecode.MethodInfo;
import jode.bytecode.ConstantPool;
import jode.bytecode.ClassFormatException;
import jode.flow.TransformConstructors;
import java.lang.reflect.Modifier;
public class ClassAnalyzer implements Analyzer {
JodeEnvironment env;
Analyzer[] analyzers;
MethodAnalyzer staticConstructor;
MethodAnalyzer[] constructors;
ClassHierarchy clazz;
gnu.bytecode.ClassType classType;
ClassInfo clazz;
ClassAnalyzer parent;
public ClassAnalyzer(ClassAnalyzer parent, ClassHierarchy clazz,
public ClassAnalyzer(ClassAnalyzer parent, ClassInfo clazz,
JodeEnvironment env)
{
clazz.loadInfo(clazz.FULLINFO);
this.parent = parent;
this.clazz = clazz;
this.env = env;
this.classType = env.getClassType(clazz.getName());
}
public boolean setFieldInitializer(String fieldName, Expression expr) {
@ -57,7 +56,7 @@ public class ClassAnalyzer implements Analyzer {
return false;
}
public ClassHierarchy getClazz() {
public ClassInfo getClazz() {
return clazz;
}
@ -65,19 +64,27 @@ public class ClassAnalyzer implements Analyzer {
int numFields = 0;
int i = 0;
analyzers = new Analyzer[classType.getFieldCount() +
classType.getMethodCount()];
for (gnu.bytecode.Field field = classType.getFields();
field != null; field = field.getNext()) {
analyzers[i] = new FieldAnalyzer(this, field, env);
FieldInfo[] fields = clazz.getFields();
MethodInfo[] methods = clazz.getMethods();
if (fields == null) {
/* This means that the class could not be loaded.
* give up.
*/
return;
}
analyzers = new Analyzer[fields.length +
methods.length];
for (int j=0; j < fields.length; j++) {
analyzers[i] = new FieldAnalyzer(this, fields[j], env);
analyzers[i++].analyze();
}
staticConstructor = null;
java.util.Vector constrVector = new java.util.Vector();
for (gnu.bytecode.Method method = classType.getMethods();
method != null; method = method.getNext()) {
MethodAnalyzer analyzer = new MethodAnalyzer(this, method, env);
for (int j=0; j < methods.length; j++) {
MethodAnalyzer analyzer =
new MethodAnalyzer(this, methods[j], env);
analyzers[i++] = analyzer;
if (analyzer.isConstructor()) {
@ -100,31 +107,33 @@ public class ClassAnalyzer implements Analyzer {
env.useClass(clazz.getName());
if (clazz.getSuperclass() != null)
env.useClass(clazz.getSuperclass().getName());
ClassHierarchy[] interfaces = clazz.getInterfaces();
ClassInfo[] interfaces = clazz.getInterfaces();
for (int j=0; j< interfaces.length; j++)
env.useClass(interfaces[j].getName());
}
public void dumpSource(TabbedPrintWriter writer) throws java.io.IOException
{
// if (cdef.getSource() != null)
// writer.println("/* Original source: "+cdef.getSource()+" */");
if (analyzers == null) {
/* This means that the class could not be loaded.
* give up.
*/
return;
}
String modif = Modifier.toString(clazz.getModifiers()
& ~Modifier.SYNCHRONIZED);
if (modif.length() > 0)
writer.print(modif + " ");
writer.print(clazz.isInterface()
? ""/*interface is in modif*/
: "class ");
? ""/*interface is in modif*/ : "class ");
writer.println(env.classString(clazz.getName()));
writer.tab();
ClassHierarchy superClazz = clazz.getSuperclass();
ClassInfo superClazz = clazz.getSuperclass();
if (superClazz != null &&
superClazz != ClassHierarchy.javaLangObject) {
superClazz != ClassInfo.javaLangObject) {
writer.println("extends "+env.classString(superClazz.getName()));
}
ClassHierarchy[] interfaces = clazz.getInterfaces();
ClassInfo[] interfaces = clazz.getInterfaces();
if (interfaces.length > 0) {
writer.print(clazz.isInterface() ? "extends " : "implements ");
for (int i=0; i < interfaces.length; i++) {
@ -144,91 +153,8 @@ public class ClassAnalyzer implements Analyzer {
writer.println("}");
}
public CpoolEntry getConstant(int i) {
return classType.getConstant(i);
}
public Type getConstantType(int i)
throws ClassFormatError
{
CpoolEntry constant = getConstant(i);
switch(constant.getTag()) {
case ConstantPool.INTEGER: {
int value = ((CpoolValue1)constant).getValue();
return ((value < Short.MIN_VALUE || value > Character.MAX_VALUE)
? Type.tInt
: (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE)
? Type.tRange(Type.tInt, Type.tChar)
: Type.tUInt);
}
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: "
+ constant.getTag());
}
}
private static String quoted(String str) {
StringBuffer result = new StringBuffer("\"");
for (int i=0; i< str.length(); i++) {
char c;
switch (c = str.charAt(i)) {
case '\0':
result.append("\\0");
break;
case '\t':
result.append("\\t");
break;
case '\n':
result.append("\\n");
break;
case '\r':
result.append("\\r");
break;
case '\\':
result.append("\\\\");
break;
case '\"':
result.append("\\\"");
break;
default:
if (c < 32) {
String oct = Integer.toOctalString(c);
result.append("\\000".substring(0, 4-oct.length()))
.append(oct);
} else if (c >= 32 && c < 127)
result.append(str.charAt(i));
else {
String hex = Integer.toHexString(c);
result.append("\\u0000".substring(0, 6-hex.length()))
.append(hex);
}
}
}
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 ConstantPool getConstantPool() {
return clazz.getConstantPool();
}
public String getTypeString(Type type) {
@ -239,4 +165,3 @@ public class ClassAnalyzer implements Analyzer {
return type.toString() + " " + name;
}
}

@ -18,7 +18,10 @@
*/
package jode;
import jode.bytecode.ClassHierarchy;
import jode.bytecode.ClassInfo;
import jode.bytecode.ConstantPool;
import jode.bytecode.AttributeInfo;
import jode.bytecode.CodeInfo;
import jode.flow.FlowBlock;
import jode.flow.TransformExceptionHandlers;
@ -29,16 +32,10 @@ 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;
import gnu.bytecode.Spy;
public class CodeAnalyzer implements Analyzer {
FlowBlock methodHeader;
CodeAttr code;
CodeInfo code;
MethodAnalyzer method;
public JodeEnvironment env;
@ -52,15 +49,14 @@ public class CodeAnalyzer implements Analyzer {
*/
public MethodAnalyzer getMethod() {return method;}
public CodeAnalyzer(MethodAnalyzer ma, CodeAttr bc, JodeEnvironment e)
public CodeAnalyzer(MethodAnalyzer ma, CodeInfo bc, JodeEnvironment e)
throws ClassFormatError
{
code = bc;
method = ma;
env = e;
LocalVarsAttr attr =
(LocalVarsAttr) Attribute.get(bc, "LocalVariableTable");
AttributeInfo attr = code.findAttribute("LocalVariableTable");
if (attr != null)
lvt = new LocalVariableTable(bc.getMaxLocals(),
method.classAnalyzer, attr);
@ -81,9 +77,10 @@ public class CodeAnalyzer implements Analyzer {
* @param code The code array.
* @param handlers The exception handlers.
*/
void readCode(byte[] code, short[] handlers)
void readCode(byte[] code, int[] handlers)
throws ClassFormatError
{
ConstantPool cpool = method.classAnalyzer.getConstantPool();
byte[] flags = new byte[code.length];
int[] lengths = new int[code.length];
try {
@ -101,7 +98,8 @@ public class CodeAnalyzer implements Analyzer {
flags[succs[i]] |= PREDECESSORS;
}
} catch (IOException ex) {
throw new ClassFormatError(ex.toString());
ex.printStackTrace();
throw new ClassFormatError(ex.getMessage());
}
for (int i=0; i<handlers.length; i += 4) {
int start = handlers[i + 0];
@ -114,6 +112,7 @@ public class CodeAnalyzer implements Analyzer {
FlowBlock[] instr = new FlowBlock[code.length];
int returnCount;
TransformExceptionHandlers excHandlers;
try {
DataInputStream stream =
new DataInputStream(new ByteArrayInputStream(code));
@ -127,7 +126,7 @@ public class CodeAnalyzer implements Analyzer {
FlowBlock lastBlock = null;
for (int addr = 0; addr < code.length; ) {
jode.flow.StructuredBlock block
= Opcodes.readOpcode(addr, stream, this);
= Opcodes.readOpcode(cpool, addr, stream, this);
if (jode.Decompiler.isVerbose && addr > mark) {
System.err.print('.');
@ -148,36 +147,34 @@ public class CodeAnalyzer implements Analyzer {
}
addr += lengths[addr];
}
} catch (IOException ex) {
throw new ClassFormatError(ex.toString());
}
for (int addr=0; addr<instr.length; ) {
instr[addr].resolveJumps(instr);
addr = instr[addr].getNextAddr();
}
TransformExceptionHandlers excHandlers
= new TransformExceptionHandlers(instr);
for (int i=0; i<handlers.length; i += 4) {
Type type = null;
int start = handlers[i + 0];
int end = handlers[i + 1];
int handler = handlers[i + 2];
if (start < 0) start += 65536;
if (end < 0) end += 65536;
if (handler < 0) handler += 65536;
if (handlers[i + 3 ] != 0) {
CpoolClass cpcls = (CpoolClass)
method.classAnalyzer.getConstant(handlers[i + 3]);
type = Type.tClass(cpcls.getName().getString());
for (int addr=0; addr<instr.length; ) {
instr[addr].resolveJumps(instr);
addr = instr[addr].getNextAddr();
}
excHandlers.addHandler(start, end, handler, type);
excHandlers = new TransformExceptionHandlers(instr);
for (int i=0; i<handlers.length; i += 4) {
Type type = null;
int start = handlers[i + 0];
int end = handlers[i + 1];
int handler = handlers[i + 2];
if (start < 0) start += 65536;
if (end < 0) end += 65536;
if (handler < 0) handler += 65536;
if (handlers[i + 3 ] != 0)
type = Type.tClass(cpool.getClassName(handlers[i + 3]));
excHandlers.addHandler(start, end, handler, type);
}
} catch (IOException ex) {
ex.printStackTrace();
throw new ClassFormatError(ex.getMessage());
}
if (Decompiler.isVerbose)
System.err.print('-');
excHandlers.analyze();
methodHeader = instr[0];
methodHeader.analyze();
@ -186,7 +183,7 @@ public class CodeAnalyzer implements Analyzer {
public void analyze()
{
byte[] codeArray = code.getCode();
short[] handlers = Spy.getExceptionHandlers(code);
int[] handlers = code.getExceptionHandlers();
readCode(codeArray, handlers);
Enumeration enum = allLocals.elements();
while (enum.hasMoreElements()) {
@ -238,7 +235,7 @@ public class CodeAnalyzer implements Analyzer {
return method.classAnalyzer.getTypeString(type);
}
public ClassHierarchy getClazz() {
public ClassInfo getClazz() {
return method.classAnalyzer.clazz;
}
}

@ -19,9 +19,9 @@
package jode;
import java.lang.reflect.Modifier;
import gnu.bytecode.Attribute;
import gnu.bytecode.MiscAttr;
import gnu.bytecode.Spy;
import jode.bytecode.FieldInfo;
import jode.bytecode.AttributeInfo;
import jode.bytecode.ClassFormatException;
public class FieldAnalyzer implements Analyzer {
ClassAnalyzer clazz;
@ -31,30 +31,34 @@ public class FieldAnalyzer implements Analyzer {
String fieldName;
Expression constant;
public FieldAnalyzer(ClassAnalyzer cla, gnu.bytecode.Field fd,
public FieldAnalyzer(ClassAnalyzer cla, FieldInfo fd,
JodeEnvironment e)
{
clazz = cla;
env = e;
modifiers = Spy.getModifiers(fd);
type = Type.tType(fd.getSignature());
modifiers = fd.getModifiers();
type = fd.getType();
fieldName = fd.getName();
constant = null;
Attribute attribute =
Attribute.get(clazz.classType.getField(fieldName),
"ConstantValue");
AttributeInfo attribute = fd.findAttribute("ConstantValue");
if (attribute != null) {
try {
int index = Spy.getAttributeStream((MiscAttr)attribute)
.readUnsignedShort();
byte[] contents = attribute.getContents();
if (contents.length != 2)
throw new AssertError("ConstantValue attribute"
+ " has wrong length");
int index = (contents[0] & 0xff) << 8 | (contents[1] & 0xff);
constant = new ConstOperator
(type.intersection(cla.getConstantType(index)),
cla.getConstantString(index));
(type.intersection(cla.getConstantPool()
.getConstantType(index)),
cla.getConstantPool().getConstantString(index));
constant.makeInitializer();
} catch (java.io.IOException ex) {
throw new AssertError("attribute too small");
} catch (ClassFormatException ex) {
ex.printStackTrace();
throw new AssertError("ClassFormatException");
}
}
}

@ -19,8 +19,7 @@
package jode;
import java.util.*;
import jode.bytecode.ClassHierarchy;
import gnu.bytecode.ClassType;
import jode.bytecode.ClassInfo;
public class JodeEnvironment {
Hashtable imports;
@ -34,24 +33,13 @@ public class JodeEnvironment {
JodeEnvironment(String path) {
classPath = new SearchPath(path);
ClassHierarchy.setClassPath(classPath);
ClassInfo.setClassPath(classPath);
Type.setEnvironment(this);
imports = new Hashtable();
/* java.lang is always imported */
imports.put("java.lang.*", new Integer(Integer.MAX_VALUE));
}
public gnu.bytecode.ClassType getClassType(String clazzName) {
try {
return gnu.bytecode.ClassFileInput.readClassType
(classPath.getFile(clazzName.replace('.', '/')
+".class"));
} catch (java.io.IOException ex) {
ex.printStackTrace();
throw new RuntimeException("Class not found.");
}
}
/**
* Checks if the className conflicts with a class imported from
* another package and must be fully qualified therefore.
@ -172,9 +160,9 @@ public class JodeEnvironment {
public void doClass(String className)
{
ClassHierarchy clazz;
ClassInfo clazz;
try {
clazz = ClassHierarchy.forName(className);
clazz = ClassInfo.forName(className);
} catch (IllegalArgumentException ex) {
System.err.println("`"+className+"' is not a class name");
return;

@ -18,35 +18,40 @@
*/
package jode;
import java.util.Enumeration;
import gnu.bytecode.LocalVarsAttr;
import gnu.bytecode.Variable;
import gnu.bytecode.Spy;
import jode.bytecode.AttributeInfo;
import jode.bytecode.ConstantPool;
import java.io.*;
public class LocalVariableTable {
LocalVariableRangeList[] locals;
public LocalVariableTable(int size,
ClassAnalyzer cla, LocalVarsAttr attr) {
ClassAnalyzer cla, AttributeInfo attr) {
locals = new LocalVariableRangeList[size];
for (int i=0; i<size; i++)
locals[i] = new LocalVariableRangeList(i);
Enumeration vars = attr.allVars();
while (vars.hasMoreElements()) {
Variable var = (Variable) vars.nextElement();
int start = Spy.getStartPC(var);
int end = Spy.getEndPC(var);
int slot = Spy.getSlot(var);
String name = var.getName();
Type type = Type.tType(var.getType().getSignature());
locals[slot].addLocal(start, end-start, name, type);
if (Decompiler.showLVT)
System.err.println(name + ": " + type
+" range "+start+" - "+end
+" slot "+slot);
ConstantPool constantPool = cla.getConstantPool();
DataInputStream stream = new DataInputStream
(new ByteArrayInputStream(attr.getContents()));
try {
int count = stream.readUnsignedShort();
for (int i=0; i < count; i++) {
int start = stream.readUnsignedShort();
int end = start + stream.readUnsignedShort();
String name = constantPool.getUTF8(stream.readUnsignedShort());
Type type = Type.tType(constantPool.getUTF8(stream.readUnsignedShort()));
int slot = stream.readUnsignedShort();
locals[slot].addLocal(start, end-start, name, type);
if (Decompiler.showLVT)
System.err.println(name + ": " + type
+" range "+start+" - "+end
+" slot "+slot);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}

@ -18,13 +18,12 @@
*/
package jode;
import jode.bytecode.MethodInfo;
import jode.bytecode.AttributeInfo;
import jode.bytecode.CodeInfo;
import java.lang.reflect.Modifier;
import gnu.bytecode.Attribute;
import gnu.bytecode.CodeAttr;
import gnu.bytecode.CpoolClass;
import gnu.bytecode.Method;
import gnu.bytecode.MiscAttr;
import gnu.bytecode.Spy;
import java.io.*;
public class MethodAnalyzer implements Analyzer {
JodeEnvironment env;
@ -36,37 +35,45 @@ public class MethodAnalyzer implements Analyzer {
MethodType methodType;
Type[] exceptions;
public MethodAnalyzer(ClassAnalyzer cla, Method mdef,
public MethodAnalyzer(ClassAnalyzer cla, MethodInfo minfo,
JodeEnvironment env) {
this.classAnalyzer = cla;
this.env = env;
this.modifiers = Spy.getModifiers(mdef);
this.methodType = new MethodType(mdef.getStaticFlag(),
mdef.getSignature());
this.methodName = mdef.getName();
this.modifiers = minfo.getModifiers();
this.methodType = minfo.getType();
this.methodName = minfo.getName();
this.isConstructor =
methodName.equals("<init>") || methodName.equals("<clinit>");
Attribute codeattr = Attribute.get(mdef, "Code");
if (codeattr != null && codeattr instanceof CodeAttr)
code = new CodeAnalyzer(this, (CodeAttr) codeattr, env);
AttributeInfo codeattr = minfo.findAttribute("Code");
if (codeattr != null) {
DataInputStream stream = new DataInputStream
(new ByteArrayInputStream(codeattr.getContents()));
CodeInfo codeinfo = new CodeInfo();
try {
codeinfo.read(classAnalyzer.getConstantPool(), stream);
code = new CodeAnalyzer(this, codeinfo, env);
} catch (IOException ex) {
ex.printStackTrace();
code = null;
}
}
Attribute excattr = Attribute.get(mdef, "Exceptions");
AttributeInfo excattr = minfo.findAttribute("Exceptions");
if (excattr == null) {
exceptions = new Type[0];
} else {
java.io.DataInputStream stream = Spy.getAttributeStream
((MiscAttr) excattr);
DataInputStream stream = new DataInputStream
(new ByteArrayInputStream(excattr.getContents()));
try {
int throwCount = stream.readUnsignedShort();
this.exceptions = new Type[throwCount];
for (int t=0; t< throwCount; t++) {
int idx = stream.readUnsignedShort();
CpoolClass cpcls = (CpoolClass)
classAnalyzer.getConstant(idx);
exceptions[t] = Type.tClass(cpcls.getName().getString());
exceptions[t] = Type.tClass(classAnalyzer.getConstantPool()
.getClassName(idx));
}
} catch (java.io.IOException ex) {
} catch (IOException ex) {
throw new AssertError("exception attribute too long?");
}
}
@ -133,7 +140,7 @@ public class MethodAnalyzer implements Analyzer {
}
public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException
throws IOException
{
if (Decompiler.immediateOutput && code != null) {
// We do the code.analyze() here, to get

@ -18,7 +18,6 @@
*/
package jode;
import gnu.bytecode.CpoolRef;
public class ConstructorOperator extends Operator {
MethodType methodType;

@ -18,7 +18,6 @@
*/
package jode;
import gnu.bytecode.CpoolRef;
public class GetFieldOperator extends Operator {
boolean staticFlag;

@ -18,8 +18,7 @@
*/
package jode;
import gnu.bytecode.CpoolRef;
import jode.bytecode.ClassHierarchy;
import jode.bytecode.ClassInfo;
public final class InvokeOperator extends Operator {
CodeAnalyzer codeAnalyzer;

@ -18,7 +18,6 @@
*/
package jode;
import gnu.bytecode.CpoolRef;
public class PutFieldOperator extends StoreInstruction {
CodeAnalyzer codeAnalyzer;

@ -116,8 +116,15 @@ public class ArrayType extends Type {
return elementType.toString()+"[]";
}
private static String pluralize(String singular) {
return singular +
((singular.endsWith("s") || singular.endsWith("x")
|| singular.endsWith("sh") || singular.endsWith("ch"))
? "es" : "s");
}
public String getDefaultName() {
return "arr_"+elementType.getDefaultName();
return pluralize(elementType.getDefaultName());
}
public boolean equals(Object o) {

@ -17,7 +17,7 @@
* $Id$
*/
package jode;
import jode.bytecode.ClassHierarchy;
import jode.bytecode.ClassInfo;
import java.util.Vector;
import java.util.Stack;
@ -35,45 +35,45 @@ import java.util.Stack;
* @author Jochen Hoenicke */
public class ClassInterfacesType extends Type {
ClassHierarchy clazz;
ClassHierarchy ifaces[];
ClassInfo clazz;
ClassInfo ifaces[];
public ClassHierarchy getClazz() {
return clazz != null ? clazz : ClassHierarchy.javaLangObject;
public ClassInfo getClazz() {
return clazz != null ? clazz : ClassInfo.javaLangObject;
}
public ClassInterfacesType(String clazzName) {
super(TC_CLASS);
ClassHierarchy clazz = ClassHierarchy.forName(clazzName);
ClassInfo clazz = ClassInfo.forName(clazzName);
if (clazz.isInterface()) {
this.clazz = null;
ifaces = new ClassHierarchy[] {clazz};
ifaces = new ClassInfo[] {clazz};
} else {
this.clazz =
(clazz == ClassHierarchy.javaLangObject) ? null : clazz;
ifaces = new ClassHierarchy[0];
(clazz == ClassInfo.javaLangObject) ? null : clazz;
ifaces = new ClassInfo[0];
}
}
public ClassInterfacesType(ClassHierarchy clazz) {
public ClassInterfacesType(ClassInfo clazz) {
super(TC_CLASS);
if (clazz.isInterface()) {
this.clazz = null;
ifaces = new ClassHierarchy[] { clazz };
ifaces = new ClassInfo[] { clazz };
} else {
this.clazz =
(clazz == ClassHierarchy.javaLangObject) ? null : clazz;
ifaces = new ClassHierarchy[0];
(clazz == ClassInfo.javaLangObject) ? null : clazz;
ifaces = new ClassInfo[0];
}
}
public ClassInterfacesType(ClassHierarchy clazz, ClassHierarchy[] ifaces) {
public ClassInterfacesType(ClassInfo clazz, ClassInfo[] ifaces) {
super(TC_CLASS);
this.clazz = clazz;
this.ifaces = ifaces;
}
private static Type create(ClassHierarchy clazz, ClassHierarchy[] ifaces) {
private static Type create(ClassInfo clazz, ClassInfo[] ifaces) {
/* Make sure that every {java.lang.Object} equals tObject */
if (ifaces.length == 0 && clazz == null)
return tObject;
@ -125,7 +125,7 @@ public class ClassInterfacesType extends Type {
* classes/interfaces that implement all bottom.ifaces.
*/
ClassHierarchy clazz = this.clazz;
ClassInfo clazz = this.clazz;
if (clazz != null) {
for (int i=0; i < bottom.ifaces.length; i++) {
if (!bottom.ifaces[i].implementedBy(clazz)) {
@ -145,7 +145,7 @@ public class ClassInterfacesType extends Type {
}
}
ClassHierarchy[] ifaces = new ClassHierarchy[this.ifaces.length];
ClassInfo[] ifaces = new ClassInfo[this.ifaces.length];
int count = 0;
big_loop:
for (int j=0; j < this.ifaces.length; j++) {
@ -157,7 +157,7 @@ public class ClassInterfacesType extends Type {
}
if (count < ifaces.length) {
ClassHierarchy[] shortIfaces = new ClassHierarchy[count];
ClassInfo[] shortIfaces = new ClassInfo[count];
System.arraycopy(ifaces, 0, shortIfaces, 0, count);
ifaces = shortIfaces;
} else if (clazz == this.clazz)
@ -166,10 +166,10 @@ public class ClassInterfacesType extends Type {
}
}
private boolean implementsAllIfaces(ClassHierarchy[] otherIfaces) {
private boolean implementsAllIfaces(ClassInfo[] otherIfaces) {
big:
for (int i=0; i < otherIfaces.length; i++) {
ClassHierarchy iface = otherIfaces[i];
ClassInfo iface = otherIfaces[i];
if (clazz != null && iface.implementedBy(clazz))
continue big;
for (int j=0; j < this.ifaces.length; j++) {
@ -197,7 +197,7 @@ public class ClassInterfacesType extends Type {
return tError;
ClassInterfacesType other = (ClassInterfacesType) type;
ClassHierarchy clazz;
ClassInfo clazz;
/* First determine the clazz, one of the two classes must be a sub
* class of the other or null.
@ -231,7 +231,7 @@ public class ClassInterfacesType extends Type {
Vector ifaces = new Vector();
big_loop_this:
for (int i=0; i< this.ifaces.length; i++) {
ClassHierarchy iface = this.ifaces[i];
ClassInfo iface = this.ifaces[i];
if (clazz != null && iface.implementedBy(clazz)) {
continue big_loop_this;
}
@ -248,12 +248,12 @@ public class ClassInterfacesType extends Type {
}
big_loop_other:
for (int i=0; i< other.ifaces.length; i++) {
ClassHierarchy iface = other.ifaces[i];
ClassInfo iface = other.ifaces[i];
if (clazz != null && iface.implementedBy(clazz)) {
continue big_loop_other;
}
for (int j=0; j<ifaces.size(); j++) {
if (iface.implementedBy((ClassHierarchy)
if (iface.implementedBy((ClassInfo)
ifaces.elementAt(j))) {
continue big_loop_other;
}
@ -265,7 +265,7 @@ public class ClassInterfacesType extends Type {
ifaces.addElement(iface);
}
ClassHierarchy[] ifaceArray = new ClassHierarchy[ifaces.size()];
ClassInfo[] ifaceArray = new ClassInfo[ifaces.size()];
ifaces.copyInto(ifaceArray);
return create(clazz, ifaceArray);
}
@ -285,7 +285,7 @@ public class ClassInterfacesType extends Type {
if (code != TC_CLASS)
return tError;
ClassInterfacesType other = (ClassInterfacesType) type;
ClassHierarchy clazz;
ClassInfo clazz;
/* First the easy part, determine the clazz */
if (this.clazz == null || other.clazz == null)
@ -298,7 +298,7 @@ public class ClassInterfacesType extends Type {
break;
clazz = clazz.getSuperclass();
}
if (clazz == ClassHierarchy.javaLangObject)
if (clazz == ClassInfo.javaLangObject)
clazz = null;
}
@ -317,9 +317,9 @@ public class ClassInterfacesType extends Type {
Stack allIfaces = new Stack();
if (this.clazz != null) {
ClassHierarchy c = this.clazz;
ClassInfo c = this.clazz;
while (clazz != c) {
ClassHierarchy clazzIfaces[] = c.getInterfaces();
ClassInfo clazzIfaces[] = c.getInterfaces();
for (int i=0; i<clazzIfaces.length; i++)
allIfaces.push(clazzIfaces[i]);
c = c.getSuperclass();
@ -337,7 +337,7 @@ public class ClassInterfacesType extends Type {
*/
iface_loop:
while (!allIfaces.isEmpty()) {
ClassHierarchy iface = (ClassHierarchy) allIfaces.pop();
ClassInfo iface = (ClassInfo) allIfaces.pop();
if ((clazz != null && iface.implementedBy(clazz))
|| ifaces.contains(iface))
/* We can skip this, as clazz or ifaces already imply it.
@ -358,12 +358,12 @@ public class ClassInterfacesType extends Type {
/* This interface is not implemented by any of the other
* ifaces. Try its parent interfaces now.
*/
ClassHierarchy clazzIfaces[] = iface.getInterfaces();
ClassInfo clazzIfaces[] = iface.getInterfaces();
for (int i=0; i<clazzIfaces.length; i++)
allIfaces.push(clazzIfaces[i]);
}
ClassHierarchy[] ifaceArray = new ClassHierarchy[ifaces.size()];
ClassInfo[] ifaceArray = new ClassInfo[ifaces.size()];
ifaces.copyInto(ifaceArray);
return create(clazz, ifaceArray);
}
@ -411,13 +411,13 @@ public class ClassInterfacesType extends Type {
}
public String getDefaultName() {
ClassHierarchy type;
ClassInfo type;
if (clazz != null)
type = clazz;
else if (ifaces.length > 0)
type = ifaces[0];
else
type = ClassHierarchy.javaLangObject;
type = ClassInfo.javaLangObject;
String name = type.getName();
int dot = name.lastIndexOf('.');
if (dot >= 0)

@ -24,12 +24,14 @@ package jode;
* @author Jochen Hoenicke
*/
public class MethodType {
final String signature;
final Type[] parameterTypes;
final Type returnType;
final boolean staticFlag;
public MethodType(boolean isStatic, String signature) {
this.staticFlag = isStatic;
this.signature = signature;
int index = 1, types = 0;
while (signature.charAt(index) != ')') {
types++;
@ -68,16 +70,14 @@ public class MethodType {
return returnType;
}
public String toString() {
return signature;
}
public boolean equals(Object o) {
MethodType mt;
if (!(o instanceof InvokeOperator)
|| !returnType.equals((mt = (MethodType)o).returnType)
|| staticFlag != mt.staticFlag
|| parameterTypes.length != mt.parameterTypes.length)
return false;
for (int i=0; i<parameterTypes.length; i++)
if (!parameterTypes[i].equals(mt.parameterTypes))
return false;
return true;
return ((o instanceof InvokeOperator)
&& signature.equals((mt = (MethodType)o).signature)
&& staticFlag == mt.staticFlag);
}
}

Loading…
Cancel
Save