switch,break- but not perfect

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@10 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 6951265a2d
commit f3f21e7d2c
  1. 4
      jode/CombineCatchLocal.java
  2. 37
      jode/CreateBreakStatement.java
  3. 84
      jode/CreateSwitchStatements.java
  4. 13
      jode/CreateTryCatchStatements.java
  5. 3
      jode/CreateWhileStatements.java
  6. 4
      jode/jode/decompiler/CodeAnalyzer.java
  7. 6
      jode/jode/decompiler/LocalInfo.java
  8. 25
      jode/jode/decompiler/LocalVariableAnalyzer.java
  9. 25
      jode/jode/decompiler/MethodAnalyzer.java
  10. 77
      jode/jode/expr/BreakInstructionHeader.java
  11. 1
      jode/jode/expr/CatchInstructionHeader.java
  12. 1
      jode/jode/expr/IfInstructionHeader.java
  13. 8
      jode/jode/expr/InstructionHeader.java
  14. 2
      jode/jode/expr/LocalLoadOperator.java
  15. 39
      jode/jode/expr/MethodInstructionHeader.java
  16. 181
      jode/jode/expr/SwitchInstructionHeader.java
  17. 34
      jode/jode/expr/TryCatchInstructionHeader.java
  18. 41
      jode/jode/expr/WhileInstructionHeader.java

@ -4,7 +4,7 @@ import sun.tools.java.Identifier;
public class CombineCatchLocal implements Transformation{
static Identifier idException = Identifier.lookup("exception");
// static Identifier idException = Identifier.lookup("exception");
public InstructionHeader transform(InstructionHeader ih) {
CatchInstructionHeader catchIH;
@ -17,10 +17,8 @@ public class CombineCatchLocal implements Transformation{
Instruction instr = ih.getInstruction();
if (instr instanceof PopOperator) {
local = new LocalInfo(99);
local.setName(idException);
} else if (instr instanceof LocalStoreOperator) {
local = ((LocalStoreOperator) instr).getLocalInfo();
local.setName(idException);
} else
return null;
} catch (ClassCastException ex) {

@ -0,0 +1,37 @@
package jode;
public class CreateBreakStatement implements Transformation {
public InstructionHeader transform(InstructionHeader ih) {
InstructionHeader breakDest;
if (ih.getFlowType() == ih.GOTO)
breakDest = ih.successors[0];
else if (ih.getFlowType() == ih.IFGOTO)
breakDest = ih.successors[1];
else
return null;
boolean needBreakLabel = false, needContLabel = false;
InstructionHeader outer = ih.outer;
while (outer != null) {
if (outer.getBreak() == breakDest) {
if (Decompiler.isVerbose)
System.err.print("b");
return new BreakInstructionHeader
(ih, needBreakLabel?outer.getLabel(): null, true);
}
if (outer.getContinue() == breakDest) {
if (Decompiler.isVerbose)
System.err.print("b");
return new BreakInstructionHeader
(ih, needContLabel?outer.getLabel(): null, false);
}
if (outer.getBreak() != null)
needBreakLabel = true;
if (outer.getContinue() != null)
needContLabel = true;
outer = outer.outer;
}
return null;
}
}

@ -0,0 +1,84 @@
package jode;
import java.util.Enumeration;
public class CreateSwitchStatements implements Transformation {
public InstructionHeader transform(InstructionHeader ih) {
if (ih.getFlowType() != ih.SWITCH)
return null;
SimpleSwitchInstructionHeader switchIH =
(SimpleSwitchInstructionHeader) ih;
int defaultCase = switchIH.successors.length - 1;
int addr = switchIH.nextInstruction.addr;
int count = 1;
for (int i=0; i < switchIH.successors.length; i++) {
if (switchIH.successors[i].addr < addr)
return null;
if (switchIH.successors[i] != switchIH.successors[defaultCase])
count ++;
}
int[] cases = new int[count];
InstructionHeader[] sorted = new InstructionHeader[count];
count = 0;
for (int i=0; i < switchIH.successors.length; i++) {
if (i != defaultCase &&
switchIH.successors[i] == switchIH.successors[defaultCase])
continue;
int insert;
for (insert = 0; insert < count; insert++) {
if (sorted[insert].addr > switchIH.successors[i].addr)
break;
}
if (insert < count) {
System.arraycopy(cases, insert,
cases, insert+1, count-insert);
System.arraycopy(sorted, insert,
sorted, insert+1, count-insert);
}
if (i == defaultCase)
defaultCase = insert;
else
cases[insert] = switchIH.cases[i];
sorted[insert] = switchIH.successors[i];
count++;
}
InstructionHeader endBlock = switchIH.outer.endBlock;
ih = sorted[count-1];
if (ih.outer == switchIH.outer) {
EndSearch:
while (ih != null) {
Enumeration enum = ih.getPredecessors().elements();
while (enum.hasMoreElements()) {
InstructionHeader pred =
(InstructionHeader)enum.nextElement();
if (pred.addr < sorted[count-1].addr &&
(pred.flowType == ih.GOTO ||
(pred.flowType == ih.IFGOTO &&
pred.successors[1] == ih))) {
endBlock = ih;
break EndSearch;
}
}
// if (ih.flowType == ih.GOTO) {
// /* XXX: while loops in default part versus
// * while loops after switches
// */
// endBlock = ih.successors[0];
// break EndSearch;
// }
ih = ih.nextInstruction;
}
} else
endBlock = ih;
if(Decompiler.isVerbose)
System.err.print("s");
return new SwitchInstructionHeader
(switchIH, cases, sorted, defaultCase, endBlock);
}
}

@ -44,24 +44,19 @@ public class CreateTryCatchStatements implements Transformation {
remaining[index2++] = tryIH.successors[i+1];
}
}
InstructionHeader endBlock = tryIH.outer.endBlock;
InstructionHeader endBlock;
if (endIH != catchIH[1]) {
if ((endIH.flowType != endIH.RETURN ||
endIH.getInstruction().getType() != MyType.tVoid) &&
endIH.flowType != endIH.GOTO)
return null;
if (endIH.successors[0].outer == tryIH.outer)
endBlock = endIH.successors[0];
else if (endIH.successors[0] != endBlock)
return null;
}
endBlock = endIH.successors[0];
} else
endBlock = tryIH.outer.endBlock;
if (Decompiler.isVerbose)
System.err.print("t");
return new TryCatchInstructionHeader
(catchIH, endIH, remaining, endBlock);
}
}

@ -9,9 +9,6 @@ public class CreateWhileStatements implements Transformation {
return null;
InstructionHeader block = gotoIH.nextInstruction;
if (block == null)
block = gotoIH.outer.endBlock;
InstructionHeader ifgoto = gotoIH.successors[0];
if (ifgoto.getFlowType() != ifgoto.IFGOTO ||

@ -73,8 +73,10 @@ public class CodeAnalyzer implements Analyzer, Constants {
static Transformation[] simplifyTrafos = { new SimplifyExpression() };
static Transformation[] blockTrafos = {
new CreateTryCatchStatements(),
new CreateBreakStatement(),
new CreateIfStatements(),
new CreateWhileStatements()
new CreateWhileStatements(),
new CreateSwitchStatements()
};
public void analyze()

@ -43,8 +43,10 @@ public class LocalInfo {
if (shadow != null)
shadow.combineWith(li);
li = li.getLocalInfo();
if (this != li)
if (this != li) {
shadow = li;
li.setType(type);
}
}
/**
@ -98,7 +100,7 @@ public class LocalInfo {
return shadow.setType(newType);
this.type = MyType.intersection(this.type, newType);
if (this.type == MyType.tError)
System.err.println("Type error in "+name.toString());
System.err.println("Type error in "+getName());
return this.type;
}

@ -120,7 +120,14 @@ public class LocalVariableAnalyzer {
continue;
}
if (instr.getInstruction() instanceof LocalVarOperator) {
if (instr instanceof MethodInstructionHeader) {
/* This is the first instruction
*/
for (int i=0; i < argLocals.length; i++) {
if (reads[i] != null)
argLocals[i].combineWith(reads[i]);
}
} else if (instr.getInstruction() instanceof LocalVarOperator) {
if (Decompiler.isVerbose)
System.err.print(".");
@ -146,23 +153,13 @@ public class LocalVariableAnalyzer {
}
predec = instr.getPredecessors().elements();
if (predec.hasMoreElements()) {
while (predec.hasMoreElements()) {
instrStack.push(predec.nextElement());
readsStack.push(reads);
}
} else {
/* This is the first instruction
*/
for (int i=0; i < argLocals.length; i++) {
if (reads[i] != null)
argLocals[i].combineWith(reads[i]);
}
while (predec.hasMoreElements()) {
instrStack.push(predec.nextElement());
readsStack.push(reads);
}
}
if (!mdef.isStatic())
argLocals[0].setName(Constants.idThis);
// System.err.println("done!");
}
public void createLocalInfo(CodeAnalyzer code) {

@ -35,21 +35,26 @@ public class MethodAnalyzer implements Analyzer, Constants {
{
if (code == null)
return;
if (Decompiler.isVerbose)
System.err.print(mdef.getName().toString()+": locals ");
lva.createLocalInfo(code);
if (Decompiler.isVerbose) {
System.err.println("");
System.err.print("code ");
}
code.analyze();
if (Decompiler.isVerbose)
System.err.println("");
// if (Decompiler.isVerbose)
// System.err.print(mdef.getName().toString()+": ");
// lva.createLocalInfo(code);
// code.analyze();
// if (Decompiler.isVerbose)
// System.err.println("");
}
public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException
{
if (code != null) {
if (Decompiler.isVerbose)
System.err.print(mdef.getName().toString()+": ");
lva.createLocalInfo(code);
code.analyze();
if (Decompiler.isVerbose)
System.err.println("");
}
writer.println("");
String modif = Modifier.toString(mdef.getModifiers());
if (modif.length() > 0)

@ -0,0 +1,77 @@
package jode;
import java.util.Enumeration;
/** This instruction header represents an break, continue or an
* if + break/continue statement.
*/
public class BreakInstructionHeader extends InstructionHeader {
boolean conditional;
boolean isBreak;
String breakLabel;
/**
* Creates a new break statement.
* @param gotoHeader the instruction header whichs contains the
* (maybe conditonal) goto statement.
* @param label the label where to break to, may be null.
* @param isBreak is this a break or a continue.
*/
public BreakInstructionHeader(InstructionHeader gotoHeader,
String label,
boolean isBreak) {
super(BREAKSTATEMENT, gotoHeader.addr, gotoHeader.nextAddr,
gotoHeader.successors, gotoHeader.outer);
this.instr = gotoHeader.getInstruction();
this.isBreak = isBreak;
this.conditional = (gotoHeader.flowType == IFGOTO);
this.breakLabel = label;
this.movePredecessors(gotoHeader);
this.successors = gotoHeader.successors;
for (int i=0; i< successors.length; i++) {
successors[i].predecessors.removeElement(gotoHeader);
successors[i].predecessors.addElement(this);
}
this.nextInstruction = gotoHeader.nextInstruction;
if (nextInstruction != null)
nextInstruction.prevInstruction = this;
}
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();
}
if (conditional) {
writer.println("if ("+instr.toString()+")");
writer.tab();
} else {
if (!(instr instanceof NopOperator)) {
if (instr.getType() != MyType.tVoid)
writer.print("push ");
writer.println(instr.toString()+";");
}
}
writer.println((isBreak?"break":"continue") +
(breakLabel != null?" "+breakLabel:"")+";");
if (conditional)
writer.untab();
if (Decompiler.isDebugging)
writer.untab();
}
}

@ -48,6 +48,7 @@ public class CatchInstructionHeader extends InstructionHeader {
return false;
this.local = local;
local.setType(type);
successors = next.successors;
nextInstruction = next.nextInstruction;
if (nextInstruction != null)

@ -71,7 +71,6 @@ public class IfInstructionHeader extends InstructionHeader {
this.instr = ((Expression)ifHeader.getInstruction()).negate();
this.movePredecessors(ifHeader);
this.outer = ifHeader.outer;
this.endBlock = endBlock;
successors[0].predecessors.removeElement(ifHeader);
successors[1].predecessors.removeElement(ifHeader);

@ -25,7 +25,9 @@ public class InstructionHeader {
public final static int WHILESTATEMENT = 11;
public final static int DOWHILESTATEMENT = 12;
public final static int FORSTATEMENT = 13;
public final static int TRYCATCHBLOCK = 14;
public final static int SWITCHSTATEMENT = 14;
public final static int TRYCATCHBLOCK = 15;
public final static int BREAKSTATEMENT = 19;
public final static int EMPTY = 99;
@ -298,6 +300,8 @@ public class InstructionHeader {
* Returns true if this instruction header needs a label.
*/
protected boolean needsLabel() {
if (label != null)
return true;
/* An instruction my have only one prevInstruction, but
* may have more then one predecessor that has its
* nextInstruction pointing to us.
@ -371,7 +375,7 @@ public class InstructionHeader {
writer.print(""+predecessors.elementAt(i));
}
writer.println("");
writer.print("outend: "+outer.endBlock+
writer.print("out: "+outer+" end: "+endBlock+
" prev: "+prevInstruction+", next: "+ nextInstruction +
" succs: ");
for (int i=0; i<successors.length; i++) {

@ -29,7 +29,7 @@ implements LocalVarOperator {
}
public Type getType() {
// System.err.println("LocalLoad.getType of "+local.getName()+": "+local.getType());
// System.err.println("LocalLoad.getType of "+local.getName()+": "+local.getType());
return local.getType();
}

@ -8,8 +8,6 @@ import sun.tools.java.Type;
* @author Jochen Hoenicke
*/
public class MethodInstructionHeader extends InstructionHeader {
InstructionHeader first, last;
/**
* Create a new InstructionHeader.
* @param addr The address of this Instruction.
@ -19,30 +17,21 @@ public class MethodInstructionHeader extends InstructionHeader {
public MethodInstructionHeader(JodeEnvironment env,
InstructionHeader[] instr,
BinaryExceptionHandler[] handlers) {
super(METHOD, 0, instr.length, new InstructionHeader[0], null);
first = new InstructionHeader(EMPTY, 0, this);
last = new InstructionHeader(EMPTY, instr.length, this);
first.nextInstruction = instr[0];
instr[0].prevInstruction = first;
super(METHOD, 0, instr.length, new InstructionHeader[1], null);
successors[0] = instr[0];
instr[0].predecessors.addElement(this);
endBlock = new InstructionHeader(EMPTY, instr.length, null);
for (int addr = 0; ; addr = instr[addr].nextAddr) {
for (int addr = 0; addr < instr.length; addr = instr[addr].nextAddr) {
instr[addr].outer = this;
instr[addr].resolveSuccessors(instr);
if (instr[addr].flowType == RETURN) {
InstructionHeader[] lastArr = { last };
instr[addr].successors = lastArr;
last.predecessors.addElement(instr[addr]);
}
if (instr[addr].nextAddr == instr.length) {
instr[addr].nextInstruction = last;
last.prevInstruction = instr[addr];
break;
InstructionHeader[] retSuccs = { endBlock };
instr[addr].successors = retSuccs;
endBlock.predecessors.addElement(instr[addr]);
}
}
for (int i=0; i<handlers.length; i++) {
InstructionHeader tryIH = instr[handlers[i].startPC];
@ -60,29 +49,27 @@ public class MethodInstructionHeader extends InstructionHeader {
InstructionHeader catchIH = instr[handlers[i].handlerPC];
((TryInstructionHeader)tryIH).addHandler(endIH, catchIH);
}
endBlock = last;
}
public InstructionHeader getFirst() {
return first.nextInstruction;
return successors[0];
}
public Vector getReturns() {
return last.predecessors;
return endBlock.predecessors;
}
public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException
{
for (InstructionHeader ih = first.nextInstruction;
ih != last; ih = ih.nextInstruction)
for (InstructionHeader ih = successors[0]; ih != null;
ih = ih.nextInstruction)
ih.dumpSource(writer);
}
public InstructionHeader doTransformations(Transformation[] trafo) {
InstructionHeader next;
for (InstructionHeader ih = first.nextInstruction;
ih != last; ih = next) {
for (InstructionHeader ih = successors[0]; ih != null; ih = next) {
if ((next = ih.doTransformations(trafo)) == null)
next = ih.getNextInstruction();
}

@ -0,0 +1,181 @@
package jode;
import java.util.Enumeration;
/**
* This instruction header represents an if instruction. The
* linkage of the instructions is as follow:
* <pre>
* A: ....
* <p>
* prev = A, next = H, pred = normal, succ = {C,E}
* B: switch ( value ) {
* <p>
* case 1:
* <p>
* prev = null, next = D, pred = {B}, succ = {D}
* C: then-instr 1
* <p>
* prev = C, next = H!, pred = normal succ = {E}
* D: instructions of then part
* <p>
* case 2:
* <p>
* prev = null, next = D, pred = {B}, succ = {D}
* E: else-instr 1
* <p>
* prev = E, next = null, pred = normal, succ = normal
* F: instructions of then part
* <p>
* }
* prev = B, ..., pred = normal, succ = normal
* H: ...
* </pre>
*/
public class SwitchInstructionHeader extends InstructionHeader {
int[] cases;
int defaultCase;
/**
* Creates a new if statement. There are several conditions that
* must be met:
* <ul>
* <li><code> ifHeader.successors[0] == thenStart
* </code></li>
* <li><code> ifHeader.successors[1] == thenEnd.nextInstruction
* </code></li>
* <li><code> elseStart == null || (thenEnd.flowType = GOTO &&
* elseEnd.nextInstruction == thenEnd.successors[0])
* </code></li>
* <li><code> elseStart == null || elseStart = thenEnd.nextInstruction
* </code></li>
* <li><code> thenStart.nextInstruction....nextInstruction = thenEnd
* </code></li>
* <li><code> elseStart.nextInstruction....nextInstruction = elseEnd
* </code></li>
* </ul>
* @param ifHeader the instruction header whichs contains the
* if goto statement.
* @param cases the values belonging to the case labels.
* @param successors the successors of this instruction (the cases).
* This array must be sorted from low to high addresses.
* @param defaultCase the position of the default case in the array.
* @param endBlock the next instruction after this switch statement.
*/
public SwitchInstructionHeader(InstructionHeader switchIH,
int []cases,
InstructionHeader []successors,
int defaultCase,
InstructionHeader endBlock) {
super(SWITCHSTATEMENT, switchIH.addr, endBlock.addr,
successors, switchIH.outer);
this.instr = switchIH.getInstruction();
this.movePredecessors(switchIH);
this.endBlock = endBlock;
this.defaultCase = defaultCase;
this.cases = cases;
/* switchIH may have more succesors than we:
* CreateSwitchStatements removes case labels, that are the
* default.
*/
for (int i=0; i<switchIH.successors.length; i++)
switchIH.successors[i].predecessors.removeElement(switchIH);
for (int i=0; i<successors.length; i++)
successors[i].predecessors.addElement(this);
for (int i=0; i<successors.length; i++) {
if (successors[i].outer == outer) {
if (successors[i].prevInstruction != null)
successors[i].prevInstruction.nextInstruction = null;
successors[i].prevInstruction = null;
}
}
if (endBlock.outer == outer) {
if (endBlock.prevInstruction != null)
endBlock.prevInstruction.nextInstruction = null;
nextInstruction = endBlock;
endBlock.prevInstruction = this;
} else {
if (endBlock != outer.endBlock) {
/* Create a goto after this block, that
* jumps to endBlock
*/
nextInstruction = new InstructionHeader
(GOTO, endBlock.addr, endBlock.addr,
new InstructionHeader[1], this);
nextInstruction.instr = new NopOperator(MyType.tVoid);
nextInstruction.prevInstruction = this;
nextInstruction.successors[0] = endBlock;
endBlock.predecessors.addElement(nextInstruction);
} else
nextInstruction = null;
}
for (int i=0; i < successors.length && successors[i] != endBlock; i++)
for (InstructionHeader ih = successors[i]; ih != null;
ih = ih.nextInstruction)
if (ih.outer == outer)
ih.outer = this;
}
/**
* 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 endBlock;
}
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();
}
writer.println("switch (" + instr.toString() + ") {");
for (int i=0; i<successors.length; i++) {
if (i != defaultCase)
writer.println("case "+cases[i]+":");
if (successors[i] == endBlock)
break;
if (i+1 < successors.length && successors[i] == successors[i+1])
continue;
if (i == defaultCase)
writer.println("default:");
writer.tab();
for (InstructionHeader ih = successors[i]; ih != null;
ih = ih.nextInstruction)
ih.dumpSource(writer);
writer.untab();
}
writer.println("} ");
if (Decompiler.isDebugging)
writer.untab();
}
public InstructionHeader doTransformations(Transformation[] trafo) {
InstructionHeader next;
for (int i=0; i < successors.length && successors[i] != endBlock; i++)
for (InstructionHeader ih = successors[i]; ih != null; ih = next) {
if ((next = ih.doTransformations(trafo)) == null)
next = ih.getNextInstruction();
}
return super.doTransformations(trafo);
}
}

@ -64,16 +64,32 @@ public class TryCatchInstructionHeader extends InstructionHeader {
tryHeader.prevInstruction = null;
tryHeader.successors = remaining;
} else {
successors[0] = tryHeader.nextInstruction;
if (successors[0] != null) {
successors[0].prevInstruction = null;
successors[0].predecessors.addElement(this);
}
successors[0] = tryHeader.successors[0];
successors[0].predecessors.removeElement(tryHeader);
successors[0].predecessors.addElement(this);
if (tryHeader.nextInstruction != null)
tryHeader.nextInstruction.prevInstruction = null;
}
this.endBlock = endBlock;
this.nextInstruction = (endBlock.outer == outer) ? endBlock : null;
if (nextInstruction != null)
if (endBlock.outer == outer) {
nextInstruction = endBlock;
endBlock.prevInstruction = this;
} else {
if (endBlock != outer.endBlock) {
/* Create a goto after this block, that
* jumps to endBlock
*/
nextInstruction = new InstructionHeader
(GOTO, endBlock.addr, endBlock.addr,
new InstructionHeader[1], this);
nextInstruction.instr = new NopOperator(MyType.tVoid);
nextInstruction.prevInstruction = this;
nextInstruction.successors[0] = endBlock;
endBlock.predecessors.addElement(nextInstruction);
} else
nextInstruction = null;
}
if (endHeader != successors[1])
endHeader.successors[0].predecessors.removeElement(endHeader);
@ -129,8 +145,8 @@ public class TryCatchInstructionHeader extends InstructionHeader {
writer.println("try {");
writer.tab();
if (successors[0] == null)
writer.print("/* empty */");
if (successors[0] == endBlock)
writer.print("/* empty?? */");
else {
for (InstructionHeader ih = successors[0]; ih != null;
ih = ih.nextInstruction)

@ -60,18 +60,21 @@ public class WhileInstructionHeader extends InstructionHeader {
if (nextInstruction != null)
nextInstruction.prevInstruction = this;
successors[1].prevInstruction = null;
ifHeader.prevInstruction.nextInstruction = null;
successors[0].predecessors.removeElement(ifHeader);
successors[1].predecessors.removeElement(ifHeader);
successors[0].predecessors.addElement(this);
successors[1].predecessors.addElement(this);
for (InstructionHeader ih = successors[1]; ih != null;
ih = ih.nextInstruction)
if (ih.outer == outer)
ih.outer = this;
if (successors[1] != this) {
successors[1].prevInstruction = null;
for (InstructionHeader ih = successors[1]; ih != null;
ih = ih.nextInstruction) {
if (ih.outer == outer)
ih.outer = this;
if (ih.nextInstruction == this)
ih.nextInstruction = null;
}
}
}
public void dumpSource(TabbedPrintWriter writer)
@ -88,14 +91,18 @@ public class WhileInstructionHeader extends InstructionHeader {
writer.tab();
}
boolean braces = successors[1].nextInstruction != null;
boolean braces = (successors[1] == this ||
successors[1].nextInstruction != null);
writer.println("while (" + instr.toString() + ")" +
(braces ? " {": ""));
writer.tab();
for (InstructionHeader ih = successors[1]; ih != null;
ih = ih.nextInstruction)
ih.dumpSource(writer);
writer.tab();
if (successors[1] != this) {
for (InstructionHeader ih = successors[1]; ih != null;
ih = ih.nextInstruction)
ih.dumpSource(writer);
} else
writer.println("/* empty */");
writer.untab();
if (braces)
@ -124,10 +131,12 @@ public class WhileInstructionHeader extends InstructionHeader {
public InstructionHeader doTransformations(Transformation[] trafo) {
InstructionHeader next;
for (InstructionHeader ih = successors[1]; ih != null; ih = next) {
if ((next = ih.doTransformations(trafo)) == null)
next = ih.getNextInstruction();
}
if (successors[1] != this)
for (InstructionHeader ih = successors[1]; ih != null; ih = next) {
if ((next = ih.doTransformations(trafo)) == null)
next = ih.getNextInstruction();
}
return super.doTransformations(trafo);
}
}

Loading…
Cancel
Save