From 5c4d86e1cb13206aef4e222bb853773349c4ed8b Mon Sep 17 00:00:00 2001 From: jochen Date: Tue, 11 Aug 1998 22:23:42 +0000 Subject: [PATCH] do while git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@12 379699f6-c40d-0410-875b-85095c16579e --- jode/CreateConstantArray.java | 2 +- jode/CreateDoWhileStatements.java | 29 ++++ jode/jode/decompiler/CodeAnalyzer.java | 1 + jode/jode/expr/CaseInstructionHeader.java | 3 + jode/jode/expr/DoWhileInstructionHeader.java | 158 +++++++++++++++++++ 5 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 jode/CreateDoWhileStatements.java create mode 100644 jode/jode/expr/DoWhileInstructionHeader.java diff --git a/jode/CreateConstantArray.java b/jode/CreateConstantArray.java index f8cff1c..c5685c3 100644 --- a/jode/CreateConstantArray.java +++ b/jode/CreateConstantArray.java @@ -25,7 +25,7 @@ public class CreateConstantArray implements Transformation { if (!MyType.isOfType(indexop.getType(), MyType.tUInt)) return null; int index = Integer.parseInt(indexop.getValue()); - if (index > 0 && consts == null) { + if (index >= 0 && consts == null) { lastindex = index; consts = new Expression[lastindex+1]; } else if (index < 0 || index > lastindex) diff --git a/jode/CreateDoWhileStatements.java b/jode/CreateDoWhileStatements.java new file mode 100644 index 0000000..86047df --- /dev/null +++ b/jode/CreateDoWhileStatements.java @@ -0,0 +1,29 @@ +package jode; +import java.util.Enumeration; + +public class CreateDoWhileStatements extends FlowTransformation +implements Transformation { + + public InstructionHeader transform(InstructionHeader head) { + + if (head.predecessors.size() == 0 || + head.flowType == head.DOWHILESTATEMENT) + return null; + + InstructionHeader end = head; + Enumeration enum = head.predecessors.elements(); + while (enum.hasMoreElements()) { + InstructionHeader pre = (InstructionHeader) enum.nextElement(); + if (pre.outer == head.outer && pre.addr > end.addr) + end = pre; + } + + if (end != head) + if (end.flowType == end.IFGOTO || end.flowType == end.GOTO) { + if(Decompiler.isVerbose) + System.err.print("d"); + return new DoWhileInstructionHeader(head, end); + } + return null; + } +} diff --git a/jode/jode/decompiler/CodeAnalyzer.java b/jode/jode/decompiler/CodeAnalyzer.java index 2e72335..137e689 100644 --- a/jode/jode/decompiler/CodeAnalyzer.java +++ b/jode/jode/decompiler/CodeAnalyzer.java @@ -72,6 +72,7 @@ public class CodeAnalyzer implements Analyzer, Constants { static Transformation[] simplifyTrafos = { new SimplifyExpression() }; static Transformation[] blockTrafos = { + new CreateDoWhileStatements(), new CreateTryCatchStatements(), new CreateIfStatements(), new CreateBreakStatement(), diff --git a/jode/jode/expr/CaseInstructionHeader.java b/jode/jode/expr/CaseInstructionHeader.java index 2aac7ae..8efcc80 100644 --- a/jode/jode/expr/CaseInstructionHeader.java +++ b/jode/jode/expr/CaseInstructionHeader.java @@ -35,6 +35,9 @@ public class CaseInstructionHeader extends InstructionHeader { ih = ih.nextInstruction) ih.dumpSource(writer); writer.untab(); + + if (Decompiler.isDebugging) + writer.untab(); } /** diff --git a/jode/jode/expr/DoWhileInstructionHeader.java b/jode/jode/expr/DoWhileInstructionHeader.java new file mode 100644 index 0000000..6ef3f46 --- /dev/null +++ b/jode/jode/expr/DoWhileInstructionHeader.java @@ -0,0 +1,158 @@ +package jode; + +/** + * This instruction header represents an if instruction. The + * linkage of the instructions is as follow: + *
+ *  A: ....
+ * 

+ * prev = A, next = H or null, pred = normal, succ = {H,C} + * B: while ( instr ) { + *

+ * prev = null, next = D, pred = {B}, succ = {D} + * C: first block-instr + *

+ * prev = C, next = E, pred = normal succ = normal + * D: ... + *

+ * prev = D, next = null, pred = normal succ = {B} + * E: last block-instr + * } + *

+ * prev = B, ..., pred = (normal+{G}) \ {C..F}, succ = normal + * H: ... + *

+ */ +public class DoWhileInstructionHeader extends InstructionHeader { + + InstructionHeader endHeader; + + /** + * Creates a new while statement. + * @param head the first instruction of this do-while loop + * @param end the last instruction which contains the + * if-goto (or goto) statement. + */ + public DoWhileInstructionHeader(InstructionHeader head, + InstructionHeader end) { + + super(DOWHILESTATEMENT, + head.addr, end.nextAddr, + new InstructionHeader[1], end.outer); + + this.endHeader = end; + + if (end.flowType == GOTO) { + /* This is a for(;;) loop + */ + this.instr = null; + end.successors[0].predecessors.removeElement(end); + } else { + this.instr = end.instr; + end.successors[0].predecessors.removeElement(end); + end.successors[1].predecessors.removeElement(end); + } + this.addPredecessors(head); + this.successors[0] = head; + head.predecessors.addElement(this); + + this.prevInstruction = head.prevInstruction; + if (prevInstruction != null) + prevInstruction.nextInstruction = this; + + this.nextInstruction = end.nextInstruction; + if (nextInstruction != null) + nextInstruction.prevInstruction = this; + + if (successors[0] != this) { + successors[0].prevInstruction = null; + for (InstructionHeader ih = successors[0]; ih != null; + ih = ih.nextInstruction) { + if (ih.outer == outer) + ih.outer = this; + if (ih.nextInstruction == end) + ih.nextInstruction = null; + } + } + } + + /** + * This should be implemented for those blocks, that is headers + * which are outer of other headers. This gives the instruction + * where the control flows after this block. + * @return the first instruction after this block. + */ + InstructionHeader getEndBlock() { + return getContinue(); + } + + public void dumpSource(TabbedPrintWriter writer) + throws java.io.IOException + { + if (Decompiler.isDebugging) { + dumpDebugging(writer); + writer.tab(); + } + + if (needsLabel()) { + writer.untab(); + writer.println(getLabel()+": "); + writer.tab(); + } + + boolean braces = (successors[0].flowType != NORMAL || + successors[0].nextInstruction != null); + + writer.println((instr == null ? "for(;;)" : "do")+ + (braces ? " {": "")); + + writer.tab(); + if (successors[0] != this) { + for (InstructionHeader ih = successors[0]; ih != null; + ih = ih.nextInstruction) + ih.dumpSource(writer); + } else + writer.println("/* empty */"); + writer.untab(); + + if (instr != null) + writer.println((braces ? "} " : "") + "while ("+instr+");"); + else if (braces) + writer.println("}"); + + if (Decompiler.isDebugging) + writer.untab(); + } + + /** + * Returns the InstructionHeader where a break of this instruction + * would jump to. Does only make sense for do/while/for-loops and + * switch instructions. + */ + public InstructionHeader getBreak() { + return super.getEndBlock(); + } + + public InstructionHeader getShadow() { + return successors[0]; + } + + /** + * Returns the InstructionHeader where a continue of this instruction + * would jump to. Does only make sense for do/while/for-loops. + */ + public InstructionHeader getContinue() { + return (instr == null)? this : endHeader; + } + + public InstructionHeader doTransformations(Transformation[] trafo) { + InstructionHeader next; + if (successors[0] != this) + for (InstructionHeader ih = successors[0]; ih != null; ih = next) { + if ((next = ih.doTransformations(trafo)) == null) + next = ih.getNextInstruction(); + } + return super.doTransformations(trafo); + } +} +