From 38a01116c14d0af26cf10cc3a83b09f3cf31eaa8 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 4 Nov 1999 00:26:27 +0000 Subject: [PATCH] OuterValues added inner/anonymous classes completely reworked FieldOperator added to remove doubled code in Put/Get-FieldOperator LocalVarOperator is now a class LValueExpression is only an interface ArrayStoreOperator extends ArrayLoadOperator git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1192 379699f6-c40d-0410-875b-85095c16579e --- jode/jode/expr/ArrayLoadOperator.java | 1 - jode/jode/expr/ArrayStoreOperator.java | 32 +--- jode/jode/expr/FieldOperator.java.in | 228 +++++++++++++++++++++++++ jode/jode/expr/GetFieldOperator.java | 159 +---------------- jode/jode/expr/InvokeOperator.java.in | 120 +++++++------ jode/jode/expr/LValueExpression.java | 7 +- jode/jode/expr/LocalLoadOperator.java | 43 +---- jode/jode/expr/LocalStoreOperator.java | 33 +--- jode/jode/expr/LocalVarOperator.java | 53 ++++-- jode/jode/expr/Makefile.am | 1 + jode/jode/expr/Operator.java.in | 2 +- jode/jode/expr/OuterLocalOperator.java | 5 + jode/jode/expr/PrePostFixOperator.java | 2 +- jode/jode/expr/PutFieldOperator.java | 161 +---------------- jode/jode/expr/StoreInstruction.java | 2 +- 15 files changed, 362 insertions(+), 487 deletions(-) create mode 100644 jode/jode/expr/FieldOperator.java.in diff --git a/jode/jode/expr/ArrayLoadOperator.java b/jode/jode/expr/ArrayLoadOperator.java index 161ee1b..dc85842 100644 --- a/jode/jode/expr/ArrayLoadOperator.java +++ b/jode/jode/expr/ArrayLoadOperator.java @@ -23,7 +23,6 @@ import jode.type.ArrayType; import jode.decompiler.TabbedPrintWriter; public class ArrayLoadOperator extends Operator { - String value; public ArrayLoadOperator(Type type) { super(type, 0); diff --git a/jode/jode/expr/ArrayStoreOperator.java b/jode/jode/expr/ArrayStoreOperator.java index a565889..796262b 100644 --- a/jode/jode/expr/ArrayStoreOperator.java +++ b/jode/jode/expr/ArrayStoreOperator.java @@ -22,40 +22,14 @@ import jode.type.Type; import jode.type.ArrayType; import jode.decompiler.TabbedPrintWriter; -public class ArrayStoreOperator extends LValueExpression { +public class ArrayStoreOperator extends ArrayLoadOperator + implements LValueExpression { public ArrayStoreOperator(Type type) { - super(type); - initOperands(2); + super(type); } public boolean matches(Operator loadop) { return loadop instanceof ArrayLoadOperator; } - - public int getPriority() { - return 950; - } - - public void updateSubTypes() { - subExpressions[0].setType(Type.tArray(type)); - subExpressions[1].setType(Type.tSubType(Type.tInt)); - } - - public void updateType() { - Type subType = subExpressions[0].getType() - .intersection(Type.tArray(type)); - if (!(subType instanceof ArrayType)) - updateParentType(Type.tError); - else - updateParentType(((ArrayType)subType).getElementType()); - } - - public void dumpExpression(TabbedPrintWriter writer) - throws java.io.IOException { - subExpressions[0].dumpExpression(writer, 950); - writer.print("["); - subExpressions[1].dumpExpression(writer, 0); - writer.print("]"); - } } diff --git a/jode/jode/expr/FieldOperator.java.in b/jode/jode/expr/FieldOperator.java.in new file mode 100644 index 0000000..d810ca5 --- /dev/null +++ b/jode/jode/expr/FieldOperator.java.in @@ -0,0 +1,228 @@ +/* FieldOperator Copyright (C) 1998-1999 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.expr; +import jode.type.Type; +import jode.type.NullType; +import jode.type.ClassInterfacesType; +import jode.bytecode.FieldInfo; +import jode.bytecode.ClassInfo; +import jode.bytecode.Reference; +import jode.bytecode.InnerClassInfo; +import jode.decompiler.MethodAnalyzer; +import jode.decompiler.ClassAnalyzer; +import jode.decompiler.MethodAnalyzer; +import jode.decompiler.FieldAnalyzer; +import jode.decompiler.TabbedPrintWriter; +import jode.decompiler.Scope; +import jode.Decompiler; + +import @COLLECTIONS@.Collection; + +/** + * This class contains everything shared between PutFieldOperator and + * GetFieldOperator + */ +public abstract class FieldOperator extends Operator { + MethodAnalyzer methodAnalyzer; + boolean staticFlag; + Reference ref; + Type classType; + + public FieldOperator(MethodAnalyzer methodAnalyzer, boolean staticFlag, + Reference ref) { + super(Type.tType(ref.getType())); + this.methodAnalyzer = methodAnalyzer; + this.staticFlag = staticFlag; + this.classType = Type.tType(ref.getClazz()); + this.ref = ref; + if (staticFlag) + methodAnalyzer.useType(classType); + initOperands(staticFlag ? 0 : 1); + } + + public int getPriority() { + return 950; + } + + public void updateSubTypes() { + if (!staticFlag) + subExpressions[0].setType(Type.tSubType(classType)); + } + + public void updateType() { + updateParentType(getFieldType()); + } + + public boolean isStatic() { + return staticFlag; + } + + public ClassInfo getClassInfo() { + if (classType instanceof ClassInterfacesType) + return ((ClassInterfacesType) classType).getClassInfo(); + return null; + } + + public FieldAnalyzer getField() { + ClassInfo clazz = getClassInfo(); + if (clazz != null) { + ClassAnalyzer ana = methodAnalyzer.getClassAnalyzer(); + while (true) { + if (clazz == ana.getClazz()) { + return ana.getField(ana.getFieldIndex + (ref.getName(), + Type.tType(ref.getType()))); + } + if (ana.getParent() == null) + return null; + if (ana.getParent() instanceof MethodAnalyzer) + ana = ((MethodAnalyzer) ana.getParent()) + .getClassAnalyzer(); + else if (ana.getParent() instanceof ClassAnalyzer) + ana = (ClassAnalyzer) ana.getParent(); + else + throw new jode.AssertError("Unknown parent"); + } + } + return null; + } + + public String getFieldName() { + return ref.getName(); + } + + public Type getFieldType() { + return Type.tType(ref.getType()); + } + + public boolean needsCast(Type type) { + if (type instanceof NullType) + return true; + if (!(type instanceof ClassInterfacesType + && classType instanceof ClassInterfacesType)) + return false; + + ClassInfo clazz = ((ClassInterfacesType) classType).getClassInfo(); + ClassInfo parClazz = ((ClassInterfacesType) type).getClassInfo(); + while (clazz != parClazz && clazz != null) { + FieldInfo[] fields = parClazz.getFields(); + for (int i = 0; i < fields.length; i++) { + if (fields[i].getName().equals(ref.getName())) + return true; + } + parClazz = parClazz.getSuperclass(); + } + return false; + } + + public InnerClassInfo getOuterClassInfo(ClassInfo ci) { + if (ci != null) { + InnerClassInfo[] outers = ci.getOuterClasses(); + if (outers != null) + return outers[0]; + } + return null; + } + + /** + * We add the named method scoped classes to the declarables. + */ + public void fillDeclarables(Collection used) { + ClassInfo clazz = getClassInfo(); + InnerClassInfo outer = getOuterClassInfo(clazz); + ClassAnalyzer clazzAna = methodAnalyzer.getClassAnalyzer(clazz); + + if ((Decompiler.options & Decompiler.OPTION_ANON) != 0 + && clazzAna != null + && outer != null && (outer.outer == null || outer.name == null)) { + + if (outer.name != null) { + if (clazzAna.getParent() == methodAnalyzer) { + /* This is a named method scope class, declare it. + * But first declare all method scoped classes, + * that are used inside; order does matter. + */ + clazzAna.fillDeclarables(used); + used.add(clazzAna); + } + } + } + } + + public void dumpExpression(TabbedPrintWriter writer) + throws java.io.IOException { + boolean opIsThis = !staticFlag + && subExpressions[0] instanceof ThisOperator; + String fieldName = ref.getName(); + if (staticFlag) { + if (!classType.equals(Type.tClass(methodAnalyzer.getClazz())) + || methodAnalyzer.findLocal(fieldName) != null) { + writer.printType(classType); + writer.print("."); + } + writer.print(fieldName); + } else if (needsCast(subExpressions[0].getType().getCanonic())) { + writer.print("(("); + writer.printType(classType); + writer.print(") "); + subExpressions[0].dumpExpression(writer, 700); + writer.print(")."); + writer.print(fieldName); + } else { + if (opIsThis) { + ThisOperator thisOp = (ThisOperator) subExpressions[0]; + Scope scope = writer.getScope(thisOp.getClassInfo(), + Scope.CLASSSCOPE); + + if (scope == null || writer.conflicts(fieldName, scope, + Scope.FIELDNAME)) { + thisOp.dumpExpression(writer, 950); + writer.print("."); + } else if (writer.conflicts(fieldName, scope, + Scope.AMBIGUOUSNAME) + || (/* This is a inherited field conflicting + * with a field name in some outer class. + */ + getField() == null + && writer.conflicts(fieldName, null, + Scope.NOSUPERFIELDNAME))) { + + ClassAnalyzer ana = methodAnalyzer.getClassAnalyzer(); + while (ana.getParent() instanceof ClassAnalyzer + && ana != scope) + ana = (ClassAnalyzer) ana.getParent(); + if (ana == scope) + // For a simple outer class we can say this + writer.print("this."); + else { + // For a class that owns a method that owns + // us, we have to give the full class name + thisOp.dumpExpression(writer, 950); + writer.print("."); + } + } + } else { + subExpressions[0].dumpExpression(writer, 950); + writer.print("."); + } + writer.print(fieldName); + } + } +} diff --git a/jode/jode/expr/GetFieldOperator.java b/jode/jode/expr/GetFieldOperator.java index ff1a05e..1e8ff45 100644 --- a/jode/jode/expr/GetFieldOperator.java +++ b/jode/jode/expr/GetFieldOperator.java @@ -31,165 +31,10 @@ import jode.decompiler.FieldAnalyzer; import jode.decompiler.TabbedPrintWriter; import jode.decompiler.Scope; -public class GetFieldOperator extends Operator { - boolean staticFlag; - MethodAnalyzer methodAnalyzer; - Reference ref; - Type classType; - +public class GetFieldOperator extends FieldOperator { public GetFieldOperator(MethodAnalyzer methodAnalyzer, boolean staticFlag, Reference ref) { - super(Type.tType(ref.getType()), 0); - this.methodAnalyzer = methodAnalyzer; - this.staticFlag = staticFlag; - this.classType = Type.tType(ref.getClazz()); - this.ref = ref; - if (staticFlag) - methodAnalyzer.useType(classType); - initOperands(staticFlag ? 0 : 1); - } - - public int getPriority() { - return 950; - } - - public void updateSubTypes() { - if (!staticFlag) - subExpressions[0].setType(Type.tSubType(classType)); - } - public void updateType() { - } - - /** - * Checks, whether this is a call of a method from this class or an - * outer instance. - */ - public boolean isOuter() { - if (classType instanceof ClassInterfacesType) { - ClassInfo clazz = ((ClassInterfacesType) classType).getClassInfo(); - ClassAnalyzer ana = methodAnalyzer.getClassAnalyzer(); - while (true) { - if (clazz == ana.getClazz()) - return true; - if (ana.getParent() instanceof MethodAnalyzer) - ana = ((MethodAnalyzer) ana.getParent()) - .getClassAnalyzer(); - else if (ana.getParent() instanceof ClassAnalyzer) - ana = (ClassAnalyzer) ana.getParent(); - else - return false; - } - } - return false; - } - - public ClassInfo getClassInfo() { - if (classType instanceof ClassInterfacesType) - return ((ClassInterfacesType) classType).getClassInfo(); - return null; - } - - public FieldAnalyzer getField() { - ClassInfo clazz = getClassInfo(); - if (clazz != null) { - ClassAnalyzer ana = methodAnalyzer.getClassAnalyzer(); - while (true) { - if (clazz == ana.getClazz()) { - return ana.getField(ref.getName(), - Type.tType(ref.getType())); - } - if (ana.getParent() == null) - return null; - if (ana.getParent() instanceof MethodAnalyzer) - ana = ((MethodAnalyzer) ana.getParent()) - .getClassAnalyzer(); - else if (ana.getParent() instanceof ClassAnalyzer) - ana = (ClassAnalyzer) ana.getParent(); - else - throw new jode.AssertError("Unknown parent"); - } - } - return null; - } - - public boolean needsCast(Type type) { - if (type instanceof NullType) - return true; - if (!(type instanceof ClassInterfacesType - && classType instanceof ClassInterfacesType)) - return false; - - ClassInfo clazz = ((ClassInterfacesType) classType).getClassInfo(); - ClassInfo parClazz = ((ClassInterfacesType) type).getClassInfo(); - while (clazz != parClazz && clazz != null) { - FieldInfo[] fields = parClazz.getFields(); - for (int i = 0; i < fields.length; i++) { - if (fields[i].getName().equals(ref.getName())) - return true; - } - parClazz = parClazz.getSuperclass(); - } - return false; - } - - public void dumpExpression(TabbedPrintWriter writer) - throws java.io.IOException { - boolean opIsThis = !staticFlag - && subExpressions[0] instanceof ThisOperator; - String fieldName = ref.getName(); - if (staticFlag) { - if (!classType.equals(Type.tClass(methodAnalyzer.getClazz())) - || methodAnalyzer.findLocal(fieldName) != null) { - writer.printType(classType); - writer.print("."); - } - writer.print(fieldName); - } else if (needsCast(subExpressions[0].getType().getCanonic())) { - writer.print("(("); - writer.printType(classType); - writer.print(") "); - subExpressions[0].dumpExpression(writer, 700); - writer.print(")."); - writer.print(fieldName); - } else { - if (opIsThis) { - ThisOperator thisOp = (ThisOperator) subExpressions[0]; - Scope scope = writer.getScope(thisOp.getClassInfo(), - Scope.CLASSSCOPE); - - if (scope == null || writer.conflicts(fieldName, scope, - Scope.FIELDNAME)) { - thisOp.dumpExpression(writer, 950); - writer.print("."); - } else if (writer.conflicts(fieldName, scope, - Scope.AMBIGUOUSNAME) - || (/* This is a inherited field conflicting - * with a field name in some outer class. - */ - getField() == null - && writer.conflicts(fieldName, null, - Scope.NOSUPERFIELDNAME))) { - - ClassAnalyzer ana = methodAnalyzer.getClassAnalyzer(); - while (ana.getParent() instanceof ClassAnalyzer - && ana != scope) - ana = (ClassAnalyzer) ana.getParent(); - if (ana == scope) - // For a simple outer class we can say this - writer.print("this."); - else { - // For a class that owns a method that owns - // us, we have to give the full class name - thisOp.dumpExpression(writer, 950); - writer.print("."); - } - } - } else { - subExpressions[0].dumpExpression(writer, 950); - writer.print("."); - } - writer.print(fieldName); - } + super(methodAnalyzer, staticFlag, ref); } public Expression simplify() { diff --git a/jode/jode/expr/InvokeOperator.java.in b/jode/jode/expr/InvokeOperator.java.in index 4246805..46e2433 100644 --- a/jode/jode/expr/InvokeOperator.java.in +++ b/jode/jode/expr/InvokeOperator.java.in @@ -25,6 +25,7 @@ import jode.decompiler.MethodAnalyzer; import jode.decompiler.MethodAnalyzer; import jode.decompiler.ClassAnalyzer; import jode.decompiler.TabbedPrintWriter; +import jode.decompiler.OuterValues; import jode.GlobalOptions; import jode.bytecode.*; import jode.jvm.*; @@ -173,12 +174,10 @@ public final class InvokeOperator extends Operator } public void checkAnonymousClasses() { - if ((Decompiler.options & Decompiler.OPTION_ANON) == 0) - return; - if (methodFlag != CONSTRUCTOR) + if (methodFlag != CONSTRUCTOR + || (Decompiler.options & Decompiler.OPTION_ANON) == 0) return; - ClassInfo clazz = getClassInfo(); - InnerClassInfo outer = getOuterClassInfo(clazz); + InnerClassInfo outer = getOuterClassInfo(getClassInfo()); if (outer != null && (outer.outer == null || outer.name == null)) { methodAnalyzer.addAnonymousConstructor(this); } @@ -277,24 +276,29 @@ public final class InvokeOperator extends Operator callee = ClassInfo.forName(outers[nested - 1].outer); } - /* Now we iterate the caller analyzer queue to find the class - * analyzer for callee - */ - ClassAnalyzer ana = methodAnalyzer.getClassAnalyzer(); - while (callee != ana.getClazz()) { - if (ana.getParent() == null) - return null; - if (ana.getParent() instanceof MethodAnalyzer - && (Decompiler.options & Decompiler.OPTION_ANON) != 0) - ana = ((MethodAnalyzer) ana.getParent()) - .getClassAnalyzer(); - else if (ana.getParent() instanceof ClassAnalyzer - && (Decompiler.options + /* First check if it is an inner class */ + ClassAnalyzer ana = methodAnalyzer.getClassAnalyzer(callee); + + if (ana == null) { + /* Now we iterate the caller analyzer queue to find the class + * analyzer for callee + */ + ana = methodAnalyzer.getClassAnalyzer(); + while (callee != ana.getClazz()) { + if (ana.getParent() == null) + return null; + if (ana.getParent() instanceof MethodAnalyzer + && (Decompiler.options & Decompiler.OPTION_ANON) != 0) + ana = ((MethodAnalyzer) ana.getParent()) + .getClassAnalyzer(); + else if (ana.getParent() instanceof ClassAnalyzer + && (Decompiler.options & Decompiler.OPTION_INNER) != 0) ana = (ClassAnalyzer) ana.getParent(); - else - throw new jode.AssertError - ("Unknown parent: "+ana+": "+ana.getParent()); + else + throw new jode.AssertError + ("Unknown parent: "+ana+": "+ana.getParent()); + } } /* Now get the ClassAnalyzer of the real callee */ @@ -692,14 +696,10 @@ public final class InvokeOperator extends Operator * only fillDeclarables on the parameters we will print. */ public void fillDeclarables(Collection used) { - if (!isConstructor()) { - super.fillDeclarables(used); - return; - } - ClassInfo clazz = getClassInfo(); InnerClassInfo outer = getOuterClassInfo(clazz); ClassAnalyzer clazzAna = methodAnalyzer.getClassAnalyzer(clazz); + int arg = 1; int length = subExpressions.length; boolean jikesAnonymousInner = false; @@ -707,37 +707,50 @@ public final class InvokeOperator extends Operator if ((Decompiler.options & Decompiler.OPTION_ANON) != 0 && clazzAna != null && outer != null && (outer.outer == null || outer.name == null)) { - arg += clazzAna.getOuterValues().length; - for (int i=1; i< arg; i++) { - Expression expr = subExpressions[i]; - if (expr instanceof CheckNullOperator) { - CheckNullOperator cno = (CheckNullOperator) expr; - expr = cno.subExpressions[0]; + + if (outer.name != null) { + if (clazzAna.getParent() == methodAnalyzer) { + /* This is a named method scope class, declare it. + * But first declare all method scoped classes, + * that are used inside; order does matter. + */ + clazzAna.fillDeclarables(used); + used.add(clazzAna); } - expr.fillDeclarables(used); } - jikesAnonymousInner = clazzAna.isJikesAnonymousInner(); + if (isConstructor()) { + OuterValues ov = clazzAna.getOuterValues(); + arg += ov.getCount(); + jikesAnonymousInner = ov.isJikesAnonymousInner(); + + for (int i=1; i< arg; i++) { + Expression expr = subExpressions[i]; + if (expr instanceof CheckNullOperator) { + CheckNullOperator cno = (CheckNullOperator) expr; + expr = cno.subExpressions[0]; + } + expr.fillDeclarables(used); + } - if (outer.name != null) { - if (clazzAna.getParent() == methodAnalyzer) - /* This is a named method scope class, declare it */ - used.add(clazzAna); - } else { - /* This is an anonymous class */ - ClassInfo superClazz = clazz.getSuperclass(); - ClassInfo[] interfaces = clazz.getInterfaces(); - if (interfaces.length == 1 - && (superClazz == null - || superClazz == ClassInfo.javaLangObject)) { - clazz = interfaces[0]; - } else { - clazz = (superClazz != null - ? superClazz : ClassInfo.javaLangObject); + if (outer.name == null) { + /* This is an anonymous class */ + ClassInfo superClazz = clazz.getSuperclass(); + ClassInfo[] interfaces = clazz.getInterfaces(); + if (interfaces.length == 1 + && (superClazz == null + || superClazz == ClassInfo.javaLangObject)) { + clazz = interfaces[0]; + } else { + clazz = (superClazz != null + ? superClazz : ClassInfo.javaLangObject); + } + outer = getOuterClassInfo(clazz); + } - outer = getOuterClassInfo(clazz); } } - if ((Decompiler.options & Decompiler.OPTION_INNER) != 0 + if (isConstructor() + && (Decompiler.options & Decompiler.OPTION_INNER) != 0 && outer != null && outer.outer != null && outer.name != null && !Modifier.isStatic(outer.modifiers)) { @@ -792,8 +805,9 @@ public final class InvokeOperator extends Operator && (outer.outer == null || outer.name == null)) { /* This is a method scoped class, skip the outerValues */ - arg += clazzAna.getOuterValues().length; - jikesAnonymousInner = clazzAna.isJikesAnonymousInner(); + OuterValues ov = clazzAna.getOuterValues(); + arg += ov.getCount(); + jikesAnonymousInner = ov.isJikesAnonymousInner(); if (outer.name == null) { /* This is an anonymous class */ diff --git a/jode/jode/expr/LValueExpression.java b/jode/jode/expr/LValueExpression.java index 8c65fa2..6b12dde 100644 --- a/jode/jode/expr/LValueExpression.java +++ b/jode/jode/expr/LValueExpression.java @@ -22,10 +22,5 @@ import jode.type.Type; import jode.GlobalOptions; import jode.decompiler.TabbedPrintWriter; -public abstract class LValueExpression extends Operator - implements MatchableOperator { - - public LValueExpression(Type lvalueType) { - super(lvalueType, 0); - } +public interface LValueExpression extends MatchableOperator { } diff --git a/jode/jode/expr/LocalLoadOperator.java b/jode/jode/expr/LocalLoadOperator.java index ea70d7d..81a4e36 100644 --- a/jode/jode/expr/LocalLoadOperator.java +++ b/jode/jode/expr/LocalLoadOperator.java @@ -25,18 +25,14 @@ import jode.decompiler.ClassAnalyzer; import jode.decompiler.LocalInfo; import jode.decompiler.TabbedPrintWriter; -public class LocalLoadOperator extends Operator - implements LocalVarOperator { +public class LocalLoadOperator extends LocalVarOperator { + MethodAnalyzer methodAnalyzer; - LocalInfo local; public LocalLoadOperator(Type type, MethodAnalyzer methodAnalyzer, LocalInfo local) { - super(type); + super(type, local); this.methodAnalyzer = methodAnalyzer; - this.local = local; - local.setOperator(this); - initOperands(0); } public boolean isRead() { @@ -51,38 +47,10 @@ public class LocalLoadOperator extends Operator return false; } - public int getPriority() { - return 1000; - } - - public LocalInfo getLocalInfo() { - return local.getLocalInfo(); - } - public void setMethodAnalyzer(MethodAnalyzer ma) { methodAnalyzer = ma; } - public void setLocalInfo(LocalInfo newLocal) { - local = newLocal; - updateType(); - } - - public void updateSubTypes() { - if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_TYPES) != 0) - GlobalOptions.err.println("setType of "+local.getName()+": " - +local.getType()); - local.setType(type); - } - - public void updateType() { - if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_TYPES) != 0) - GlobalOptions.err.println("local "+local.getName()+" changed: " - +type+" to "+local.getType() - +" in "+parent); - updateParentType(local.getType()); - } - public boolean opEquals(Operator o) { return (o instanceof LocalLoadOperator && ((LocalLoadOperator) o).local.getSlot() == local.getSlot()); @@ -93,9 +61,4 @@ public class LocalLoadOperator extends Operator return local.getExpression().simplify(); return super.simplify(); } - - public void dumpExpression(TabbedPrintWriter writer) - throws java.io.IOException { - writer.print(local.getName()); - } } diff --git a/jode/jode/expr/LocalStoreOperator.java b/jode/jode/expr/LocalStoreOperator.java index 45dfcf5..2d31d9b 100644 --- a/jode/jode/expr/LocalStoreOperator.java +++ b/jode/jode/expr/LocalStoreOperator.java @@ -23,15 +23,11 @@ import jode.type.Type; import jode.decompiler.LocalInfo; import jode.decompiler.TabbedPrintWriter; -public class LocalStoreOperator extends LValueExpression - implements LocalVarOperator { - LocalInfo local; +public class LocalStoreOperator extends LocalVarOperator + implements LValueExpression { public LocalStoreOperator(Type lvalueType, LocalInfo local) { - super(lvalueType); - this.local = local; - local.setOperator(this); - initOperands(0); + super(lvalueType, local); } public boolean isRead() { @@ -43,33 +39,10 @@ public class LocalStoreOperator extends LValueExpression return true; } - public void updateSubTypes() { - if (parent != null - && (GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_TYPES) != 0) - GlobalOptions.err.println("local type changed in: "+parent); - local.setType(type); - } - - public void updateType() { - updateParentType(local.getType()); - } - - public LocalInfo getLocalInfo() { - return local.getLocalInfo(); - } - public boolean matches(Operator loadop) { return loadop instanceof LocalLoadOperator && ((LocalLoadOperator)loadop).getLocalInfo().getSlot() == local.getSlot(); } - - public int getPriority() { - return 1000; - } - - public void dumpExpression(TabbedPrintWriter writer) { - writer.print(local.getName()); - } } diff --git a/jode/jode/expr/LocalVarOperator.java b/jode/jode/expr/LocalVarOperator.java index baa8966..7e370ef 100644 --- a/jode/jode/expr/LocalVarOperator.java +++ b/jode/jode/expr/LocalVarOperator.java @@ -1,4 +1,4 @@ -/* LocalVarOperator Copyright (C) 1998-1999 Jochen Hoenicke. +/* LocalOperator Copyright (C) 1998-1999 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 @@ -18,16 +18,49 @@ */ package jode.expr; +import jode.GlobalOptions; import jode.type.Type; import jode.decompiler.LocalInfo; +import jode.decompiler.TabbedPrintWriter; -public interface LocalVarOperator { - public boolean isRead(); - public boolean isWrite(); - public LocalInfo getLocalInfo(); - /** - * This is called by the local info when the type - * of it changed - */ - public void updateType(); +public abstract class LocalVarOperator extends Operator { + LocalInfo local; + + public LocalVarOperator(Type lvalueType, LocalInfo local) { + super(lvalueType); + this.local = local; + local.setOperator(this); + initOperands(0); + } + + public abstract boolean isRead(); + public abstract boolean isWrite(); + + public void updateSubTypes() { + if (parent != null + && (GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_TYPES) != 0) + GlobalOptions.err.println("local type changed in: "+parent); + local.setType(type); + } + + public void updateType() { + updateParentType(local.getType()); + } + + public LocalInfo getLocalInfo() { + return local.getLocalInfo(); + } + + public void setLocalInfo(LocalInfo newLocal) { + local = newLocal; + updateType(); + } + + public int getPriority() { + return 1000; + } + + public void dumpExpression(TabbedPrintWriter writer) { + writer.print(local.getName()); + } } diff --git a/jode/jode/expr/Makefile.am b/jode/jode/expr/Makefile.am index 6d846cf..4cb258a 100644 --- a/jode/jode/expr/Makefile.am +++ b/jode/jode/expr/Makefile.am @@ -26,6 +26,7 @@ MY_JAVA_FILES = \ ConstantArrayOperator.java \ ConvertOperator.java \ Expression.java \ + FieldOperator.java \ GetFieldOperator.java \ IIncOperator.java \ IfThenElseOperator.java \ diff --git a/jode/jode/expr/Operator.java.in b/jode/jode/expr/Operator.java.in index 92d154f..de19bb9 100644 --- a/jode/jode/expr/Operator.java.in +++ b/jode/jode/expr/Operator.java.in @@ -224,7 +224,7 @@ public abstract class Operator extends Expression { public boolean containsMatchingLoad(CombineableOperator comb) { Operator combOp = (Operator) comb; if (comb.getLValue().matches(this)) { - if (subsEquals(comb.getLValue())) + if (subsEquals((Operator) comb.getLValue())) return true; } for (int i=0; i < subExpressions.length; i++) { diff --git a/jode/jode/expr/OuterLocalOperator.java b/jode/jode/expr/OuterLocalOperator.java index 8f7495e..6562913 100644 --- a/jode/jode/expr/OuterLocalOperator.java +++ b/jode/jode/expr/OuterLocalOperator.java @@ -56,6 +56,11 @@ public class OuterLocalOperator extends Operator { public void updateType() { } + public boolean opEquals(Operator o) { + return (o instanceof OuterLocalOperator && + ((OuterLocalOperator) o).local.getSlot() == local.getSlot()); + } + public Expression simplify() { return super.simplify(); } diff --git a/jode/jode/expr/PrePostFixOperator.java b/jode/jode/expr/PrePostFixOperator.java index 86bf04d..1b0857c 100644 --- a/jode/jode/expr/PrePostFixOperator.java +++ b/jode/jode/expr/PrePostFixOperator.java @@ -33,7 +33,7 @@ public class PrePostFixOperator extends Operator { this.postfix = postfix; setOperatorIndex(operatorIndex); initOperands(1); - setSubExpressions(0, lvalue); + setSubExpressions(0, (Operator) lvalue); } public int getPriority() { diff --git a/jode/jode/expr/PutFieldOperator.java b/jode/jode/expr/PutFieldOperator.java index bd8f91d..f141d09 100644 --- a/jode/jode/expr/PutFieldOperator.java +++ b/jode/jode/expr/PutFieldOperator.java @@ -30,72 +30,12 @@ import jode.decompiler.FieldAnalyzer; import jode.decompiler.TabbedPrintWriter; import jode.decompiler.Scope; -public class PutFieldOperator extends LValueExpression { - MethodAnalyzer methodAnalyzer; - boolean staticFlag; - Reference ref; - Type classType; +public class PutFieldOperator extends FieldOperator + implements LValueExpression { public PutFieldOperator(MethodAnalyzer methodAnalyzer, boolean staticFlag, Reference ref) { - super(Type.tType(ref.getType())); - this.methodAnalyzer = methodAnalyzer; - this.staticFlag = staticFlag; - this.ref = ref; - this.classType = Type.tType(ref.getClazz()); - if (staticFlag) - methodAnalyzer.useType(classType); - initOperands(staticFlag ? 0 : 1); - } - - public boolean isStatic() { - return staticFlag; - } - - /** - * Checks, whether this is a call of a method from this class. - * @XXX check, if this class implements the method and if not - * allow super class - */ - public boolean isThis() { - return (classType.equals(Type.tClass(methodAnalyzer.getClazz()))); - } - - public ClassInfo getClassInfo() { - if (classType instanceof ClassInterfacesType) - return ((ClassInterfacesType) classType).getClassInfo(); - return null; - } - - public FieldAnalyzer getField() { - ClassInfo clazz = getClassInfo(); - if (clazz != null) { - ClassAnalyzer ana = methodAnalyzer.getClassAnalyzer(); - while (true) { - if (clazz == ana.getClazz()) { - return ana.getField(ref.getName(), - Type.tType(ref.getType())); - } - if (ana.getParent() == null) - return null; - if (ana.getParent() instanceof MethodAnalyzer) - ana = ((MethodAnalyzer) ana.getParent()) - .getClassAnalyzer(); - else if (ana.getParent() instanceof ClassAnalyzer) - ana = (ClassAnalyzer) ana.getParent(); - else - throw new jode.AssertError("Unknown parent"); - } - } - return null; - } - - public String getFieldName() { - return ref.getName(); - } - - public Type getFieldType() { - return Type.tType(ref.getType()); + super(methodAnalyzer, staticFlag, ref); } public boolean matches(Operator loadop) { @@ -103,101 +43,6 @@ public class PutFieldOperator extends LValueExpression { && ((GetFieldOperator)loadop).ref.equals(ref); } - public int getPriority() { - return 950; - } - - public void updateSubTypes() { - if (!staticFlag) - subExpressions[0].setType(Type.tSubType(classType)); - } - - public void updateType() { - updateParentType(getFieldType()); - } - - public boolean needsCast(Type type) { - if (type instanceof NullType) - return true; - if (!(type instanceof ClassInterfacesType - && classType instanceof ClassInterfacesType)) - return false; - - ClassInfo clazz = ((ClassInterfacesType) classType).getClassInfo(); - ClassInfo parClazz = ((ClassInterfacesType) type).getClassInfo(); - while (clazz != parClazz && clazz != null) { - FieldInfo[] fields = parClazz.getFields(); - for (int i = 0; i < fields.length; i++) { - if (fields[i].getName().equals(ref.getName())) - return true; - } - parClazz = parClazz.getSuperclass(); - } - return false; - } - - public void dumpExpression(TabbedPrintWriter writer) - throws java.io.IOException { - boolean opIsThis = !staticFlag - && subExpressions[0] instanceof ThisOperator; - String fieldName = ref.getName(); - if (staticFlag) { - if (!classType.equals(Type.tClass(methodAnalyzer.getClazz())) - || methodAnalyzer.findLocal(fieldName) != null) { - writer.printType(classType); - writer.print("."); - } - writer.print(fieldName); - } else if (needsCast(subExpressions[0].getType().getCanonic())) { - writer.print("(("); - writer.printType(classType); - writer.print(") "); - subExpressions[0].dumpExpression(writer, 700); - writer.print(")."); - writer.print(fieldName); - } else { - if (opIsThis) { - ThisOperator thisOp = (ThisOperator) subExpressions[0]; - ClassInfo clazz = thisOp.getClassInfo(); - Scope scope = writer.getScope(clazz, Scope.CLASSSCOPE); - - if (scope == null || writer.conflicts(fieldName, scope, - Scope.FIELDNAME)) { - thisOp.dumpExpression(writer, 950); - writer.print("."); - } else { - if (writer.conflicts(fieldName, scope, - Scope.AMBIGUOUSNAME) - || (/* This is a inherited field conflicting - * with a field name in some outer class. - */ - getField() == null - && writer.conflicts(fieldName, null, - Scope.NOSUPERFIELDNAME))) { - - ClassAnalyzer ana = methodAnalyzer.getClassAnalyzer(); - while (ana.getParent() instanceof ClassAnalyzer - && ana != scope) - ana = (ClassAnalyzer) ana.getParent(); - if (ana == scope) - // For a simple outer class we can say this - writer.print("this."); - else { - // For a class that owns a method that owns - // us, we have to give the full class name - thisOp.dumpExpression(writer, 950); - writer.print("."); - } - } - } - } else { - subExpressions[0].dumpExpression(writer, 950); - writer.print("."); - } - writer.print(fieldName); - } - } - public boolean opEquals(Operator o) { return o instanceof PutFieldOperator && ((PutFieldOperator)o).ref.equals(ref); diff --git a/jode/jode/expr/StoreInstruction.java b/jode/jode/expr/StoreInstruction.java index 6c14e9a..5531f06 100644 --- a/jode/jode/expr/StoreInstruction.java +++ b/jode/jode/expr/StoreInstruction.java @@ -30,7 +30,7 @@ public class StoreInstruction extends Operator public StoreInstruction(LValueExpression lvalue) { super(Type.tVoid, ASSIGN_OP); initOperands(2); - setSubExpressions(0, lvalue); + setSubExpressions(0, (Operator) lvalue); } public LValueExpression getLValue() {