mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-15 01:01:54 +00:00
Default clause position in switch fixed
This commit is contained in:
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user