Pascal style.

Better gnu style.
Some bug fixes (see Changelog).


git-svn-id: https://svn.code.sf.net/p/jode/code/branches/branch_1_1@1292 379699f6-c40d-0410-875b-85095c16579e
branch_1_1
hoenicke 24 years ago
parent 816bca302d
commit cb12d3ead2
  1. 53
      jode/ChangeLog
  2. 2
      jode/THANKS
  3. 9
      jode/jode/decompiler/ClassAnalyzer.java.in
  4. 2
      jode/jode/decompiler/Decompiler.java
  5. 5
      jode/jode/decompiler/FieldAnalyzer.java.in
  6. 2
      jode/jode/decompiler/Main.java
  7. 7
      jode/jode/decompiler/MethodAnalyzer.java.in
  8. 11
      jode/jode/decompiler/Options.java
  9. 71
      jode/jode/decompiler/TabbedPrintWriter.java
  10. 28
      jode/jode/expr/InvokeOperator.java.in
  11. 11
      jode/jode/expr/PopOperator.java
  12. 3
      jode/jode/expr/UnaryOperator.java
  13. 42
      jode/jode/jvm/SyntheticAnalyzer.java.in
  14. 11
      jode/jode/type/NullType.java

@ -0,0 +1,53 @@
Tue Jan 30 15:35:19 2001 Jochen Hoenicke <jochen@gnu.org>
* jode/decompiler/TabbedPrintWriter.java: Better gnu style handling:
(openBraceClass) (closeBraceClass)
(openBraceNoIndent) (closeBraceNoIndent): new functions.
(closeBraceNoSpace): Removed.
* jode/decompiler/Options.java (GNU_SPACING): new constant.
(GNU_STYLE): changed to include GNU_SPACING.
* jode/decompiler/ClassAnalyzer.java.in (dumpSource): Use
open/closeBraceClass.
* jode/decompiler/MethodAnalyzer.java.in (dumpSource): Use
open/closeBraceNoIndent. Insert a space for GNU_SPACING.
* jode/decompiler/InvokeOperator.java.in (dumpExpression): Insert
a space for GNU_SPACING, use open/closeBraceClass for inner
classes.
* jode/decompiler/UnaryOperator.java (dumpExpression): Insert
a space for GNU_SPACING.
Tue Jan 30 15:28:10 2001 Jochen Hoenicke <jochen@gnu.org>
Added pascal style from Rolf Howarth <rolf@squarebox.co.uk>
* jode/decompiler/Options.java (PASCAL_STYLE): new constant.
(BRACE_FLUSH_LEFT): dito.
* jode/decompiler/Decompiler.java (setOption): detect pascal option.
* jode/decompiler/Main.java (main): dito.
* jode/decompiler/TabbedPrintWriter.java (openBrace,
openBraceContinue, closeBrace, closeBraceNoSpace,
closeBraceContinue): handle flush left.
Tue Jan 30 00:28:10 2001 Jochen Hoenicke <jochen@gnu.org>
* jode/type/NullType.java (intersection): Removed, since the
version in ReferenceType is more correct. Before
tNull.isOfType(tRange(X,tNull)) returned false, which lead to
incorrect behaviour in InvokeOperator.needsCast.
* jode/decompiler/FieldAnalyzer.java.in (dumpSource): Removed the
"= null" hack for final fields; it was not correct, since the
field could be initialized in a constructor.
* jode/decompiler/TabbedPrintWriter.java (BreakPoint.endOp):
Simplified the code, copy options always from child.
* jode/jvm/SyntheticAnalyzer.java.in (unifyParam): new field.
(checkConstructorAccess): Allow the special Parameter, whose
purpose is to distinguish the wrapper from the real constructor
and give him a "$" in the type signature, to appear at every
position. It doesn't appear at position 1 for inner classes.
Store the position in unifyParam.
* jode/expr/InvokeOperator.java (isGetClass): Allow the method to
be declared inside an outer class: We simply check if we can get
the method analyzer.
(simplify): handle unifyParam.
* jode/expr/PopOperator.java (getBreakPenalty): return penalty of
inner expression. (dumpExpression): Call dumpExpression of
subexpression immediately without priority.

@ -1 +1,3 @@
Rolf Howarth <rolf@squarebox.co.uk> for pascal indentaton style.
Martin Schmitz <m.schmitz@e-sign.com> for finding many bugs in the obfuscator.
zzzeek <classic@io.com> zzzeek <classic@io.com>

@ -564,15 +564,12 @@ public class ClassAnalyzer
} }
writer.println(); writer.println();
writer.openBrace(); writer.openBraceClass();
writer.tab(); writer.tab();
dumpBlock(writer, pl, done, scale); dumpBlock(writer, pl, done, scale);
writer.untab(); writer.untab();
if (parent instanceof MethodAnalyzer) { writer.closeBraceClass();
/* This is a method scope class */ writer.println();
writer.closeBraceNoSpace();
} else
writer.closeBrace();
clazz.dropInfo(clazz.KNOWNATTRIBS | clazz.UNKNOWNATTRIBS); clazz.dropInfo(clazz.KNOWNATTRIBS | clazz.UNKNOWNATTRIBS);
} }

@ -103,6 +103,8 @@ public class Decompiler {
Options.outputStyle = Options.GNU_STYLE; Options.outputStyle = Options.GNU_STYLE;
else if (value.equals("sun")) else if (value.equals("sun"))
Options.outputStyle = Options.SUN_STYLE; Options.outputStyle = Options.SUN_STYLE;
else if (value.equals("pascal"))
Options.outputStyle = Options.PASCAL_STYLE;
else else
throw new IllegalArgumentException("Invalid style "+value); throw new IllegalArgumentException("Invalid style "+value);
return; return;

@ -187,11 +187,6 @@ public class FieldAnalyzer implements Analyzer {
writer.breakOp(); writer.breakOp();
writer.print(" = "); writer.print(" = ");
constant.dumpExpression(writer.IMPL_PAREN, writer); constant.dumpExpression(writer.IMPL_PAREN, writer);
} else if ((modifiers & (Modifier.STATIC | Modifier.FINAL))
== (Modifier.STATIC | Modifier.FINAL)) {
/* Static final fields must always be initialized */
writer.breakOp();
writer.print(" = null");
} }
writer.endOp(); writer.endOp();
writer.println(";"); writer.println(";");

@ -258,6 +258,8 @@ public class Main extends Options {
outputStyle = SUN_STYLE; outputStyle = SUN_STYLE;
else if ("gnu".startsWith(arg)) else if ("gnu".startsWith(arg))
outputStyle = GNU_STYLE; outputStyle = GNU_STYLE;
else if ("pascal".startsWith(arg))
outputStyle = Options.PASCAL_STYLE;
else { else {
GlobalOptions.err.println GlobalOptions.err.println
("jode.decompiler.Main: Unknown style `"+arg+"'."); ("jode.decompiler.Main: Unknown style `"+arg+"'.");

@ -27,6 +27,7 @@ import jode.bytecode.Handler;
import jode.bytecode.Instruction; import jode.bytecode.Instruction;
import jode.bytecode.LocalVariableInfo; import jode.bytecode.LocalVariableInfo;
import jode.jvm.SyntheticAnalyzer; import jode.jvm.SyntheticAnalyzer;
import jode.decompiler.Options;
import jode.type.*; import jode.type.*;
import jode.expr.Expression; import jode.expr.Expression;
import jode.expr.ConstOperator; import jode.expr.ConstOperator;
@ -866,6 +867,8 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
writer.print(" " + methodName); writer.print(" " + methodName);
} }
writer.breakOp(); writer.breakOp();
if ((Options.outputStyle & Options.GNU_SPACING) != 0)
writer.print(" ");
writer.print("("); writer.print("(");
writer.startOp(writer.EXPL_PAREN, 0); writer.startOp(writer.EXPL_PAREN, 0);
int offset = skipParams + (isStatic() ? 0 : 1); int offset = skipParams + (isStatic() ? 0 : 1);
@ -895,11 +898,11 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
} }
writer.endOp(); writer.endOp();
if (code != null) { if (code != null) {
writer.openBrace(); writer.openBraceNoIndent();
writer.tab(); writer.tab();
methodHeader.dumpSource(writer); methodHeader.dumpSource(writer);
writer.untab(); writer.untab();
writer.closeBrace(); writer.closeBraceNoIndent();
} else } else
writer.println(";"); writer.println(";");
writer.popScope(); writer.popScope();

@ -22,10 +22,13 @@ import jode.bytecode.ClassInfo;
import jode.bytecode.InnerClassInfo; import jode.bytecode.InnerClassInfo;
public class Options { public class Options {
public static final int TAB_SIZE_MASK = 0x0f; public static final int TAB_SIZE_MASK = 0x0f;
public static final int BRACE_AT_EOL = 0x10; public static final int BRACE_AT_EOL = 0x10;
public static final int SUN_STYLE = 0x14; public static final int BRACE_FLUSH_LEFT = 0x20;
public static final int GNU_STYLE = 0x02; public static final int GNU_SPACING = 0x40;
public static final int SUN_STYLE = 0x14;
public static final int GNU_STYLE = 0x42;
public static final int PASCAL_STYLE = 0x24;
public static final int OPTION_LVT = 0x0001; public static final int OPTION_LVT = 0x0001;
public static final int OPTION_INNER = 0x0002; public static final int OPTION_INNER = 0x0002;

@ -120,17 +120,15 @@ public class TabbedPrintWriter {
public void endOp(int pos) { public void endOp(int pos) {
endPos = pos; endPos = pos;
if (childBPs.size() == 1) { if (childBPs.size() == 1) {
BreakPoint child = /* There is no breakpoint in this op, replace this with
(BreakPoint) currentBP.childBPs.elementAt(0); * our child, if possible.
if (child.startPos == -1) { */
startPos = endPos = -1; BreakPoint child = (BreakPoint) childBPs.elementAt(0);
childBPs = null; options = child.options;
} else if (child.startPos == currentBP.startPos startPos = child.startPos;
&& child.endPos == currentBP.endPos) { endPos = child.endPos;
if (options == DONT_BREAK) breakPenalty = child.breakPenalty;
options = child.options; childBPs = child.childBPs;
childBPs = child.childBPs;
}
} }
} }
@ -746,12 +744,38 @@ public class TabbedPrintWriter {
} else { } else {
if (currentLine.length() > 0) if (currentLine.length() > 0)
println(); println();
if (currentIndent > 0) if ((Options.outputStyle & Options.BRACE_FLUSH_LEFT) == 0
&& currentIndent > 0)
tab(); tab();
println("{"); println("{");
} }
} }
public void openBraceClass() {
if (currentLine.length() > 0) {
if ((Options.outputStyle & Options.BRACE_AT_EOL) != 0)
print(" ");
else
println();
}
println("{");
}
/**
* Print a opening brace with the current indentation style.
* Called at the end the line of a method declaration.
*/
public void openBraceNoIndent() {
if ((Options.outputStyle & Options.BRACE_AT_EOL) != 0) {
print(currentLine.length() > 0 ? " {" : "{");
println();
} else {
if (currentLine.length() > 0)
println();
println("{");
}
}
/** /**
* Print a opening brace with the current indentation style. * Print a opening brace with the current indentation style.
* Called at the end of the line of the instance that opens the * Called at the end of the line of the instance that opens the
@ -763,7 +787,8 @@ public class TabbedPrintWriter {
else { else {
if (currentLine.length() > 0) if (currentLine.length() > 0)
println(); println();
if (currentIndent > 0) if ((Options.outputStyle & Options.BRACE_FLUSH_LEFT) == 0
&& currentIndent > 0)
tab(); tab();
println("{"); println("{");
} }
@ -774,19 +799,14 @@ public class TabbedPrintWriter {
print("} "); print("} ");
else { else {
println("}"); println("}");
if (currentIndent > 0) if ((Options.outputStyle & Options.BRACE_FLUSH_LEFT) == 0
&& currentIndent > 0)
untab(); untab();
} }
} }
public void closeBraceNoSpace() { public void closeBraceClass() {
if ((Options.outputStyle & Options.BRACE_AT_EOL) != 0) print("}");
print("}");
else {
println("}");
if (currentIndent > 0)
untab();
}
} }
public void closeBrace() { public void closeBrace() {
@ -794,11 +814,16 @@ public class TabbedPrintWriter {
println("}"); println("}");
else { else {
println("}"); println("}");
if (currentIndent > 0) if ((Options.outputStyle & Options.BRACE_FLUSH_LEFT) == 0
&& currentIndent > 0)
untab(); untab();
} }
} }
public void closeBraceNoIndent() {
println("}");
}
public void flush() { public void flush() {
pw.flush(); pw.flush();
} }

@ -398,12 +398,12 @@ public final class InvokeOperator extends Operator
* @return true if this is the magic class$ method, false otherwise. * @return true if this is the magic class$ method, false otherwise.
*/ */
public boolean isGetClass() { public boolean isGetClass() {
if (isThis()) { MethodAnalyzer mana = getMethodAnalyzer();
SyntheticAnalyzer synth = getMethodAnalyzer().getSynthetic(); if (mana == null)
if (synth != null && synth.getKind() == SyntheticAnalyzer.GETCLASS) return false;
return true; SyntheticAnalyzer synth = getMethodAnalyzer().getSynthetic();
} return (synth != null
return false; && synth.getKind() == SyntheticAnalyzer.GETCLASS);
} }
class Environment extends SimpleRuntimeEnvironment { class Environment extends SimpleRuntimeEnvironment {
@ -572,6 +572,7 @@ public final class InvokeOperator extends Operator
if (getMethodAnalyzer() != null) { if (getMethodAnalyzer() != null) {
SyntheticAnalyzer synth = getMethodAnalyzer().getSynthetic(); SyntheticAnalyzer synth = getMethodAnalyzer().getSynthetic();
if (synth != null) { if (synth != null) {
int unifyParam = synth.getUnifyParam();
Expression op = null; Expression op = null;
switch (synth.getKind()) { switch (synth.getKind()) {
case SyntheticAnalyzer.ACCESSGETFIELD: case SyntheticAnalyzer.ACCESSGETFIELD:
@ -601,9 +602,9 @@ public final class InvokeOperator extends Operator
synth.getReference()); synth.getReference());
break; break;
case SyntheticAnalyzer.ACCESSCONSTRUCTOR: case SyntheticAnalyzer.ACCESSCONSTRUCTOR:
if (subExpressions[1] instanceof ConstOperator if (subExpressions[unifyParam] instanceof ConstOperator
&& ((ConstOperator) && ((ConstOperator)
subExpressions[1]).getValue() == null) { subExpressions[unifyParam]).getValue() == null) {
op = new InvokeOperator(methodAnalyzer, CONSTRUCTOR, op = new InvokeOperator(methodAnalyzer, CONSTRUCTOR,
synth.getReference()); synth.getReference());
} }
@ -613,7 +614,7 @@ public final class InvokeOperator extends Operator
if (op != null) { if (op != null) {
if (subExpressions != null) { if (subExpressions != null) {
for (int i=subExpressions.length; i-- > 0; ) { for (int i=subExpressions.length; i-- > 0; ) {
if (i == 1 && synth.getKind() if (i == unifyParam && synth.getKind()
== SyntheticAnalyzer.ACCESSCONSTRUCTOR) == SyntheticAnalyzer.ACCESSCONSTRUCTOR)
// skip the null param. // skip the null param.
continue; continue;
@ -675,9 +676,10 @@ public final class InvokeOperator extends Operator
} }
for (int p = offset; p < paramTypes.length; p++) { for (int p = offset; p < paramTypes.length; p++) {
if (!paramTypes[p] if (!paramTypes[p]
.isOfType(Type.tSubType(otherParamTypes[p-offset]))) .isOfType(Type.tSubType(otherParamTypes[p-offset]))){
/* No conflict here */ /* No conflict here */
continue next_method; continue next_method;
}
} }
/* There is a conflict that can be resolved by a cast. */ /* There is a conflict that can be resolved by a cast. */
return true; return true;
@ -1103,6 +1105,8 @@ public final class InvokeOperator extends Operator
writer.endOp(); writer.endOp();
writer.breakOp(); writer.breakOp();
if ((Options.outputStyle & Options.GNU_SPACING) != 0)
writer.print(" ");
writer.print("("); writer.print("(");
writer.startOp(writer.EXPL_PAREN, 0); writer.startOp(writer.EXPL_PAREN, 0);
boolean first = true; boolean first = true;
@ -1136,11 +1140,11 @@ public final class InvokeOperator extends Operator
* dump the source code of the anonymous class. * dump the source code of the anonymous class.
*/ */
Object state = writer.saveOps(); Object state = writer.saveOps();
writer.openBrace(); writer.openBraceClass();
writer.tab(); writer.tab();
clazzAna.dumpBlock(writer); clazzAna.dumpBlock(writer);
writer.untab(); writer.untab();
writer.closeBraceNoSpace(); writer.closeBraceClass();
writer.restoreOps(state); writer.restoreOps(state);
} }
} }

@ -41,8 +41,17 @@ public class PopOperator extends Operator {
public void updateType() { public void updateType() {
} }
public int getBreakPenalty() {
if (subExpressions[0] instanceof Operator)
return ((Operator) subExpressions[0]).getBreakPenalty();
return 0;
}
public void dumpExpression(TabbedPrintWriter writer) public void dumpExpression(TabbedPrintWriter writer)
throws java.io.IOException { throws java.io.IOException {
subExpressions[0].dumpExpression(writer, 0); /* Don't give a priority; we can't allow parens around
* a statement.
*/
subExpressions[0].dumpExpression(writer);
} }
} }

@ -19,6 +19,7 @@
package jode.expr; package jode.expr;
import jode.type.Type; import jode.type.Type;
import jode.decompiler.Options;
import jode.decompiler.TabbedPrintWriter; import jode.decompiler.TabbedPrintWriter;
public class UnaryOperator extends Operator { public class UnaryOperator extends Operator {
@ -57,6 +58,8 @@ public class UnaryOperator extends Operator {
public void dumpExpression(TabbedPrintWriter writer) public void dumpExpression(TabbedPrintWriter writer)
throws java.io.IOException { throws java.io.IOException {
writer.print(getOperatorString()); writer.print(getOperatorString());
if ((Options.outputStyle & Options.GNU_SPACING) != 0)
writer.print(" ");
subExpressions[0].dumpExpression(writer, 700); subExpressions[0].dumpExpression(writer, 700);
} }
} }

@ -27,6 +27,7 @@ import jode.bytecode.Instruction;
import jode.bytecode.MethodInfo; import jode.bytecode.MethodInfo;
import jode.bytecode.Opcodes; import jode.bytecode.Opcodes;
import jode.bytecode.Reference; import jode.bytecode.Reference;
import jode.bytecode.TypeSignature;
import jode.type.Type; import jode.type.Type;
import jode.type.MethodType; import jode.type.MethodType;
@ -48,6 +49,7 @@ public class SyntheticAnalyzer implements Opcodes {
int kind = UNKNOWN; int kind = UNKNOWN;
Reference reference; Reference reference;
MethodInfo method; MethodInfo method;
int unifyParam = -1;
public SyntheticAnalyzer(MethodInfo method, boolean checkName) { public SyntheticAnalyzer(MethodInfo method, boolean checkName) {
this.method = method; this.method = method;
@ -72,6 +74,14 @@ public class SyntheticAnalyzer implements Opcodes {
return reference; return reference;
} }
/**
* Gets the index of the dummy parameter for an ACCESSCONSTRUCTOR.
* Normally the 1 but for inner classes it may be 2.
*/
public int getUnifyParam() {
return unifyParam;
}
private static final int[] getClassOpcodes = { private static final int[] getClassOpcodes = {
opc_aload, opc_invokestatic, opc_areturn, opc_aload, opc_invokestatic, opc_areturn,
opc_astore, opc_new, opc_dup, opc_aload, opc_astore, opc_new, opc_dup, opc_aload,
@ -325,17 +335,23 @@ public class SyntheticAnalyzer implements Opcodes {
return false; return false;
Iterator iter = bytecode.getInstructions().iterator(); Iterator iter = bytecode.getInstructions().iterator();
Instruction instr = (Instruction) iter.next();
if (instr.getOpcode() != opc_aload || instr.getLocalSlot() != 0)
return false;
instr = (Instruction) iter.next();
// slot begins with 2. Slot 1 contains a dummy value, that Instruction instr = (Instruction) iter.next();
// is used so that the constructor has a different type signature. int params = 0, slot = 0;
int params = 0, slot = 2;
while (instr.getOpcode() >= opc_iload while (instr.getOpcode() >= opc_iload
&& instr.getOpcode() <= opc_aload && instr.getOpcode() <= opc_aload) {
&& instr.getLocalSlot() == slot) {
if (instr.getLocalSlot() > slot
&& unifyParam == -1 && params > 0
&& TypeSignature.getParameterTypes(method.getType())
[params - 1].charAt(0) == 'L') {
unifyParam = params;
params++;
slot++;
}
if (instr.getLocalSlot() != slot)
return false;
params++; params++;
slot += (instr.getOpcode() == opc_lload slot += (instr.getOpcode() == opc_lload
|| instr.getOpcode() == opc_dload) ? 2 : 1; || instr.getOpcode() == opc_dload) ? 2 : 1;
@ -352,13 +368,17 @@ public class SyntheticAnalyzer implements Opcodes {
MethodType refType = Type.tMethod(ref.getType()); MethodType refType = Type.tMethod(ref.getType());
if ((refMethod.getModifiers() & modifierMask) != Modifier.PRIVATE if ((refMethod.getModifiers() & modifierMask) != Modifier.PRIVATE
|| !refMethod.getName().equals("<init>") || !refMethod.getName().equals("<init>")
|| refType.getParameterTypes().length != params) || unifyParam == -1
|| refType.getParameterTypes().length != params - 2)
return false; return false;
instr = (Instruction) iter.next(); instr = (Instruction) iter.next();
if (instr.getOpcode() != opc_return) if (instr.getOpcode() != opc_return)
return false; return false;
/* For valid bytecode the types matches automatically */ /* We don't check if types matches. No problem since we only
* need to make sure, this constructor doesn't do anything
* more than relay to the real one.
*/
reference = ref; reference = ref;
kind = ACCESSCONSTRUCTOR; kind = ACCESSCONSTRUCTOR;
return true; return true;

@ -71,15 +71,4 @@ public class NullType extends ReferenceType {
public String toString() { public String toString() {
return "tNull"; return "tNull";
} }
/**
* Intersect this type with another type and return the new type.
* @param type the other type.
* @return the intersection, or tError, if a type conflict happens.
*/
public Type intersection(Type type) {
if (type == this)
return type;
return tError;
}
} }

Loading…
Cancel
Save