Decompiler, JodeApplet and JodeWindow moved into decompile package

makeDeclaration now transmits the done set over class borders


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1202 379699f6-c40d-0410-875b-85095c16579e
branch_1_1
jochen 25 years ago
parent c5b840847b
commit 915439b1ff
  1. 4
      jode/jode/expr/Expression.java.in
  2. 26
      jode/jode/expr/FieldOperator.java.in
  3. 154
      jode/jode/expr/InvokeOperator.java.in
  4. 10
      jode/jode/expr/Operator.java.in
  5. 5
      jode/jode/expr/StoreInstruction.java
  6. 16
      jode/jode/flow/FlowBlock.java.in
  7. 15
      jode/jode/flow/IfThenElseBlock.java.in
  8. 16
      jode/jode/flow/InstructionContainer.java.in
  9. 50
      jode/jode/flow/LoopBlock.java.in
  10. 1
      jode/jode/flow/SpecialBlock.java
  11. 50
      jode/jode/flow/StructuredBlock.java.in
  12. 12
      jode/jode/flow/TransformConstructors.java

@ -23,6 +23,7 @@ import jode.GlobalOptions;
import jode.decompiler.TabbedPrintWriter;
import @COLLECTIONS@.Collection;
import @COLLECTIONS@.Set;
public abstract class Expression {
protected Type type;
@ -230,6 +231,9 @@ public abstract class Expression {
public void fillDeclarables(Collection used) {
}
public void makeDeclaration(Set done) {
}
public abstract void dumpExpression(TabbedPrintWriter writer)
throws java.io.IOException;

@ -29,9 +29,9 @@ import jode.decompiler.MethodAnalyzer;
import jode.decompiler.ClassAnalyzer;
import jode.decompiler.MethodAnalyzer;
import jode.decompiler.FieldAnalyzer;
import jode.decompiler.Options;
import jode.decompiler.TabbedPrintWriter;
import jode.decompiler.Scope;
import jode.Decompiler;
import @COLLECTIONS@.Collection;
@ -157,21 +157,19 @@ public abstract class FieldOperator extends Operator {
InnerClassInfo outer = getOuterClassInfo(clazz);
ClassAnalyzer clazzAna = methodAnalyzer.getClassAnalyzer(clazz);
if ((Decompiler.options & Decompiler.OPTION_ANON) != 0
if ((Options.options & Options.OPTION_ANON) != 0
&& outer != null && outer.outer == null && outer.name != null
&& 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);
}
}
&& 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);
}
super.fillDeclarables(used);
}
public void dumpExpression(TabbedPrintWriter writer)

@ -20,17 +20,17 @@
package jode.expr;
import java.lang.reflect.Modifier;
import jode.Decompiler;
import jode.decompiler.MethodAnalyzer;
import jode.decompiler.MethodAnalyzer;
import jode.decompiler.ClassAnalyzer;
import jode.decompiler.TabbedPrintWriter;
import jode.decompiler.Options;
import jode.decompiler.OuterValues;
import jode.decompiler.Scope;
import jode.GlobalOptions;
import jode.bytecode.*;
import jode.jvm.*;
import jode.type.*;
import jode.decompiler.Scope;
import jode.util.SimpleMap;
import java.lang.reflect.InvocationTargetException;
@ -39,6 +39,7 @@ import @COLLECTIONS@.Collections;
import @COLLECTIONS@.Collection;
import @COLLECTIONS@.Map;
import @COLLECTIONS@.Iterator;
import @COLLECTIONS@.Set;
public final class InvokeOperator extends Operator
implements MatchableOperator {
@ -175,7 +176,7 @@ public final class InvokeOperator extends Operator
public void checkAnonymousClasses() {
if (methodFlag != CONSTRUCTOR
|| (Decompiler.options & Decompiler.OPTION_ANON) == 0)
|| (Options.options & Options.OPTION_ANON) == 0)
return;
InnerClassInfo outer = getOuterClassInfo(getClassInfo());
if (outer != null && (outer.outer == null || outer.name == null)) {
@ -251,8 +252,8 @@ public final class InvokeOperator extends Operator
* inside the same base class as the caller class, null otherwise.
*/
public ClassAnalyzer getClassAnalyzer() {
if ((Decompiler.options &
(Decompiler.OPTION_ANON | Decompiler.OPTION_INNER)) == 0)
if ((Options.options &
(Options.OPTION_ANON | Options.OPTION_INNER)) == 0)
return null;
ClassInfo callee = getClassInfo();
@ -261,7 +262,7 @@ public final class InvokeOperator extends Operator
int nested = 0;
InnerClassInfo[] outers = callee.getOuterClasses();
if ((Decompiler.options & Decompiler.OPTION_INNER) != 0
if ((Options.options & Options.OPTION_INNER) != 0
&& outers != null) {
/* If the callee class is an inner class we take its
* (outermost) parent instead. This will assure that we
@ -288,12 +289,12 @@ public final class InvokeOperator extends Operator
if (ana.getParent() == null)
return null;
if (ana.getParent() instanceof MethodAnalyzer
&& (Decompiler.options & Decompiler.OPTION_ANON) != 0)
&& (Options.options & Options.OPTION_ANON) != 0)
ana = ((MethodAnalyzer) ana.getParent())
.getClassAnalyzer();
else if (ana.getParent() instanceof ClassAnalyzer
&& (Decompiler.options
& Decompiler.OPTION_INNER) != 0)
&& (Options.options
& Options.OPTION_INNER) != 0)
ana = (ClassAnalyzer) ana.getParent();
else
throw new jode.AssertError
@ -325,12 +326,12 @@ public final class InvokeOperator extends Operator
if (ana.getParent() == null)
break;
if (ana.getParent() instanceof MethodAnalyzer
&& (Decompiler.options & Decompiler.OPTION_ANON) != 0)
&& (Options.options & Options.OPTION_ANON) != 0)
ana = ((MethodAnalyzer) ana.getParent())
.getClassAnalyzer();
else if (ana.getParent() instanceof ClassAnalyzer
&& (Decompiler.options
& Decompiler.OPTION_INNER) != 0)
&& (Options.options
& Options.OPTION_INNER) != 0)
ana = (ClassAnalyzer) ana.getParent();
else
throw new jode.AssertError
@ -367,7 +368,7 @@ public final class InvokeOperator extends Operator
}
public boolean isConstant() {
if ((Decompiler.options & Decompiler.OPTION_ANON) == 0)
if ((Options.options & Options.OPTION_ANON) == 0)
return super.isConstant();
ClassInfo clazz = getClassInfo();
@ -545,7 +546,7 @@ public final class InvokeOperator extends Operator
result.addOperand(right);
result.addOperand(subExpressions[0].simplify());
}
else if ((Decompiler.options & Decompiler.OPTION_DECRYPT) != 0
else if ((Options.options & Options.OPTION_DECRYPT) != 0
&& isThis() && isStatic()
&& methodType.getParameterTypes().length == 1
&& methodType.getParameterTypes()[0].equals(Type.tString)
@ -700,63 +701,68 @@ public final class InvokeOperator extends Operator
InnerClassInfo outer = getOuterClassInfo(clazz);
ClassAnalyzer clazzAna = methodAnalyzer.getClassAnalyzer(clazz);
if ((Options.options & Options.OPTION_ANON) != 0
&& outer != null && outer.outer == null && outer.name != null
&& clazzAna != null
&& 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);
}
if (!isConstructor() || isStatic()) {
super.fillDeclarables(used);
return;
}
int arg = 1;
int length = subExpressions.length;
boolean jikesAnonymousInner = false;
if ((Decompiler.options & Decompiler.OPTION_ANON) != 0
if ((Options.options & Options.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);
}
}
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;
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) {
/* 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);
expr.fillDeclarables(used);
}
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);
}
}
if (isConstructor()
&& (Decompiler.options & Decompiler.OPTION_INNER) != 0
if ((Options.options & Options.OPTION_INNER) != 0
&& outer != null && outer.outer != null && outer.name != null
&& !Modifier.isStatic(outer.modifiers)) {
Expression outerExpr = jikesAnonymousInner
? subExpressions[--length]
: subExpressions[arg++];
? subExpressions[--length]
: subExpressions[arg++];
if (outerExpr instanceof CheckNullOperator) {
CheckNullOperator cno = (CheckNullOperator) outerExpr;
outerExpr = cno.subExpressions[0];
@ -767,6 +773,27 @@ public final class InvokeOperator extends Operator
subExpressions[i].fillDeclarables(used);
}
/**
* We add the named method scoped classes to the declarables, and
* only fillDeclarables on the parameters we will print.
*/
public void makeDeclaration(Set done) {
super.makeDeclaration(done);
if (isConstructor() && !isStatic()
&& (Options.options & Options.OPTION_ANON) != 0) {
ClassInfo clazz = getClassInfo();
InnerClassInfo outer = getOuterClassInfo(clazz);
ClassAnalyzer clazzAna = methodAnalyzer.getClassAnalyzer(clazz);
if (clazzAna != null && outer != null && outer.name == null) {
/* call makeDeclaration on the anonymous class, since
* _we_ will declare the anonymous class. */
clazzAna.makeDeclaration(done);
}
}
}
/* Invokes never equals: they may return different values even if
* they have the same parameters.
*/
@ -798,8 +825,8 @@ public final class InvokeOperator extends Operator
if (outer != null && outer.name == null)
anonymousNew = true;
clazzAna = methodAnalyzer.getClassAnalyzer(clazz);
if ((~Decompiler.options &
(Decompiler.OPTION_ANON | Decompiler.OPTION_CONTRAFO)) == 0
if ((~Options.options &
(Options.OPTION_ANON | Options.OPTION_CONTRAFO)) == 0
&& clazzAna != null
&& outer != null
&& (outer.outer == null || outer.name == null)) {
@ -846,9 +873,9 @@ public final class InvokeOperator extends Operator
*/
if (outer != null && outer.outer != null && outer.name != null
&& !Modifier.isStatic(outer.modifiers)
&& (~Decompiler.options &
(Decompiler.OPTION_INNER
| Decompiler.OPTION_CONTRAFO)) == 0) {
&& (~Options.options &
(Options.OPTION_INNER
| Options.OPTION_CONTRAFO)) == 0) {
Expression outerExpr = jikesAnonymousInner
? subExpressions[--length]
@ -914,10 +941,7 @@ public final class InvokeOperator extends Operator
break;
}
case SPECIAL:
if (subExpressions[0] instanceof ThisOperator
&& (((ThisOperator)subExpressions[0]).getClassInfo()
== methodAnalyzer.getClazz())) {
if (isSuperOrThis()) {
if (!isThis()) {
/* We don't have to check if this is the real super
* class, as long as ACC_SUPER is set.

@ -23,6 +23,7 @@ import jode.GlobalOptions;
import jode.decompiler.TabbedPrintWriter;
import @COLLECTIONS@.Collection;
import @COLLECTIONS@.Set;
public abstract class Operator extends Expression {
/* Don't reorder these constants unless you know what you are doing! */
@ -172,13 +173,16 @@ public abstract class Operator extends Expression {
}
public void fillDeclarables(Collection used) {
if (this instanceof LocalVarOperator) {
used.add(((LocalVarOperator) this).getLocalInfo());
}
for (int i=0; i< subExpressions.length; i++)
subExpressions[i].fillDeclarables(used);
}
public void makeDeclaration(Set done) {
for (int i=0; i< subExpressions.length; i++)
subExpressions[i].makeDeclaration(done);
}
/**
* Checks if the value of the given expression can change, due to
* side effects in this expression. If this returns false, the

@ -89,8 +89,9 @@ public class StoreInstruction extends Operator
ConstOperator one = (ConstOperator) subExpressions[1];
if ((getOperatorIndex() == OPASSIGN_OP+ADD_OP ||
getOperatorIndex() == OPASSIGN_OP+SUB_OP) &&
((Number)one.getValue()).doubleValue() == 1.0) {
getOperatorIndex() == OPASSIGN_OP+SUB_OP)
&& one.getValue() instanceof Number
&& ((Number)one.getValue()).doubleValue() == 1.0) {
int op = (getOperatorIndex() == OPASSIGN_OP+ADD_OP)
? INC_OP : DEC_OP;

@ -1612,23 +1612,13 @@ public class FlowBlock {
/**
* Make declarations. It will determine, where in each block the
*
* variables and method scoped classes must be declared.
*/
public void makeDeclaration() {
public void makeDeclaration(Set done) {
block.propagateUsage();
Set done = new SimpleSet();
done.addAll(in);
block.makeDeclaration(done);
if (nextByAddr != null)
nextByAddr.makeDeclaration();
}
/**
* Make declarations. It will determine, where in each block the
*
*/
public void makeDeclaration(LocalInfo[] param) {
makeDeclaration();
nextByAddr.makeDeclaration(done);
}
/**

@ -140,6 +140,21 @@ public class IfThenElseBlock extends StructuredBlock {
return used;
}
/**
* Make the declarations, i.e. initialize the declare variable
* to correct values. This will declare every variable that
* is marked as used, but not done.<br>
*
* This will now also combine locals, that use the same slot, have
* compatible types and are declared in the same block. <br>
*
* @param done The set of the already declare variables.
*/
public void makeDeclaration(Set done) {
cond.makeDeclaration(done);
super.makeDeclaration(done);
}
/**
* Print the source code for this structured block. This may be
* called only once, because it remembers which local variables

@ -44,6 +44,22 @@ public abstract class InstructionContainer extends StructuredBlock {
setJump(jump);
}
/**
* Make the declarations, i.e. initialize the declare variable
* to correct values. This will declare every variable that
* is marked as used, but not done.<br>
*
* This will now also combine locals, that use the same slot, have
* compatible types and are declared in the same block. <br>
*
* @param done The set of the already declare variables.
*/
public void makeDeclaration(Set done) {
if (instr != null)
instr.makeDeclaration(done);
super.makeDeclaration(done);
}
/**
* This method should remove local variables that are only written
* and read one time directly after another. <br>

@ -199,6 +199,28 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
this.type = type;
}
/**
* Replaces the given sub block with a new block.
* @param oldBlock the old sub block.
* @param newBlock the new sub block.
* @return false, if oldBlock wasn't a direct sub block.
*/
public boolean replaceSubBlock(StructuredBlock oldBlock,
StructuredBlock newBlock) {
if (bodyBlock == oldBlock)
bodyBlock = newBlock;
else
return false;
return true;
}
/**
* Returns all sub block of this structured block.
*/
public StructuredBlock[] getSubBlocks() {
return new StructuredBlock[] { bodyBlock };
}
/**
* Remove all variables from set, that we can declare inside the
* loop-block. This is the initializer for for-blocks.
@ -225,28 +247,6 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
return used;
}
/**
* Replaces the given sub block with a new block.
* @param oldBlock the old sub block.
* @param newBlock the new sub block.
* @return false, if oldBlock wasn't a direct sub block.
*/
public boolean replaceSubBlock(StructuredBlock oldBlock,
StructuredBlock newBlock) {
if (bodyBlock == oldBlock)
bodyBlock = newBlock;
else
return false;
return true;
}
/**
* Returns all sub block of this structured block.
*/
public StructuredBlock[] getSubBlocks() {
return new StructuredBlock[] { bodyBlock };
}
/**
* Check if this is an local store instruction to a not yet declared
* variable. In that case mark this as declaration and return the
@ -278,6 +278,12 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
* @param done The set of the already declare variables.
*/
public void makeDeclaration(Set done) {
if (type == FOR) {
if (initInstr != null)
initInstr.makeDeclaration(done);
incrInstr.makeDeclaration(done);
}
cond.makeDeclaration(done);
super.makeDeclaration(done);
if (type == FOR && initInstr != null)
checkDeclaration(declare);

@ -19,7 +19,6 @@
package jode.flow;
import jode.decompiler.TabbedPrintWriter;
import jode.Decompiler;
import jode.expr.*;
/**

@ -23,6 +23,7 @@ import jode.GlobalOptions;
import jode.decompiler.TabbedPrintWriter;
import jode.decompiler.LocalInfo;
import jode.decompiler.Declarable;
import jode.decompiler.ClassAnalyzer;
import jode.util.SimpleSet;
import @COLLECTIONS@.Collections;
@ -464,31 +465,27 @@ public abstract class StructuredBlock {
if (!(previous instanceof LocalInfo))
continue;
LocalInfo prevLocal = (LocalInfo) previous;
if (prevLocal.getSlot() == local.getSlot()) {
/* XXX - I have to think about this...
* there may be a case where this leads to type errors.
* TODO: Give a formal proof ;-)
* One bad thing that may happen is that the name
* of prevLocal (it has already a name) doesn't match
* the intersected type.
*
* We don't want to merge variables, whose names
* are not generated by us and differ. And we
* don't want to merge special locals that have a
* constant expression, e.g. this.
*/
if (prevLocal.getType().isOfType(local.getType())
&& (prevLocal.isNameGenerated()
|| local.isNameGenerated()
|| localName.equals(prevLocal.getName()))
&& !prevLocal.isFinal()
&& !local.isFinal()
&& prevLocal.getExpression() == null
&& local.getExpression() == null) {
local.combineWith(prevLocal);
continue next_used;
}
/* We only merge locals living in the same
* method and having the same slot.
*
* We don't want to merge variables, whose names
* are not generated by us and differ. And we
* don't want to merge special locals that have a
* constant expression, e.g. this.
*/
if (prevLocal.getMethodAnalyzer()
== local.getMethodAnalyzer()
&& prevLocal.getSlot() == local.getSlot()
&& prevLocal.getType().isOfType(local.getType())
&& (prevLocal.isNameGenerated()
|| local.isNameGenerated()
|| localName.equals(prevLocal.getName()))
&& !prevLocal.isFinal()
&& !local.isFinal()
&& prevLocal.getExpression() == null
&& local.getExpression() == null) {
local.combineWith(prevLocal);
continue next_used;
}
}
}
@ -500,11 +497,14 @@ public abstract class StructuredBlock {
if (declarable.getName().equals(previous.getName())) {
/* A name conflict happened. */
declarable.makeNameUnique();
break;
}
}
}
done.add(declarable);
declare.add(declarable);
if (declare instanceof ClassAnalyzer)
((ClassAnalyzer) declare).makeDeclaration(done);
}
StructuredBlock[] subs = getSubBlocks();
for (int i=0; i<subs.length; i++)

@ -20,12 +20,12 @@
package jode.flow;
import java.lang.reflect.Modifier;
import jode.GlobalOptions;
import jode.Decompiler;
import jode.decompiler.Analyzer;
import jode.decompiler.ClassAnalyzer;
import jode.decompiler.MethodAnalyzer;
import jode.decompiler.FieldAnalyzer;
import jode.decompiler.MethodAnalyzer;
import jode.decompiler.Options;
import jode.decompiler.OuterValues;
import jode.decompiler.OuterValueListener;
import jode.expr.*;
@ -241,7 +241,7 @@ public class TransformConstructors {
InvokeOperator superCall = (InvokeOperator) expr;
Expression[] subExpr = superCall.getSubExpressions();
/* An anonymous constructor may also give locals
/* An anonymous constructor may only give locals
* to its super constructor.
*/
for (int i = 1; i < subExpr.length; i++) {
@ -577,7 +577,7 @@ public class TransformConstructors {
return null;
}
if (outerValues != null
&& (Decompiler.options & Decompiler.OPTION_CONTRAFO) != 0) {
&& (Options.options & Options.OPTION_CONTRAFO) != 0) {
int slot = ((LocalLoadOperator)expr).getLocalInfo().getSlot();
Expression outExpr = outerValues.getValueBySlot(slot);
if (outExpr != null)
@ -604,7 +604,7 @@ public class TransformConstructors {
}
public void removeSynthInitializers() {
if ((Decompiler.options & Decompiler.OPTION_CONTRAFO) == 0
if ((Options.options & Options.OPTION_CONTRAFO) == 0
|| isStatic || type01Count == 0)
return;
@ -852,7 +852,7 @@ public class TransformConstructors {
InnerClassInfo[] outers = superClazz.getOuterClasses();
int superParamCount = superInvoke.getSubExpressions().length - 1;
if ((Decompiler.options & Decompiler.OPTION_INNER) != 0
if ((Options.options & Options.OPTION_INNER) != 0
&& outers != null
&& outers[0].outer != null
&& outers[0].name != null
@ -995,7 +995,7 @@ public class TransformConstructors {
* outerValue - locals).
*/
public void transform() {
if ((Decompiler.options & Decompiler.OPTION_CONTRAFO) == 0
if ((Options.options & Options.OPTION_CONTRAFO) == 0
|| cons.length == 0)
return;

Loading…
Cancel
Save