git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@12 379699f6-c40d-0410-875b-85095c16579estable
parent
3360965bb1
commit
5c4d86e1cb
@ -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; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,158 @@ |
|||||||
|
package jode; |
||||||
|
|
||||||
|
/** |
||||||
|
* This instruction header represents an if instruction. The |
||||||
|
* linkage of the instructions is as follow: |
||||||
|
* <pre> |
||||||
|
* A: .... |
||||||
|
* <p> |
||||||
|
* prev = A, next = H or null, pred = normal, succ = {H,C} |
||||||
|
* B: while ( instr ) { |
||||||
|
* <p> |
||||||
|
* prev = null, next = D, pred = {B}, succ = {D} |
||||||
|
* C: first block-instr |
||||||
|
* <p> |
||||||
|
* prev = C, next = E, pred = normal succ = normal |
||||||
|
* D: ... |
||||||
|
* <p> |
||||||
|
* prev = D, next = null, pred = normal succ = {B} |
||||||
|
* E: last block-instr |
||||||
|
* } |
||||||
|
* <p> |
||||||
|
* prev = B, ..., pred = (normal+{G}) \ {C..F}, succ = normal |
||||||
|
* H: ... |
||||||
|
* </pre> |
||||||
|
*/ |
||||||
|
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); |
||||||
|
} |
||||||
|
} |
||||||
|
|
Loading…
Reference in new issue