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