Default clause position in switch fixed

This commit is contained in:
Jindra Petřík
2016-01-17 21:59:20 +01:00
parent 33e433fa26
commit 4994c4a70c
10 changed files with 279 additions and 185 deletions

View File

@@ -86,6 +86,7 @@ import com.jpexs.decompiler.graph.model.AndItem;
import com.jpexs.decompiler.graph.model.BreakItem;
import com.jpexs.decompiler.graph.model.CommaExpressionItem;
import com.jpexs.decompiler.graph.model.ContinueItem;
import com.jpexs.decompiler.graph.model.DefaultItem;
import com.jpexs.decompiler.graph.model.DoWhileItem;
import com.jpexs.decompiler.graph.model.DuplicateItem;
import com.jpexs.decompiler.graph.model.FalseItem;
@@ -606,12 +607,21 @@ public class AVM2SourceGenerator implements SourceGenerator {
AVM2Instruction forwardJump = ins(AVM2Instructions.Jump, 0);
ret.add(forwardJump);
int defIndex = -1;
for (int i = item.caseValues.size() - 1; i >= 0; i--) {
if (item.caseValues.get(i) instanceof DefaultItem) {
defIndex = i;
break;
}
}
List<AVM2Instruction> cases = new ArrayList<>();
cases.addAll(toInsList(new IntegerValueAVM2Item(null, null, (long) item.caseValues.size()).toSource(localData, this)));
cases.addAll(toInsList(new IntegerValueAVM2Item(null, null, (long) defIndex).toSource(localData, this)));
int cLen = insToBytes(cases).length;
List<AVM2Instruction> caseLast = new ArrayList<>();
caseLast.add(0, ins(AVM2Instructions.Jump, cLen));
caseLast.addAll(0, toInsList(new IntegerValueAVM2Item(null, null, (long) item.caseValues.size()).toSource(localData, this)));
caseLast.addAll(0, toInsList(new IntegerValueAVM2Item(null, null, (long) defIndex).toSource(localData, this)));
int cLastLen = insToBytes(caseLast).length;
caseLast.add(0, ins(AVM2Instructions.Jump, cLastLen));
cases.addAll(0, caseLast);
@@ -621,6 +631,9 @@ public class AVM2SourceGenerator implements SourceGenerator {
preCases.addAll(toInsList(AssignableAVM2Item.setTemp(localData, this, switchedReg)));
for (int i = item.caseValues.size() - 1; i >= 0; i--) {
if (item.caseValues.get(i) instanceof DefaultItem) {
continue;
}
List<AVM2Instruction> sub = new ArrayList<>();
sub.addAll(toInsList(new IntegerValueAVM2Item(null, null, (long) i).toSource(localData, this)));
sub.add(ins(AVM2Instructions.Jump, insToBytes(cases).length));
@@ -633,13 +646,12 @@ public class AVM2SourceGenerator implements SourceGenerator {
}
cases.addAll(0, preCases);
AVM2Instruction lookupOp = new AVM2Instruction(0, AVM2Instructions.LookupSwitch, new int[item.caseValues.size() + 1 + 1 + 1]);
AVM2Instruction lookupOp = new AVM2Instruction(0, AVM2Instructions.LookupSwitch, new int[item.caseValues.size() + 1 + 1]);
cases.addAll(toInsList(AssignableAVM2Item.killTemp(localData, this, Arrays.asList(switchedReg))));
List<AVM2Instruction> bodies = new ArrayList<>();
List<Integer> bodiesOffsets = new ArrayList<>();
int defOffset;
int casesLen = insToBytes(cases).length;
bodies.addAll(generateToInsList(localData, item.defaultCommands));
bodies.add(0, ins(AVM2Instructions.Label));
bodies.add(ins(new BreakJumpIns(item.loop.id), 0)); //There could be two breaks when default clause ends with break, but official compiler does this too, so who cares...
defOffset = -(insToBytes(bodies).length + casesLen);
@@ -650,7 +662,6 @@ public class AVM2SourceGenerator implements SourceGenerator {
}
lookupOp.operands[0] = defOffset;
lookupOp.operands[1] = item.valuesMapping.size();
lookupOp.operands[2 + item.caseValues.size()] = defOffset;
for (int i = 0; i < item.valuesMapping.size(); i++) {
lookupOp.operands[2 + i] = bodiesOffsets.get(item.valuesMapping.get(i));
}

View File

@@ -98,6 +98,7 @@ import com.jpexs.decompiler.graph.model.BlockItem;
import com.jpexs.decompiler.graph.model.BreakItem;
import com.jpexs.decompiler.graph.model.CommaExpressionItem;
import com.jpexs.decompiler.graph.model.ContinueItem;
import com.jpexs.decompiler.graph.model.DefaultItem;
import com.jpexs.decompiler.graph.model.DoWhileItem;
import com.jpexs.decompiler.graph.model.DuplicateItem;
import com.jpexs.decompiler.graph.model.ForItem;
@@ -1627,9 +1628,9 @@ public class ActionScript3Parser {
List<GraphTargetItem> caseExprsAll = new ArrayList<>();
List<Integer> valueMapping = new ArrayList<>();
int pos = 0;
while (s.type == SymbolType.CASE) {
while (s.type == SymbolType.CASE) {
GraphTargetItem curCaseExpr = expression(allOpenedNamespaces, thisType, pkg, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables);
while (s.type == SymbolType.CASE || s.type == SymbolType.DEFAULT) {
while (s.type == SymbolType.CASE || s.type == SymbolType.DEFAULT) {
GraphTargetItem curCaseExpr = s.type == SymbolType.DEFAULT ? new DefaultItem() : expression(allOpenedNamespaces, thisType, pkg, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables);
expectedType(SymbolType.COLON);
s = lex();
caseExprsAll.add(curCaseExpr);
@@ -1641,14 +1642,8 @@ public class ActionScript3Parser {
caseCmds.add(caseCmd);
s = lex();
}
List<GraphTargetItem> defCmd = new ArrayList<>();
if (s.type == SymbolType.DEFAULT) {
expectedType(SymbolType.COLON);
defCmd = commands(allOpenedNamespaces, thisType, pkg, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, variables);
s = lexer.lex();
}
expected(s, lexer.yyline(), SymbolType.CURLY_CLOSE);
ret = new SwitchItem(null, null, sloop, switchExpr, caseExprsAll, caseCmds, defCmd, valueMapping);
ret = new SwitchItem(null, null, sloop, switchExpr, caseExprsAll, caseCmds, valueMapping);
break;
case BREAK:
s = lex();

View File

@@ -31,6 +31,7 @@ import com.jpexs.decompiler.flash.action.model.operations.NeqActionItem;
import com.jpexs.decompiler.flash.action.model.operations.StrictEqActionItem;
import com.jpexs.decompiler.flash.action.swf4.ActionEquals;
import com.jpexs.decompiler.flash.action.swf4.ActionIf;
import com.jpexs.decompiler.flash.action.swf4.ActionJump;
import com.jpexs.decompiler.flash.action.swf4.ActionNot;
import com.jpexs.decompiler.flash.action.swf4.ActionPush;
import com.jpexs.decompiler.flash.action.swf4.RegisterNumber;
@@ -47,6 +48,7 @@ import com.jpexs.decompiler.graph.Loop;
import com.jpexs.decompiler.graph.TranslateStack;
import com.jpexs.decompiler.graph.model.BreakItem;
import com.jpexs.decompiler.graph.model.ContinueItem;
import com.jpexs.decompiler.graph.model.DefaultItem;
import com.jpexs.decompiler.graph.model.SwitchItem;
import com.jpexs.decompiler.graph.model.WhileItem;
import java.util.ArrayList;
@@ -64,7 +66,7 @@ public class ActionGraph extends Graph {
public ActionGraph(List<Action> code, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int version) {
super(new ActionGraphSource(code, version, registerNames, variables, functions), new ArrayList<>());
//this.version = version;
/*heads = makeGraph(code, new ArrayList<GraphPart>());
/*heads = makeGraph(code, new ArrayList<GraphPart>());
for (GraphPart head : heads) {
fixGraph(head);
makeMulti(head, new ArrayList<GraphPart>());
@@ -271,11 +273,11 @@ public class ActionGraph extends Graph {
if (switchedObject == null) {
switchedObject = new DirectValueActionItem(null, null, -1, Null.INSTANCE, null);
}
HashMap<Integer, GraphTargetItem> caseValuesMap = new HashMap<>();
List<GraphTargetItem> caseValuesMap = new ArrayList<>();
int pos = 0;
//int pos = 0;
StrictEqActionItem set = (StrictEqActionItem) stack.pop();
caseValuesMap.put(pos, set.rightSide);
caseValuesMap.add(set.rightSide);
if (set.leftSide instanceof StoreRegisterActionItem) {
switchedObject = ((StoreRegisterActionItem) set.leftSide).value;
}
@@ -290,74 +292,55 @@ public class ActionGraph extends Graph {
&& ((top = translatePartGetStack(localData, part.nextParts.get(1), stack, staticOperation)) instanceof StrictEqActionItem)) {
cnt++;
part = part.nextParts.get(1);
pos++;
caseBodyParts.add(part.nextParts.get(0));
set = (StrictEqActionItem) top;
caseValuesMap.put(pos, set.rightSide);
caseValuesMap.add(set.rightSide);
}
if (cnt == 1) {
stack.push(set);
} else {
part = part.nextParts.get(1);
GraphPart defaultPart = part; //21-21
//caseBodyParts.add(defaultPart);
List<GraphPart> defaultAndLastPart = new ArrayList<>();
defaultAndLastPart.add(defaultPart);
defaultAndLastPart.add(caseBodyParts.get(caseBodyParts.size() - 1));
GraphPart defaultPart2 = getCommonPart(localData, defaultAndLastPart, loops);//34-37
List<GraphTargetItem> defaultCommands;//= new ArrayList<>();
List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
stopPart2.add(defaultPart2);
defaultCommands = printGraph(partCodes, partCodePos, localData, stack, allParts, null, defaultPart, stopPart2, loops, staticOperation, path);
/*List<GraphPart> loopContinues = new ArrayList<>();
for (Loop l : loops) {
if (l.loopContinue != null) {
loopContinues.add(l.loopContinue);
}
}*/
List<GraphPart> breakParts = new ArrayList<>();
/*for (int g = 0; g < caseBodyParts.size(); g++) {
if (g < caseBodyParts.size() - 1) {
if (caseBodyParts.get(g).leadsTo(code, caseBodyParts.get(g + 1), loops)) {
continue;
}
}
GraphPart nsp = caseBodyParts.get(g).getNextSuperPartPath(loopContinues);
if (nsp != null) {
breakParts.add(nsp);
}
}
Collections.sort(breakParts, new Comparator<GraphPart>() {
@Override
public int compare(GraphPart o1, GraphPart o2) {
return o2.path.length() - o1.path.length();
}
});*/
//GraphPart breakPart = breakParts.isEmpty() ? null : breakParts.get(0);
List<GraphPart> mcp = new ArrayList<>();
mcp.addAll(caseBodyParts);
if (defaultPart2 != null) {
mcp.add(defaultPart2);
}
GraphPart breakPart = getMostCommonPart(localData, mcp, loops);
if ((defaultPart2 != breakPart) && (defaultCommands.isEmpty())) {
defaultPart = defaultPart2;
//caseBodyParts.add(part);
GraphPart defaultPart = part;
if (code.get(defaultPart.start) instanceof ActionJump) {
defaultPart = defaultPart.nextParts.get(0);
}
GraphPart breakPart = getMostCommonPart(localData, caseBodyParts, loops);
List<GraphTargetItem> caseValues = new ArrayList<>();
boolean hasDefault = false;
for (int i = 0; i < caseBodyParts.size(); i++) {
if (caseValuesMap.containsKey(i)) {
caseValues.add(caseValuesMap.get(i));
if (caseBodyParts.get(i) == defaultPart) {
i++;
caseValuesMap.add(i, new DefaultItem());
caseBodyParts.add(i, defaultPart);
caseValues.add(caseValuesMap.get(i));
hasDefault = true;
}
}
if (!hasDefault) {
//List<GraphPart> stops = new ArrayList<>();
//stops.addAll(caseBodyParts);
for (int i = 0; i < caseBodyParts.size(); i++) {
if (defaultPart.leadsTo(localData, this, code, caseBodyParts.get(i), loops)) {
caseValuesMap.add(i, new DefaultItem());
caseBodyParts.add(i, defaultPart);
caseValues.add(i, caseValuesMap.get(i));
hasDefault = true;
break;
}
}
}
if (!hasDefault) {
caseValuesMap.add(new DefaultItem());
caseBodyParts.add(defaultPart);
caseValues.add(caseValuesMap.get(caseValuesMap.size() - 1));
}
List<List<GraphTargetItem>> caseCommands = new ArrayList<>();
GraphPart next;
@@ -378,24 +361,6 @@ public class ActionGraph extends Graph {
valuesMapping.add(caseBodies.indexOf(cur));
}
if (defaultPart == breakPart) {
defaultPart = null;
}
if ((defaultPart != null) && (defaultCommands.isEmpty())) {
List<GraphPart> stopPart2x = new ArrayList<>(stopPart);
stopPart2x.add(next);
defaultCommands = printGraph(partCodes, partCodePos, localData, stack, allParts, null, defaultPart, stopPart2x, loops, staticOperation, path);
}
if (!defaultCommands.isEmpty()) {
if (defaultCommands.get(defaultCommands.size() - 1) instanceof BreakItem) {
BreakItem bi = (BreakItem) defaultCommands.get(defaultCommands.size() - 1);
if (bi.loopId == currentLoop.id) {
defaultCommands.remove(defaultCommands.size() - 1);
}
}
}
/*List<GraphPart> ignored = new ArrayList<>();
for (Loop l : loops) {
ignored.add(l.loopContinue);
@@ -411,12 +376,6 @@ public class ActionGraph extends Graph {
} else {
nextCase = caseBodies.get(i + 1);
}
} else if (!defaultCommands.isEmpty()) {
if (!caseBodies.get(i).leadsTo(localData, this, code, defaultPart, loops)) {
cc.add(new BreakItem(null, localData.lineStartInstruction, currentLoop.id));
} else {
nextCase = defaultPart;
}
}
}
List<GraphPart> stopPart2x = new ArrayList<>(stopPart);
@@ -426,9 +385,9 @@ public class ActionGraph extends Graph {
stopPart2x.add(b);
}
}
if (defaultPart != null) {
/*if (defaultPart != null) {
stopPart2x.add(defaultPart);
}
}*/
if (breakPart != null) {
stopPart2x.add(breakPart);
}
@@ -442,9 +401,43 @@ public class ActionGraph extends Graph {
}
caseCommands.add(cc);
}
//If the lastone is default empty and alone, remove it
if (!caseCommands.isEmpty()) {
List<GraphTargetItem> lastc = caseCommands.get(caseCommands.size() - 1);
if (!lastc.isEmpty() && (lastc.get(lastc.size() - 1) instanceof BreakItem)) {
BreakItem bi = (BreakItem) lastc.get(lastc.size() - 1);
lastc.remove(lastc.size() - 1);
}
if (lastc.isEmpty()) {
int cnt2 = 0;
if (caseValues.get(caseValues.size() - 1) instanceof DefaultItem) {
for (int i = valuesMapping.size() - 1; i >= 0; i--) {
if (valuesMapping.get(i) == caseCommands.size() - 1) {
cnt2++;
}
}
if (cnt2 == 1) {
caseValues.remove(caseValues.size() - 1);
valuesMapping.remove(valuesMapping.size() - 1);
caseCommands.remove(lastc);
}
}
}
}
//remove last break from last section
if (!caseCommands.isEmpty()) {
List<GraphTargetItem> lastc = caseCommands.get(caseCommands.size() - 1);
if (!lastc.isEmpty() && (lastc.get(lastc.size() - 1) instanceof BreakItem)) {
BreakItem bi = (BreakItem) lastc.get(lastc.size() - 1);
lastc.remove(lastc.size() - 1);
}
}
ret = new ArrayList<>();
ret.addAll(output);
SwitchItem sti = new SwitchItem(null, switchStartItem, currentLoop, switchedObject, caseValues, caseCommands, defaultCommands, valuesMapping);
SwitchItem sti = new SwitchItem(null, switchStartItem, currentLoop, switchedObject, caseValues, caseCommands, valuesMapping);
ret.add(sti);
currentLoop.phase = 2;
if (next != null) {

View File

@@ -135,6 +135,7 @@ import com.jpexs.decompiler.graph.model.BlockItem;
import com.jpexs.decompiler.graph.model.BreakItem;
import com.jpexs.decompiler.graph.model.CommaExpressionItem;
import com.jpexs.decompiler.graph.model.ContinueItem;
import com.jpexs.decompiler.graph.model.DefaultItem;
import com.jpexs.decompiler.graph.model.DoWhileItem;
import com.jpexs.decompiler.graph.model.DuplicateItem;
import com.jpexs.decompiler.graph.model.ForItem;
@@ -1110,10 +1111,10 @@ public class ActionScript2Parser {
List<GraphTargetItem> caseExprsAll = new ArrayList<>();
List<Integer> valueMapping = new ArrayList<>();
int pos = 0;
while (s.type == SymbolType.CASE) {
while (s.type == SymbolType.CASE || s.type == SymbolType.DEFAULT) {
//List<GraphTargetItem> caseExprs; = new ArrayList<>();
while (s.type == SymbolType.CASE) {
GraphTargetItem curCaseExpr = expression(inFunction, inMethod, true, variables);
while (s.type == SymbolType.CASE || s.type == SymbolType.DEFAULT) {
GraphTargetItem curCaseExpr = s.type == SymbolType.DEFAULT ? new DefaultItem() : expression(inFunction, inMethod, true, variables);
//caseExprs.add(curCaseExpr);
expectedType(SymbolType.COLON);
s = lex();
@@ -1126,14 +1127,8 @@ public class ActionScript2Parser {
caseCmds.add(caseCmd);
s = lex();
}
List<GraphTargetItem> defCmd = new ArrayList<>();
if (s.type == SymbolType.DEFAULT) {
expectedType(SymbolType.COLON);
defCmd = commands(inFunction, inMethod, forinlevel, variables);
s = lexer.lex();
}
expected(s, lexer.yyline(), SymbolType.CURLY_CLOSE);
ret = new SwitchItem(null, null, null, switchExpr, caseExprsAll, caseCmds, defCmd, valueMapping);
ret = new SwitchItem(null, null, null, switchExpr, caseExprsAll, caseCmds, valueMapping);
break;
case BREAK:
ret = new BreakItem(null, null, 0); //? There is no more than 1 level continue/break in AS1/2

View File

@@ -54,6 +54,7 @@ import com.jpexs.decompiler.graph.model.AndItem;
import com.jpexs.decompiler.graph.model.BreakItem;
import com.jpexs.decompiler.graph.model.CommaExpressionItem;
import com.jpexs.decompiler.graph.model.ContinueItem;
import com.jpexs.decompiler.graph.model.DefaultItem;
import com.jpexs.decompiler.graph.model.DoWhileItem;
import com.jpexs.decompiler.graph.model.DuplicateItem;
import com.jpexs.decompiler.graph.model.FalseItem;
@@ -321,29 +322,37 @@ public class ActionSourceGenerator implements SourceGenerator {
List<List<Action>> caseCmds = new ArrayList<>();
List<List<List<Action>>> caseExprsAll = new ArrayList<>();
int defaultPos = -1;
loopm:
for (int m = 0; m < item.caseValues.size(); m++) {
List<List<Action>> caseExprs = new ArrayList<>();
List<ActionIf> caseIfsOne = new ArrayList<>();
int mapping = item.valuesMapping.get(m);
for (; m < item.caseValues.size(); m++) {
int newmapping = item.valuesMapping.get(m);
if (newmapping != mapping) {
m--;
break;
}
List<Action> curCaseExpr = generateToActionList(localData, item.caseValues.get(m));
caseExprs.add(curCaseExpr);
if (firstCase) {
curCaseExpr.add(0, new ActionStoreRegister(exprReg));
if (item.caseValues.get(m) instanceof DefaultItem) {
defaultPos = caseIfs.size();
} else {
curCaseExpr.add(0, new ActionPush(new RegisterNumber(exprReg)));
List<Action> curCaseExpr = generateToActionList(localData, item.caseValues.get(m));
caseExprs.add(curCaseExpr);
if (firstCase) {
curCaseExpr.add(0, new ActionStoreRegister(exprReg));
} else {
curCaseExpr.add(0, new ActionPush(new RegisterNumber(exprReg)));
}
curCaseExpr.add(new ActionStrictEquals());
ActionIf aif = new ActionIf(0);
caseIfsOne.add(aif);
curCaseExpr.add(aif);
ret.addAll(curCaseExpr);
}
curCaseExpr.add(new ActionStrictEquals());
ActionIf aif = new ActionIf(0);
caseIfsOne.add(aif);
curCaseExpr.add(aif);
ret.addAll(curCaseExpr);
firstCase = false;
}
caseExprsAll.add(caseExprs);
@@ -351,16 +360,12 @@ public class ActionSourceGenerator implements SourceGenerator {
List<Action> caseCmd = generateToActionList(localData, item.caseCommands.get(mapping));
caseCmds.add(caseCmd);
}
ActionJump defJump = new ActionJump(0);
ret.add(defJump);
List<Action> defCmd = new ArrayList<>();
if (!item.defaultCommands.isEmpty()) {
defCmd = generateToActionList(localData, item.defaultCommands);
}
for (List<Action> caseCmd : caseCmds) {
ret.addAll(caseCmd);
}
ret.addAll(defCmd);
List<List<Integer>> exprLengths = new ArrayList<>();
for (List<List<Action>> caseExprs : caseExprsAll) {
@@ -374,7 +379,6 @@ public class ActionSourceGenerator implements SourceGenerator {
for (List<Action> caseCmd : caseCmds) {
caseLengths.add(Action.actionsToBytes(caseCmd, false, SWF.DEFAULT_VERSION).length);
}
int defLength = Action.actionsToBytes(defCmd, false, SWF.DEFAULT_VERSION).length;
for (int i = 0; i < caseIfs.size(); i++) {
for (int c = 0; c < caseIfs.get(i).size(); c++) {
@@ -396,7 +400,9 @@ public class ActionSourceGenerator implements SourceGenerator {
}
int defJmpPos = 0;
for (int i = 0; i < caseIfs.size(); i++) {
defJmpPos += caseLengths.get(i);
if (defaultPos == -1 || i < defaultPos) {
defJmpPos += caseLengths.get(i);
}
}
defJump.setJumpOffset(defJmpPos);
@@ -406,7 +412,6 @@ public class ActionSourceGenerator implements SourceGenerator {
caseCmdsAll.addAll(caseCmds.get(i));
breakOffset += caseLengths.get(i);
}
breakOffset += defLength;
fixLoop(caseCmdsAll, breakOffset);
return ret;
}

View File

@@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.model.AndItem;
import com.jpexs.decompiler.graph.model.BreakItem;
import com.jpexs.decompiler.graph.model.ContinueItem;
import com.jpexs.decompiler.graph.model.DefaultItem;
import com.jpexs.decompiler.graph.model.DoWhileItem;
import com.jpexs.decompiler.graph.model.DuplicateItem;
import com.jpexs.decompiler.graph.model.ExitItem;
@@ -1725,7 +1726,6 @@ public class Graph {
List<GraphTargetItem> caseValues = new ArrayList<>();
List<List<GraphTargetItem>> caseCommands = new ArrayList<>();
List<GraphTargetItem> defaultCommands = new ArrayList<>();
List<Integer> valueMappings = new ArrayList<>();
Loop swLoop = new Loop(loops.size(), null, next);
swLoop.phase = 1;
@@ -1800,15 +1800,17 @@ public class Graph {
first = true;
pos = 0;
//This is tied to AS3 switch implementation which has nextparts switched from index 1. TODO: Make more universal
GraphPart defaultPart = hasExpr ? part.nextParts.get(1 + defaultBranch) : part.nextParts.get(0);
//int defaultNum = hasExpr ? 1 + defaultBranch : 0;
for (int i = 1; i < part.nextParts.size(); i++) {
if (part.nextParts.get(i) != defaultPart) {
if (caseExpressions.containsKey(pos)) {
caseValues.add(caseExpressions.get(pos));
} else {
caseValues.add(new IntegerValueItem(null, localData.lineStartInstruction, pos));
}
if (caseExpressions.containsKey(pos)) {
caseValues.add(caseExpressions.get(pos));
} else if (part.nextParts.get(i) == defaultPart) {
caseValues.add(new DefaultItem());
} else {
caseValues.add(new IntegerValueItem(null, localData.lineStartInstruction, pos));
}
pos++;
}
@@ -1816,13 +1818,14 @@ public class Graph {
first = true;
pos = 0;
List<GraphTargetItem> nextCommands = new ArrayList<>();
for (GraphPart p : part.nextParts) {
for (int i = 1; i < part.nextParts.size(); i++) {
GraphPart p = part.nextParts.get(i);
/*if (pos == ignoredBranch) {
pos++;
continue;
}*/
if (p != defaultPart) {
//if (p != defaultPart)
{
if (vis.contains(p)) {
valueMappings.add(caseCommands.size() - 1);
continue;
@@ -1844,37 +1847,60 @@ public class Graph {
}
}
if (next != p) {
if (p == defaultPart && !defaultCommands.isEmpty()) {
//ignore
} else {
//if (p == defaultPart && !defaultCommands.isEmpty()) {
//ignore
//} else
{
TranslateStack s2 = (TranslateStack) stack.clone();
s2.clear();
nextCommands = printGraph(partCodes, partCodePos, visited, prepareBranchLocalData(localData), s2, allParts, part, p, stopPart2, loops, null, staticOperation, path, recursionLevel + 1);
makeAllCommands(nextCommands, s2);
if (p == defaultPart) {
defaultCommands = nextCommands;
} else {
caseCommands.add(nextCommands);
}
caseCommands.add(nextCommands);
vis.add(p);
}
} else if (p == defaultPart) {
defaultCommands = nextCommands;
} else {
caseCommands.add(nextCommands);
}
first = false;
pos++;
}
//remove last break from default clause
if (!defaultCommands.isEmpty() && (defaultCommands.get(defaultCommands.size() - 1) instanceof BreakItem)) {
BreakItem bi = (BreakItem) defaultCommands.get(defaultCommands.size() - 1);
if (bi.loopId == swLoop.id) {
defaultCommands.remove(defaultCommands.size() - 1);
//If the lastone is default empty and alone, remove it
if (!caseCommands.isEmpty()) {
List<GraphTargetItem> lastc = caseCommands.get(caseCommands.size() - 1);
if (!lastc.isEmpty() && (lastc.get(lastc.size() - 1) instanceof BreakItem)) {
BreakItem bi = (BreakItem) lastc.get(lastc.size() - 1);
if (bi.loopId == swLoop.id) {
lastc.remove(lastc.size() - 1);
}
}
if (lastc.isEmpty()) {
int cnt = 0;
if (caseValues.get(caseValues.size() - 1) instanceof DefaultItem) {
for (int i = valueMappings.size() - 1; i >= 0; i--) {
if (valueMappings.get(i) == caseCommands.size() - 1) {
cnt++;
}
}
if (cnt == 1) {
caseValues.remove(caseValues.size() - 1);
valueMappings.remove(valueMappings.size() - 1);
caseCommands.remove(lastc);
}
}
}
}
SwitchItem sw = new SwitchItem(null, localData.lineStartInstruction, swLoop, switchedItem, caseValues, caseCommands, defaultCommands, valueMappings);
//remove last break from last section
if (!caseCommands.isEmpty()) {
List<GraphTargetItem> lastc = caseCommands.get(caseCommands.size() - 1);
if (!lastc.isEmpty() && (lastc.get(lastc.size() - 1) instanceof BreakItem)) {
BreakItem bi = (BreakItem) lastc.get(lastc.size() - 1);
if (bi.loopId == swLoop.id) {
lastc.remove(lastc.size() - 1);
}
}
}
SwitchItem sw = new SwitchItem(null, localData.lineStartInstruction, swLoop, switchedItem, caseValues, caseCommands, valueMappings);
currentRet.add(sw);
swLoop.phase = 2;
if (next != null) {

View File

@@ -0,0 +1,24 @@
package com.jpexs.decompiler.graph.model;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.TypeItem;
public class DefaultItem extends GraphTargetItem {
@Override
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
return writer.append("default");
}
@Override
public boolean hasReturnValue() {
return true;
}
@Override
public GraphTargetItem returnType() {
return TypeItem.UNBOUNDED;
}
}

View File

@@ -42,8 +42,6 @@ public class SwitchItem extends LoopItem implements Block {
public List<List<GraphTargetItem>> caseCommands;
public List<GraphTargetItem> defaultCommands;
public List<Integer> valuesMapping;
private boolean labelUsed;
@@ -52,18 +50,14 @@ public class SwitchItem extends LoopItem implements Block {
public List<List<GraphTargetItem>> getSubs() {
List<List<GraphTargetItem>> ret = new ArrayList<>();
ret.addAll(caseCommands);
if (defaultCommands != null) {
ret.add(defaultCommands);
}
return ret;
}
public SwitchItem(GraphSourceItem instruction, GraphSourceItem lineStartIns, Loop loop, GraphTargetItem switchedObject, List<GraphTargetItem> caseValues, List<List<GraphTargetItem>> caseCommands, List<GraphTargetItem> defaultCommands, List<Integer> valuesMapping) {
public SwitchItem(GraphSourceItem instruction, GraphSourceItem lineStartIns, Loop loop, GraphTargetItem switchedObject, List<GraphTargetItem> caseValues, List<List<GraphTargetItem>> caseCommands, List<Integer> valuesMapping) {
super(instruction, lineStartIns, loop);
this.switchedObject = switchedObject;
this.caseValues = caseValues;
this.caseCommands = caseCommands;
this.defaultCommands = defaultCommands;
this.valuesMapping = valuesMapping;
}
@@ -90,7 +84,9 @@ public class SwitchItem extends LoopItem implements Block {
for (int i = 0; i < caseCommands.size(); i++) {
for (int k = 0; k < valuesMapping.size(); k++) {
if (valuesMapping.get(k) == i) {
writer.append("case ");
if (!(caseValues.get(k) instanceof DefaultItem)) {
writer.append("case ");
}
caseValues.get(k).toString(writer, localData);
writer.append(":").newLine();
}
@@ -103,19 +99,6 @@ public class SwitchItem extends LoopItem implements Block {
}
writer.unindent();
}
if (defaultCommands != null) {
if (defaultCommands.size() > 0) {
writer.append("default");
writer.append(":").newLine();
writer.indent();
for (int j = 0; j < defaultCommands.size(); j++) {
if (!defaultCommands.get(j).isEmpty()) {
defaultCommands.get(j).toStringSemicoloned(writer, localData).newLine();
}
}
writer.unindent();
}
}
writer.endBlock();
if (writer instanceof NulWriter) {
LoopWithType loopOjb = ((NulWriter) writer).endLoop(loop.id);
@@ -138,16 +121,6 @@ public class SwitchItem extends LoopItem implements Block {
}
}
}
if (defaultCommands != null) {
for (GraphTargetItem ti : defaultCommands) {
if (ti instanceof ContinueItem) {
ret.add((ContinueItem) ti);
}
if (ti instanceof Block) {
ret.addAll(((Block) ti).getContinues());
}
}
}
return ret;
}