diff --git a/trunk/src/com/jpexs/decompiler/flash/Configuration.java b/trunk/src/com/jpexs/decompiler/flash/Configuration.java index 10616c3ae..9d66e842b 100644 --- a/trunk/src/com/jpexs/decompiler/flash/Configuration.java +++ b/trunk/src/com/jpexs/decompiler/flash/Configuration.java @@ -90,7 +90,7 @@ public class Configuration { * Load replacements from file */ private static void loadReplacements(String replacementsFile) { - if(!(new File(replacementsFile)).exists()){ + if (!(new File(replacementsFile)).exists()) { return; } replacements = new ArrayList<>(); diff --git a/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java b/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java index ed71a24f5..db416791c 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java @@ -1166,13 +1166,13 @@ public class SWFInputStream extends InputStream { List> futureResults = new ArrayList<>(); List tags = new ArrayList<>(); Tag tag; - Tag previousTag = null; + Tag previousTag = null; while (true) { long pos = getPos(); - try{ + try { tag = readTag(level, pos, false); - }catch(EndOfStreamException ex){ - tag=null; + } catch (EndOfStreamException ex) { + tag = null; } if (tag == null) { break; @@ -1185,7 +1185,7 @@ public class SWFInputStream extends InputStream { Future future = executor.submit(new TagResolutionTask(tag, version, level)); futureResults.add(future); - } + } for (Future future : futureResults) { try { diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java index f9084c372..0a9fc7f75 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java @@ -133,1025 +133,6 @@ public class AVM2Graph extends Graph { localData.add((Integer) scriptIndex); return g.translate(localData); } - /* - public GraphPart getNextNoJump(GraphPart part) { - while (code.code.get(part.start).definition instanceof JumpIns) { - part = part.getSubParts().get(0).nextParts.get(0); - } - return part; - } - - public static List translateViaGraph(String path, AVM2Code code, ABC abc, MethodBody body) { - AVM2Graph g = new AVM2Graph(code, abc, body); - List allParts = new ArrayList(); - for (GraphPart head : g.heads) { - populateParts(head, allParts); - } - return g.printGraph(path, new Stack(), new Stack(), allParts, new ArrayList(), new ArrayList(), 0, null, g.heads.get(0), null, new ArrayList(), new HashMap(), body, new ArrayList()); - } - - private List getLoopsContinues(List loops) { - List ret = new ArrayList(); - for (Loop l : loops) { - if (l.loopContinue != null) { - ret.add(l.loopContinue); - } - } - return ret; - } - - private TreeItem checkLoop(GraphPart part, GraphPart stopPart, List loops) { - if (part == stopPart) { - return null; - } - for (Loop l : loops) { - if (l.loopContinue == part) { - return (new ContinueTreeItem(null, l.id)); - } - if (l.loopBreak == part) { - return (new BreakTreeItem(null, l.id)); - } - } - return null; - } - private boolean doDecompile = true; - - private void checkContinueAtTheEnd(List 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 printGraph(String methodPath, Stack stack, Stack scopeStack, List allParts, List parsedExceptions, List finallyJumps, int level, GraphPart parent, GraphPart part, GraphPart stopPart, List loops, HashMap localRegs, MethodBody body, List ignoredSwitches) { - List ret = new ArrayList(); - boolean debugMode = false; - - try { - if (!doDecompile) { - ret.add(new CommentTreeItem(null, "not decompiled")); - return ret; - } - - if (debugMode) { - System.err.println("PART " + part); - } - - if (part == stopPart) { - return ret; - } - if (part.ignored) { - return ret; - } - List fqn = new ArrayList(); - HashMap lrn = new HashMap(); - List output = new ArrayList(); - boolean isSwitch = false; - try { - code.initToSource(); - List parts = new ArrayList(); - if (part instanceof GraphPartMulti) { - parts = ((GraphPartMulti) part).parts; - } else { - parts.add(part); - } - boolean isIf = false; - int end = part.end; - for (GraphPart p : parts) { - end = p.end; - int start = p.start; - isIf = false; - if (code.code.get(end).definition instanceof JumpIns) { - end--; - } else if (code.code.get(end).definition instanceof IfTypeIns) { - end--; - isIf = true; - } else if (code.code.get(end).definition instanceof LookupSwitchIns) { - isSwitch = true; - end--; - } - ConvertOutput co = code.toSourceOutput(false, false, 0, localRegs, stack, scopeStack, abc, abc.constants, abc.method_info, body, start, end, lrn, fqn, new boolean[code.code.size()]); - output.addAll(co.output); - - } - if (isIf) { - AVM2Instruction ins = code.code.get(end + 1); - if ((stack.size() >= 2) && (ins.definition instanceof IfFalseIns) && (stack.get(stack.size() - 1) == stack.get(stack.size() - 2))) { - ret.addAll(output); - - GraphPart sp0 = getNextNoJump(part.nextParts.get(0)); - GraphPart sp1 = getNextNoJump(part.nextParts.get(1)); - boolean reversed = false; - List loopContinues = getLoopsContinues(loops); - loopContinues.add(part); - if (sp1.leadsTo(sp0, loopContinues)) { - } else if (sp0.leadsTo(sp1, loopContinues)) { - reversed = true; - } - GraphPart next = reversed ? sp0 : sp1; - TreeItem ti; - if ((ti = checkLoop(next, stopPart, loops)) != null) { - ret.add(ti); - } else { - 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)); - } - } - return ret; - } else if ((stack.size() >= 2) && (ins.definition instanceof IfTrueIns) && (stack.get(stack.size() - 1) == stack.get(stack.size() - 2))) { - ret.addAll(output); - GraphPart sp0 = getNextNoJump(part.nextParts.get(0)); - GraphPart sp1 = getNextNoJump(part.nextParts.get(1)); - boolean reversed = false; - List loopContinues = getLoopsContinues(loops); - loopContinues.add(part); - if (sp1.leadsTo(sp0, loopContinues)) { - } else if (sp0.leadsTo(sp1, loopContinues)) { - reversed = true; - } - GraphPart next = reversed ? sp0 : sp1; - TreeItem ti; - if ((ti = checkLoop(next, stopPart, loops)) != null) { - ret.add(ti); - } else { - 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)); - } - } - - 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)))) { - ret.addAll(output); - boolean reversed = false; - if (ins.definition instanceof IfStrictEqIns) { - reversed = true; - } - TreeItem switchedObject = null; - if (!output.isEmpty()) { - if (output.get(output.size() - 1) instanceof SetLocalTreeItem) { - switchedObject = ((SetLocalTreeItem) output.get(output.size() - 1)).value; - } - } - if (switchedObject == null) { - switchedObject = new NullTreeItem(null); - } - HashMap caseValuesMap = new HashMap(); - - stack.pop(); - caseValuesMap.put(code.code.get(part.nextParts.get(reversed ? 0 : 1).start).operands[0], stack.pop()); - - GraphPart switchLoc = part.nextParts.get(reversed ? 0 : 1).nextParts.get(0); - - - while ((code.code.get(part.nextParts.get(reversed ? 1 : 0).end).definition instanceof IfStrictNeIns) - || (code.code.get(part.nextParts.get(reversed ? 1 : 0).end).definition instanceof IfStrictEqIns)) { - part = part.nextParts.get(reversed ? 1 : 0); - List ps = part.getSubParts(); - for (GraphPart p : ps) { - code.toSourceOutput(false, false, 0, localRegs, stack, scopeStack, abc, abc.constants, abc.method_info, body, p.start, p.end - 1, lrn, fqn, new boolean[code.code.size()]); - } - stack.pop(); - if (code.code.get(part.end).definition instanceof IfStrictNeIns) { - reversed = false; - } else { - reversed = true; - } - caseValuesMap.put(code.code.get(part.nextParts.get(reversed ? 0 : 1).start).operands[0], stack.pop()); - - } - boolean hasDefault = false; - GraphPart dp = part.nextParts.get(reversed ? 1 : 0); - while (code.code.get(dp.start).definition instanceof JumpIns) { - if (dp instanceof GraphPartMulti) { - dp = ((GraphPartMulti) dp).parts.get(0); - } - dp = dp.nextParts.get(0); - } - if (code.code.get(dp.start).definition instanceof PushByteIns) { - hasDefault = true; - } - List caseValues = new ArrayList(); - for (int i = 0; i < switchLoc.nextParts.size() - 1; i++) { - if (caseValuesMap.containsKey(i)) { - caseValues.add(caseValuesMap.get(i)); - } else { - continue; - } - } - - List> caseCommands = new ArrayList>(); - GraphPart next = null; - - List loopContinues = getLoopsContinues(loops); - - next = switchLoc.getNextPartPath(loopContinues); - if (next == null) { - next = switchLoc.getNextSuperPartPath(loopContinues); - } - - TreeItem ti = checkLoop(next, stopPart, loops); - Loop currentLoop = new Loop(null, next); - loops.add(currentLoop); - //switchLoc.getNextPartPath(new ArrayList()); - List valuesMapping = new ArrayList(); - List caseBodies = new ArrayList(); - for (int i = 0; i < caseValues.size(); i++) { - GraphPart cur = switchLoc.nextParts.get(1 + i); - if (!caseBodies.contains(cur)) { - caseBodies.add(cur); - } - valuesMapping.add(caseBodies.indexOf(cur)); - } - - List defaultCommands = new ArrayList(); - GraphPart defaultPart = null; - if (hasDefault) { - defaultPart = switchLoc.nextParts.get(switchLoc.nextParts.size() - 1); - defaultCommands = printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, switchLoc, defaultPart, next, loops, localRegs, body, ignoredSwitches); - } - - List ignored = new ArrayList(); - for (Loop l : loops) { - ignored.add(l.loopContinue); - } - - for (int i = 0; i < caseBodies.size(); i++) { - List cc = new ArrayList(); - GraphPart nextCase = null; - nextCase = next; - if (next != null) { - if (i < caseBodies.size() - 1) { - if (!caseBodies.get(i).leadsTo(caseBodies.get(i + 1), ignored)) { - cc.add(new BreakTreeItem(null, next.start)); - } else { - nextCase = caseBodies.get(i + 1); - } - } else if (hasDefault) { - if (!caseBodies.get(i).leadsTo(defaultPart, ignored)) { - cc.add(new BreakTreeItem(null, next.start)); - } else { - nextCase = defaultPart; - } - } - } - cc.addAll(0, printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, switchLoc, caseBodies.get(i), nextCase, loops, localRegs, body, ignoredSwitches)); - caseCommands.add(cc); - } - - SwitchTreeItem sti = new SwitchTreeItem(null, next == null ? -1 : next.start, switchedObject, caseValues, caseCommands, defaultCommands, valuesMapping); - ret.add(sti); - loops.remove(currentLoop); - if (next != null) { - if (ti != null) { - ret.add(ti); - } else { - ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, null, next, stopPart, loops, localRegs, body, ignoredSwitches)); - } - } - return ret; - } else { - try { - ins.definition.translate(false, 0, new HashMap(), stack, new Stack(), abc.constants, ins, abc.method_info, output, body, abc, lrn, fqn); - } catch (Exception ex) { - System.err.println("ip:" + (end + 1)); - ex.printStackTrace(); - } - } - //((IfTypeIns)ins.definition).translateInverted(new HashMap(), co.stack, ins); - } - } catch (ConvertException ex) { - Logger.getLogger(AVM2Graph.class.getName()).log(Level.SEVERE, null, ex); - } - - int ip = part.start; - int addr = code.fixAddrAfterDebugLine(code.pos2adr(part.start)); - int maxend = -1; - List catchedExceptions = new ArrayList(); - for (int e = 0; e < body.exceptions.length; e++) { - if (addr == code.fixAddrAfterDebugLine(body.exceptions[e].start)) { - if (!body.exceptions[e].isFinally()) { - if (((body.exceptions[e].end) > maxend) && (!parsedExceptions.contains(body.exceptions[e]))) { - catchedExceptions.clear(); - maxend = code.fixAddrAfterDebugLine(body.exceptions[e].end); - catchedExceptions.add(body.exceptions[e]); - } else if (code.fixAddrAfterDebugLine(body.exceptions[e].end) == maxend) { - catchedExceptions.add(body.exceptions[e]); - } - } - } - } - if (catchedExceptions.size() > 0) { - parsedExceptions.addAll(catchedExceptions); - int endpos = code.adr2pos(code.fixAddrAfterDebugLine(catchedExceptions.get(0).end)); - int endposStartBlock = code.adr2pos(catchedExceptions.get(0).end); - - - List> catchedCommands = new ArrayList>(); - if (code.code.get(endpos).definition instanceof JumpIns) { - int afterCatchAddr = code.pos2adr(endpos + 1) + code.code.get(endpos).operands[0]; - int afterCatchPos = code.adr2pos(afterCatchAddr); - Collections.sort(catchedExceptions, new Comparator() { - public int compare(ABCException o1, ABCException o2) { - try { - return code.fixAddrAfterDebugLine(o1.target) - code.fixAddrAfterDebugLine(o2.target); - } catch (ConvertException ex) { - return 0; - } - } - }); - - - List finallyCommands = new ArrayList(); - int returnPos = afterCatchPos; - for (int e = 0; e < body.exceptions.length; e++) { - if (body.exceptions[e].isFinally()) { - if (addr == code.fixAddrAfterDebugLine(body.exceptions[e].start)) { - if (afterCatchPos + 1 == code.adr2pos(code.fixAddrAfterDebugLine(body.exceptions[e].end))) { - AVM2Instruction jmpIns = code.code.get(code.adr2pos(code.fixAddrAfterDebugLine(body.exceptions[e].end))); - if (jmpIns.definition instanceof JumpIns) { - int finStart = code.adr2pos(code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytes().length + jmpIns.operands[0]); - finallyJumps.add(finStart); - for (int f = finStart; f < code.code.size(); f++) { - if (code.code.get(f).definition instanceof LookupSwitchIns) { - AVM2Instruction swins = code.code.get(f); - if (swins.operands.length >= 3) { - if (swins.operands[0] == swins.getBytes().length) { - if (code.adr2pos(code.pos2adr(f) + swins.operands[2]) < finStart) { - GraphPart fpart = null; - for (GraphPart p : allParts) { - if (p.start == finStart) { - fpart = p; - break; - } - } - stack.push(new ExceptionTreeItem(body.exceptions[e])); - GraphPart fepart = null; - for (GraphPart p : allParts) { - if (p.start == f + 1) { - fepart = p; - break; - } - } - //code.code.get(f).ignored = true; - ignoredSwitches.add(f); - finallyCommands = printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, fpart, fepart, loops, localRegs, body, ignoredSwitches); - returnPos = f + 1; - break; - } - } - } - } - } - - break; - } - } - } - } - } - - for (int e = 0; e < catchedExceptions.size(); e++) { - int eendpos; - if (e < catchedExceptions.size() - 1) { - eendpos = code.adr2pos(code.fixAddrAfterDebugLine(catchedExceptions.get(e + 1).target)) - 2; - } else { - eendpos = afterCatchPos - 1; - } - Stack substack = new Stack(); - substack.add(new ExceptionTreeItem(catchedExceptions.get(e))); - - GraphPart npart = null; - int findpos = code.adr2pos(code.fixAddrAfterDebugLine(catchedExceptions.get(e).target)); - for (GraphPart p : allParts) { - if (p.start == findpos) { - npart = p; - break; - } - } - - GraphPart nepart = null; - for (GraphPart p : allParts) { - if (p.start == eendpos + 1) { - nepart = p; - break; - } - } - stack.add(new ExceptionTreeItem(catchedExceptions.get(e))); - catchedCommands.add(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, npart, nepart, loops, localRegs, body, ignoredSwitches)); - } - - GraphPart nepart = null; - - for (GraphPart p : allParts) { - if (p.start == endposStartBlock) { - nepart = p; - break; - } - } - List tryCommands = printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, part, nepart, loops, localRegs, body, ignoredSwitches); - - output.clear(); - output.add(new TryTreeItem(tryCommands, catchedExceptions, catchedCommands, finallyCommands)); - ip = returnPos; - addr = code.pos2adr(ip); - } - - } - - if (ip != part.start) { - part = null; - for (GraphPart p : allParts) { - List ps = p.getSubParts(); - for (GraphPart p2 : ps) { - if (p2.start == ip) { - part = p2; - break; - } - } - } - ret.addAll(output); - TreeItem lop = checkLoop(part, stopPart, loops); - if (lop == null) { - ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, null, part, stopPart, loops, localRegs, body, ignoredSwitches)); - } else { - ret.add(lop); - } - return ret; - } - - List loopContinues = new ArrayList(); - for (Loop l : loops) { - if (l.loopContinue != null) { - loopContinues.add(l.loopContinue); - } - } - boolean loop = false; - boolean reversed = false; - boolean whileTrue = false; - Loop whileTrueLoop = null; - if ((!part.nextParts.isEmpty()) && part.nextParts.get(0).leadsTo(part, loopContinues)) { - 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; - } - if (((part.nextParts.size() == 2) || ((part.nextParts.size() == 1) && loop)) && (!isSwitch)) { - - boolean doWhile = loop; - if (loop && output.isEmpty()) { - doWhile = false; - } - Loop currentLoop = new Loop(part, null); - if (loop) { - loops.add(currentLoop); - } - - loopContinues = new ArrayList(); - for (Loop l : loops) { - if (l.loopContinue != null) { - loopContinues.add(l.loopContinue); - } - } - - if ((part.nextParts.size() > 1) && (!doWhile)) { - currentLoop.loopBreak = part.nextParts.get(reversed ? 0 : 1); - } - - 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()) { - 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, currentLoop.id, part.start, output, expr)); - } else { - ret.addAll(output); - } - GraphPart loopBodyStart = null; - GraphPart next = part.getNextPartPath(loopContinues); - if (reversed && (expr instanceof LogicalOp)) { - expr = ((LogicalOp) expr).invert(); - } - List retx = ret; - if ((!loop) || (doWhile && (part.nextParts.size() > 1))) { - if (doWhile) { - retx = output; - - } - int stackSizeBefore = stack.size(); - Stack trueStack = (Stack) stack.clone(); - Stack falseStack = (Stack) stack.clone(); - TreeItem lopTrue = checkLoop(part.nextParts.get(1), stopPart, loops); - TreeItem lopFalse = null; - if (next != part.nextParts.get(0)) { - lopFalse = checkLoop(part.nextParts.get(0), stopPart, loops); - } - List onTrue = new ArrayList(); - if (lopTrue != null) { - onTrue.add(lopTrue); - } else { - if (debugMode) { - System.err.println("ONTRUE: (inside " + part + ")"); - } - onTrue = printGraph(methodPath, trueStack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, part, part.nextParts.get(1), next == null ? stopPart : next, loops, localRegs, body, ignoredSwitches); - if (debugMode) { - System.err.println("/ONTRUE (inside " + part + ")"); - } - } - List onFalse = new ArrayList(); - if (lopFalse != null) { - onFalse.add(lopFalse); - } else { - if (debugMode) { - System.err.println("ONFALSE: (inside " + part + ")"); - } - onFalse = (((next == part.nextParts.get(0)) || (part.nextParts.get(0).path.equals(part.path) || part.nextParts.get(0).path.length() < part.path.length())) ? new ArrayList() : printGraph(methodPath, falseStack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, part, part.nextParts.get(0), next == null ? stopPart : next, loops, localRegs, body, ignoredSwitches)); - if (debugMode) { - System.err.println("/ONFALSE (inside " + part + ")"); - } - } - - if (onTrue.isEmpty() && onFalse.isEmpty() && (trueStack.size() > stackSizeBefore) && (falseStack.size() > stackSizeBefore)) { - stack.push(new TernarOpTreeItem(null, expr, trueStack.pop(), falseStack.pop())); - } else { - List retw = retx; - if (whileTrue) { - retw = new ArrayList(); - 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())) { - if (onTrue.get(onTrue.size() - 1) instanceof ContinueTreeItem) { - 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); - 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) { // && (!doWhile)) { - List loopBody = null; - List 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(), 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 addIf = new ArrayList(); - 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) { - if (next.start == f) { - finallyJump = true; - break; - } - } - if (!finallyJump) { - TreeItem ti = checkLoop(next, stopPart, loops); - if (ti != null) { - ret.add(ti); - } else { - if (debugMode) { - System.err.println("NEXT: (inside " + part + ")"); - } - ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level, part, next, stopPart, loops, localRegs, body, ignoredSwitches)); - if (debugMode) { - System.err.println("/NEXT: (inside " + part + ")"); - } - } - } - } - } else { - ret.addAll(output); - } - onepart: - if (part.nextParts.size() == 1 && (!loop)) { - if (part.end - part.start > 4) { - if (code.code.get(part.end).definition instanceof PopIns) { - if (code.code.get(part.end - 1).definition instanceof LabelIns) { - if (code.code.get(part.end - 2).definition instanceof PushByteIns) { - - //if (code.code.get(part.end - 3).definition instanceof SetLocalTypeIns) { - if (part.nextParts.size() == 1) { - GraphPart sec = part.nextParts.get(0); - - if (code.code.get(sec.end).definition instanceof ReturnValueIns) { - if (sec.end - sec.start >= 3) { - if (code.code.get(sec.end - 1).definition instanceof KillIns) { - if (code.code.get(sec.end - 2).definition instanceof GetLocalTypeIns) { - if (!output.isEmpty()) { - if (output.get(output.size() - 1) instanceof SetLocalTreeItem) { - sec.ignored = true; - ret.add(new ReturnValueTreeItem(code.code.get(sec.end), ((SetLocalTreeItem) output.get(output.size() - 1)).value)); - break onepart; - } - } - } - } - } - - } else if (code.code.get(sec.end).definition instanceof ReturnVoidIns) { - ret.add(new ReturnVoidTreeItem(code.code.get(sec.end))); - break onepart; - } - //} - } - } - } - } - } - - for (int f : finallyJumps) { - if (part.nextParts.get(0).start == f) { - if ((!output.isEmpty()) && (output.get(output.size() - 1) instanceof SetLocalTreeItem)) { - ret.add(new ReturnValueTreeItem(null, ((SetLocalTreeItem) output.get(output.size() - 1)).value)); - } else { - ret.add(new ReturnVoidTreeItem(null)); - } - - break onepart; - } - } - - GraphPart p = part.nextParts.get(0); - TreeItem lop = checkLoop(p, stopPart, loops); - if (lop == null) { - if (p.path.length() == part.path.length()) { - ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, part, p, stopPart, loops, localRegs, body, ignoredSwitches)); - } else { - if ((p != stopPart) && (p.refs.size() > 1)) { - ContinueTreeItem cti = new ContinueTreeItem(null, -1); - //p.forContinues.add(cti); - ret.add(new CommentTreeItem(null, "Unknown jump to part " + p)); - ret.add(cti); - } - } - } else { - ret.add(lop); - } - //} - //ret += (strOfChars(level, TAB) + "continue;\r\n"); - //} - } - if (isSwitch && (!ignoredSwitches.contains(part.end))) { - //ret.add(new CommentTreeItem(code.code.get(part.end), "Switch not supported")); - TreeItem switchedObject = stack.pop(); - List caseValues = new ArrayList(); - List valueMappings = new ArrayList(); - List> caseCommands = new ArrayList>(); - - GraphPart next = part.getNextPartPath(loopContinues); - int breakPos = -1; - if (next != null) { - breakPos = next.start; - } - List defaultCommands = printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, part, part.nextParts.get(0), stopPart, loops, localRegs, body, ignoredSwitches); - - for (int i = 0; i < part.nextParts.size() - 1; i++) { - caseValues.add(new IntegerValueTreeItem(null, (Long) (long) i)); - valueMappings.add(i); - GraphPart nextCase = next; - List caseBody = new ArrayList(); - if (i < part.nextParts.size() - 1 - 1) { - if (!part.nextParts.get(1 + i).leadsTo(part.nextParts.get(1 + i + 1), new ArrayList())) { - caseBody.add(new BreakTreeItem(null, breakPos)); - } else { - nextCase = part.nextParts.get(1 + i + 1); - } - } else if (!part.nextParts.get(1 + i).leadsTo(part.nextParts.get(0), new ArrayList())) { - caseBody.add(new BreakTreeItem(null, breakPos)); - } else { - nextCase = part.nextParts.get(0); - } - caseBody.addAll(0, printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, part, part.nextParts.get(1 + i), nextCase, loops, localRegs, body, ignoredSwitches)); - caseCommands.add(caseBody); - } - - SwitchTreeItem swt = new SwitchTreeItem(null, breakPos, switchedObject, caseValues, caseCommands, defaultCommands, valueMappings); - ret.add(swt); - - 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)); - } - } - - } - - } catch (ForException fex) { - ret.addAll(fex.output); - fex.output = ret; - throw fex; - } - code.clearTemporaryRegisters(ret); - if (!part.forContinues.isEmpty()) { - throw new ForException(new ArrayList(), ret, part); - } - return ret; - } - - private List makeGraph(AVM2Code code, List allBlocks, MethodBody body) { - HashMap> refs = code.visitCode(body); - List ret = new ArrayList(); - boolean visited[] = new boolean[code.code.size()]; - ret.add(makeGraph(null, "0", code, 0, 0, allBlocks, refs, visited)); - for (ABCException ex : body.exceptions) { - GraphPart e1 = new GraphPart(-1, -1); - e1.path = "e"; - GraphPart e2 = new GraphPart(-1, -1); - e2.path = "e"; - GraphPart e3 = new GraphPart(-1, -1); - e3.path = "e"; - makeGraph(e1, "e", code, code.adr2pos(ex.start), code.adr2pos(ex.start), allBlocks, refs, visited); - makeGraph(e2, "e", code, code.adr2pos(ex.end), code.adr2pos(ex.end), allBlocks, refs, visited); - ret.add(makeGraph(e3, "e", code, code.adr2pos(ex.target), code.adr2pos(ex.target), allBlocks, refs, visited)); - } - return ret; - } - - private GraphPart makeGraph(GraphPart parent, String path, AVM2Code code, int startip, int lastIp, List allBlocks, HashMap> refs, boolean visited2[]) { - - int ip = startip; - for (GraphPart p : allBlocks) { - if (p.start == ip) { - p.refs.add(parent); - return p; - } - } - GraphPart g; - GraphPart ret = new GraphPart(ip, -1); - ret.path = path; - GraphPart part = ret; - while (ip < code.code.size()) { - if (visited2[ip] || ((ip != startip) && (refs.get(ip).size() > 1))) { - part.end = lastIp; - GraphPart found = null; - for (GraphPart p : allBlocks) { - if (p.start == ip) { - found = p; - break; - } - } - - allBlocks.add(part); - - if (found != null) { - part.nextParts.add(found); - found.refs.add(part); - break; - } else { - GraphPart gp = new GraphPart(ip, -1); - gp.path = path; - part.nextParts.add(gp); - gp.refs.add(part); - part = gp; - } - } - lastIp = ip; - AVM2Instruction ins = code.code.get(ip); - if ((ins.definition instanceof ThrowIns) || (ins.definition instanceof ReturnValueIns) || (ins.definition instanceof ReturnVoidIns)) { - part.end = ip; - allBlocks.add(part); - break; - } - if (ins.definition instanceof LookupSwitchIns) { - part.end = ip; - allBlocks.add(part); - try { - part.nextParts.add(g = makeGraph(part, path + "0", code, code.adr2pos(code.pos2adr(ip) + ins.operands[0]), ip, allBlocks, refs, visited2)); - g.refs.add(part); - for (int i = 2; i < ins.operands.length; i++) { - part.nextParts.add(g = makeGraph(part, path + (i - 1), code, code.adr2pos(code.pos2adr(ip) + ins.operands[i]), ip, allBlocks, refs, visited2)); - g.refs.add(part); - } - break; - } catch (ConvertException ex) { - } - } - if (ins.definition instanceof JumpIns) { - try { - part.end = ip; - allBlocks.add(part); - ip = code.adr2pos(code.pos2adr(ip) + ins.getBytes().length + ins.operands[0]); - part.nextParts.add(g = makeGraph(part, path, code, ip, lastIp, allBlocks, refs, visited2)); - g.refs.add(part); - break; - } catch (ConvertException ex) { - Logger.getLogger(AVM2Code.class.getName()).log(Level.FINE, null, ex); - } - } else if (ins.definition instanceof IfTypeIns) { - part.end = ip; - allBlocks.add(part); - try { - part.nextParts.add(g = makeGraph(part, path + "0", code, code.adr2pos(code.pos2adr(ip) + ins.getBytes().length + ins.operands[0]), ip, allBlocks, refs, visited2)); - g.refs.add(part); - part.nextParts.add(g = makeGraph(part, path + "1", code, ip + 1, ip, allBlocks, refs, visited2)); - g.refs.add(part); - - } catch (ConvertException ex) { - Logger.getLogger(AVM2Code.class.getName()).log(Level.FINE, null, ex); - } - break; - } - ip++; - }; - return ret; - }*/ @Override protected List check(GraphSource srcCode, List localData, List allParts, Stack stack, GraphPart parent, GraphPart part, List stopPart, List loops, List output) { @@ -1234,7 +215,7 @@ public class AVM2Graph extends Graph { } //code.code.get(f).ignored = true; ignoredSwitches.add(f); - List stopPart2=new ArrayList<>(stopPart); + List stopPart2 = new ArrayList<>(stopPart); stopPart2.add(fepart); finallyCommands = printGraph(new ArrayList(), localData, stack, allParts, parent, fpart, stopPart2, loops); returnPos = f + 1; @@ -1283,8 +264,8 @@ public class AVM2Graph extends Graph { List localData2 = new ArrayList<>(); localData2.addAll(localData); localData2.set(DATA_SCOPESTACK, new Stack()); - List stopPart2=new ArrayList<>(stopPart); - stopPart2.add(nepart); + List stopPart2 = new ArrayList<>(stopPart); + stopPart2.add(nepart); catchedCommands.add(printGraph(new ArrayList(), localData2, stack, allParts, parent, npart, stopPart2, loops)); } @@ -1296,8 +277,8 @@ public class AVM2Graph extends Graph { break; } } - List stopPart2=new ArrayList<>(stopPart); - stopPart2.add(nepart); + List stopPart2 = new ArrayList<>(stopPart); + stopPart2.add(nepart); List tryCommands = printGraph(new ArrayList(), localData, stack, allParts, parent, part, stopPart2, loops); output.clear(); @@ -1412,7 +393,13 @@ public class AVM2Graph extends Graph { reversed = true; } caseValuesMap.put(code.code.get(code.fixIPAfterDebugLine(part.nextParts.get(reversed ? 0 : 1).start)).operands[0], tar); - + while (code.code.get(part.nextParts.get(reversed ? 1 : 0).start).definition instanceof JumpIns) { + reversed = false; + part = part.nextParts.get(reversed ? 1 : 0); + if (part instanceof GraphPartMulti) { + part = ((GraphPartMulti) part).parts.get(0); + } + } } boolean hasDefault = false; GraphPart dp = part.nextParts.get(reversed ? 1 : 0); @@ -1446,7 +433,7 @@ public class AVM2Graph extends Graph { GraphTargetItem ti = checkLoop(next, stopPart, loops); Loop currentLoop = new Loop(loops.size(), null, next); - currentLoop.phase=1; + currentLoop.phase = 1; currentLoop.used = true; loops.add(currentLoop); //switchLoc.getNextPartPath(new ArrayList()); @@ -1464,9 +451,9 @@ public class AVM2Graph extends Graph { GraphPart defaultPart = null; if (hasDefault) { defaultPart = switchLoc.nextParts.get(switchLoc.nextParts.size() - 1); - List stopPart2=new ArrayList<>(stopPart); - stopPart2.add(next); - defaultCommands = printGraph(new ArrayList(), localData, stack, allParts, switchLoc, defaultPart,stopPart2 , loops); + List stopPart2 = new ArrayList<>(stopPart); + stopPart2.add(next); + defaultCommands = printGraph(new ArrayList(), localData, stack, allParts, switchLoc, defaultPart, stopPart2, loops); if (!defaultCommands.isEmpty()) { if (defaultCommands.get(defaultCommands.size() - 1) instanceof BreakItem) { if (((BreakItem) defaultCommands.get(defaultCommands.size() - 1)).loopId == currentLoop.id) { @@ -1500,8 +487,8 @@ public class AVM2Graph extends Graph { } } } - List stopPart2=new ArrayList<>(stopPart); - stopPart2.add(nextCase); + List stopPart2 = new ArrayList<>(stopPart); + stopPart2.add(nextCase); cc.addAll(0, printGraph(new ArrayList(), localData, stack, allParts, switchLoc, caseBodies.get(i), stopPart2, loops)); caseCommands.add(cc); } @@ -1511,10 +498,10 @@ public class AVM2Graph extends Graph { //loops.remove(currentLoop); if (next != null) { /*if (ti != null) { - ret.add(ti); - } else {*/ - currentLoop.phase=2; - ret.addAll(printGraph(new ArrayList(), localData, stack, allParts, null, next, stopPart, loops)); + ret.add(ti); + } else {*/ + currentLoop.phase = 2; + ret.addAll(printGraph(new ArrayList(), localData, stack, allParts, null, next, stopPart, loops)); //} } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetPropertyIns.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetPropertyIns.java index 44dd74cc1..74682231e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetPropertyIns.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetPropertyIns.java @@ -58,8 +58,9 @@ public class SetPropertyIns extends InstructionDefinition implements SetTypeIns if (insideProp.propertyName.compareSame(multiname)) { GraphTargetItem insideObj = obj.getThroughDuplicate(); if (insideObj instanceof LocalRegTreeItem) { - if(((LocalRegTreeItem) insideObj).computedValue!=null) - insideObj = ((LocalRegTreeItem) insideObj).computedValue.getThroughNotCompilable().getThroughDuplicate(); + if (((LocalRegTreeItem) insideObj).computedValue != null) { + insideObj = ((LocalRegTreeItem) insideObj).computedValue.getThroughNotCompilable().getThroughDuplicate(); + } } if (insideProp.object.getThroughDuplicate() == insideObj) { if (stack.size() > 0) { @@ -89,8 +90,9 @@ public class SetPropertyIns extends InstructionDefinition implements SetTypeIns if (insideProp.propertyName.compareSame(multiname)) { GraphTargetItem insideObj = obj.getThroughDuplicate(); if (insideObj instanceof LocalRegTreeItem) { - if(((LocalRegTreeItem) insideObj).computedValue!=null) - insideObj = ((LocalRegTreeItem) insideObj).computedValue.getThroughNotCompilable().getThroughDuplicate(); + if (((LocalRegTreeItem) insideObj).computedValue != null) { + insideObj = ((LocalRegTreeItem) insideObj).computedValue.getThroughNotCompilable().getThroughDuplicate(); + } } if (insideProp.object.getThroughDuplicate() == insideObj) { if (stack.size() > 0) { diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/ConvertTreeItem.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/ConvertTreeItem.java index 84db5131c..362aa050d 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/ConvertTreeItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/ConvertTreeItem.java @@ -35,7 +35,6 @@ public class ConvertTreeItem extends TreeItem { @Override public String toString(ConstantPool constants, HashMap localRegNames, List fullyQualifiedNames) { - //return hilight("("+type+")")+ return value.toString(constants, localRegNames, fullyQualifiedNames); } @@ -43,4 +42,79 @@ public class ConvertTreeItem extends TreeItem { public GraphTargetItem getNotCoerced() { return value.getNotCoerced(); } + + @Override + public double toNumber() { + return toBoolean() ? 1 : 0; + } + + @Override + public boolean toBoolean() { + if (type.contains("Boolean")) { + if (value instanceof UndefinedTreeItem) { + return false; + } + if (value instanceof NullTreeItem) { + return false; + } + if (value instanceof BooleanTreeItem) { + return ((BooleanTreeItem) value).value; + } + if (value instanceof IntegerValueTreeItem) { + IntegerValueTreeItem iv = (IntegerValueTreeItem) value; + return iv.value != 0; + } + if (value instanceof FloatValueTreeItem) { + FloatValueTreeItem fv = (FloatValueTreeItem) value; + return !(fv.value == 0 || fv.value.isNaN()); + } + if (value instanceof StringTreeItem) { + StringTreeItem sv = (StringTreeItem) value; + return !sv.value.equals(""); + } + + if (value instanceof ThisTreeItem) { + return true; + } + if (value instanceof ClassTreeItem) { + return true; + } + //object + return false; + } + return false; + } + + @Override + public boolean isCompileTime() { + if (type.contains("Boolean")) { + if (value instanceof UndefinedTreeItem) { + return true; + } + if (value instanceof NullTreeItem) { + return true; + } + if (value instanceof BooleanTreeItem) { + return true; + } + if (value instanceof IntegerValueTreeItem) { + return true; + } + if (value instanceof FloatValueTreeItem) { + return true; + } + if (value instanceof StringTreeItem) { + return true; + } + if (value instanceof ThisTreeItem) { + return true; + } + if (value instanceof ClassTreeItem) { + return true; + } + //object + return false; + } + return false; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/FullMultinameTreeItem.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/FullMultinameTreeItem.java index a8087ec55..5d00096c8 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/FullMultinameTreeItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/FullMultinameTreeItem.java @@ -101,8 +101,9 @@ public class FullMultinameTreeItem extends TreeItem { name = name.getThroughDuplicate(); } while (tiName instanceof LocalRegTreeItem) { - if(((LocalRegTreeItem) tiName).computedValue!=null) - tiName = ((LocalRegTreeItem) tiName).computedValue.getThroughNotCompilable().getThroughDuplicate(); + if (((LocalRegTreeItem) tiName).computedValue != null) { + tiName = ((LocalRegTreeItem) tiName).computedValue.getThroughNotCompilable().getThroughDuplicate(); + } } GraphTargetItem tiName2 = other.name; @@ -110,8 +111,9 @@ public class FullMultinameTreeItem extends TreeItem { tiName2 = tiName2.getThroughDuplicate(); } while (tiName2 instanceof LocalRegTreeItem) { - if(((LocalRegTreeItem) tiName2).computedValue!=null) - tiName2 = ((LocalRegTreeItem) tiName2).computedValue.getThroughNotCompilable().getThroughDuplicate(); + if (((LocalRegTreeItem) tiName2).computedValue != null) { + tiName2 = ((LocalRegTreeItem) tiName2).computedValue.getThroughNotCompilable().getThroughDuplicate(); + } } if (tiName != tiName2) { return false; @@ -122,8 +124,9 @@ public class FullMultinameTreeItem extends TreeItem { tiNameSpace = tiNameSpace.getThroughDuplicate(); } while (tiNameSpace instanceof LocalRegTreeItem) { - if(((LocalRegTreeItem) tiNameSpace).computedValue!=null) - tiNameSpace = ((LocalRegTreeItem) tiNameSpace).computedValue.getThroughNotCompilable().getThroughDuplicate(); + if (((LocalRegTreeItem) tiNameSpace).computedValue != null) { + tiNameSpace = ((LocalRegTreeItem) tiNameSpace).computedValue.getThroughNotCompilable().getThroughDuplicate(); + } } GraphTargetItem tiNameSpace2 = other.namespace; @@ -131,8 +134,9 @@ public class FullMultinameTreeItem extends TreeItem { tiNameSpace2 = tiNameSpace2.getThroughDuplicate(); } while (tiNameSpace2 instanceof LocalRegTreeItem) { - if(((LocalRegTreeItem) tiNameSpace2).computedValue!=null) - tiNameSpace2 = ((LocalRegTreeItem) tiNameSpace2).computedValue.getThroughNotCompilable().getThroughDuplicate(); + if (((LocalRegTreeItem) tiNameSpace2).computedValue != null) { + tiNameSpace2 = ((LocalRegTreeItem) tiNameSpace2).computedValue.getThroughNotCompilable().getThroughDuplicate(); + } } if (tiNameSpace != tiNameSpace2) { return false; diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/LocalRegTreeItem.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/LocalRegTreeItem.java index 76045c439..1b41076cc 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/LocalRegTreeItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/LocalRegTreeItem.java @@ -48,7 +48,7 @@ public class LocalRegTreeItem extends TreeItem { @Override public GraphTargetItem getThroughRegister() { - if(computedValue == null){ + if (computedValue == null) { return this; } return computedValue.getThroughRegister(); @@ -56,7 +56,7 @@ public class LocalRegTreeItem extends TreeItem { @Override public double toNumber() { - if(computedValue==null){ + if (computedValue == null) { return 0; } return computedValue.toNumber(); @@ -64,7 +64,7 @@ public class LocalRegTreeItem extends TreeItem { @Override public boolean toBoolean() { - if(computedValue==null){ + if (computedValue == null) { return false; } return computedValue.toBoolean(); @@ -72,7 +72,7 @@ public class LocalRegTreeItem extends TreeItem { @Override public boolean isCompileTime() { - if(computedValue==null){ + if (computedValue == null) { return false; } return computedValue.isCompileTime(); diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/TreeItem.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/TreeItem.java index 241b40af9..316b555e1 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/TreeItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/TreeItem.java @@ -79,7 +79,7 @@ public abstract class TreeItem extends GraphTargetItem { obStr = "(" + obStr + ")"; } if (object instanceof LocalRegTreeItem) { - if(((LocalRegTreeItem) object).computedValue!=null){ + if (((LocalRegTreeItem) object).computedValue != null) { if (((LocalRegTreeItem) object).computedValue.getThroughNotCompilable() instanceof FindPropertyTreeItem) { obStr = ""; } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/Multiname.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/Multiname.java index b47c2eba5..db01cb231 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/Multiname.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/Multiname.java @@ -174,7 +174,7 @@ public class Multiname { } private String typeNameToStr(ConstantPool constants, List fullyQualifiedNames) { - if(constants.constant_multiname[qname_index].name_index==name_index){ + if (constants.constant_multiname[qname_index].name_index == name_index) { return "ambiguousTypeName"; } String typeNameStr = constants.constant_multiname[qname_index].getName(constants, fullyQualifiedNames); diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java index c3ac3d403..0404cc04b 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java @@ -403,19 +403,19 @@ public class TraitClass extends Trait implements TraitWithSlot { } imports = imports2;*/ - for(int i=0;i(), false, highlight, fullyQualifiedNames, null), 3); } catch (StackOverflowError er) { diff --git a/trunk/src/com/jpexs/decompiler/flash/action/ActionGraph.java b/trunk/src/com/jpexs/decompiler/flash/action/ActionGraph.java index 019757c32..a38af617c 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/ActionGraph.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/ActionGraph.java @@ -184,11 +184,11 @@ public class ActionGraph extends Graph { defaultAndLastPart.add(defaultPart); defaultAndLastPart.add(caseBodyParts.get(caseBodyParts.size() - 1)); - GraphPart defaultPart2 = getCommonPart(defaultAndLastPart,new ArrayList()); + GraphPart defaultPart2 = getCommonPart(defaultAndLastPart, new ArrayList()); List defaultCommands = new ArrayList<>(); - List stopPart2=new ArrayList<>(stopPart); - stopPart2.add(defaultPart2); + List stopPart2 = new ArrayList<>(stopPart); + stopPart2.add(defaultPart2); defaultCommands = printGraph(new ArrayList(), localData, stack, allParts, null, defaultPart, stopPart2, loops); @@ -261,8 +261,8 @@ public class ActionGraph extends Graph { defaultPart = null; } if ((defaultPart != null) && (defaultCommands.isEmpty())) { - List stopPart2x=new ArrayList<>(stopPart); - stopPart2x.add(next); + List stopPart2x = new ArrayList<>(stopPart); + stopPart2x.add(next); defaultCommands = printGraph(new ArrayList(), localData, stack, allParts, null, defaultPart, stopPart2x, loops); } @@ -290,8 +290,8 @@ public class ActionGraph extends Graph { } } } - List stopPart2x=new ArrayList<>(stopPart); - stopPart2.add(nextCase); + List stopPart2x = new ArrayList<>(stopPart); + stopPart2.add(nextCase); cc.addAll(0, printGraph(new ArrayList(), localData, stack, allParts, null, caseBodies.get(i), stopPart2x, loops)); if (cc.size() >= 2) { if (cc.get(cc.size() - 1) instanceof BreakItem) { diff --git a/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionPop.java b/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionPop.java index 425a5b2af..e14186228 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionPop.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionPop.java @@ -20,7 +20,6 @@ import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.treemodel.CallFunctionTreeItem; import com.jpexs.decompiler.flash.action.treemodel.CallMethodTreeItem; import com.jpexs.decompiler.flash.action.treemodel.NewMethodTreeItem; -import com.jpexs.decompiler.flash.action.treemodel.PopTreeItem; import com.jpexs.decompiler.flash.action.treemodel.SetTypeTreeItem; import com.jpexs.decompiler.flash.graph.GraphTargetItem; import java.util.HashMap; diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/BinaryOpItem.java b/trunk/src/com/jpexs/decompiler/flash/graph/BinaryOpItem.java index b937d9359..1ae774e5e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/graph/BinaryOpItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/graph/BinaryOpItem.java @@ -48,7 +48,11 @@ public abstract class BinaryOpItem extends GraphTargetItem { } else { ret += leftSide.toString(localData); } + if (ret.length() > 500) { + return "/*line too long*/"; + } ret += hilight(operator); + if (rightSide.getPrecedence() > precedence) { ret += "(" + rightSide.toString(localData) + ")"; } else { diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java b/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java index 1e162cf9d..9a8e817fe 100644 --- a/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java +++ b/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java @@ -17,10 +17,6 @@ package com.jpexs.decompiler.flash.graph; import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.graph.cfg.BBType; -import com.jpexs.decompiler.flash.graph.cfg.BasicBlock; -import com.jpexs.decompiler.flash.graph.cfg.CFG; -import com.jpexs.decompiler.flash.graph.cfg.StructType; import com.jpexs.decompiler.flash.helpers.Highlighting; import java.util.ArrayList; import java.util.HashMap; @@ -40,17 +36,10 @@ public class Graph { public List heads; protected GraphSource code; - public List headsCFG; public Graph(GraphSource code, List alternateEntries) { this.code = code; - headsCFG = new ArrayList<>(); heads = makeGraph(code, new ArrayList(), alternateEntries); - List blocks=new ArrayList<>(); - List headsbb = makeCFG(code, blocks, alternateEntries); - CFG cfg=new CFG(blocks, headsbb.get(0)); - cfg.structure(); - headsCFG.add(cfg); for (GraphPart head : heads) { fixGraph(head); makeMulti(head, new ArrayList()); @@ -187,7 +176,9 @@ public class Graph { } private void makeMulti(GraphPart part, List visited) { - if(true) return; + if (true) { + return; + } if (visited.contains(part)) { return; } @@ -409,74 +400,40 @@ public class Graph { Graph g = new Graph(code, alternateEntries); return g.translate(localData); } - - private List getLoopsFromCFG(){ - List ret=new ArrayList<>(); - List allParts=new ArrayList<>(); - for(GraphPart h:heads){ - populateParts(h, allParts); - } - for(CFG cfg:headsCFG){ - for(BasicBlock bb:cfg.m_listBB){ - if(bb.getStructType()== StructType.Loop - || bb.getStructType()== StructType.LoopCond){ - GraphPart loopContinue=null; - GraphPart loopBreak=null; - for(GraphPart p:allParts){ - if(p.start==bb.startAddress){ - loopContinue=p; - break; - } - } - if(bb.loopFollow!=null){ - for(GraphPart p:allParts){ - if(p.start==bb.loopFollow.startAddress){ - loopBreak=p; - break; - } - } - } - ret.add(new Loop(ret.size(),loopContinue,loopBreak)); - } - } - } - return ret; - } public List translate(List localData) { - try{ - List allParts = new ArrayList<>(); - for (GraphPart head : heads) { - populateParts(head, allParts); - } - Stack stack = new Stack<>(); - List loops = new ArrayList<>(); - loops=getLoopsFromCFG(); - //getLoops(heads.get(0), loops, null); - /*System.out.println(""); - for (Loop el : loops) { - System.out.println(el); - } - System.out.println("");*/ - getPrecontinues(null, heads.get(0), loops, null); - /*System.out.println(""); - for (Loop el : loops) { - System.out.println(el); - } - System.out.println("");*/ - - List ret = printGraph(new ArrayList(), localData, stack, allParts, null, heads.get(0), null, loops); - processIfs(ret); - finalProcessStack(stack, ret); - finalProcessAll(ret, 0); - return ret; + try { + List allParts = new ArrayList<>(); + for (GraphPart head : heads) { + populateParts(head, allParts); + } + Stack stack = new Stack<>(); + List loops = new ArrayList<>(); + getLoops(heads.get(0), loops, null); + /*System.out.println(""); + for (Loop el : loops) { + System.out.println(el); + } + System.out.println("");*/ + getPrecontinues(null, heads.get(0), loops, null); + /*System.out.println(""); + for (Loop el : loops) { + System.out.println(el); + } + System.out.println("");*/ + + List ret = printGraph(new ArrayList(), localData, stack, allParts, null, heads.get(0), null, loops); + processIfs(ret); + finalProcessStack(stack, ret); + finalProcessAll(ret, 0); + return ret; } catch (StackOverflowError soe) { - List ret =new ArrayList<>(); + List ret = new ArrayList<>(); ret.add(new CommentItem("StackOverflowError")); Logger.getLogger(Graph.class.getName()).log(Level.SEVERE, "error during printGraph", soe); return ret; } - + } public void finalProcessStack(Stack stack, List output) { @@ -735,16 +692,29 @@ public class Graph { getPrecontinues(parent, part, loops, stopPart, 0, new ArrayList()); clearLoops(loops); } - - - private void getPrecontinues(GraphPart parent, GraphPart part, List loops, List stopPart, int level, List visited) { + private void getPrecontinues(GraphPart parent, GraphPart part, List loops, List stopPart, int level, List visited) { + boolean debugMode = false; if (stopPart == null) { stopPart = new ArrayList<>(); } + + if (debugMode) { + System.err.println("preco " + part); + } + if (stopPart.contains(part)) { + return; + } for (Loop el : loops) { + if ((el.phase == 2) && (el.loopContinue == part)) { + throw new RuntimeException("Phase 2 visited again:" + el); + //return; + } if (el.phase != 1) { + if (debugMode) { + //System.err.println("ignoring "+el); + } continue; } if (el.loopContinue == part) { @@ -757,9 +727,7 @@ public class Graph { return; } } - if (stopPart.contains(part)) { - return; - } + if (visited.contains(part)) { //(part.level > level) { List nextList = new ArrayList<>(); @@ -819,13 +787,33 @@ public class Graph { if (part.nextParts.size() > 2) { GraphPart next = getNextCommonPart(part, loops); - List stopParts2 = new ArrayList<>(stopPart); - if (next != null) { - stopParts2.add(next); - } + List vis = new ArrayList<>(); for (GraphPart p : part.nextParts) { + if (vis.contains(p)) { + continue; + } + List stopPart2 = new ArrayList<>(stopPart); + if (next != null) { + stopPart2.add(next); + } + for (GraphPart p2 : part.nextParts) { + if (p2 == p) { + continue; + } + List p12 = new ArrayList<>(); + p12.add(p); + p12.add(p2); + GraphPart n = getCommonPart(p12, loops); + if (!stopPart2.contains(n)) { + stopPart2.add(n); + } + if (!stopPart2.contains(p2)) { + stopPart2.add(p2); + } + } if (next != p) { - getPrecontinues(part, p, loops, next == null ? stopPart : stopParts2, level + 1, visited); + getPrecontinues(part, p, loops, stopPart2, level + 1, visited); + vis.add(p); } } if (next != null) { @@ -857,37 +845,42 @@ public class Graph { } private void getLoops(GraphPart part, List loops, List stopPart, boolean first) { - if(stopPart==null){ - stopPart=new ArrayList<>(); + boolean debugMode = false; + + if (stopPart == null) { + stopPart = new ArrayList<>(); } if (part == null) { return; } + if (debugMode) { + System.err.println("getloops: " + part); + } List loopContinues = getLoopsContinues(loops); - Loop lastP1=null; + Loop lastP1 = null; for (Loop el : loops) { - if ((el.phase==1) && el.loopBreak == null) { //break not found yet + if ((el.phase == 1) && el.loopBreak == null) { //break not found yet if (el.loopContinue != part) { - lastP1=el; - + lastP1 = el; + } } } - if(lastP1!=null){ + if (lastP1 != null) { if (lastP1.breakCandidates.contains(part)) { - lastP1.breakCandidates.add(part); - return; - } else { - List loopContinues2 = new ArrayList<>(loopContinues); - loopContinues2.remove(lastP1.loopContinue); - List loops2 = new ArrayList<>(loops); - loops2.remove(lastP1); - if (!part.leadsTo(code, lastP1.loopContinue, loops2)) { - lastP1.breakCandidates.add(part); - return; - } - } + lastP1.breakCandidates.add(part); + return; + } else { + List loopContinues2 = new ArrayList<>(loopContinues); + loopContinues2.remove(lastP1.loopContinue); + List loops2 = new ArrayList<>(loops); + loops2.remove(lastP1); + if (!part.leadsTo(code, lastP1.loopContinue, loops2)) { + lastP1.breakCandidates.add(part); + return; + } + } } for (Loop el : loops) { @@ -896,7 +889,7 @@ public class Graph { } } - if (part == stopPart) { + if (stopPart.contains(part)) { return; } @@ -911,24 +904,40 @@ public class Graph { if (part.nextParts.size() == 2) { GraphPart next = getNextCommonPart(part, loops);//part.getNextPartPath(loopContinues); - List stopPart2=new ArrayList<>(stopPart); - if(next!=null){ + List stopPart2 = new ArrayList<>(stopPart); + if (next != null) { stopPart2.add(next); } - getLoops(part.nextParts.get(0), loops, stopPart2, false); - getLoops(part.nextParts.get(1), loops, stopPart2, false); + if (next != part.nextParts.get(0)) { + getLoops(part.nextParts.get(0), loops, stopPart2, false); + } + if (next != part.nextParts.get(1)) { + getLoops(part.nextParts.get(1), loops, stopPart2, false); + } if (next != null) { getLoops(next, loops, stopPart, false); } } if (part.nextParts.size() > 2) { GraphPart next = getNextCommonPart(part, loops); - List stopPart2=new ArrayList<>(stopPart); - if(next!=null){ - stopPart2.add(next); - } + + for (GraphPart p : part.nextParts) { - getLoops(p, loops, stopPart2, false); + List stopPart2 = new ArrayList<>(stopPart); + if (next != null) { + stopPart2.add(next); + } + for (GraphPart p2 : part.nextParts) { + if (p2 == p) { + continue; + } + if (!stopPart2.contains(p2)) { + stopPart2.add(p2); + } + } + if (next != p) { + getLoops(p, loops, stopPart2, false); + } } if (next != null) { getLoops(next, loops, stopPart, false); @@ -940,35 +949,39 @@ public class Graph { if (isLoop) { - + GraphPart found; - List backupCandidates=new ArrayList<>(); - for(int i=currentLoop.breakCandidates.size()-1;i>=0;i--){ - if(stopPart.contains(currentLoop.breakCandidates.get(i))){ + List backupCandidates = new ArrayList<>(); + List spcheck = new ArrayList<>(stopPart); + if (!spcheck.isEmpty()) { + spcheck.remove(spcheck.size() - 1); + } + for (int i = currentLoop.breakCandidates.size() - 1; i >= 0; i--) { + if (spcheck.contains(currentLoop.breakCandidates.get(i))) { backupCandidates.add(currentLoop.breakCandidates.remove(i)); } } - Set removed=new HashSet<>(); + Set removed = new HashSet<>(); /* - Set newcommon=new HashSet<>(); - for (GraphPart cand : currentLoop.breakCandidates) { - for (GraphPart cand2 : currentLoop.breakCandidates) { - if(cand==cand2){ - continue; - } - List c=new ArrayList<>(); - c.add(cand); - c.add(cand2); + Set newcommon=new HashSet<>(); + for (GraphPart cand : currentLoop.breakCandidates) { + for (GraphPart cand2 : currentLoop.breakCandidates) { + if(cand==cand2){ + continue; + } + List c=new ArrayList<>(); + c.add(cand); + c.add(cand2); - GraphPart common=getCommonPart(c, loops); - if(common!=null){ - if(!currentLoop.breakCandidates.contains(common)){ - newcommon.add(common); - } - } - } - } - currentLoop.breakCandidates.addAll(newcommon);*/ + GraphPart common=getCommonPart(c, loops); + if(common!=null){ + if(!currentLoop.breakCandidates.contains(common)){ + newcommon.add(common); + } + } + } + } + currentLoop.breakCandidates.addAll(newcommon);*/ do { found = null; loopcand: @@ -976,8 +989,8 @@ public class Graph { for (GraphPart cand2 : currentLoop.breakCandidates) { if (cand.leadsTo(code, cand2, loops)) { /*if (cand.path.equals(cand2.path)) { - found = cand2; - } else {*/ + found = cand2; + } else {*/ found = cand; //} break loopcand; @@ -993,30 +1006,31 @@ public class Graph { Map count = new HashMap<>(); GraphPart winner = null; int winnerCount = 0; - boolean winnerBreakCandidate=true; + boolean winnerBreakCandidate = true; for (GraphPart cand : currentLoop.breakCandidates) { - + if (!count.containsKey(cand)) { count.put(cand, 0); } count.put(cand, count.get(cand) + 1); - boolean otherBreakCandidate=false; - for(Loop el:loops){ - if(el==currentLoop) continue; - if(el.breakCandidates.contains(cand)){ - otherBreakCandidate=true; + boolean otherBreakCandidate = false; + for (Loop el : loops) { + if (el == currentLoop) { + continue; + } + if (el.breakCandidates.contains(cand)) { + otherBreakCandidate = true; break; } } /*if(winnerBreakCandidate && !otherBreakCandidate){ - winnerCount = count.get(cand); - winner = cand; - winnerBreakCandidate=otherBreakCandidate; - }else if(!winnerBreakCandidate && otherBreakCandidate){ - */ - if(otherBreakCandidate){ - - }else if (count.get(cand) > winnerCount) { + winnerCount = count.get(cand); + winner = cand; + winnerBreakCandidate=otherBreakCandidate; + }else if(!winnerBreakCandidate && otherBreakCandidate){ + */ + if (otherBreakCandidate) { + } else if (count.get(cand) > winnerCount) { winnerCount = count.get(cand); winner = cand; } else if (count.get(cand) == winnerCount) { @@ -1025,34 +1039,39 @@ public class Graph { } } } - if(winner==null){ - if(!backupCandidates.isEmpty()){ - winner=backupCandidates.get(backupCandidates.size()-1); - } + if (winner == null) { + if (!backupCandidates.isEmpty()) { + winner = backupCandidates.get(backupCandidates.size() - 1); + } + } + for (GraphPart cand : currentLoop.breakCandidates) { + if (cand != winner) { + removed.add(cand); + } } currentLoop.loopBreak = winner; currentLoop.phase = 2; - boolean start=false; - for(int l=0;l(); } //try { - boolean debugMode = false; + boolean debugMode = true; - if (debugMode) { - System.err.println("PART " + part); + + if (debugMode) { + System.err.println("PART " + part); + } + + /*while (((part != null) && (part.getHeight() == 1)) && (code.size() > part.start) && (code.get(part.start).isJump())) { //Parts with only jump in it gets ignored + + if (part == stopPart) { + return ret; + } + GraphTargetItem lop = checkLoop(part.nextParts.get(0), stopPart, loops); + if (lop == null) { + part = part.nextParts.get(0); + } else { + break; + } + }*/ + + + + + + if (part == null) { + return ret; + } + part = checkPart(localData, part); + if (part == null) { + return ret; + } + + if (part.ignored) { + return ret; + } + + + /* if ((parent != null) && (part.path.length() < parent.path.length())) { + boolean can = true; + for (Loop el : loops) { + if (el.loopContinue == part) { + can = false; + break; + } + if (el.loopBreak == part) { + can = false; + break; + } + if (el.breakCandidates.containsKey(part)) { + can = false; + break; + } + } + if (can) { + if ((part != stopPart) && (part.refs.size() > 1)) { + List nextList = new ArrayList<>(); + populateParts(part, nextList); + Loop nearestLoop = null; + loopn: + for (GraphPart n : nextList) { + for (Loop l : loops) { + if (l.loopContinue == n) { + nearestLoop = l; + break loopn; + } + } + } + + if ((nearestLoop != null)) {// && (nearestLoop.loopBreak != null)) { + + List finalCommands = printGraph(visited, localData, stack, allParts, null, part, nearestLoop.loopContinue, loops); + nearestLoop.loopContinue = part; + forFinalCommands.put(nearestLoop, finalCommands); + ContinueItem cti = new ContinueItem(null, nearestLoop.id); + ret.add(cti); + //ret.add(new CommentItem("CONTTEST")); + return ret; + } + } + } + } + */ + List loopContinues = getLoopsContinues(loops); + boolean isLoop = false; //part.leadsTo(code, part, loopContinues); + Loop currentLoop = null; + for (Loop el : loops) { + if ((el.loopContinue == part) && (el.phase == 0)) { + currentLoop = el; + currentLoop.phase = 1; + isLoop = true; + break; } + } + /*Loop currentLoop = null; + if (isLoop) { + currentLoop = new Loop(loops.size(), part, null); + loops.add(currentLoop); + loopContinues.add(part); + }*/ - /*while (((part != null) && (part.getHeight() == 1)) && (code.size() > part.start) && (code.get(part.start).isJump())) { //Parts with only jump in it gets ignored - - if (part == stopPart) { - return ret; - } - GraphTargetItem lop = checkLoop(part.nextParts.get(0), stopPart, loops); - if (lop == null) { - part = part.nextParts.get(0); - } else { - break; - } - }*/ - - - - - - if (part == null) { + if (debugMode) { + System.err.println("loopsize:" + loops.size()); + } + for (int l = loops.size() - 1; l >= 0; l--) { + Loop el = loops.get(l); + if (el == currentLoop) { + if (debugMode) { + System.err.println("ignoring current loop " + el); + } + continue; + } + if (el.phase != 1) { + if (debugMode) { + //System.err.println("ignoring loop "+el); + } + continue; + } + if (el.loopBreak == part) { + ret.add(new BreakItem(null, el.id)); return ret; } - part = checkPart(localData, part); - if (part == null) { + if (el.loopPreContinue == part) { + ret.add(new ContinueItem(null, el.id)); return ret; } - - if (part.ignored) { + if (el.loopContinue == part) { + ret.add(new ContinueItem(null, el.id)); return ret; } + } - /* if ((parent != null) && (part.path.length() < parent.path.length())) { - boolean can = true; - for (Loop el : loops) { - if (el.loopContinue == part) { - can = false; - break; - } - if (el.loopBreak == part) { - can = false; - break; - } - if (el.breakCandidates.containsKey(part)) { - can = false; - break; - } - } - if (can) { - if ((part != stopPart) && (part.refs.size() > 1)) { - List nextList = new ArrayList<>(); - populateParts(part, nextList); - Loop nearestLoop = null; - loopn: - for (GraphPart n : nextList) { - for (Loop l : loops) { - if (l.loopContinue == n) { - nearestLoop = l; - break loopn; - } - } - } - if ((nearestLoop != null)) {// && (nearestLoop.loopBreak != null)) { + if (stopPart.contains(part)) { + return ret; + } - List finalCommands = printGraph(visited, localData, stack, allParts, null, part, nearestLoop.loopContinue, loops); - nearestLoop.loopContinue = part; - forFinalCommands.put(nearestLoop, finalCommands); - ContinueItem cti = new ContinueItem(null, nearestLoop.id); - ret.add(cti); - //ret.add(new CommentItem("CONTTEST")); - return ret; - } - } - } - } - */ - List loopContinues = getLoopsContinues(loops); - boolean isLoop = false; //part.leadsTo(code, part, loopContinues); - Loop currentLoop = null; - for (Loop el : loops) { - if ((el.loopContinue == part) && (el.phase == 0)) { - currentLoop = el; - currentLoop.phase = 1; - isLoop = true; - break; + if ((part != null) && (code.size() <= part.start)) { + ret.add(new ScriptEndItem()); + return ret; + } + + if (currentLoop != null) { + currentLoop.used = true; + } + + + List currentRet = ret; + UniversalLoopItem loopItem = null; + if (isLoop) { + loopItem = new UniversalLoopItem(null, currentLoop); + //loopItem.commands=printGraph(visited, localData, stack, allParts, parent, part, stopPart, loops); + currentRet.add(loopItem); + loopItem.commands = new ArrayList<>(); + currentRet = loopItem.commands; + //return ret; + } + + boolean parseNext = true; + + //****************************DECOMPILING PART************* + List output = new ArrayList<>(); + + List parts = new ArrayList<>(); + if (part instanceof GraphPartMulti) { + parts = ((GraphPartMulti) part).parts; + } else { + parts.add(part); + } + int end = part.end; + for (GraphPart p : parts) { + end = p.end; + int start = p.start; + + try { + output.addAll(code.translatePart(p, localData, stack, start, end)); + if ((end >= code.size() - 1) && p.nextParts.isEmpty()) { + output.add(new ScriptEndItem()); } - } - /*Loop currentLoop = null; - if (isLoop) { - currentLoop = new Loop(loops.size(), part, null); - loops.add(currentLoop); - loopContinues.add(part); - }*/ - - - for (int l = loops.size() - 1; l >= 0; l--) { - Loop el = loops.get(l); - if (el == currentLoop) { - continue; - } - if (el.phase != 1) { - continue; - } - if (el.loopBreak == part) { - ret.add(new BreakItem(null, el.id)); - return ret; - } - if (el.loopPreContinue == part) { - ret.add(new ContinueItem(null, el.id)); - return ret; - } - if (el.loopContinue == part) { - ret.add(new ContinueItem(null, el.id)); - return ret; - } - } - - - - if (stopPart.contains(part)) { - return ret; - } - - if ((part != null) && (code.size() <= part.start)) { - ret.add(new ScriptEndItem()); + } catch (Exception ex) { + Logger.getLogger(Graph.class.getName()).log(Level.SEVERE, "error during printgraph", ex); return ret; } + } - if (currentLoop != null) { - currentLoop.used = true; - } + //Assuming part with two nextparts is an IF + /* //If with both branches empty + if (part.nextParts.size() == 2) { + if (part.nextParts.get(0) == part.nextParts.get(1)) { + if (!stack.isEmpty()) { + GraphTargetItem expr = stack.pop(); + if (expr instanceof LogicalOpItem) { + expr = ((LogicalOpItem) expr).invert(); + } else { + expr = new NotItem(null, expr); + } + output.add(new IfItem(null, expr, new ArrayList(), new ArrayList())); + } + part.nextParts.remove(0); + } + }*/ - List currentRet = ret; - UniversalLoopItem loopItem = null; - if (isLoop) { - loopItem = new UniversalLoopItem(null, currentLoop); - //loopItem.commands=printGraph(visited, localData, stack, allParts, parent, part, stopPart, loops); - currentRet.add(loopItem); - loopItem.commands = new ArrayList<>(); - currentRet = loopItem.commands; + /** + * AND / OR detection + */ + if (part.nextParts.size() == 2) { + if ((stack.size() >= 2) && (stack.get(stack.size() - 1) instanceof NotItem) && (((NotItem) (stack.get(stack.size() - 1))).getOriginal().getNotCoerced() == stack.get(stack.size() - 2).getNotCoerced())) { + currentRet.addAll(output); + GraphPart sp0 = getNextNoJump(part.nextParts.get(0)); + GraphPart sp1 = getNextNoJump(part.nextParts.get(1)); + boolean reversed = false; + loopContinues = getLoopsContinues(loops); + loopContinues.add(part);//??? + if (sp1.leadsTo(code, sp0, loops)) { + } else if (sp0.leadsTo(code, sp1, loops)) { + reversed = true; + } + GraphPart next = reversed ? sp0 : sp1; + GraphTargetItem ti; + if ((ti = checkLoop(next, stopPart, loops)) != null) { + currentRet.add(ti); + } else { + List stopPart2 = new ArrayList<>(stopPart); + stopPart2.add(reversed ? sp1 : sp0); + printGraph(visited, localData, stack, allParts, parent, next, stopPart2, loops); + GraphTargetItem second = stack.pop(); + GraphTargetItem first = stack.pop(); + + if (!reversed) { + AndItem a = new AndItem(null, first, second); + stack.push(a); + a.firstPart = part; + if (second instanceof AndItem) { + a.firstPart = ((AndItem) second).firstPart; + } + if (second instanceof OrItem) { + a.firstPart = ((OrItem) second).firstPart; + } + } else { + OrItem o = new OrItem(null, first, second); + stack.push(o); + o.firstPart = part; + if (second instanceof AndItem) { + o.firstPart = ((AndItem) second).firstPart; + } + if (second instanceof OrItem) { + o.firstPart = ((OrItem) second).firstPart; + } + } + next = reversed ? sp1 : sp0; + if ((ti = checkLoop(next, stopPart, loops)) != null) { + currentRet.add(ti); + } else { + currentRet.addAll(printGraph(visited, localData, stack, allParts, parent, next, stopPart, loops)); + } + } + parseNext = false; + //return ret; + } else if ((stack.size() >= 2) && (stack.get(stack.size() - 1).getNotCoerced() == stack.get(stack.size() - 2).getNotCoerced())) { + currentRet.addAll(output); + GraphPart sp0 = getNextNoJump(part.nextParts.get(0)); + GraphPart sp1 = getNextNoJump(part.nextParts.get(1)); + boolean reversed = false; + loopContinues = getLoopsContinues(loops); + loopContinues.add(part);//??? + if (sp1.leadsTo(code, sp0, loops)) { + } else if (sp0.leadsTo(code, sp1, loops)) { + reversed = true; + } + GraphPart next = reversed ? sp0 : sp1; + GraphTargetItem ti; + if ((ti = checkLoop(next, stopPart, loops)) != null) { + currentRet.add(ti); + } else { + List stopPart2 = new ArrayList<>(stopPart); + stopPart2.add(reversed ? sp1 : sp0); + printGraph(visited, localData, stack, allParts, parent, next, stopPart2, loops); + GraphTargetItem second = stack.pop(); + GraphTargetItem first = stack.pop(); + + if (reversed) { + AndItem a = new AndItem(null, first, second); + stack.push(a); + a.firstPart = part; + if (second instanceof AndItem) { + a.firstPart = ((AndItem) second).firstPart; + } + if (second instanceof OrItem) { + a.firstPart = ((AndItem) second).firstPart; + } + } else { + OrItem o = new OrItem(null, first, second); + stack.push(o); + o.firstPart = part; + if (second instanceof OrItem) { + o.firstPart = ((OrItem) second).firstPart; + } + if (second instanceof OrItem) { + o.firstPart = ((OrItem) second).firstPart; + } + } + + next = reversed ? sp1 : sp0; + if ((ti = checkLoop(next, stopPart, loops)) != null) { + currentRet.add(ti); + } else { + currentRet.addAll(printGraph(visited, localData, stack, allParts, parent, next, stopPart, loops)); + } + } + parseNext = false; //return ret; } - - boolean parseNext = true; - - //****************************DECOMPILING PART************* - List output = new ArrayList<>(); - - List parts = new ArrayList<>(); - if (part instanceof GraphPartMulti) { - parts = ((GraphPartMulti) part).parts; - } else { - parts.add(part); - } - int end = part.end; - for (GraphPart p : parts) { - end = p.end; - int start = p.start; - - try { - output.addAll(code.translatePart(p, localData, stack, start, end)); - if ((end >= code.size() - 1) && p.nextParts.isEmpty()) { - output.add(new ScriptEndItem()); - } - } catch (Exception ex) { - Logger.getLogger(Graph.class.getName()).log(Level.SEVERE, "error during printgraph", ex); - return ret; - } - } - - //Assuming part with two nextparts is an IF - - /* //If with both branches empty - if (part.nextParts.size() == 2) { - if (part.nextParts.get(0) == part.nextParts.get(1)) { - if (!stack.isEmpty()) { - GraphTargetItem expr = stack.pop(); - if (expr instanceof LogicalOpItem) { - expr = ((LogicalOpItem) expr).invert(); - } else { - expr = new NotItem(null, expr); - } - output.add(new IfItem(null, expr, new ArrayList(), new ArrayList())); - } - part.nextParts.remove(0); - } - }*/ - - /** - * AND / OR detection - */ - if (part.nextParts.size() == 2) { - if ((stack.size() >= 2) && (stack.get(stack.size() - 1) instanceof NotItem) && (((NotItem) (stack.get(stack.size() - 1))).getOriginal().getNotCoerced() == stack.get(stack.size() - 2).getNotCoerced())) { - currentRet.addAll(output); - GraphPart sp0 = getNextNoJump(part.nextParts.get(0)); - GraphPart sp1 = getNextNoJump(part.nextParts.get(1)); - boolean reversed = false; - loopContinues = getLoopsContinues(loops); - loopContinues.add(part);//??? - if (sp1.leadsTo(code, sp0, loops)) { - } else if (sp0.leadsTo(code, sp1, loops)) { - reversed = true; - } - GraphPart next = reversed ? sp0 : sp1; - GraphTargetItem ti; - if ((ti = checkLoop(next, stopPart, loops)) != null) { - currentRet.add(ti); - } else { - List stopPart2 = new ArrayList<>(stopPart); - stopPart2.add(reversed ? sp1 : sp0); - printGraph(visited, localData, stack, allParts, parent, next, stopPart2, new ArrayList()/*ignore loops*/); - GraphTargetItem second = stack.pop(); - GraphTargetItem first = stack.pop(); - - if (!reversed) { - AndItem a = new AndItem(null, first, second); - stack.push(a); - a.firstPart = part; - if (second instanceof AndItem) { - a.firstPart = ((AndItem) second).firstPart; - } - if (second instanceof OrItem) { - a.firstPart = ((OrItem) second).firstPart; - } - } else { - OrItem o = new OrItem(null, first, second); - stack.push(o); - o.firstPart = part; - if (second instanceof AndItem) { - o.firstPart = ((AndItem) second).firstPart; - } - if (second instanceof OrItem) { - o.firstPart = ((OrItem) second).firstPart; - } - } - next = reversed ? sp1 : sp0; - if ((ti = checkLoop(next, stopPart, loops)) != null) { - currentRet.add(ti); - } else { - currentRet.addAll(printGraph(visited, localData, stack, allParts, parent, next, stopPart, loops)); - } - } - parseNext = false; - //return ret; - } else if ((stack.size() >= 2) && (stack.get(stack.size() - 1).getNotCoerced() == stack.get(stack.size() - 2).getNotCoerced())) { - currentRet.addAll(output); - GraphPart sp0 = getNextNoJump(part.nextParts.get(0)); - GraphPart sp1 = getNextNoJump(part.nextParts.get(1)); - boolean reversed = false; - loopContinues = getLoopsContinues(loops); - loopContinues.add(part);//??? - if (sp1.leadsTo(code, sp0, loops)) { - } else if (sp0.leadsTo(code, sp1, loops)) { - reversed = true; - } - GraphPart next = reversed ? sp0 : sp1; - GraphTargetItem ti; - if ((ti = checkLoop(next, stopPart, loops)) != null) { - currentRet.add(ti); - } else { - List stopPart2 = new ArrayList<>(stopPart); - stopPart2.add(reversed ? sp1 : sp0); - printGraph(visited, localData, stack, allParts, parent, next, stopPart2, new ArrayList()/*ignore loops*/); - GraphTargetItem second = stack.pop(); - GraphTargetItem first = stack.pop(); - - if (reversed) { - AndItem a = new AndItem(null, first, second); - stack.push(a); - a.firstPart = part; - if (second instanceof AndItem) { - a.firstPart = ((AndItem) second).firstPart; - } - if (second instanceof OrItem) { - a.firstPart = ((AndItem) second).firstPart; - } - } else { - OrItem o = new OrItem(null, first, second); - stack.push(o); - o.firstPart = part; - if (second instanceof OrItem) { - o.firstPart = ((OrItem) second).firstPart; - } - if (second instanceof OrItem) { - o.firstPart = ((OrItem) second).firstPart; - } - } - - next = reversed ? sp1 : sp0; - if ((ti = checkLoop(next, stopPart, loops)) != null) { - currentRet.add(ti); - } else { - currentRet.addAll(printGraph(visited, localData, stack, allParts, parent, next, stopPart, loops)); - } - } - parseNext = false; - //return ret; - } - } + } //********************************END PART DECOMPILING - if (parseNext) { - List retCheck = check(code, localData, allParts, stack, parent, part, stopPart, loops, output); - if (retCheck != null) { - if (!retCheck.isEmpty()) { - currentRet.addAll(retCheck); - } - return ret; + if (parseNext) { + List retCheck = check(code, localData, allParts, stack, parent, part, stopPart, loops, output); + if (retCheck != null) { + if (!retCheck.isEmpty()) { + currentRet.addAll(retCheck); + } + return ret; + } else { + currentRet.addAll(output); + } + + if (part.nextParts.size() == 2) { + //List ignore = new ArrayList<>(); + //ignore.addAll(loopContinues); + + /*for (Loop el : loops) { + if (el.loopContinue == next) { + next = null; + break; + } + if (el.loopBreak == next) { + next = null; + break; + } + }*/ + + GraphTargetItem expr = stack.pop(); + if (expr instanceof LogicalOpItem) { + expr = ((LogicalOpItem) expr).invert(); } else { - currentRet.addAll(output); + expr = new NotItem(null, expr); + } + GraphPart next = getNextCommonPart(part, loops);//part.getNextPartPath(loopContinues); //loopContinues); + + @SuppressWarnings("unchecked") + Stack trueStack = (Stack) stack.clone(); + @SuppressWarnings("unchecked") + Stack falseStack = (Stack) stack.clone(); + int trueStackSizeBefore = trueStack.size(); + int falseStackSizeBefore = falseStack.size(); + List onTrue = new ArrayList<>(); + boolean isEmpty = part.nextParts.get(0) == part.nextParts.get(1); + + if (isEmpty) { + next = part.nextParts.get(0); } - if (part.nextParts.size() == 2) { - //List ignore = new ArrayList<>(); - //ignore.addAll(loopContinues); - - /*for (Loop el : loops) { - if (el.loopContinue == next) { - next = null; - break; - } - if (el.loopBreak == next) { - next = null; - break; - } - }*/ - - GraphTargetItem expr = stack.pop(); - if (expr instanceof LogicalOpItem) { - expr = ((LogicalOpItem) expr).invert(); - } else { - expr = new NotItem(null, expr); - } - GraphPart next = getNextCommonPart(part, loops);//part.getNextPartPath(loopContinues); //loopContinues); - - @SuppressWarnings("unchecked") - Stack trueStack = (Stack) stack.clone(); - @SuppressWarnings("unchecked") - Stack falseStack = (Stack) stack.clone(); - int trueStackSizeBefore = trueStack.size(); - int falseStackSizeBefore = falseStack.size(); - List onTrue = new ArrayList<>(); - boolean isEmpty = part.nextParts.get(0) == part.nextParts.get(1); - - if (isEmpty) { - next = part.nextParts.get(0); - } - - List stopPart2 = new ArrayList<>(stopPart); - if (next != null) { - stopPart2.add(next); - } - if (!isEmpty) { - onTrue = printGraph(visited, localData, trueStack, allParts, part, part.nextParts.get(1), stopPart2, loops); - } - List onFalse = new ArrayList<>(); - - if (!isEmpty) { - onFalse = printGraph(visited, localData, falseStack, allParts, part, part.nextParts.get(0), stopPart2, loops); - } - if (isEmpty(onTrue) && isEmpty(onFalse) && (trueStack.size() > trueStackSizeBefore) && (falseStack.size() > falseStackSizeBefore)) { - stack.push(new TernarOpItem(null, expr, trueStack.pop(), falseStack.pop())); - } else { - currentRet.add(new IfItem(null, expr, onTrue, onFalse)); - } - if (next != null) { - printGraph(visited, localData, stack, allParts, part, next, stopPart, loops, currentRet); - //currentRet.addAll(); - } - } else if (part.nextParts.size() == 1) { - - printGraph(visited, localData, stack, allParts, part, part.nextParts.get(0), stopPart, loops, currentRet); + List stopPart2 = new ArrayList<>(stopPart); + if (next != null) { + stopPart2.add(next); } + if (!isEmpty) { + onTrue = printGraph(visited, localData, trueStack, allParts, part, part.nextParts.get(1), stopPart2, loops); + } + List onFalse = new ArrayList<>(); + if (!isEmpty) { + onFalse = printGraph(visited, localData, falseStack, allParts, part, part.nextParts.get(0), stopPart2, loops); + } + if (isEmpty(onTrue) && isEmpty(onFalse) && (trueStack.size() > trueStackSizeBefore) && (falseStack.size() > falseStackSizeBefore)) { + stack.push(new TernarOpItem(null, expr, trueStack.pop(), falseStack.pop())); + } else { + currentRet.add(new IfItem(null, expr, onTrue, onFalse)); + } + if (next != null) { + printGraph(visited, localData, stack, allParts, part, next, stopPart, loops, currentRet); + //currentRet.addAll(); + } + } else if (part.nextParts.size() == 1) { + + printGraph(visited, localData, stack, allParts, part, part.nextParts.get(0), stopPart, loops, currentRet); } - if (isLoop) { - currentLoop.phase = 2; - LoopItem li = loopItem; - boolean loopTypeFound = false; + + } + if (isLoop) { + currentLoop.phase = 2; + LoopItem li = loopItem; + boolean loopTypeFound = false; - checkContinueAtTheEnd(loopItem.commands, currentLoop); + checkContinueAtTheEnd(loopItem.commands, currentLoop); - //Loop with condition at the beginning (While) - if (!loopTypeFound && (!loopItem.commands.isEmpty())) { - if (loopItem.commands.get(0) instanceof IfItem) { - IfItem ifi = (IfItem) loopItem.commands.get(0); - - - List bodyBranch = null; - boolean inverted = false; - if ((ifi.onTrue.size() == 1) && (ifi.onTrue.get(0) instanceof BreakItem)) { - BreakItem bi = (BreakItem) ifi.onTrue.get(0); - if (bi.loopId == currentLoop.id) { - bodyBranch = ifi.onFalse; - inverted = true; - } - } else if ((ifi.onFalse.size() == 1) && (ifi.onFalse.get(0) instanceof BreakItem)) { - BreakItem bi = (BreakItem) ifi.onFalse.get(0); - if (bi.loopId == currentLoop.id) { - bodyBranch = ifi.onTrue; - } + //Loop with condition at the beginning (While) + if (!loopTypeFound && (!loopItem.commands.isEmpty())) { + if (loopItem.commands.get(0) instanceof IfItem) { + IfItem ifi = (IfItem) loopItem.commands.get(0); + + + List bodyBranch = null; + boolean inverted = false; + if ((ifi.onTrue.size() == 1) && (ifi.onTrue.get(0) instanceof BreakItem)) { + BreakItem bi = (BreakItem) ifi.onTrue.get(0); + if (bi.loopId == currentLoop.id) { + bodyBranch = ifi.onFalse; + inverted = true; } - if (bodyBranch != null) { - int index = ret.indexOf(loopItem); - ret.remove(index); - List exprList = new ArrayList<>(); - GraphTargetItem expr = ifi.expression; - if (inverted) { - if (expr instanceof LogicalOpItem) { - expr = ((LogicalOpItem) expr).invert(); - } else { - expr = new NotItem(null, expr); - } - } - exprList.add(expr); - List commands = new ArrayList<>(); - commands.addAll(bodyBranch); - loopItem.commands.remove(0); - commands.addAll(loopItem.commands); - checkContinueAtTheEnd(commands, currentLoop); - List finalComm = new ArrayList<>(); - if (currentLoop.loopPreContinue != null) { - GraphPart backup = currentLoop.loopPreContinue; - currentLoop.loopPreContinue = null; - List stopPart2 = new ArrayList<>(stopPart); - stopPart2.add(currentLoop.loopContinue); - finalComm = printGraph(visited, localData, new Stack(), allParts, null, backup, stopPart2, loops); - currentLoop.loopPreContinue = backup; - checkContinueAtTheEnd(finalComm, currentLoop); - } - if (!finalComm.isEmpty()) { - ret.add(index, li = new ForTreeItem(null, currentLoop, new ArrayList(), exprList.get(exprList.size() - 1), finalComm, commands)); - } else { - ret.add(index, li = new WhileItem(null, currentLoop, exprList, commands)); - } - - loopTypeFound = true; + } else if ((ifi.onFalse.size() == 1) && (ifi.onFalse.get(0) instanceof BreakItem)) { + BreakItem bi = (BreakItem) ifi.onFalse.get(0); + if (bi.loopId == currentLoop.id) { + bodyBranch = ifi.onTrue; } } - } - - - //Loop with condition at the end (Do..While) - if (!loopTypeFound && (!loopItem.commands.isEmpty())) { - if (loopItem.commands.get(loopItem.commands.size() - 1) instanceof IfItem) { - IfItem ifi = (IfItem) loopItem.commands.get(loopItem.commands.size() - 1); - List bodyBranch = null; - boolean inverted = false; - if ((ifi.onTrue.size() == 1) && (ifi.onTrue.get(0) instanceof BreakItem)) { - BreakItem bi = (BreakItem) ifi.onTrue.get(0); - if (bi.loopId == currentLoop.id) { - bodyBranch = ifi.onFalse; - inverted = true; - } - } else if ((ifi.onFalse.size() == 1) && (ifi.onFalse.get(0) instanceof BreakItem)) { - BreakItem bi = (BreakItem) ifi.onFalse.get(0); - if (bi.loopId == currentLoop.id) { - bodyBranch = ifi.onTrue; - } - } - if (bodyBranch != null) { - //Condition at the beginning - int index = ret.indexOf(loopItem); - ret.remove(index); - List exprList = new ArrayList<>(); - GraphTargetItem expr = ifi.expression; - if (inverted) { - if (expr instanceof LogicalOpItem) { - expr = ((LogicalOpItem) expr).invert(); - } else { - expr = new NotItem(null, expr); - } - } - - checkContinueAtTheEnd(bodyBranch, currentLoop); - - - List commands = new ArrayList<>(); - loopItem.commands.remove(loopItem.commands.size() - 1); - if (!bodyBranch.isEmpty()) { - /*exprList.addAll(loopItem.commands); - commands.addAll(bodyBranch); - exprList.add(expr); - checkContinueAtTheEnd(commands, currentLoop); - ret.add(index, li = new WhileItem(null, currentLoop, exprList, commands));*/ + if (bodyBranch != null) { + int index = ret.indexOf(loopItem); + ret.remove(index); + List exprList = new ArrayList<>(); + GraphTargetItem expr = ifi.expression; + if (inverted) { + if (expr instanceof LogicalOpItem) { + expr = ((LogicalOpItem) expr).invert(); } else { - commands.addAll(loopItem.commands); - commands.addAll(bodyBranch); - exprList.add(expr); - checkContinueAtTheEnd(commands, currentLoop); - ret.add(index, li = new DoWhileItem(null, currentLoop, commands, exprList)); - + expr = new NotItem(null, expr); } - loopTypeFound = true; } - } - } - - if (!loopTypeFound) { - if (currentLoop.loopPreContinue != null) { - loopTypeFound = true; - GraphPart backup = currentLoop.loopPreContinue; - currentLoop.loopPreContinue = null; - List stopPart2 = new ArrayList<>(stopPart); - stopPart2.add(currentLoop.loopContinue); - List finalComm = printGraph(visited, localData, new Stack(), allParts, null, backup, stopPart2, loops); - currentLoop.loopPreContinue = backup; - checkContinueAtTheEnd(finalComm, currentLoop); - + exprList.add(expr); + List commands = new ArrayList<>(); + commands.addAll(bodyBranch); + loopItem.commands.remove(0); + commands.addAll(loopItem.commands); + checkContinueAtTheEnd(commands, currentLoop); + List finalComm = new ArrayList<>(); + if (currentLoop.loopPreContinue != null) { + GraphPart backup = currentLoop.loopPreContinue; + currentLoop.loopPreContinue = null; + List stopPart2 = new ArrayList<>(stopPart); + stopPart2.add(currentLoop.loopContinue); + finalComm = printGraph(visited, localData, new Stack(), allParts, null, backup, stopPart2, loops); + currentLoop.loopPreContinue = backup; + checkContinueAtTheEnd(finalComm, currentLoop); + } if (!finalComm.isEmpty()) { - if (finalComm.get(finalComm.size() - 1) instanceof IfItem) { - IfItem ifi = (IfItem) finalComm.get(finalComm.size() - 1); - boolean ok = false; - boolean invert = false; - if (((ifi.onTrue.size() == 1) && (ifi.onTrue.get(0) instanceof BreakItem) && (((BreakItem) ifi.onTrue.get(0)).loopId == currentLoop.id)) - && ((ifi.onTrue.size() == 1) && (ifi.onFalse.get(0) instanceof ContinueItem) && (((ContinueItem) ifi.onFalse.get(0)).loopId == currentLoop.id))) { - ok = true; - invert = true; - } - if (((ifi.onTrue.size() == 1) && (ifi.onTrue.get(0) instanceof ContinueItem) && (((ContinueItem) ifi.onTrue.get(0)).loopId == currentLoop.id)) - && ((ifi.onTrue.size() == 1) && (ifi.onFalse.get(0) instanceof BreakItem) && (((BreakItem) ifi.onFalse.get(0)).loopId == currentLoop.id))) { - ok = true; - } - if (ok) { - finalComm.remove(finalComm.size() - 1); - int index = ret.indexOf(loopItem); - ret.remove(index); - List exprList = new ArrayList<>(finalComm); - GraphTargetItem expr = ifi.expression; - if (invert) { - if (expr instanceof LogicalOpItem) { - expr = ((LogicalOpItem) expr).invert(); - } else { - expr = new NotItem(null, expr); - } + ret.add(index, li = new ForTreeItem(null, currentLoop, new ArrayList(), exprList.get(exprList.size() - 1), finalComm, commands)); + } else { + ret.add(index, li = new WhileItem(null, currentLoop, exprList, commands)); + } + + loopTypeFound = true; + } + } + } + + + //Loop with condition at the end (Do..While) + if (!loopTypeFound && (!loopItem.commands.isEmpty())) { + if (loopItem.commands.get(loopItem.commands.size() - 1) instanceof IfItem) { + IfItem ifi = (IfItem) loopItem.commands.get(loopItem.commands.size() - 1); + List bodyBranch = null; + boolean inverted = false; + if ((ifi.onTrue.size() == 1) && (ifi.onTrue.get(0) instanceof BreakItem)) { + BreakItem bi = (BreakItem) ifi.onTrue.get(0); + if (bi.loopId == currentLoop.id) { + bodyBranch = ifi.onFalse; + inverted = true; + } + } else if ((ifi.onFalse.size() == 1) && (ifi.onFalse.get(0) instanceof BreakItem)) { + BreakItem bi = (BreakItem) ifi.onFalse.get(0); + if (bi.loopId == currentLoop.id) { + bodyBranch = ifi.onTrue; + } + } + if (bodyBranch != null) { + //Condition at the beginning + int index = ret.indexOf(loopItem); + ret.remove(index); + List exprList = new ArrayList<>(); + GraphTargetItem expr = ifi.expression; + if (inverted) { + if (expr instanceof LogicalOpItem) { + expr = ((LogicalOpItem) expr).invert(); + } else { + expr = new NotItem(null, expr); + } + } + + checkContinueAtTheEnd(bodyBranch, currentLoop); + + + List commands = new ArrayList<>(); + loopItem.commands.remove(loopItem.commands.size() - 1); + if (!bodyBranch.isEmpty()) { + /*exprList.addAll(loopItem.commands); + commands.addAll(bodyBranch); + exprList.add(expr); + checkContinueAtTheEnd(commands, currentLoop); + ret.add(index, li = new WhileItem(null, currentLoop, exprList, commands));*/ + } else { + commands.addAll(loopItem.commands); + commands.addAll(bodyBranch); + exprList.add(expr); + checkContinueAtTheEnd(commands, currentLoop); + ret.add(index, li = new DoWhileItem(null, currentLoop, commands, exprList)); + + } + loopTypeFound = true; + } + } + } + + if (!loopTypeFound) { + if (currentLoop.loopPreContinue != null) { + loopTypeFound = true; + GraphPart backup = currentLoop.loopPreContinue; + currentLoop.loopPreContinue = null; + List stopPart2 = new ArrayList<>(stopPart); + stopPart2.add(currentLoop.loopContinue); + List finalComm = printGraph(visited, localData, new Stack(), allParts, null, backup, stopPart2, loops); + currentLoop.loopPreContinue = backup; + checkContinueAtTheEnd(finalComm, currentLoop); + + if (!finalComm.isEmpty()) { + if (finalComm.get(finalComm.size() - 1) instanceof IfItem) { + IfItem ifi = (IfItem) finalComm.get(finalComm.size() - 1); + boolean ok = false; + boolean invert = false; + if (((ifi.onTrue.size() == 1) && (ifi.onTrue.get(0) instanceof BreakItem) && (((BreakItem) ifi.onTrue.get(0)).loopId == currentLoop.id)) + && ((ifi.onTrue.size() == 1) && (ifi.onFalse.get(0) instanceof ContinueItem) && (((ContinueItem) ifi.onFalse.get(0)).loopId == currentLoop.id))) { + ok = true; + invert = true; + } + if (((ifi.onTrue.size() == 1) && (ifi.onTrue.get(0) instanceof ContinueItem) && (((ContinueItem) ifi.onTrue.get(0)).loopId == currentLoop.id)) + && ((ifi.onTrue.size() == 1) && (ifi.onFalse.get(0) instanceof BreakItem) && (((BreakItem) ifi.onFalse.get(0)).loopId == currentLoop.id))) { + ok = true; + } + if (ok) { + finalComm.remove(finalComm.size() - 1); + int index = ret.indexOf(loopItem); + ret.remove(index); + List exprList = new ArrayList<>(finalComm); + GraphTargetItem expr = ifi.expression; + if (invert) { + if (expr instanceof LogicalOpItem) { + expr = ((LogicalOpItem) expr).invert(); + } else { + expr = new NotItem(null, expr); } - exprList.add(expr); - ret.add(index, li = new DoWhileItem(null, currentLoop, loopItem.commands, exprList)); } + exprList.add(expr); + ret.add(index, li = new DoWhileItem(null, currentLoop, loopItem.commands, exprList)); } } } } + } - if (!loopTypeFound) { - checkContinueAtTheEnd(loopItem.commands, currentLoop); - } + if (!loopTypeFound) { + checkContinueAtTheEnd(loopItem.commands, currentLoop); + } - GraphTargetItem replaced = checkLoop(li, localData, loops); - if (replaced != li) { - int index = ret.indexOf(li); - ret.remove(index); - if (replaced != null) { - ret.add(index, replaced); - } - } - - //loops.remove(currentLoop); - if (currentLoop.loopBreak != null) { - ret.addAll(printGraph(visited, localData, stack, allParts, part, currentLoop.loopBreak, stopPart, loops)); + GraphTargetItem replaced = checkLoop(li, localData, loops); + if (replaced != li) { + int index = ret.indexOf(li); + ret.remove(index); + if (replaced != null) { + ret.add(index, replaced); } } - return ret; - + //loops.remove(currentLoop); + if (currentLoop.loopBreak != null) { + ret.addAll(printGraph(visited, localData, stack, allParts, part, currentLoop.loopBreak, stopPart, loops)); + } + } + + return ret; + } private List makeGraph(GraphSource code, List allBlocks, List alternateEntries) { @@ -1659,27 +1687,11 @@ public class Graph { } return ret; } - - private List makeCFG(GraphSource code, List allBlocks, List alternateEntries) { - HashMap> refs = code.visitCode(alternateEntries); - List ret = new ArrayList<>(); - boolean visited[] = new boolean[code.size()]; - ret.add(makeCFG(null, new GraphPath(), code, 0, 0, allBlocks, refs, visited)); - for (int pos : alternateEntries) { - BasicBlock e1 = new BasicBlock(); - e1.startAddress=-1; - e1.endAddress=-1; - //e1.path = new GraphPath("e"); - ret.add(makeCFG(e1, new GraphPath("e"), code, pos, pos, allBlocks, refs, visited)); - } - return ret; - } protected int checkIp(int ip) { return ip; } - private GraphPart makeGraph(GraphPart parent, GraphPath path, GraphSource code, int startip, int lastIp, List allBlocks, HashMap> refs, boolean visited2[]) { int ip = startip; @@ -1783,127 +1795,6 @@ public class Graph { } return ret; } - - private BasicBlock makeCFG(BasicBlock parent, GraphPath path, GraphSource code, int startip, int lastIp, List allBlocks, HashMap> refs, boolean visited2[]) { - - int ip = startip; - for (BasicBlock p : allBlocks) { - if (p.startAddress == ip) { - p.addInEdge(parent); - return p; - } - } - BasicBlock g; - BasicBlock ret = new BasicBlock(); - ret.startAddress=ip; - ret.endAddress=-1; - //ret.path = path; - BasicBlock part = ret; - while (ip < code.size()) { - if (visited2[ip] || ((ip != startip) && (refs.get(ip).size() > 1))) { - part.endAddress = lastIp; - BasicBlock found = null; - for (BasicBlock p : allBlocks) { - if (p.startAddress == ip) { - found = p; - break; - } - } - - allBlocks.add(part); - - if (found != null) { - part.addOutEdge(found); - found.addInEdge(part); - break; - } else { - BasicBlock gp = new BasicBlock(); - gp.startAddress=ip; - gp.endAddress=-1; - //gp.path = path; - part.addOutEdge(gp); - gp.addInEdge(part); - part = gp; - } - } - - ip = checkIp(ip); - lastIp = ip; - GraphSourceItem ins = code.get(ip); - if (ins.isIgnored()) { - ip++; - continue; - } - if (ins instanceof GraphSourceItemContainer) { - GraphSourceItemContainer cnt = (GraphSourceItemContainer) ins; - if (ins instanceof Action) { //TODO: Remove dependency of AVM1 - long endAddr = ((Action) ins).getAddress() + cnt.getHeaderSize(); - for (long size : cnt.getContainerSizes()) { - endAddr += size; - } - ip = code.adr2pos(endAddr); - } - continue; - } else if (ins.isExit()) { - part.endAddress = ip; - allBlocks.add(part); - part.setType(BBType.RET); - break; - } else if (ins.isJump()) { - part.endAddress = ip; - allBlocks.add(part); - part.setType(BBType.ONEWAY); - ip = ins.getBranches(code).get(0); - part.addOutEdge(g = makeCFG(part, path, code, ip, lastIp, allBlocks, refs, visited2)); - g.addInEdge(part); - - break; - } else if (ins.isBranch()) { - part.endAddress = ip; - - - allBlocks.add(part); - List branches = ins.getBranches(code); - if(branches.size()==2){ - part.setType(BBType.TWOWAY); - }else{ - part.setType(BBType.NWAY); - } - for (int i = 0; i < branches.size(); i++) { - part.addOutEdge(g = makeCFG(part, path.sub(i, ip), code, branches.get(i), ip, allBlocks, refs, visited2)); - g.addInEdge(part); - } - break; - } - ip++; - } - if ((part.endAddress == -1) && (ip >= code.size())) { - if (part.startAddress == code.size()) { - part.endAddress = code.size(); - part.setType(BBType.RET); - allBlocks.add(part); - } else { - part.endAddress = ip - 1; - for (BasicBlock p : allBlocks) { - if (p.startAddress == ip) { - p.addInEdge(part); - part.addOutEdge(p); - allBlocks.add(part); - return ret; - } - } - part.setType(BBType.RET); - BasicBlock gp = new BasicBlock(); - gp.startAddress=ip; - gp.endAddress=ip; - allBlocks.add(gp); - gp.addInEdge(part); - part.addOutEdge(gp); - allBlocks.add(part); - } - } - return ret; - } /** * String used to indent line when converting to string */ @@ -1931,12 +1822,8 @@ public class Graph { public static String graphToString(List tree, Object... localData) { StringBuilder ret = new StringBuilder(); List localDataList = new ArrayList<>(); - if((localData.length==1)&&(localData[0] instanceof List)){ - localDataList=(List)localData[0]; - }else{ - for (Object o : localData) { - localDataList.add(o); - } + for (Object o : localData) { + localDataList.add(o); } for (GraphTargetItem ti : tree) { if (!ti.isEmpty()) { @@ -2034,5 +1921,4 @@ public class Graph { public List prepareBranchLocalData(List localData) { return localData; } - } diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/GraphPart.java b/trunk/src/com/jpexs/decompiler/flash/graph/GraphPart.java index 4848ff630..9d9d99acd 100644 --- a/trunk/src/com/jpexs/decompiler/flash/graph/GraphPart.java +++ b/trunk/src/com/jpexs/decompiler/flash/graph/GraphPart.java @@ -36,46 +36,44 @@ public class GraphPart { public boolean ignored = false; public List forContinues = new ArrayList<>(); public int level; - public int discoveredTime; public int finishedTime; public int order; - - - public int setTime(int time,List ordered,List visited){ + + public int setTime(int time, List ordered, List visited) { discoveredTime = time; visited.add(this); - for(GraphPart next:nextParts){ - if(!visited.contains(next)){ - time=next.setTime(time+1, ordered, visited); + for (GraphPart next : nextParts) { + if (!visited.contains(next)) { + time = next.setTime(time + 1, ordered, visited); } } time++; finishedTime = time; - order=ordered.size(); - ordered.add(this); + order = ordered.size(); + ordered.add(this); return time; } - + private boolean leadsTo(GraphSource code, GraphPart part, List visited, List loops) { - Loop currentLoop=null; - for(Loop l:loops){ + Loop currentLoop = null; + for (Loop l : loops) { /*if(l.phase==0){ - if(l.loopContinue==this){ - l.leadsToMark = 1; - next = l.loopBreak; - currentLoop = l; - continue; - } - }*/ - if(l.phase==1){ - if(l.loopContinue==this){ + if(l.loopContinue==this){ + l.leadsToMark = 1; + next = l.loopBreak; + currentLoop = l; + continue; + } + }*/ + if (l.phase == 1) { + if (l.loopContinue == this) { return false; } - if(l.loopPreContinue==this){ + if (l.loopPreContinue == this) { return false; } - if(l.loopBreak==this){ + if (l.loopBreak == this) { return false; } } @@ -84,8 +82,8 @@ public class GraphPart { return false; } /*if (loops.contains(this)) { - return false; - }*/ + return false; + }*/ visited.add(this); if (end < code.size() && code.get(end).isBranch() && (code.get(end).ignoredLoops())) { return false; @@ -103,7 +101,7 @@ public class GraphPart { } public boolean leadsTo(GraphSource code, GraphPart part, List loops) { - for(Loop l:loops){ + for (Loop l : loops) { l.leadsToMark = 0; } return leadsTo(code, part, new ArrayList(), loops); diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/Loop.java b/trunk/src/com/jpexs/decompiler/flash/graph/Loop.java index 047784e39..35e09c125 100644 --- a/trunk/src/com/jpexs/decompiler/flash/graph/Loop.java +++ b/trunk/src/com/jpexs/decompiler/flash/graph/Loop.java @@ -44,6 +44,6 @@ public class Loop { @Override public String toString() { - return "loop(id:" + id + (loopPreContinue != null ? ",precontinue:" + loopPreContinue : "") + ",continue:" + loopContinue + ", break:" + loopBreak + ", phase:"+phase+")"; + return "loop(id:" + id + (loopPreContinue != null ? ",precontinue:" + loopPreContinue : "") + ",continue:" + loopContinue + ", break:" + loopBreak + ", phase:" + phase + ")"; } } diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/BBType.java b/trunk/src/com/jpexs/decompiler/flash/graph/cfg/BBType.java deleted file mode 100644 index ba5626b74..000000000 --- a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/BBType.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2013 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.graph.cfg; - -/** - * Adapted from Boomerang, basicblock.h Copyright (C) 1997-2000, The University - * of Queensland Copyright (C) 2000-2001, Sun Microsystems, Inc Copyright (C) - * 2002, Trent Waddington - */ -/** - * - * @author JPEXS - */ -public enum BBType { - - ONEWAY, // unconditional branch - TWOWAY, // conditional branch - NWAY, // case branch - CALL, // procedure call - RET, // return - FALL, // fall-through node - COMPJUMP, // computed jump - COMPCALL, // computed call - INVALID // invalid instruction -} diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/BasicBlock.java b/trunk/src/com/jpexs/decompiler/flash/graph/cfg/BasicBlock.java deleted file mode 100644 index c33f361aa..000000000 --- a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/BasicBlock.java +++ /dev/null @@ -1,577 +0,0 @@ -/* - * Copyright (C) 2013 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -/** - * Adapted from Boomerang, basicblock.cpp - * Copyright (C) 1997-2000, The University of Queensland - * Copyright (C) 2000-2001, Sun Microsystems, Inc - * Copyright (C) 2002, Trent Waddington - */ -package com.jpexs.decompiler.flash.graph.cfg; - -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class BasicBlock { - - public int m_DFTfirst; // depth-first traversal first visit - public int m_DFTlast; // depth-first traversal last visit - public int m_DFTrevfirst; // reverse depth-first traversal first visit - public int m_DFTrevlast; // reverse depth-first traversal last visit - - /* high level structuring */ - public SBBType m_structType; // structured type of this node - public SBBType m_loopCondType; // type of conditional to treat this loop header as (if any) - public BasicBlock m_loopHead; // head of the most nested enclosing loop - public BasicBlock m_caseHead; // head of the most nested enclosing case - public BasicBlock m_condFollow; // follow of a conditional header - public BasicBlock m_loopFollow; // follow of a loop header - public BasicBlock m_latchNode; // latch node of a loop header - //protected: - /* general basic block information */ - public BBType m_nodeType; // type of basic block - //std::list* m_pRtls; // Ptr to list of RTLs - public int m_iLabelNum; // Nonzero if start of BB needs label - public String m_labelStr; // string label of this bb. - public boolean m_labelneeded; - public boolean m_bIncomplete; // True if not yet complete - public boolean m_bJumpReqd; // True if jump required for "fall through" - - /* in-edges and out-edges */ - public List m_InEdges = new ArrayList<>(); // Vector of in-edges - public List m_OutEdges = new ArrayList<>();// Vector of out-edges - public int m_iNumInEdges; // We need these two because GCC doesn't - public int m_iNumOutEdges; // support resize() of vectors! - - /* for traversal */ - public boolean m_iTraversed; // traversal marker - - /* Liveness */ - //LocationSet liveIn; // Set of locations live at BB start - //protected: - /* Control flow analysis stuff, lifted from Doug Simon's honours thesis. - */ - public int ord; // node's position within the ordering structure - public int revOrd; // position within ordering structure for the reverse graph - public int inEdgesVisited; // counts the number of in edges visited during a DFS - public int numForwardInEdges; // inedges to this node that aren't back edges - public int loopStamps[] = new int[2]; - public int revLoopStamps[] = new int[2]; // used for structuring analysis - public TravType traversed; // traversal flag for the numerous DFS's - public boolean hllLabel; // emit a label for this node when generating HL code? - public String labelStr; // the high level label for this node (if needed) - public int indentLevel; // the indentation level of this node in the final code - // analysis information - public BasicBlock immPDom; // immediate post dominator - public BasicBlock loopHead; // head of the most nested enclosing loop - public BasicBlock condFollow; // follow of a conditional header - public BasicBlock loopFollow; // follow of a loop header - public BasicBlock latchNode; // latching node of a loop header - // Structured type of the node - public StructType sType; // the structuring class (Loop, Cond , etc) - public UnStructType usType; // the restructured type of a conditional header - public LoopType lType; // the loop type of a loop header - public CondType cType; // the conditional type of a conditional header - // true if processing for overlapped registers on statements in this BB - // has been completed. - public int startAddress; - public int endAddress; - public static final int BTHEN = 0; - public static final int BELSE = 1; - - public BasicBlock() { - m_DFTfirst = 0; - m_DFTlast = 0; - m_structType = SBBType.NONE; - m_loopCondType = SBBType.NONE; - m_loopHead = null; - m_caseHead = null; - m_condFollow = null; - m_loopFollow = null; - m_latchNode = null; - m_nodeType = BBType.INVALID; - //m_pRtls=null; - m_iLabelNum = 0; - m_labelneeded = false; - m_bIncomplete = true; - m_bJumpReqd = false; - m_iNumInEdges = 0; - m_iNumOutEdges = 0; - m_iTraversed = false; - // From Doug's code - ord = -1; - revOrd = -1; - inEdgesVisited = 0; - numForwardInEdges = -1; - traversed = TravType.UNTRAVERSED; - hllLabel = false; - indentLevel = 0; - immPDom = null; - loopHead = null; - condFollow = null; - loopFollow = null; - latchNode = null; - sType = StructType.Seq; - usType = UnStructType.Structured; - // Others - } - - public BasicBlock(BasicBlock bb) { - m_DFTfirst = 0; - m_DFTlast = 0; - m_structType = bb.m_structType; - m_loopCondType = bb.m_loopCondType; - m_loopHead = bb.m_loopHead; - m_caseHead = bb.m_caseHead; - m_condFollow = bb.m_condFollow; - m_loopFollow = bb.m_loopFollow; - m_latchNode = bb.m_latchNode; - m_nodeType = bb.m_nodeType; - //m_pRtls=null; - m_iLabelNum = bb.m_iLabelNum; - m_labelneeded = false; - m_bIncomplete = bb.m_bIncomplete; - m_bJumpReqd = bb.m_bJumpReqd; - m_InEdges = bb.m_InEdges; - m_OutEdges = bb.m_OutEdges; - m_iNumInEdges = bb.m_iNumInEdges; - m_iNumOutEdges = bb.m_iNumOutEdges; - m_iTraversed = false; -// From Doug's code - ord = bb.ord; - revOrd = bb.revOrd; - inEdgesVisited = bb.inEdgesVisited; - numForwardInEdges = bb.numForwardInEdges; - traversed = (bb.traversed); - hllLabel = (bb.hllLabel); - indentLevel = (bb.indentLevel); - immPDom = (bb.immPDom); - loopHead = (bb.loopHead); - condFollow = (bb.condFollow); - loopFollow = (bb.loopFollow); - latchNode = (bb.latchNode); - sType = (bb.sType); - usType = (bb.usType); - - //setRTLs(bb.m_pRtls); - } - - public int getLabel() { - return m_iLabelNum; - } - - public boolean isTraversed() { - return m_iTraversed; - } - - public void setTraversed(boolean bTraversed) { - m_iTraversed = bTraversed; - } - - public BBType getType() { - return m_nodeType; - } - - public void updateType(BBType bbType, int iNumOutEdges) { - m_nodeType = bbType; - m_iNumOutEdges = iNumOutEdges; - } - - public void setJumpReqd() { - m_bJumpReqd = true; - } - - public boolean isJumpReqd() { - return m_bJumpReqd; - } - - public boolean isBackEdge(int inEdge) { - BasicBlock in = m_InEdges.get(inEdge); - return this == in || (m_DFTfirst < in.m_DFTfirst && m_DFTlast > in.m_DFTlast); - } - - public List getInEdges() { - return m_InEdges; - } - - public List getOutEdges() { - return m_OutEdges; - } - - public void setInEdge(int i, BasicBlock pNewInEdge) { - m_InEdges.set(i, pNewInEdge); - } - - public void setOutEdge(int i, BasicBlock pNewOutEdge) { - if (m_OutEdges.isEmpty()) { - assert (i == 0); - m_OutEdges.add(pNewOutEdge); - } else { - assert (i < (int) m_OutEdges.size()); - m_OutEdges.set(i, pNewOutEdge); - } - } - - public BasicBlock getOutEdge(int i) { - if (i < m_OutEdges.size()) { - return m_OutEdges.get(i); - } else { - return null; - } - } - - public int getLowAddr() { - return startAddress; - } - - public int getHiAddr() { - return endAddress; - } - - BasicBlock getCorrectOutEdge(int a) { - for (BasicBlock b : m_OutEdges) { - if (b.getLowAddr() == a) { - return b; - } - } - return null; - } - - public void addInEdge(BasicBlock pNewInEdge) { - m_InEdges.add(pNewInEdge); - m_iNumInEdges++; - } - - public void addOutEdge(BasicBlock pNewOutEdge) { - m_OutEdges.add(pNewOutEdge); - m_iNumOutEdges++; - } - - public void deleteInEdge(List blocks) { - m_InEdges.removeAll(blocks); - m_iNumInEdges--; - } - - public void deleteInEdge(BasicBlock edge) { - if (m_InEdges.contains(edge)) { - m_InEdges.remove(edge); - m_iNumInEdges--; - } - } - - public void deleteEdge(BasicBlock edge) { - edge.deleteInEdge(this); - if (m_OutEdges.contains(edge)) { - m_OutEdges.remove(edge); - m_iNumOutEdges--; - } - } - - public int DFTOrder(RefInt first, RefInt last) { - first.value++; - m_DFTfirst = first.value; - - int numTraversed = 1; - m_iTraversed = true; - - for (BasicBlock child : m_OutEdges) { - if (child.m_iTraversed == false) { - numTraversed = numTraversed + child.DFTOrder(first, last); - } - } - - last.value++; - m_DFTlast = last.value; - - return numTraversed; - } - - public int RevDFTOrder(RefInt first, RefInt last) { - first.value++; - m_DFTrevfirst = first.value; - - int numTraversed = 1; - m_iTraversed = true; - - for (BasicBlock parent : m_InEdges) { - if (parent.m_iTraversed == false) { - numTraversed = numTraversed + parent.RevDFTOrder(first, last); - } - } - - last.value++; - m_DFTrevlast = last.value; - - return numTraversed; - } - - public boolean lessAddress(BasicBlock bb1, BasicBlock bb2) { - return bb1.getLowAddr() < bb2.getLowAddr(); - } - - public boolean lessFirstDFT(BasicBlock bb1, BasicBlock bb2) { - return bb1.m_DFTfirst < bb2.m_DFTfirst; - } - - public boolean lessLastDFT(BasicBlock bb1, BasicBlock bb2) { - return bb1.m_DFTlast < bb2.m_DFTlast; - } - //getCallDest() - //getCallDestProc() - - BasicBlock getLoopBody() { - assert (m_structType == SBBType.PRETESTLOOP || m_structType == SBBType.POSTTESTLOOP || m_structType == SBBType.ENDLESSLOOP); - assert (m_iNumOutEdges == 2); - if (m_OutEdges.get(0) != m_loopFollow) { - return m_OutEdges.get(0); - } - return m_OutEdges.get(1); - } - - public boolean isAncestorOf(BasicBlock other) { - return ((loopStamps[0] < other.loopStamps[0] - && loopStamps[1] > other.loopStamps[1]) - || (revLoopStamps[0] < other.revLoopStamps[0] - && revLoopStamps[1] > other.revLoopStamps[1])); - } - - public boolean hasBackEdgeTo(BasicBlock dest) { -// assert(HasEdgeTo(dest) || dest == this); - return dest == this || dest.isAncestorOf(this); - } - - // had its code generated - public boolean allParentsGenerated() { - for (int i = 0; i < m_InEdges.size(); i++) { - if (!m_InEdges.get(i).hasBackEdgeTo(this) - && m_InEdges.get(i).traversed != TravType.DFS_CODEGEN) { - return false; - } - } - return true; - } - //emitGotoAndLabel - - public void setLoopStamps(RefInt time, List order) { - // timestamp the current node with the current time and set its traversed - // flag - traversed = TravType.DFS_LNUM; - loopStamps[0] = time.value; - - // recurse on unvisited children and set inedges for all children - for (int i = 0; i < m_OutEdges.size(); i++) { - // set the in edge from this child to its parent (the current node) - // (not done here, might be a problem) - // outEdges[i].inEdges.Add(this); - - // recurse on this child if it hasn't already been visited - if (m_OutEdges.get(i).traversed != TravType.DFS_LNUM) { - time.value++; - m_OutEdges.get(i).setLoopStamps(time, order); - } - } - - // set the the second loopStamp value - time.value++; - loopStamps[1] = time.value; - - // add this node to the ordering structure as well as recording its position within the ordering - ord = order.size(); - order.add(this); - } - - public void setRevLoopStamps(RefInt time) { - // timestamp the current node with the current time and set its traversed flag - traversed = TravType.DFS_RNUM; - revLoopStamps[0] = time.value; - - // recurse on the unvisited children in reverse order - for (int i = m_OutEdges.size() - 1; i >= 0; i--) { - // recurse on this child if it hasn't already been visited - if (m_OutEdges.get(i).traversed != TravType.DFS_RNUM) { - time.value++; - m_OutEdges.get(i).setRevLoopStamps(time); - } - } - - // set the the second loopStamp value - time.value++; - revLoopStamps[1] = time.value; - } - - public void setRevOrder(List order) { - // Set this node as having been traversed during the post domimator DFS ordering traversal - traversed = TravType.DFS_PDOM; - - // recurse on unvisited children - for (int i = 0; i < m_InEdges.size(); i++) { - if (m_InEdges.get(i).traversed != TravType.DFS_PDOM) { - m_InEdges.get(i).setRevOrder(order); - } - } - - // add this node to the ordering structure and record the post dom. order of this node as its index within this - // ordering structure - revOrd = order.size(); - order.add(this); - } - - //setCaseHead - public void setStructType(StructType s) { - // if this is a conditional header, determine exactly which type of conditional header it is (i.e. switch, if-then, - // if-then-else etc.) - if (s == StructType.Cond) { - if (getType() == BBType.NWAY) { - cType = CondType.Case; - } else if (m_OutEdges.get(BELSE) == condFollow) { - cType = CondType.IfThen; - } else if (m_OutEdges.get(BTHEN) == condFollow) { - cType = CondType.IfElse; - } else { - cType = CondType.IfThenElse; - } - } - - sType = s; - } - - public void setUnstructType(UnStructType us) { - assert ((sType == StructType.Cond || sType == StructType.LoopCond) && cType != CondType.Case); - usType = us; - } - - public UnStructType getUnstructType() { - assert ((sType == StructType.Cond || sType == StructType.LoopCond) && cType != CondType.Case); - return usType; - } - - public void setLoopType(LoopType l) { - assert (sType == StructType.Loop || sType == StructType.LoopCond); - lType = l; - - // set the structured class (back to) just Loop if the loop type is PreTested OR it's PostTested and is a single - // block loop - if (lType == LoopType.PreTested || (lType == LoopType.PostTested && this == latchNode)) { - sType = StructType.Loop; - } - } - - public LoopType getLoopType() { - assert (sType == StructType.Loop || sType == StructType.LoopCond); - return lType; - } - - public void setCondType(CondType c) { - assert (sType == StructType.Cond || sType == StructType.LoopCond); - cType = c; - } - - public CondType getCondType() { - assert (sType == StructType.Cond || sType == StructType.LoopCond); - return cType; - } - - public boolean inLoop(BasicBlock header, BasicBlock latch) { - assert (header.latchNode == latch); - assert (header == latch - || ((header.loopStamps[0] > latch.loopStamps[0] && latch.loopStamps[1] > header.loopStamps[1]) - || (header.loopStamps[0] < latch.loopStamps[0] && latch.loopStamps[1] < header.loopStamps[1]))); - // this node is in the loop if it is the latch node OR - // this node is within the header and the latch is within this when using the forward loop stamps OR - // this node is within the header and the latch is within this when using the reverse loop stamps - return this == latch - || (header.loopStamps[0] < loopStamps[0] && loopStamps[1] < header.loopStamps[1] - && loopStamps[0] < latch.loopStamps[0] && latch.loopStamps[1] < loopStamps[1]) - || (header.revLoopStamps[0] < revLoopStamps[0] && revLoopStamps[1] < header.revLoopStamps[1] - && revLoopStamps[0] < latch.revLoopStamps[0] && latch.revLoopStamps[1] < revLoopStamps[1]); - } - -//////////////////////////////////////////////////// -// Basically the "whichPred" function as per Briggs, Cooper, et al (and presumably "Cryton, Ferante, Rosen, Wegman, and -// Zadek"). Return -1 if not found - public int whichPred(BasicBlock pred) { - int n = m_InEdges.size(); - for (int i = 0; i < n; i++) { - if (m_InEdges.get(i) == pred) { - return i; - } - } - assert false; - return -1; - } - - public boolean hasBackEdge() { - for (int i = 0; i < m_OutEdges.size(); i++) { - if (hasBackEdgeTo(m_OutEdges.get(i))) { - return true; - } - } - return false; - } - - public void setCondFollow(BasicBlock other) { - condFollow = other; - } - - public BasicBlock getCondFollow() { - return condFollow; - } - - public void setLoopHead(BasicBlock head) { - loopHead = head; - } - - public BasicBlock getLoopHead() { - return loopHead; - } - - public void setLatchNode(BasicBlock latch) { - latchNode = latch; - } - - public boolean isLatchNode() { - return loopHead != null && loopHead.latchNode == this; - } - - public BasicBlock getLatchNode() { - return latchNode; - } - - public StructType getStructType() { - return sType; - } - - public void setLoopFollow(BasicBlock other) { - loopFollow = other; - } - - public BasicBlock getLoopFollow() { - return loopFollow; - } - - public void setType(BBType type) { - this.m_nodeType = type; - } - - @Override - public String toString() { - return (startAddress + 1) + "-" + (endAddress + 1); - } -} diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/CFG.java b/trunk/src/com/jpexs/decompiler/flash/graph/cfg/CFG.java deleted file mode 100644 index 66ddb196c..000000000 --- a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/CFG.java +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Copyright (C) 2013 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -/** - * Adapted from Boomerang, cfg.cpp - * Copyright (C) 1997-2000, The University of Queensland - * Copyright (C) 2000-2001, Sun Microsystems, Inc - * Copyright (C) 2002, Trent Waddington - */ -package com.jpexs.decompiler.flash.graph.cfg; - -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class CFG { - /* - * The list of pointers to BBs. - */ - - public List m_listBB; - - /* - * Ordering of BBs for control flow structuring - */ - public List Ordering = new ArrayList<>(); - public List revOrdering = new ArrayList<>(); - - /* - * The ADDRESS to BasicBlock map. - */ - //MABasicBlock m_maBasicBlock; - - /* - * The entry and exit BBs. - */ - public BasicBlock entryBB; - public BasicBlock exitBB; - - /* - * True if well formed. - */ - public boolean m_bWellFormed, structured; - /* - * Last label (positive integer) used by any BB this Cfg - */ - public int lastLabel; - - public void setTimeStamps() { - // set DFS tag - for (BasicBlock it : m_listBB) { - it.traversed = TravType.DFS_TAG; - } - - // set the parenthesis for the nodes as well as setting the post-order ordering between the nodes - RefInt time = new RefInt(); - time.value = 1; - Ordering.clear(); - entryBB.setLoopStamps(time, Ordering); - - // set the reverse parenthesis for the nodes - time.value = 1; - entryBB.setRevLoopStamps(time); - - BasicBlock retNode = findRetNode(); - assert (retNode != null); - revOrdering.clear(); - if(retNode!=null){ - retNode.setRevOrder(revOrdering); - } - } - - public void getReachableBlocks(BasicBlock b, List ret) { - if (ret.contains(b)) { - return; - } - ret.add(b); - for (BasicBlock next : b.m_OutEdges) { - getReachableBlocks(next, ret); - } - } - - public BasicBlock getCommonBlock(List parts, List visited) { - if (parts.isEmpty()) { - return null; - } - - List> reachable = new ArrayList<>(); - for (BasicBlock p : parts) { - List r1 = new ArrayList<>(); - getReachableBlocks(p, r1); - r1.add(p); - reachable.add(r1); - } - List first = reachable.get(0); - for (BasicBlock p : first) { - /*if (ignored.contains(p)) { - continue; - }*/ - boolean common = true; - for (List r : reachable) { - if (!r.contains(p)) { - common = false; - break; - } - } - if (common) { - return p; - } - } - return null; - } - - BasicBlock findRetNode() { - BasicBlock retNode = null; - for (BasicBlock it : m_listBB) { - if (it.getType() == BBType.RET) { - retNode = it; - break; - } - } - return retNode; - } - - public void findImmedPDom() { - BasicBlock curNode, succNode; // the current Node and its successor - - // traverse the nodes in order (i.e from the bottom up) - int i; - for (i = revOrdering.size() - 1; i >= 0; i--) { - curNode = revOrdering.get(i); - List oEdges = curNode.getOutEdges(); - for (int j = 0; j < oEdges.size(); j++) { - succNode = oEdges.get(j); - if (succNode.revOrd > curNode.revOrd) { - curNode.immPDom = commonPDom(curNode.immPDom, succNode); - } - } - } - - // make a second pass but consider the original CFG ordering this time - int u; - for (u = 0; u < Ordering.size(); u++) { - curNode = Ordering.get(u); - List oEdges = curNode.getOutEdges(); - if (oEdges.size() > 1) { - for (int j = 0; j < oEdges.size(); j++) { - succNode = oEdges.get(j); - curNode.immPDom = commonPDom(curNode.immPDom, succNode); - } - } - } - - // one final pass to fix up nodes involved in a loop - for (u = 0; u < Ordering.size(); u++) { - curNode = Ordering.get(u); - List oEdges = curNode.getOutEdges(); - if (oEdges.size() > 1) { - for (int j = 0; j < oEdges.size(); j++) { - succNode = oEdges.get(j); - if (curNode.hasBackEdgeTo(succNode) && (curNode.getOutEdges().size() > 1) - && (succNode.immPDom != null) - && (succNode.immPDom.ord < curNode.immPDom.ord)) { - curNode.immPDom = commonPDom(succNode.immPDom, curNode.immPDom); - } else { - curNode.immPDom = commonPDom(curNode.immPDom, succNode); - } - } - } - } - } - - // Finds the common post dominator of the current immediate post dominator and its successor's immediate post dominator - public BasicBlock commonPDom(BasicBlock curImmPDom, BasicBlock succImmPDom) { - if (curImmPDom == null) { - return succImmPDom; - } - if (succImmPDom == null) { - return curImmPDom; - } - if (curImmPDom.revOrd == succImmPDom.revOrd) { - return curImmPDom; // ordering hasn't been done - } - BasicBlock oldCurImmPDom = curImmPDom; - BasicBlock oldSuccImmPDom = succImmPDom; - - int giveup = 0; - final int GIVEUP = 10000; - while (giveup < GIVEUP && (curImmPDom != null) && (succImmPDom != null) && (curImmPDom != succImmPDom)) { - if (curImmPDom.revOrd > succImmPDom.revOrd) { - succImmPDom = succImmPDom.immPDom; - } else { - curImmPDom = curImmPDom.immPDom; - } - giveup++; - } - - if (giveup >= GIVEUP) { - /*if (VERBOSE) - LOG << "failed to find commonPDom for " << oldCurImmPDom.getLowAddr() << " and " << - oldSuccImmPDom.getLowAddr() << "\n";*/ - return oldCurImmPDom; // no change - } - - return curImmPDom; - } - - // Structures all conditional headers (i.e. nodes with more than one outedge) - public void structConds() { - // Process the nodes in order - for (int i = 0; i < Ordering.size(); i++) { - BasicBlock curNode = Ordering.get(i); - - // does the current node have more than one out edge? - if (curNode.getOutEdges().size() > 1) { - // if the current conditional header is a two way node and has a back edge, then it won't have a follow - if (curNode.hasBackEdge() && curNode.getType() == BBType.TWOWAY) { - curNode.setStructType(StructType.Cond); - continue; - } - - // set the follow of a node to be its immediate post dominator - curNode.setCondFollow(curNode.immPDom); - - // set the structured type of this node - curNode.setStructType(StructType.Cond); - - // if this is an nway header, then we have to tag each of the nodes within the body of the nway subgraph - //if (curNode.getCondType() == CondType.Case) - //curNode.setCaseHead(curNode,curNode.getCondFollow()); - } - } - } - -// Pre: The graph for curProc has been built. -// Post: Each node is tagged with the header of the most nested loop of which it is a member (possibly none). -// The header of each loop stores information on the latching node as well as the type of loop it heads. - public void structLoops() { - for (int i = Ordering.size() - 1; i >= 0; i--) { - BasicBlock curNode = Ordering.get(i); // the current node under investigation - BasicBlock latch = null; // the latching node of the loop - - // If the current node has at least one back edge into it, it is a loop header. If there are numerous back edges - // into the header, determine which one comes form the proper latching node. - // The proper latching node is defined to have the following properties: - // i) has a back edge to the current node - // ii) has the same case head as the current node - // iii) has the same loop head as the current node - // iv) is not an nway node - // v) is not the latch node of an enclosing loop - // vi) has a lower ordering than all other suitable candiates - // If no nodes meet the above criteria, then the current node is not a loop header - List iEdges = curNode.getInEdges(); - for (int j = 0; j < iEdges.size(); j++) { - BasicBlock pred = iEdges.get(j); - if (/*pred.getCaseHead() == curNode.getCaseHead() && // ii)*//*pred.getLoopHead() == curNode.getLoopHead() &&*/ // iii) - ((latch == null) || latch.ord > pred.ord) && // vi) - !((pred.getLoopHead() != null) - && pred.getLoopHead().getLatchNode() == pred) && // v) - pred.hasBackEdgeTo(curNode)) // i) - { - latch = pred; - } - } - - // if a latching node was found for the current node then it is a loop header. - if (latch != null) { - // define the map that maps each node to whether or not it is within the current loop - boolean loopNodes[] = new boolean[Ordering.size()]; - for (int j = 0; j < Ordering.size(); j++) { - loopNodes[j] = false; - } - - curNode.setLatchNode(latch); - - // the latching node may already have been structured as a conditional header. If it is not also the loop - // header (i.e. the loop is over more than one block) then reset it to be a sequential node otherwise it - // will be correctly set as a loop header only later - if (latch != curNode && latch.getStructType() == StructType.Cond) { - latch.setStructType(StructType.Seq); - } - - // set the structured type of this node - curNode.setStructType(StructType.Loop); - - // tag the members of this loop - tagNodesInLoop(curNode, loopNodes); - - // calculate the type of this loop - determineLoopType(curNode, loopNodes); - - // calculate the follow node of this loop - findLoopFollow(curNode, loopNodes); - - // delete the space taken by the loopnodes map - //delete[] loopNodes; - } - } - } - -// Pre: The loop induced by (head,latch) has already had all its member nodes tagged -// Post: The type of loop has been deduced - public void determineLoopType(BasicBlock header, boolean loopNodes[]) { - assert (header.getLatchNode() != null); - - // if the latch node is a two way node then this must be a post tested loop - if (header.getLatchNode().getType() == BBType.TWOWAY) { - header.setLoopType(LoopType.PostTested); - - // if the head of the loop is a two way node and the loop spans more than one block then it must also be a - // conditional header - if (header.getType() == BBType.TWOWAY && header != header.getLatchNode()) { - header.setStructType(StructType.LoopCond); - } - } // otherwise it is either a pretested or endless loop - else if (header.getType() == BBType.TWOWAY) { - // if the header is a two way node then it must have a conditional follow (since it can't have any backedges - // leading from it). If this follow is within the loop then this must be an endless loop - if ((header.getCondFollow() != null) && loopNodes[header.getCondFollow().ord]) { - header.setLoopType(LoopType.Endless); - - // retain the fact that this is also a conditional header - header.setStructType(StructType.LoopCond); - } else { - header.setLoopType(LoopType.PreTested); - } - } // both the header and latch node are one way nodes so this must be an endless loop - else { - header.setLoopType(LoopType.Endless); - } - } - -// Pre: The loop headed by header has been induced and all it's member nodes have been tagged -// Post: The follow of the loop has been determined. - void findLoopFollow(BasicBlock header, boolean loopNodes[]) { - assert (header.getStructType() == StructType.Loop || header.getStructType() == StructType.LoopCond); - LoopType lType = header.getLoopType(); - BasicBlock latch = header.getLatchNode(); - - if (lType == LoopType.PreTested) { - // if the 'while' loop's true child is within the loop, then its false child is the loop follow - if (loopNodes[header.getOutEdges().get(0).ord]) { - header.setLoopFollow(header.getOutEdges().get(1)); - } else { - header.setLoopFollow(header.getOutEdges().get(0)); - } - } else if (lType == LoopType.PostTested) { - // the follow of a post tested ('repeat') loop is the node on the end of the non-back edge from the latch node - if (latch.getOutEdges().get(0) == header) { - header.setLoopFollow(latch.getOutEdges().get(1)); - } else { - header.setLoopFollow(latch.getOutEdges().get(0)); - } - } else { - // endless loop - BasicBlock follow = null; - List follows = new ArrayList<>(); - - // traverse the ordering array between the header and latch nodes. - //BasicBlock latch = header.getLatchNode(); - for (int i = header.ord - 1; i > latch.ord; i--) { - BasicBlock desc = Ordering.get(i); - // the follow for an endless loop will have the following - // properties: - // i) it will have a parent that is a conditional header inside the loop whose follow is outside the - // loop - // ii) it will be outside the loop according to its loop stamp pair - // iii) have the highest ordering of all suitable follows (i.e. highest in the graph) - - if (desc.getStructType() == StructType.Cond && (desc.getCondFollow() != null) - && desc.getLoopHead() == header) { - if (loopNodes[desc.getCondFollow().ord]) { - // if the conditional's follow is in the same loop AND is lower in the loop, jump to this follow - if (desc.ord > desc.getCondFollow().ord) { - i = desc.getCondFollow().ord; - } // otherwise there is a backward jump somewhere to a node earlier in this loop. We don't need to any - // nodes below this one as they will all have a conditional within the loop. - else { - break; - } - } else { - // otherwise find the child (if any) of the conditional header that isn't inside the same loop - BasicBlock succ = desc.getOutEdges().get(0); - if (loopNodes[succ.ord]) { - if (!loopNodes[desc.getOutEdges().get(1).ord]) { - succ = desc.getOutEdges().get(1); - } else { - succ = null; - } - } - // if a potential follow was found, compare its ordering with the currently found follow - if (succ != null) { - follows.add(succ); - } - /*if ((succ != null) && ((follow == null) || succ.ord > follow.ord)) { - follow = succ; - }*/ - } - } - } - // if a follow was found, assign it to be the follow of the loop under - // investigation - follow = getCommonBlock(follows, new ArrayList()); - if (follow != null) { - header.setLoopFollow(follow); - } - } - } - - public void tagNodesInLoop(BasicBlock header, boolean loopNodes[]) { - assert (header.getLatchNode() != null); - - // traverse the ordering structure from the header to the latch node tagging the nodes determined to be within the - // loop. These are nodes that satisfy the following: - // i) header.loopStamps encloses curNode.loopStamps and curNode.loopStamps encloses latch.loopStamps - // OR - // ii) latch.revLoopStamps encloses curNode.revLoopStamps and curNode.revLoopStamps encloses header.revLoopStamps - // OR - // iii) curNode is the latch node - - BasicBlock latch = header.getLatchNode(); - for (int i = header.ord - 1; i >= latch.ord; i--) { - if (Ordering.get(i).inLoop(header, latch)) { - // update the membership map to reflect that this node is within the loop - loopNodes[i] = true; - - Ordering.get(i).setLoopHead(header); - } - } - } - - public void structure() { - setTimeStamps(); - findImmedPDom(); - structConds(); - structLoops(); - } - - public CFG(List blocks, BasicBlock entry) { - this.m_listBB = blocks; - this.entryBB = entry; - } -} diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/CondType.java b/trunk/src/com/jpexs/decompiler/flash/graph/cfg/CondType.java deleted file mode 100644 index 7d2caa5bf..000000000 --- a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/CondType.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2013 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.graph.cfg; - -/** - * Adapted from Boomerang, basicblock.h - * Copyright (C) 1997-2000, The University of Queensland - * Copyright (C) 2000-2001, Sun Microsystems, Inc - * Copyright (C) 2002, Trent Waddington - */ -/** - * - * @author JPEXS - */ -public enum CondType { - - IfThen, // conditional with only a then clause - IfThenElse, // conditional with a then and an else clause - IfElse, // conditional with only an else clause - Case, // nway conditional header (case statement) -}; diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/LoopType.java b/trunk/src/com/jpexs/decompiler/flash/graph/cfg/LoopType.java deleted file mode 100644 index 2b78f6d1a..000000000 --- a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/LoopType.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2013 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.graph.cfg; - -/** - * Adapted from Boomerang, basicblock.h - * Copyright (C) 1997-2000, The University of Queensland - * Copyright (C) 2000-2001, Sun Microsystems, Inc - * Copyright (C) 2002, Trent Waddington - */ -/** - * - * @author JPEXS - */ -public enum LoopType { - - PreTested, // Header of a while loop - PostTested, // Header of a repeat loop - Endless // Header of an endless loop -} diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/RefInt.java b/trunk/src/com/jpexs/decompiler/flash/graph/cfg/RefInt.java deleted file mode 100644 index 5d5076fcf..000000000 --- a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/RefInt.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2013 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.graph.cfg; - -/** - * - * @author JPEXS - */ -public class RefInt { - - public int value; -} diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/SBBType.java b/trunk/src/com/jpexs/decompiler/flash/graph/cfg/SBBType.java deleted file mode 100644 index 29d58875a..000000000 --- a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/SBBType.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.graph.cfg; - -/** - * Adapted from Boomerang, basicblock.h - * Copyright (C) 1997-2000, The University of Queensland - * Copyright (C) 2000-2001, Sun Microsystems, Inc - * Copyright (C) 2002, Trent Waddington - */ -/** - * - * @author JPEXS - */ -public enum SBBType { - - NONE, // not structured - PRETESTLOOP, // header of a loop - POSTTESTLOOP, - ENDLESSLOOP, - JUMPINOUTLOOP, // an unstructured jump in or out of a loop - JUMPINTOCASE, // an unstructured jump into a case statement - IFGOTO, // unstructured conditional - IFTHEN, // conditional with then clause - IFTHENELSE, // conditional with then and else clauses - IFELSE, // conditional with else clause only - CASE // case statement (switch) -} diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/StructType.java b/trunk/src/com/jpexs/decompiler/flash/graph/cfg/StructType.java deleted file mode 100644 index 2e96c76d0..000000000 --- a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/StructType.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2013 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.graph.cfg; - -/** - * Adapted from Boomerang, basicblock.h - * Copyright (C) 1997-2000, The University of Queensland - * Copyright (C) 2000-2001, Sun Microsystems, Inc - * Copyright (C) 2002, Trent Waddington - */ -/** - * - * @author JPEXS - */ -public enum StructType { - - Loop, // Header of a loop only - Cond, // Header of a conditional only (if-then-else or switch) - LoopCond, // Header of a loop and a conditional - Seq // sequential statement (default) -} diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/TravType.java b/trunk/src/com/jpexs/decompiler/flash/graph/cfg/TravType.java deleted file mode 100644 index f3621ca3a..000000000 --- a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/TravType.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2013 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.graph.cfg; - -/** - * Adapted from Boomerang, basicblock.h - * Copyright (C) 1997-2000, The University of Queensland - * Copyright (C) 2000-2001, Sun Microsystems, Inc - * Copyright (C) 2002, Trent Waddington - */ -/** - * - * @author JPEXS - */ -public enum TravType { - - UNTRAVERSED, // Initial value - DFS_TAG, // Remove redundant nodes pass - DFS_LNUM, // DFS loop stamping pass - DFS_RNUM, // DFS reverse loop stamping pass - DFS_CASE, // DFS case head tagging traversal - DFS_PDOM, // DFS post dominator ordering - DFS_CODEGEN // Code generating pass -} diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/UnStructType.java b/trunk/src/com/jpexs/decompiler/flash/graph/cfg/UnStructType.java deleted file mode 100644 index ea9dc4176..000000000 --- a/trunk/src/com/jpexs/decompiler/flash/graph/cfg/UnStructType.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2013 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.graph.cfg; - -/** - * Adapted from Boomerang, basicblock.h - * Copyright (C) 1997-2000, The University of Queensland - * Copyright (C) 2000-2001, Sun Microsystems, Inc - * Copyright (C) 2002, Trent Waddington - */ -/** - * - * @author JPEXS - */ -public enum UnStructType { - - Structured, - JumpInOutLoop, - JumpIntoCase -} diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java index 852c4ded0..78027d1e1 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java @@ -89,16 +89,16 @@ public class FlashPlayerPanel extends Panel { SHELLEXECUTEINFO sei = new SHELLEXECUTEINFO(); sei.fMask = 0x00000040; - String appDir=""; + String appDir = ""; try { - appDir=new File(URLDecoder.decode(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath(),"UTF-8")).getParentFile().getAbsolutePath(); + appDir = new File(URLDecoder.decode(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath(), "UTF-8")).getParentFile().getAbsolutePath(); } catch (UnsupportedEncodingException ex) { Logger.getLogger(FlashPlayerPanel.class.getName()).log(Level.SEVERE, null, ex); } - if(!appDir.endsWith("\\")){ - appDir+="\\"; + if (!appDir.endsWith("\\")) { + appDir += "\\"; } - sei.lpFile = new WString(appDir+"lib\\FlashPlayer.exe"); + sei.lpFile = new WString(appDir + "lib\\FlashPlayer.exe"); sei.lpParameters = new WString(hwnd.getPointer().hashCode() + " " + hwndFrame.getPointer().hashCode()); sei.nShow = WinUser.SW_NORMAL; Shell32.INSTANCE.ShellExecuteEx(sei);