AS3: Fixed do..while, while true, while &&

This commit is contained in:
Jindra Petk
2013-02-23 19:16:30 +01:00
parent 655206adc3
commit 6d644179ca
18 changed files with 290 additions and 169 deletions

View File

@@ -62,13 +62,13 @@ public class ReReadableInputStream extends InputStream {
return ret;
}
int i = is.read();
if(i>-1){
if (i > -1) {
baos.write(i);
count++;
count++;
}
pos++;
converted = null;
return i;
}

View File

@@ -2414,7 +2414,7 @@ public class SWFInputStream extends InputStream {
COLORMAPDATA ret = new COLORMAPDATA();
ret.colorTableRGB = new RGB[colorTableSize + 1];
for (int i = 0; i < colorTableSize + 1; i++) {
ret.colorTableRGB[i] = readRGB();
ret.colorTableRGB[i] = readRGB();
}
int dataLen = 0;
for (int y = 0; y < bitmapHeight; y++) {

View File

@@ -137,23 +137,28 @@ public class AVM2Graph extends Graph {
}
for (Loop l : loops) {
if (l.loopContinue == part) {
return (new ContinueTreeItem(null, l.loopBreak == null ? -1 : l.loopBreak.start));
return (new ContinueTreeItem(null, l.id));
}
if (l.loopBreak == part) {
return (new BreakTreeItem(null, part.start));
return (new BreakTreeItem(null, l.id));
}
}
return null;
}
private boolean doDecompile = true;
private void checkContinueAtTheEnd(List<TreeItem> commands, Loop loop) {
if (!commands.isEmpty()) {
if (commands.get(commands.size() - 1) instanceof ContinueTreeItem) {
if (((ContinueTreeItem) commands.get(commands.size() - 1)).loopPos == loop.id) {
commands.remove(commands.size() - 1);
}
}
}
}
private List<TreeItem> printGraph(String methodPath, Stack<TreeItem> stack, Stack<TreeItem> scopeStack, List<GraphPart> allParts, List<ABCException> parsedExceptions, List<Integer> finallyJumps, int level, GraphPart parent, GraphPart part, GraphPart stopPart, List<Loop> loops, HashMap<Integer, TreeItem> localRegs, MethodBody body, List<Integer> ignoredSwitches) {
List<TreeItem> ret = new ArrayList<TreeItem>();
if (level > 50) {
//System.err.println(methodPath+": Level>50 :"+part);
//new Exception().printStackTrace();
//return ret;
}
boolean debugMode = false;
try {
@@ -217,17 +222,42 @@ public class AVM2Graph extends Graph {
} else if (sp0.leadsTo(sp1, loopContinues)) {
reversed = true;
}
printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, reversed ? sp0 : sp1, reversed ? sp1 : sp0, loops, localRegs, body, ignoredSwitches);
TreeItem second = stack.pop();
TreeItem first = stack.pop();
if (reversed) {
stack.push(new OrTreeItem(ins, first, second));
GraphPart next = reversed ? sp0 : sp1;
TreeItem ti;
if ((ti = checkLoop(next, stopPart, loops)) != null) {
ret.add(ti);
} else {
stack.push(new AndTreeItem(ins, first, second));
printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, next, reversed ? sp1 : sp0, loops, localRegs, body, ignoredSwitches);
TreeItem second = stack.pop();
TreeItem first = stack.pop();
if (!reversed) {
AndTreeItem a = new AndTreeItem(ins, first, second);
stack.push(a);
a.firstPart = part;
if (second instanceof AndTreeItem) {
a.firstPart = ((AndTreeItem) second).firstPart;
}
if (second instanceof OrTreeItem) {
a.firstPart = ((AndTreeItem) second).firstPart;
}
} else {
OrTreeItem o = new OrTreeItem(ins, first, second);
stack.push(o);
o.firstPart = part;
if (second instanceof OrTreeItem) {
o.firstPart = ((OrTreeItem) second).firstPart;
}
if (second instanceof OrTreeItem) {
o.firstPart = ((OrTreeItem) second).firstPart;
}
}
next = reversed ? sp1 : sp0;
if ((ti = checkLoop(next, stopPart, loops)) != null) {
ret.add(ti);
} else {
ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, next, stopPart, loops, localRegs, body, ignoredSwitches));
}
}
ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, reversed ? sp1 : sp0, stopPart, loops, localRegs, body, ignoredSwitches));
return ret;
} else if ((stack.size() >= 2) && (ins.definition instanceof IfTrueIns) && (stack.get(stack.size() - 1) == stack.get(stack.size() - 2))) {
ret.addAll(output);
@@ -240,16 +270,44 @@ public class AVM2Graph extends Graph {
} else if (sp0.leadsTo(sp1, loopContinues)) {
reversed = true;
}
printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, reversed ? sp0 : sp1, reversed ? sp1 : sp0, loops, localRegs, body, ignoredSwitches);
TreeItem second = stack.pop();
TreeItem first = stack.pop();
if (reversed) {
stack.push(new AndTreeItem(ins, first, second));
GraphPart next = reversed ? sp0 : sp1;
TreeItem ti;
if ((ti = checkLoop(next, stopPart, loops)) != null) {
ret.add(ti);
} else {
stack.push(new OrTreeItem(ins, first, second));
printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, next, reversed ? sp1 : sp0, loops, localRegs, body, ignoredSwitches);
TreeItem second = stack.pop();
TreeItem first = stack.pop();
if (reversed) {
AndTreeItem a = new AndTreeItem(ins, first, second);
stack.push(a);
a.firstPart = part;
if (second instanceof AndTreeItem) {
a.firstPart = ((AndTreeItem) second).firstPart;
}
if (second instanceof OrTreeItem) {
a.firstPart = ((AndTreeItem) second).firstPart;
}
} else {
OrTreeItem o = new OrTreeItem(ins, first, second);
stack.push(o);
o.firstPart = part;
if (second instanceof OrTreeItem) {
o.firstPart = ((OrTreeItem) second).firstPart;
}
if (second instanceof OrTreeItem) {
o.firstPart = ((OrTreeItem) second).firstPart;
}
}
next = reversed ? sp1 : sp0;
if ((ti = checkLoop(next, stopPart, loops)) != null) {
ret.add(ti);
} else {
ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, next, stopPart, loops, localRegs, body, ignoredSwitches));
}
}
ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, reversed ? sp1 : sp0, stopPart, loops, localRegs, body, ignoredSwitches));
return ret;
} else if ((((ins.definition instanceof IfStrictNeIns)) && ((part.nextParts.get(1).getHeight() == 2) && (code.code.get(part.nextParts.get(1).start).definition instanceof PushByteIns) && (code.code.get(part.nextParts.get(1).nextParts.get(0).end).definition instanceof LookupSwitchIns)))
|| (((ins.definition instanceof IfStrictEqIns)) && ((part.nextParts.get(0).getHeight() == 2) && (code.code.get(part.nextParts.get(0).start).definition instanceof PushByteIns) && (code.code.get(part.nextParts.get(0).nextParts.get(0).end).definition instanceof LookupSwitchIns)))) {
@@ -568,8 +626,21 @@ public class AVM2Graph extends Graph {
}
boolean loop = false;
boolean reversed = false;
boolean whileTrue = false;
Loop whileTrueLoop = null;
if ((!part.nextParts.isEmpty()) && part.nextParts.get(0).leadsTo(part, loopContinues)) {
loop = true;
if ((part.nextParts.size() > 1) && part.nextParts.get(1).leadsTo(part, loopContinues)) {
if (output.isEmpty()) {
whileTrueLoop = new Loop(part, null);
loops.add(whileTrueLoop);
whileTrue = true;
} else {
loop = true;//doWhile
}
} else {
loop = true;
}
} else if ((part.nextParts.size() > 1) && part.nextParts.get(1).leadsTo(part, loopContinues)) {
loop = true;
reversed = true;
@@ -592,90 +663,43 @@ public class AVM2Graph extends Graph {
}
}
if (part.nextParts.size() > 1) {
if ((part.nextParts.size() > 1) && (!doWhile)) {
currentLoop.loopBreak = part.nextParts.get(reversed ? 0 : 1);
}
int breakIp = -1;
if (currentLoop.loopBreak != null) {
breakIp = currentLoop.loopBreak.start;
}
TreeItem expr = null;
if ((code.code.get(part.end).definition instanceof JumpIns) || (!(code.code.get(part.end).definition instanceof IfTypeIns))) {
expr = new BooleanTreeItem(null, true);
} else {
if (stack.isEmpty()) {
if (!stack.isEmpty()) {
expr = stack.pop();
}
expr = stack.pop();
}
if (loop) {
if (expr instanceof AndTreeItem) {
currentLoop.loopContinue = ((AndTreeItem) expr).firstPart;
}
if (expr instanceof OrTreeItem) {
currentLoop.loopContinue = ((OrTreeItem) expr).firstPart;
}
}
if (doWhile) {
ret.add(new DoWhileTreeItem(null, breakIp, part.start, output, expr));
//ret.add(new DoWhileTreeItem(null, currentLoop.id, part.start, output, expr));
} else {
ret.addAll(output);
}
GraphPart loopBodyStart = null;
GraphPart next = part.getNextPartPath(loopContinues);
if (expr instanceof LogicalOp) {
if (reversed && (expr instanceof LogicalOp)) {
expr = ((LogicalOp) expr).invert();
}
if (loop && (!doWhile)) {
List<TreeItem> loopBody = null;
List<TreeItem> finalCommands = null;
GraphPart finalPart = null;
boolean isFor = false;
try {
loopBody = printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, part, part.nextParts.get(reversed ? 1 : 0), stopPart, loops, localRegs, body, ignoredSwitches);
} catch (ForException fex) {
loopBody = fex.output;
finalCommands = fex.finalOutput;
if (!finalCommands.isEmpty()) {
finalCommands.remove(finalCommands.size() - 1); //remove continue
}
finalPart = fex.continuePart;
isFor = true;
for (Object o : finalPart.forContinues) {
if (o instanceof ContinueTreeItem) {
((ContinueTreeItem) o).loopPos = breakIp;
}
}
List<TreeItem> retx = ret;
if ((!loop) || (doWhile && (part.nextParts.size() > 1))) {
if (doWhile) {
retx = output;
}
if (isFor) {
ret.add(new ForTreeItem(null, breakIp, finalPart.start, new ArrayList<TreeItem>(), expr, finalCommands, loopBody));
} else if ((expr instanceof HasNextTreeItem) && ((HasNextTreeItem) expr).collection.getNotCoerced().getThroughRegister() instanceof FilteredCheckTreeItem) {
TreeItem gti = ((HasNextTreeItem) expr).collection.getNotCoerced().getThroughRegister();
boolean found = false;
if ((loopBody.size() == 3) || (loopBody.size() == 4)) {
TreeItem ft = loopBody.get(0);
if (ft instanceof WithTreeItem) {
ft = loopBody.get(1);
if (ft instanceof IfTreeItem) {
IfTreeItem ift = (IfTreeItem) ft;
if (ift.onTrue.size() > 0) {
ft = ift.onTrue.get(0);
if (ft instanceof SetPropertyTreeItem) {
SetPropertyTreeItem spt = (SetPropertyTreeItem) ft;
if (spt.object instanceof LocalRegTreeItem) {
int regIndex = ((LocalRegTreeItem) spt.object).regIndex;
HasNextTreeItem iti = (HasNextTreeItem) expr;
localRegs.put(regIndex, new FilterTreeItem(null, iti.collection.getThroughRegister(), ift.expression));
}
}
}
}
}
}
} else if ((expr instanceof HasNextTreeItem) && (!loopBody.isEmpty()) && (loopBody.get(0) instanceof SetTypeTreeItem) && (((SetTypeTreeItem) loopBody.get(0)).getValue().getNotCoerced() instanceof NextValueTreeItem)) {
TreeItem obj = ((SetTypeTreeItem) loopBody.get(0)).getObject();
loopBody.remove(0);
ret.add(new ForEachInTreeItem(null, breakIp, part.start, new InTreeItem(expr.instruction, obj, ((HasNextTreeItem) expr).collection), loopBody));
} else if ((expr instanceof HasNextTreeItem) && (!loopBody.isEmpty()) && (loopBody.get(0) instanceof SetTypeTreeItem) && (((SetTypeTreeItem) loopBody.get(0)).getValue().getNotCoerced() instanceof NextNameTreeItem)) {
TreeItem obj = ((SetTypeTreeItem) loopBody.get(0)).getObject();
loopBody.remove(0);
ret.add(new ForInTreeItem(null, breakIp, part.start, new InTreeItem(expr.instruction, obj, ((HasNextTreeItem) expr).collection), loopBody));
} else {
ret.add(new WhileTreeItem(null, breakIp, part.start, expr, loopBody));
}
} else if (!loop) {
int stackSizeBefore = stack.size();
Stack<TreeItem> trueStack = (Stack<TreeItem>) stack.clone();
Stack<TreeItem> falseStack = (Stack<TreeItem>) stack.clone();
@@ -712,7 +736,14 @@ public class AVM2Graph extends Graph {
if (onTrue.isEmpty() && onFalse.isEmpty() && (trueStack.size() > stackSizeBefore) && (falseStack.size() > stackSizeBefore)) {
stack.push(new TernarOpTreeItem(null, expr, trueStack.pop(), falseStack.pop()));
} else {
ret.add(new IfTreeItem(null, expr, onTrue, onFalse));
List<TreeItem> retw = retx;
if (whileTrue) {
retw = new ArrayList<TreeItem>();
retw.add(new IfTreeItem(null, expr, onTrue, onFalse));
retx.add(new WhileTreeItem(null, whileTrueLoop.id, whileTrueLoop.loopContinue.start, new BooleanTreeItem(null, true), retw));
} else {
retx.add(new IfTreeItem(null, expr, onTrue, onFalse));
}
//Same continues in onTrue and onFalse gets continue on parent level
if ((!onTrue.isEmpty()) && (!onFalse.isEmpty())) {
@@ -720,19 +751,125 @@ public class AVM2Graph extends Graph {
if (onFalse.get(onFalse.size() - 1) instanceof ContinueTreeItem) {
if (((ContinueTreeItem) onTrue.get(onTrue.size() - 1)).loopPos == ((ContinueTreeItem) onFalse.get(onFalse.size() - 1)).loopPos) {
onTrue.remove(onTrue.size() - 1);
ret.add(onFalse.remove(onFalse.size() - 1));
retw.add(onFalse.remove(onFalse.size() - 1));
}
}
}
}
if ((!onTrue.isEmpty()) && (!onFalse.isEmpty())) {
if (onTrue.get(onTrue.size() - 1) instanceof ReturnValueTreeItem || onTrue.get(onTrue.size() - 1) instanceof ReturnVoidTreeItem) {
if (onFalse.get(onFalse.size() - 1) instanceof ContinueTreeItem) {
retw.add(onFalse.remove(onFalse.size() - 1));
}
}
}
if ((!onTrue.isEmpty()) && (!onFalse.isEmpty())) {
if (onFalse.get(onFalse.size() - 1) instanceof ReturnValueTreeItem || onFalse.get(onFalse.size() - 1) instanceof ReturnVoidTreeItem) {
if (onTrue.get(onTrue.size() - 1) instanceof ContinueTreeItem) {
retw.add(onTrue.remove(onTrue.size() - 1));
}
}
}
if (whileTrue) {
checkContinueAtTheEnd(retw, whileTrueLoop);
}
}
if (doWhile) {
loopBodyStart = next;
}
}
if (loop && (part.nextParts.size() > 1)) {
if (loop) { // && (!doWhile)) {
List<TreeItem> loopBody = null;
List<TreeItem> finalCommands = null;
GraphPart finalPart = null;
boolean isFor = false;
try {
loopBody = printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, part, loopBodyStart != null ? loopBodyStart : part.nextParts.get(reversed ? 1 : 0), stopPart, loops, localRegs, body, ignoredSwitches);
checkContinueAtTheEnd(loopBody, currentLoop);
} catch (ForException fex) {
loopBody = fex.output;
finalCommands = fex.finalOutput;
if (!finalCommands.isEmpty()) {
finalCommands.remove(finalCommands.size() - 1); //remove continue
}
finalPart = fex.continuePart;
isFor = true;
for (Object o : finalPart.forContinues) {
if (o instanceof ContinueTreeItem) {
((ContinueTreeItem) o).loopPos = currentLoop.id;
}
}
}
if (isFor) {
ret.add(new ForTreeItem(null, currentLoop.id, finalPart.start, new ArrayList<TreeItem>(), expr, finalCommands, loopBody));
} else if ((expr instanceof HasNextTreeItem) && ((HasNextTreeItem) expr).collection.getNotCoerced().getThroughRegister() instanceof FilteredCheckTreeItem) {
TreeItem gti = ((HasNextTreeItem) expr).collection.getNotCoerced().getThroughRegister();
boolean found = false;
if ((loopBody.size() == 3) || (loopBody.size() == 4)) {
TreeItem ft = loopBody.get(0);
if (ft instanceof WithTreeItem) {
ft = loopBody.get(1);
if (ft instanceof IfTreeItem) {
IfTreeItem ift = (IfTreeItem) ft;
if (ift.onTrue.size() > 0) {
ft = ift.onTrue.get(0);
if (ft instanceof SetPropertyTreeItem) {
SetPropertyTreeItem spt = (SetPropertyTreeItem) ft;
if (spt.object instanceof LocalRegTreeItem) {
int regIndex = ((LocalRegTreeItem) spt.object).regIndex;
HasNextTreeItem iti = (HasNextTreeItem) expr;
localRegs.put(regIndex, new FilterTreeItem(null, iti.collection.getThroughRegister(), ift.expression));
}
}
}
}
}
}
} else if ((expr instanceof HasNextTreeItem) && (!loopBody.isEmpty()) && (loopBody.get(0) instanceof SetTypeTreeItem) && (((SetTypeTreeItem) loopBody.get(0)).getValue().getNotCoerced() instanceof NextValueTreeItem)) {
TreeItem obj = ((SetTypeTreeItem) loopBody.get(0)).getObject();
loopBody.remove(0);
ret.add(new ForEachInTreeItem(null, currentLoop.id, part.start, new InTreeItem(expr.instruction, obj, ((HasNextTreeItem) expr).collection), loopBody));
} else if ((expr instanceof HasNextTreeItem) && (!loopBody.isEmpty()) && (loopBody.get(0) instanceof SetTypeTreeItem) && (((SetTypeTreeItem) loopBody.get(0)).getValue().getNotCoerced() instanceof NextNameTreeItem)) {
TreeItem obj = ((SetTypeTreeItem) loopBody.get(0)).getObject();
loopBody.remove(0);
ret.add(new ForInTreeItem(null, currentLoop.id, part.start, new InTreeItem(expr.instruction, obj, ((HasNextTreeItem) expr).collection), loopBody));
} else {
if (doWhile) {
if (stack.isEmpty()) {
expr = new BooleanTreeItem(null, true);
} else {
expr = stack.pop();
}
loopBody.addAll(0, output);
checkContinueAtTheEnd(loopBody, currentLoop);
List<TreeItem> addIf = new ArrayList<TreeItem>();
if ((!loopBody.isEmpty()) && (loopBody.get(loopBody.size() - 1) instanceof IfTreeItem)) {
IfTreeItem ift = (IfTreeItem) loopBody.get(loopBody.size() - 1);
if (ift.onFalse.isEmpty()) {
expr = ift.expression;
addIf = ift.onTrue;
loopBody.remove(loopBody.size() - 1);
}
}
ret.add(new DoWhileTreeItem(null, currentLoop.id, part.start, loopBody, expr));
ret.addAll(addIf);
} else {
ret.add(new WhileTreeItem(null, currentLoop.id, part.start, expr, loopBody));
}
}
}
if ((!doWhile) && (!whileTrue) && loop && (part.nextParts.size() > 1)) {
loops.remove(currentLoop); //remove loop so no break shows up
//ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level, part, part.nextParts.get(reversed ? 0 : 1), stopPart, loops, localRegs, body, ignoredSwitches));
next = part.nextParts.get(reversed ? 0 : 1);
}
if (doWhile) {
next = null;
}
if (next != null) {
boolean finallyJump = false;
for (int f : finallyJumps) {
@@ -817,7 +954,7 @@ public class AVM2Graph extends Graph {
if ((p != stopPart) && (p.refs.size() > 1)) {
ContinueTreeItem cti = new ContinueTreeItem(null, -1);
//p.forContinues.add(cti);
ret.add(new CommentTreeItem(null, "Unknown jump"));
ret.add(new CommentTreeItem(null, "Unknown jump to part " + p));
ret.add(cti);
}
}
@@ -865,11 +1002,13 @@ public class AVM2Graph extends Graph {
SwitchTreeItem swt = new SwitchTreeItem(null, breakPos, switchedObject, caseValues, caseCommands, defaultCommands, valueMappings);
ret.add(swt);
TreeItem lopNext = checkLoop(next, stopPart, loops);
if (lopNext != null) {
ret.add(lopNext);
} else {
ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, part, next, stopPart, loops, localRegs, body, ignoredSwitches));
if (next != null) {
TreeItem lopNext = checkLoop(next, stopPart, loops);
if (lopNext != null) {
ret.add(lopNext);
} else {
ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, part, next, stopPart, loops, localRegs, body, ignoredSwitches));
}
}
}

View File

@@ -23,14 +23,14 @@ import java.util.List;
public class BreakTreeItem extends TreeItem {
public int loopPos;
public long loopPos;
public boolean isKnown;
public BreakTreeItem(AVM2Instruction instruction, int loopPos) {
public BreakTreeItem(AVM2Instruction instruction, long loopPos) {
this(instruction, loopPos, true);
}
public BreakTreeItem(AVM2Instruction instruction, int loopPos, boolean isKnown) {
public BreakTreeItem(AVM2Instruction instruction, long loopPos, boolean isKnown) {
super(instruction, NOPRECEDENCE);
this.loopPos = loopPos;
this.isKnown = isKnown;

View File

@@ -23,14 +23,14 @@ import java.util.List;
public class ContinueTreeItem extends TreeItem {
public int loopPos;
public long loopPos;
public boolean isKnown;
public ContinueTreeItem(AVM2Instruction instruction, int loopPos) {
public ContinueTreeItem(AVM2Instruction instruction, long loopPos) {
this(instruction, loopPos, true);
}
public ContinueTreeItem(AVM2Instruction instruction, int loopPos, boolean isKnown) {
public ContinueTreeItem(AVM2Instruction instruction, long loopPos, boolean isKnown) {
super(instruction, NOPRECEDENCE);
this.loopPos = loopPos;
this.isKnown = isKnown;

View File

@@ -34,27 +34,22 @@ public class DoWhileTreeItem extends LoopTreeItem implements Block {
return false;
}
public DoWhileTreeItem(AVM2Instruction instruction, int loopBreak, int loopContinue, List<TreeItem> commands, TreeItem expression) {
super(instruction, loopBreak, loopContinue);
public DoWhileTreeItem(AVM2Instruction instruction, long loopId, int loopContinue, List<TreeItem> commands, TreeItem expression) {
super(instruction, loopId, loopContinue);
this.expression = expression;
this.commands = commands;
if ((!commands.isEmpty()) && (commands.get(commands.size() - 1) instanceof ContinueTreeItem)) {
if (((ContinueTreeItem) commands.get(commands.size() - 1)).loopPos == loopBreak) {
commands.remove(commands.size() - 1);
}
}
}
@Override
public String toString(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
String ret = "";
ret += "loop" + loopBreak + ":\r\n";
ret += "loop" + loopId + ":\r\n";
ret += hilight("do\r\n{") + "\r\n";
for (TreeItem ti : commands) {
ret += ti.toStringSemicoloned(constants, localRegNames, fullyQualifiedNames) + "\r\n";
}
ret += hilight("}\r\nwhile(") + expression.toString(constants, localRegNames, fullyQualifiedNames) + hilight(");") + "\r\n";
ret += ":loop" + loopBreak;
ret += ":loop" + loopId;
return ret;
}

View File

@@ -28,8 +28,8 @@ public class ForEachInTreeItem extends LoopTreeItem implements Block {
public InTreeItem expression;
public List<TreeItem> commands;
public ForEachInTreeItem(AVM2Instruction instruction, int loopBreak, int loopContinue, InTreeItem expression, List<TreeItem> commands) {
super(instruction, loopBreak, loopContinue);
public ForEachInTreeItem(AVM2Instruction instruction, long loopId, int loopContinue, InTreeItem expression, List<TreeItem> commands) {
super(instruction, loopId, loopContinue);
if (!commands.isEmpty()) {
TreeItem firstAssign = commands.get(0);
if (firstAssign instanceof SetTypeTreeItem) {
@@ -47,11 +47,6 @@ public class ForEachInTreeItem extends LoopTreeItem implements Block {
}
this.expression = expression;
this.commands = commands;
if ((!commands.isEmpty()) && (commands.get(commands.size() - 1) instanceof ContinueTreeItem)) {
if (((ContinueTreeItem) commands.get(commands.size() - 1)).loopPos == loopBreak) {
commands.remove(commands.size() - 1);
}
}
}
@Override
@@ -62,13 +57,13 @@ public class ForEachInTreeItem extends LoopTreeItem implements Block {
@Override
public String toString(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
String ret = "";
ret += "loop" + loopBreak + ":\r\n";
ret += "loop" + loopId + ":\r\n";
ret += hilight("for each (") + expression.toString(constants, localRegNames, fullyQualifiedNames) + ")\r\n{\r\n";
for (TreeItem ti : commands) {
ret += ti.toStringSemicoloned(constants, localRegNames, fullyQualifiedNames) + "\r\n";
}
ret += hilight("}") + "\r\n";
ret += ":loop" + loopBreak;
ret += ":loop" + loopId;
return ret;
}

View File

@@ -28,8 +28,8 @@ public class ForInTreeItem extends LoopTreeItem implements Block {
public InTreeItem expression;
public List<TreeItem> commands;
public ForInTreeItem(AVM2Instruction instruction, int loopBreak, int loopContinue, InTreeItem expression, List<TreeItem> commands) {
super(instruction, loopBreak, loopContinue);
public ForInTreeItem(AVM2Instruction instruction, long loopId, int loopContinue, InTreeItem expression, List<TreeItem> commands) {
super(instruction, loopId, loopContinue);
if (!commands.isEmpty()) {
TreeItem firstAssign = commands.get(0);
if (firstAssign instanceof SetTypeTreeItem) {
@@ -47,12 +47,6 @@ public class ForInTreeItem extends LoopTreeItem implements Block {
}
this.expression = expression;
this.commands = commands;
if ((!commands.isEmpty()) && (commands.get(commands.size() - 1) instanceof ContinueTreeItem)) {
if (((ContinueTreeItem) commands.get(commands.size() - 1)).loopPos == loopBreak) {
commands.remove(commands.size() - 1);
}
}
}
@Override
@@ -63,13 +57,13 @@ public class ForInTreeItem extends LoopTreeItem implements Block {
@Override
public String toString(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
String ret = "";
ret += "loop" + loopBreak + ":\r\n";
ret += "loop" + loopId + ":\r\n";
ret += hilight("for (") + expression.toString(constants, localRegNames, fullyQualifiedNames) + hilight(")") + "\r\n{\r\n";
for (TreeItem ti : commands) {
ret += ti.toStringSemicoloned(constants, localRegNames, fullyQualifiedNames) + "\r\n";
}
ret += hilight("}") + "\r\n";
ret += ":loop" + loopBreak;
ret += ":loop" + loopId;
return ret;
}

View File

@@ -31,18 +31,12 @@ public class ForTreeItem extends LoopTreeItem implements Block {
public List<TreeItem> finalCommands;
public List<TreeItem> commands;
public ForTreeItem(AVM2Instruction instruction, int loopBreak, int loopContinue, List<TreeItem> firstCommands, TreeItem expression, List<TreeItem> finalCommands, List<TreeItem> commands) {
public ForTreeItem(AVM2Instruction instruction, long loopBreak, int loopContinue, List<TreeItem> firstCommands, TreeItem expression, List<TreeItem> finalCommands, List<TreeItem> commands) {
super(instruction, loopBreak, loopContinue);
this.firstCommands = firstCommands;
this.expression = expression;
this.finalCommands = finalCommands;
this.commands = commands;
if ((!commands.isEmpty()) && (commands.get(commands.size() - 1) instanceof ContinueTreeItem)) {
if (((ContinueTreeItem) commands.get(commands.size() - 1)).loopPos == loopBreak) {
commands.remove(commands.size() - 1);
}
}
}
private String stripSemicolon(String s) {
@@ -55,7 +49,7 @@ public class ForTreeItem extends LoopTreeItem implements Block {
@Override
public String toString(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
String ret = "";
ret += "loop" + loopBreak + ":\r\n";
ret += "loop" + loopId + ":\r\n";
ret += hilight("for(");
for (int i = 0; i < firstCommands.size(); i++) {
if (i > 0) {
@@ -77,7 +71,7 @@ public class ForTreeItem extends LoopTreeItem implements Block {
ret += ti.toStringSemicoloned(constants, localRegNames, fullyQualifiedNames) + "\r\n";
}
ret += hilight("}") + "\r\n";
ret += ":loop" + loopBreak;
ret += ":loop" + loopId;
return ret;
}

View File

@@ -21,12 +21,12 @@ import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
public abstract class LoopTreeItem extends TreeItem {
public int loopBreak;
public long loopId;
public int loopContinue;
public LoopTreeItem(AVM2Instruction instruction, int loopBreak, int loopContinue) {
public LoopTreeItem(AVM2Instruction instruction, long loopId, int loopContinue) {
super(instruction, NOPRECEDENCE);
this.loopBreak = loopBreak;
this.loopId = loopId;
this.loopContinue = loopContinue;
}

View File

@@ -46,7 +46,7 @@ public class SwitchTreeItem extends LoopTreeItem implements Block {
@Override
public String toString(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
String ret = "";
ret += "loop" + loopBreak + ":\r\n";
ret += "loop" + loopId + ":\r\n";
ret += hilight("switch(") + switchedObject.toString(constants, localRegNames, fullyQualifiedNames) + hilight(")") + "\r\n{\r\n";
for (int i = 0; i < caseCommands.size(); i++) {
for (int k = 0; k < valuesMapping.size(); k++) {
@@ -61,7 +61,7 @@ public class SwitchTreeItem extends LoopTreeItem implements Block {
ret += AVM2Code.IDENTCLOSE + "\r\n";
}
if (defaultCommands.size() > 0) {
if (!((defaultCommands.size() == 1) && (defaultCommands.get(0) instanceof BreakTreeItem) && (((BreakTreeItem) defaultCommands.get(0)).loopPos == loopBreak))) {
if (!((defaultCommands.size() == 1) && (defaultCommands.get(0) instanceof BreakTreeItem) && (((BreakTreeItem) defaultCommands.get(0)).loopPos == loopId))) {
ret += hilight("default") + ":\r\n";
ret += AVM2Code.IDENTOPEN + "\r\n";
for (int j = 0; j < defaultCommands.size(); j++) {
@@ -72,7 +72,7 @@ public class SwitchTreeItem extends LoopTreeItem implements Block {
}
ret += hilight("}") + "\r\n";
ret += ":loop" + loopBreak;
ret += ":loop" + loopId;
return ret;
}

View File

@@ -29,28 +29,22 @@ public class WhileTreeItem extends LoopTreeItem implements Block {
public TreeItem expression;
public List<TreeItem> commands;
public WhileTreeItem(AVM2Instruction instruction, int loopBreak, int loopContinue, TreeItem expression, List<TreeItem> commands) {
super(instruction, loopBreak, loopContinue);
public WhileTreeItem(AVM2Instruction instruction, long loopId, int loopContinue, TreeItem expression, List<TreeItem> commands) {
super(instruction, loopId, loopContinue);
this.expression = expression;
this.commands = commands;
if ((!commands.isEmpty()) && (commands.get(commands.size() - 1) instanceof ContinueTreeItem)) {
if (((ContinueTreeItem) commands.get(commands.size() - 1)).loopPos == loopBreak) {
commands.remove(commands.size() - 1);
}
}
}
@Override
public String toString(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
String ret = "";
ret += "loop" + loopBreak + ":\r\n";
ret += "loop" + loopId + ":\r\n";
ret += hilight("while(") + expression.toString(constants, localRegNames, fullyQualifiedNames) + hilight(")") + "\r\n{\r\n";
for (TreeItem ti : commands) {
ret += ti.toStringSemicoloned(constants, localRegNames, fullyQualifiedNames) + "\r\n";
}
ret += hilight("}") + "\r\n";
ret += ":loop" + loopBreak;
ret += ":loop" + loopId;
return ret;
}

View File

@@ -18,9 +18,12 @@ package com.jpexs.decompiler.flash.abc.avm2.treemodel.operations;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.graph.GraphPart;
public class AndTreeItem extends BinaryOpTreeItem {
public GraphPart firstPart;
public AndTreeItem(AVM2Instruction instruction, TreeItem leftSide, TreeItem rightSide) {
super(instruction, PRECEDENCE_LOGICALAND, leftSide, rightSide, "&&");
}

View File

@@ -18,9 +18,12 @@ package com.jpexs.decompiler.flash.abc.avm2.treemodel.operations;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.graph.GraphPart;
public class OrTreeItem extends BinaryOpTreeItem {
public GraphPart firstPart;
public OrTreeItem(AVM2Instruction instruction, TreeItem leftSide, TreeItem rightSide) {
super(instruction, PRECEDENCE_LOGICALOR, leftSide, rightSide, "||");
}

View File

@@ -67,7 +67,7 @@ public class GraphPart {
}
private GraphPart getNextPartPath(GraphPart original, String path, List<GraphPart> visited) {
if (visited.contains(this)) {
if (visited.contains(this) && (this != original)) {
return null;
}
visited.add(this);

View File

@@ -24,9 +24,13 @@ public class Loop {
public GraphPart loopContinue;
public GraphPart loopBreak;
public long id;
static long maxLoopId = 0;
public Loop(GraphPart loopContinue, GraphPart loopBreak) {
this.loopContinue = loopContinue;
this.loopBreak = loopBreak;
id = maxLoopId;
maxLoopId++;
}
}

View File

@@ -134,7 +134,7 @@ public class DefineBitsLossless2Tag extends CharacterTag implements AloneTag {
for (int y = 0; y < bitmapHeight; y++) {
for (int x = 0; x < bitmapWidth; x++) {
if ((bitmapFormat == DefineBitsLossless2Tag.FORMAT_8BIT_COLORMAPPED)) {
RGBA color = colorMapData.colorTableRGB[colorMapData.colorMapPixelData[pos32aligned]&0xff];
RGBA color = colorMapData.colorTableRGB[colorMapData.colorMapPixelData[pos32aligned] & 0xff];
g.setColor(new Color(color.red, color.green, color.blue, color.alpha));
}
if ((bitmapFormat == DefineBitsLossless2Tag.FORMAT_15BIT_RGB) || (bitmapFormat == DefineBitsLossless2Tag.FORMAT_24BIT_RGB)) {

View File

@@ -62,8 +62,8 @@ public class DefineBitsLosslessTag extends CharacterTag implements AloneTag {
int pos = 0;
for (int y = 0; y < bitmapHeight; y++) {
for (int x = 0; x < bitmapWidth; x++) {
if (bitmapFormat == DefineBitsLosslessTag.FORMAT_8BIT_COLORMAPPED) {
RGB color = colorMapData.colorTableRGB[colorMapData.colorMapPixelData[pos32aligned]&0xff];
if (bitmapFormat == DefineBitsLosslessTag.FORMAT_8BIT_COLORMAPPED) {
RGB color = colorMapData.colorTableRGB[colorMapData.colorMapPixelData[pos32aligned] & 0xff];
g.setColor(new Color(color.red, color.green, color.blue));
}
if (bitmapFormat == DefineBitsLosslessTag.FORMAT_15BIT_RGB) {