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
@@ -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) {
@@ -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
@@ -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;
}