mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-08 08:55:05 +00:00
AS1/2 Try..catch with error types support - decompilation and direct editation
This commit is contained in:
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.model.clauses;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
@@ -20,9 +21,21 @@ import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.action.model.ActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.ConstantPool;
|
||||
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
|
||||
import com.jpexs.decompiler.flash.action.parser.script.ActionSourceGenerator;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionIf;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionJump;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionPop;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionPush;
|
||||
import com.jpexs.decompiler.flash.action.swf4.RegisterNumber;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionEquals2;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionPushDuplicate;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionStackSwap;
|
||||
import com.jpexs.decompiler.flash.action.swf7.ActionCastOp;
|
||||
import com.jpexs.decompiler.flash.action.swf7.ActionThrow;
|
||||
import com.jpexs.decompiler.flash.action.swf7.ActionTry;
|
||||
import com.jpexs.decompiler.flash.ecma.Null;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.graph.Block;
|
||||
import com.jpexs.decompiler.graph.CompilationException;
|
||||
@@ -33,6 +46,8 @@ import com.jpexs.decompiler.graph.model.ContinueItem;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -42,7 +57,9 @@ public class TryActionItem extends ActionItem implements Block {
|
||||
|
||||
public List<GraphTargetItem> tryCommands;
|
||||
|
||||
|
||||
public List<GraphTargetItem> catchExceptionNames;
|
||||
|
||||
public List<GraphTargetItem> catchExceptionTypes;
|
||||
|
||||
public List<List<GraphTargetItem>> catchCommands;
|
||||
|
||||
@@ -61,10 +78,11 @@ public class TryActionItem extends ActionItem implements Block {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
public TryActionItem(List<GraphTargetItem> tryCommands, List<GraphTargetItem> catchExceptionNames, List<GraphTargetItem> catchExceptionTypes, List<List<GraphTargetItem>> catchCommands, List<GraphTargetItem> finallyCommands) {
|
||||
super(null, null, NOPRECEDENCE);
|
||||
this.tryCommands = tryCommands;
|
||||
this.tryCommands = tryCommands;
|
||||
this.catchExceptionNames = catchExceptionNames;
|
||||
this.catchExceptionTypes = catchExceptionTypes;
|
||||
this.catchCommands = catchCommands;
|
||||
this.finallyCommands = finallyCommands;
|
||||
}
|
||||
@@ -73,19 +91,23 @@ public class TryActionItem extends ActionItem implements Block {
|
||||
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
writer.append("try");
|
||||
appendBlock(null, writer, localData, tryCommands);
|
||||
appendBlock(null, writer, localData, tryCommands);
|
||||
for (int e = 0; e < catchExceptionNames.size(); e++) {
|
||||
writer.newLine();
|
||||
writer.append("catch");
|
||||
if (writer.getFormatting().spaceBeforeParenthesesCatchParentheses) {
|
||||
writer.append(" ");
|
||||
}
|
||||
writer.append("(");
|
||||
writer.append("(");
|
||||
catchExceptionNames.get(e).toStringNoQuotes(writer, localData);
|
||||
if (catchExceptionTypes.get(e) != null) {
|
||||
writer.append(":");
|
||||
catchExceptionTypes.get(e).toStringNoQuotes(writer, localData);
|
||||
}
|
||||
writer.append(")");
|
||||
List<GraphTargetItem> commands = catchCommands.get(e);
|
||||
appendBlock(null, writer, localData, commands);
|
||||
}
|
||||
}
|
||||
if (catchExceptionNames.isEmpty() || finallyCommands.size() > 0) {
|
||||
writer.newLine();
|
||||
writer.append("finally");
|
||||
appendBlock(null, writer, localData, finallyCommands);
|
||||
@@ -140,15 +162,82 @@ public class TryActionItem extends ActionItem implements Block {
|
||||
List<Action> finallyCommandsA = finallyCommands == null ? null : asGenerator.toActionList(asGenerator.generate(localData, finallyCommands));
|
||||
List<Action> catchCommandsA = null;
|
||||
String catchName = null;
|
||||
String catchName = null;
|
||||
if (catchExceptions != null) {
|
||||
if (!catchExceptions.isEmpty()) {
|
||||
catchName = catchExceptions.get(0).toStringNoQuotes(LocalData.create(new ConstantPool(asGenerator.getConstantPool())));
|
||||
}
|
||||
|
||||
int catchSize = 0;
|
||||
int catchRegister = 0;
|
||||
boolean catchInRegisterFlag = false;
|
||||
if (catchCommands != null && !catchCommands.isEmpty()) {
|
||||
if (catchCommands != null && !catchCommands.isEmpty()) {
|
||||
|
||||
List<GraphSourceItem> fullCatchBody = new ArrayList<>();
|
||||
|
||||
if (catchExceptionNames.size() == 1 && catchExceptionTypes.get(0) == null) { //catch everything without any type
|
||||
GraphTargetItem ename = catchExceptionNames.get(0);
|
||||
if (ename instanceof DirectValueActionItem) {
|
||||
catchName = ((DirectValueActionItem) ename).getAsString();
|
||||
} else {
|
||||
Logger.getLogger(TryActionItem.class.getName()).log(Level.SEVERE, "Invalid catchName, string expected");
|
||||
}
|
||||
catchInRegisterFlag = false;
|
||||
fullCatchBody = GraphTargetItem.toSourceMerge(localData, generator, catchCommands.get(0));
|
||||
} else {
|
||||
catchInRegisterFlag = true;
|
||||
catchRegister = asGenerator.getTempRegister(localData);
|
||||
boolean allCatched = false;
|
||||
for (int i = catchExceptionNames.size() - 1; i >= 0; i--) {
|
||||
GraphTargetItem etype = catchExceptionTypes.get(i);
|
||||
if (etype == null) {
|
||||
allCatched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!allCatched) {
|
||||
fullCatchBody.addAll(0, GraphTargetItem.toSourceMerge(localData, generator,
|
||||
new ActionPush(new RegisterNumber(catchRegister)),
|
||||
new ActionThrow()
|
||||
));
|
||||
}
|
||||
|
||||
for (int i = catchExceptionNames.size() - 1; i >= 0; i--) {
|
||||
GraphTargetItem ename = catchExceptionNames.get(i);
|
||||
GraphTargetItem etype = catchExceptionTypes.get(i);
|
||||
List<GraphTargetItem> ebody = catchCommands.get(i);
|
||||
if (etype == null) {
|
||||
fullCatchBody.addAll(0, GraphTargetItem.toSourceMerge(localData, generator,
|
||||
new DirectValueActionItem(new RegisterNumber(catchRegister)),
|
||||
ename,
|
||||
new ActionStackSwap(),
|
||||
new ActionDefineLocal(),
|
||||
ebody
|
||||
));
|
||||
} else {
|
||||
List<GraphSourceItem> ifBody = GraphTargetItem.toSourceMerge(localData, generator,
|
||||
ename,
|
||||
new ActionStackSwap(),
|
||||
new ActionDefineLocal(),
|
||||
ebody);
|
||||
fullCatchBody.add(0, new ActionPop());
|
||||
int toFinishSize = Action.actionsToBytes(asGenerator.toActionList(fullCatchBody), false, SWF.DEFAULT_VERSION).length;
|
||||
ActionJump finishJump = new ActionJump(toFinishSize);
|
||||
ifBody.add(finishJump);
|
||||
List<Action> ifBodyA = asGenerator.toActionList(ifBody);
|
||||
int ifBodySize = Action.actionsToBytes(ifBodyA, false, SWF.DEFAULT_VERSION).length;
|
||||
fullCatchBody.addAll(0, ifBody);
|
||||
fullCatchBody.addAll(0,
|
||||
GraphTargetItem.toSourceMerge(localData, generator,
|
||||
etype,
|
||||
new ActionPush(new RegisterNumber(catchRegister)),
|
||||
new ActionCastOp(),
|
||||
new ActionPushDuplicate(),
|
||||
new ActionPush(Null.INSTANCE),
|
||||
new ActionEquals2(),
|
||||
new ActionIf(ifBodySize)
|
||||
));
|
||||
|
||||
}
|
||||
}
|
||||
asGenerator.releaseTempRegister(localData, catchRegister);
|
||||
}
|
||||
catchCommandsA = asGenerator.toActionList(fullCatchBody);
|
||||
catchSize = Action.actionsToBytes(catchCommandsA, false, SWF.DEFAULT_VERSION).length;
|
||||
tryCommandsA.add(new ActionJump(catchSize));
|
||||
}
|
||||
@@ -157,7 +246,7 @@ public class TryActionItem extends ActionItem implements Block {
|
||||
finallySize = Action.actionsToBytes(finallyCommandsA, false, SWF.DEFAULT_VERSION).length;
|
||||
}
|
||||
int trySize = Action.actionsToBytes(tryCommandsA, false, SWF.DEFAULT_VERSION).length;
|
||||
int trySize = Action.actionsToBytes(tryCommandsA, false, SWF.DEFAULT_VERSION).length;
|
||||
ret.add(new ActionTry(catchInRegisterFlag, finallyCommands != null, catchCommands != null, catchName, catchRegister, trySize, catchSize, finallySize, SWF.DEFAULT_VERSION));
|
||||
ret.addAll(tryCommandsA);
|
||||
if (catchCommandsA != null) {
|
||||
ret.addAll(catchCommandsA);
|
||||
|
||||
@@ -1152,14 +1152,25 @@ public class ActionScript2Parser {
|
||||
s = lex();
|
||||
boolean found = false;
|
||||
List<List<GraphTargetItem>> catchCommands = null;
|
||||
List<GraphTargetItem> catchExceptions = new ArrayList<>();
|
||||
if (s.type == SymbolType.CATCH) {
|
||||
List<GraphTargetItem> catchExceptionNames = new ArrayList<>();
|
||||
List<GraphTargetItem> catchExceptionTypes = new ArrayList<>();
|
||||
|
||||
while (s.type == SymbolType.CATCH) {
|
||||
expectedType(SymbolType.PARENT_OPEN);
|
||||
s = lex();
|
||||
expected(s, lexer.yyline(), SymbolType.IDENTIFIER, SymbolType.STRING);
|
||||
catchExceptions.add(pushConst((String) s.value));
|
||||
catchExceptionNames.add(pushConst((String) s.value));
|
||||
s = lex();
|
||||
if (s.type == SymbolType.COLON) {
|
||||
catchExceptionTypes.add(type(variables));
|
||||
} else {
|
||||
catchExceptionTypes.add(null);
|
||||
lexer.pushback(s);
|
||||
}
|
||||
expectedType(SymbolType.PARENT_CLOSE);
|
||||
catchCommands = new ArrayList<>();
|
||||
if (catchCommands == null) {
|
||||
catchCommands = new ArrayList<>();
|
||||
}
|
||||
List<GraphTargetItem> cc = new ArrayList<>();
|
||||
cc.add(command(inFunction, inMethod, forinlevel, true, variables, functions));
|
||||
catchCommands.add(cc);
|
||||
@@ -1177,7 +1188,7 @@ public class ActionScript2Parser {
|
||||
expected(s, lexer.yyline(), SymbolType.CATCH, SymbolType.FINALLY);
|
||||
}
|
||||
lexer.pushback(s);
|
||||
ret = new TryActionItem(tryCommands, catchExceptions, catchCommands, finallyCommands);
|
||||
ret = new TryActionItem(tryCommands, catchExceptionNames, catchExceptionTypes, catchCommands, finallyCommands);
|
||||
break;
|
||||
case THROW:
|
||||
ret = new ThrowActionItem(null, null, expression(inFunction, inMethod, true, variables, functions));
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.swf7;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
@@ -21,12 +22,16 @@ import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import com.jpexs.decompiler.flash.action.LocalDataArea;
|
||||
import com.jpexs.decompiler.flash.action.model.ActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.CastOpActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.DefineLocalActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.ThrowActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.clauses.TryActionItem;
|
||||
import com.jpexs.decompiler.flash.action.parser.ActionParseException;
|
||||
import com.jpexs.decompiler.flash.action.parser.pcode.ASMParsedSymbol;
|
||||
import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer;
|
||||
import com.jpexs.decompiler.flash.action.swf4.RegisterNumber;
|
||||
import com.jpexs.decompiler.flash.ecma.Null;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Reserved;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
|
||||
@@ -34,6 +39,9 @@ import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItemContainer;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import com.jpexs.decompiler.graph.model.IfItem;
|
||||
import com.jpexs.decompiler.graph.model.PopItem;
|
||||
import com.jpexs.decompiler.graph.model.PushItem;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.utf8.Utf8Helper;
|
||||
import java.io.IOException;
|
||||
@@ -274,23 +282,89 @@ public class ActionTry extends Action implements GraphSourceItemContainer {
|
||||
@Override
|
||||
public void translateContainer(List<List<GraphTargetItem>> contents, GraphSourceItem lineStartItem, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions) {
|
||||
List<GraphTargetItem> tryCommands = contents.get(0);
|
||||
List<GraphTargetItem> tryCommands = contents.get(0);
|
||||
ActionItem catchName;
|
||||
if (catchInRegisterFlag) {
|
||||
catchName = new DirectValueActionItem(this, lineStartItem, -1, new RegisterNumber(this.catchRegister), new ArrayList<>());
|
||||
} else {
|
||||
catchName = new DirectValueActionItem(this, lineStartItem, -1, this.catchName, new ArrayList<>());
|
||||
}
|
||||
List<GraphTargetItem> catchExceptions = new ArrayList<>();
|
||||
if (catchBlockFlag) {
|
||||
catchExceptions.add(catchName);
|
||||
|
||||
List<GraphTargetItem> catchExceptionNames = new ArrayList<>();
|
||||
List<GraphTargetItem> catchExceptionTypes = new ArrayList<>();
|
||||
List<List<GraphTargetItem>> catchCommands = new ArrayList<>();
|
||||
|
||||
if (catchBlockFlag) {
|
||||
if (catchBlockFlag) {
|
||||
List<GraphTargetItem> body = contents.get(1);
|
||||
if (catchInRegisterFlag) {
|
||||
//catchName = new DirectValueActionItem(this, lineStartItem, -1, new RegisterNumber(this.catchRegister), new ArrayList<>());
|
||||
if (body.size() >= 2) {
|
||||
int pos = 0;
|
||||
loopex:
|
||||
while (body.get(pos) instanceof PushItem) {
|
||||
PushItem pi = (PushItem) body.get(pos);
|
||||
if (pi.value instanceof CastOpActionItem) {
|
||||
CastOpActionItem co = (CastOpActionItem) pi.value;
|
||||
if ((co.object instanceof DirectValueActionItem) && (((DirectValueActionItem) co.object).value instanceof RegisterNumber)) {
|
||||
RegisterNumber rn = (RegisterNumber) ((DirectValueActionItem) co.object).value;
|
||||
if (rn.number == catchRegister) {
|
||||
catchExceptionTypes.add(co.constructor);
|
||||
if (body.get(pos + 1) instanceof IfItem) {
|
||||
IfItem ifi = (IfItem) body.get(pos + 1);
|
||||
if (!ifi.onTrue.isEmpty()) {
|
||||
if (ifi.onTrue.get(0) instanceof DefineLocalActionItem) {
|
||||
DefineLocalActionItem dl = (DefineLocalActionItem) ifi.onTrue.get(0);
|
||||
catchExceptionNames.add(dl.name);
|
||||
List<GraphTargetItem> catchBody = new ArrayList<>(ifi.onTrue);
|
||||
catchBody.remove(0);
|
||||
catchCommands.add(catchBody);
|
||||
if (!ifi.onFalse.isEmpty()) {
|
||||
if (ifi.onFalse.get(0) instanceof PopItem) {
|
||||
pos = 1;
|
||||
body = ifi.onFalse;
|
||||
continue loopex;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
/*if (body.size() == pos + 4) {
|
||||
if (body.get(pos + 2) instanceof PopItem) {
|
||||
if (body.get(pos + 3) instanceof ThrowActionItem) {
|
||||
ThrowActionItem ta = (ThrowActionItem) body.get(pos + 3);
|
||||
if (ta.value instanceof DirectValueActionItem) {
|
||||
if (((DirectValueActionItem) ta.value).value instanceof RegisterNumber) {
|
||||
RegisterNumber rn2 = (RegisterNumber) ((DirectValueActionItem) ta.value).value;
|
||||
if (rn2.number == catchRegister) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (body.get(pos) instanceof DefineLocalActionItem) {
|
||||
DefineLocalActionItem dl = (DefineLocalActionItem) body.get(pos);
|
||||
catchExceptionNames.add(dl.name);
|
||||
catchExceptionTypes.add(null);
|
||||
List<GraphTargetItem> catchBody = new ArrayList<>(body);
|
||||
catchBody.remove(0); //pop
|
||||
catchBody.remove(0); //definelocal
|
||||
catchCommands.add(catchBody);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
catchExceptionNames.add(new DirectValueActionItem(this, lineStartItem, -1, this.catchName, new ArrayList<>()));
|
||||
catchExceptionTypes.add(null);
|
||||
catchCommands.add(body);
|
||||
}
|
||||
}
|
||||
List<GraphTargetItem> finallyCommands = contents.get(2);
|
||||
List<GraphTargetItem> finallyCommands = contents.get(2);
|
||||
output.add(new TryActionItem(tryCommands, catchExceptions, catchCommands, finallyCommands));
|
||||
output.add(new TryActionItem(tryCommands, catchExceptionNames, catchExceptionTypes, catchCommands, finallyCommands));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user