mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-08 18:46:12 +00:00
AS3: Fixed do..while, while true, while &&
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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, "&&");
|
||||
}
|
||||
|
||||
@@ -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, "||");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user