mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-05-28 20:44:55 +00:00
better try..catch..finally detection
This commit is contained in:
60
libsrc/ffdec_lib/graphviz/try_finally_asc2.gv
Normal file
60
libsrc/ffdec_lib/graphviz/try_finally_asc2.gv
Normal file
@@ -0,0 +1,60 @@
|
||||
|
||||
digraph try_finally_asc2 {
|
||||
label = "Try..Finally clause in ASC2";
|
||||
node[shape=rect];
|
||||
|
||||
start->before;
|
||||
before->finally_init->in_try;
|
||||
try_f_begin->in_try;
|
||||
try_c_begin->in_try;
|
||||
in_try->finally;
|
||||
try_c_end->finally;
|
||||
in_catch->finally;
|
||||
try_c_target->in_catch;
|
||||
try_f_end->finally;
|
||||
try_f_target->catch_f->finally:ne;
|
||||
|
||||
finally->lookupswitch;
|
||||
|
||||
lookupswitch->after;
|
||||
lookupswitch->finally_throw[label="X"];
|
||||
|
||||
after->end;
|
||||
|
||||
finally_init[label="loc_N=0;"];
|
||||
catch_f[label="loc_E = exception;\lloc_N = X;\l"];
|
||||
finally_throw[label="throw loc_E;"];
|
||||
|
||||
try_c_target[shape=ellipse];
|
||||
try_c_begin[shape=ellipse];
|
||||
try_c_end[shape=ellipse];
|
||||
|
||||
try_f_target[shape=ellipse];
|
||||
try_f_begin[shape=ellipse];
|
||||
try_f_end[shape=ellipse];
|
||||
|
||||
start[shape=ellipse];
|
||||
end[shape=ellipse];
|
||||
|
||||
lookupswitch[label="lookupswitch(loc_N)"]
|
||||
|
||||
in_try->in_try_ret[label=return];
|
||||
in_try_ret[label="loc_R = returnedValue;\lloc_N = Y;\l"]
|
||||
in_try_ret->finally;
|
||||
lookupswitch->finally_return[label="Y"];
|
||||
finally_return[label="return loc_R;"];
|
||||
|
||||
in_try->in_try_continue[label=continue];
|
||||
in_try_continue[label="loc_N = Z;"]
|
||||
in_try_continue->finally;
|
||||
lookupswitch->finally_continue[label="Z"];
|
||||
finally_continue[label="continue label;"];
|
||||
|
||||
/*
|
||||
All ways go through finally clause. There is also lookupswitch with getlocal.
|
||||
Local register is set before entering in_try block.
|
||||
For every return/continue, there is local register set to specific value.
|
||||
Lookupswitch then decides what will happen.
|
||||
*/
|
||||
|
||||
}
|
||||
BIN
libsrc/ffdec_lib/graphviz/try_finally_asc2.png
Normal file
BIN
libsrc/ffdec_lib/graphviz/try_finally_asc2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 91 KiB |
60
libsrc/ffdec_lib/graphviz/try_finally_flex.gv
Normal file
60
libsrc/ffdec_lib/graphviz/try_finally_flex.gv
Normal file
@@ -0,0 +1,60 @@
|
||||
digraph try_finally_flex {
|
||||
label = "Try..Finally clause in Adobe Flex";
|
||||
node[shape=rect];
|
||||
|
||||
start->before;
|
||||
before->in_try;
|
||||
try_f_begin->in_try;
|
||||
try_c_begin->in_try;
|
||||
in_try->pushbyteminusone;
|
||||
try_c_end->pushbyteminusone;
|
||||
in_catch->pushbyteminusone;
|
||||
pushbyteminusone->finally;
|
||||
try_c_target->in_catch;
|
||||
try_f_end->finally;
|
||||
try_f_target->catch_f->finally:ne;
|
||||
|
||||
finally->lookupswitch;
|
||||
|
||||
lookupswitch->after;
|
||||
lookupswitch->finally_throw[label="X"];
|
||||
|
||||
after->end;
|
||||
|
||||
pushbyteminusone[label="pushbyte -1"];
|
||||
catch_f[label="loc_E = exception;\lpushbyte X;\l"];
|
||||
finally_throw[label="throw loc_E;"];
|
||||
|
||||
try_c_target[shape=ellipse];
|
||||
try_c_begin[shape=ellipse];
|
||||
try_c_end[shape=ellipse];
|
||||
|
||||
try_f_target[shape=ellipse];
|
||||
try_f_begin[shape=ellipse];
|
||||
try_f_end[shape=ellipse];
|
||||
|
||||
start[shape=ellipse];
|
||||
end[shape=ellipse];
|
||||
|
||||
lookupswitch[label="lookupswitch(§§pop())"]
|
||||
|
||||
in_try->in_try_ret[label=return];
|
||||
in_try_ret[label="loc_R = returnedValue;\lpushbyte Y;\l"]
|
||||
in_try_ret->finally;
|
||||
lookupswitch->finally_return[label="Y"];
|
||||
finally_return[label="return loc_R;"];
|
||||
|
||||
in_try->in_try_continue[label=continue];
|
||||
in_try_continue[label="pushbyte Z;"]
|
||||
in_try_continue->finally;
|
||||
lookupswitch->finally_continue[label="Z"];
|
||||
finally_continue[label="continue label;"];
|
||||
|
||||
/*
|
||||
All ways go through finally clause. There is also lookupswitch which uses value on stack..
|
||||
Value -1 is pushed on stack after in_try and after catch bodys.
|
||||
For every return/continue, there is also specific value pushed to stack.
|
||||
Lookupswitch then decides what will happen.
|
||||
*/
|
||||
|
||||
}
|
||||
BIN
libsrc/ffdec_lib/graphviz/try_finally_flex.png
Normal file
BIN
libsrc/ffdec_lib/graphviz/try_finally_flex.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 89 KiB |
44
libsrc/ffdec_lib/graphviz/try_finally_swftools.gv
Normal file
44
libsrc/ffdec_lib/graphviz/try_finally_swftools.gv
Normal file
@@ -0,0 +1,44 @@
|
||||
digraph try_finally_swftools {
|
||||
label = "Try..Finally clause in swftools";
|
||||
node[shape=rect];
|
||||
|
||||
start->before;
|
||||
before->in_try;
|
||||
try_f_begin->in_try;
|
||||
try_c_begin->in_try;
|
||||
in_try->finally;
|
||||
try_c_end->finally;
|
||||
in_catch->finally;
|
||||
try_c_target->in_catch;
|
||||
try_f_end->finally;
|
||||
try_f_target->catch_f;
|
||||
|
||||
finally->after;
|
||||
|
||||
|
||||
|
||||
after->end;
|
||||
|
||||
catch_f[label="finally;\lthrow exception;\l"];
|
||||
try_c_target[shape=ellipse];
|
||||
try_c_begin[shape=ellipse];
|
||||
try_c_end[shape=ellipse];
|
||||
|
||||
try_f_target[shape=ellipse];
|
||||
try_f_begin[shape=ellipse];
|
||||
try_f_end[shape=ellipse];
|
||||
|
||||
start[shape=ellipse];
|
||||
end[shape=ellipse];
|
||||
|
||||
in_try->in_try_ret[label=return];
|
||||
in_try_ret[label="§§push(returnedValue);\lfinally;\lreturn §§pop();\l"]
|
||||
|
||||
in_try->in_try_continue[label=continue];
|
||||
in_try_continue[label="finally;\lcontinue label;\l"];
|
||||
|
||||
/*
|
||||
Finally is inlined in every its usage.
|
||||
In try_f_target there is finnally alone with throw - we can take it from there.
|
||||
*/
|
||||
}
|
||||
BIN
libsrc/ffdec_lib/graphviz/try_finally_swftools.png
Normal file
BIN
libsrc/ffdec_lib/graphviz/try_finally_swftools.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
@@ -12,18 +12,21 @@
|
||||
* 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.abc;
|
||||
|
||||
import com.jpexs.decompiler.flash.BaseLocalData;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.CodeStats;
|
||||
import com.jpexs.decompiler.flash.abc.types.ABCException;
|
||||
import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
|
||||
import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.ScopeStack;
|
||||
import java.util.ArrayList;
|
||||
@@ -57,11 +60,17 @@ public class AVM2LocalData extends BaseLocalData {
|
||||
|
||||
public ArrayList<ABCException> parsedExceptions;
|
||||
|
||||
|
||||
//public Map<Integer, List<Integer>> finallyJumps;
|
||||
/**
|
||||
* Mapped jumps from pushbyte xx part to apropriate lookupswitch branch
|
||||
*/
|
||||
public Map<GraphPart, GraphPart> finallyJumps = new HashMap<>();
|
||||
|
||||
|
||||
//public Map<Integer, Integer> ignoredSwitches;
|
||||
//exception index => switchPart
|
||||
public Map<Integer, GraphPart> ignoredSwitches;
|
||||
|
||||
|
||||
//public List<Integer> ignoredSwitches2;
|
||||
|
||||
public Integer scriptIndex;
|
||||
|
||||
@@ -77,6 +86,8 @@ public class AVM2LocalData extends BaseLocalData {
|
||||
|
||||
public Map<Integer, Set<Integer>> setLocalPosToGetLocalPos = new HashMap<>();
|
||||
|
||||
public CodeStats codeStats;
|
||||
|
||||
public AVM2LocalData() {
|
||||
|
||||
}
|
||||
@@ -103,7 +114,7 @@ public class AVM2LocalData extends BaseLocalData {
|
||||
parsedExceptions = localData.parsedExceptions;
|
||||
finallyJumps = localData.finallyJumps;
|
||||
ignoredSwitches = localData.ignoredSwitches;
|
||||
ignoredSwitches = localData.ignoredSwitches;
|
||||
//ignoredSwitches2 = localData.ignoredSwitches2;
|
||||
scriptIndex = localData.scriptIndex;
|
||||
localRegAssignmentIps = localData.localRegAssignmentIps;
|
||||
ip = localData.ip;
|
||||
@@ -111,6 +122,7 @@ public class AVM2LocalData extends BaseLocalData {
|
||||
code = localData.code;
|
||||
thisHasDefaultToPrimitive = localData.thisHasDefaultToPrimitive;
|
||||
setLocalPosToGetLocalPos = localData.setLocalPosToGetLocalPos;
|
||||
codeStats = localData.codeStats;
|
||||
}
|
||||
|
||||
public AVM2ConstantPool getConstants() {
|
||||
|
||||
@@ -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.abc.avm2;
|
||||
|
||||
import com.jpexs.decompiler.flash.EndOfStreamException;
|
||||
@@ -1493,21 +1494,30 @@ public class AVM2Code implements Cloneable {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getIpThroughJumpAndDebugLine(int ip) {
|
||||
if (code.isEmpty()) {
|
||||
return ip;
|
||||
}
|
||||
if (ip >= code.size()) {
|
||||
return code.size() - 1;
|
||||
}
|
||||
}
|
||||
while (code.get(ip).definition instanceof DebugLineIns) {
|
||||
while (ip < code.size()) {
|
||||
if (code.get(ip).definition instanceof DebugLineIns) {
|
||||
ip++;
|
||||
} else if (code.get(ip).definition instanceof JumpIns) {
|
||||
ip = adr2pos(pos2adr(ip + 1) + code.get(ip).operands[0]);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ip >= code.size()) {
|
||||
return code.size() - 1;
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
|
||||
public long fixAddrAfterDebugLine(long addr) throws ConvertException {
|
||||
public long getAddrThroughJumpAndDebugLine(long addr) throws ConvertException {
|
||||
return pos2adr(getIpThroughJumpAndDebugLine(adr2pos(addr, true)));
|
||||
}
|
||||
|
||||
public ConvertOutput toSourceOutput(Map<Integer, Set<Integer>> setLocalPosToGetLocalPos, boolean thisHasDefaultToPrimitive, Reference<GraphSourceItem> lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, ABC abc, MethodBody body, int start, int end, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, boolean[] visited, HashMap<Integer, Integer> localRegAssigmentIps, HashMap<Integer, List<Integer>> refs) throws ConvertException, InterruptedException {
|
||||
@@ -2373,7 +2383,7 @@ public class AVM2Code implements Cloneable {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean walkCode(CodeStats stats, int pos, int stack, int scope, ABC abc, boolean autoFill) {
|
||||
while (pos < code.size()) {
|
||||
AVM2Instruction ins = code.get(pos);
|
||||
if (stats.instructionStats[pos].seen) {
|
||||
@@ -2383,7 +2393,9 @@ public class AVM2Code implements Cloneable {
|
||||
|
||||
if (ins.definition instanceof NewFunctionIns) {
|
||||
MethodBody innerBody = abc.findBody(ins.operands[0]);
|
||||
MethodBody innerBody = abc.findBody(ins.operands[0]);
|
||||
if (autoFill) {
|
||||
innerBody.autoFillStats(abc, stats.initscope + (stats.has_activation ? 1 : 0), false);
|
||||
}
|
||||
}
|
||||
|
||||
stats.instructionStats[pos].seen = true;
|
||||
@@ -2445,7 +2457,7 @@ public class AVM2Code implements Cloneable {
|
||||
} else if (ins.definition instanceof IfTypeIns) {
|
||||
try {
|
||||
int newpos = adr2pos(ins.getTargetAddress());
|
||||
int newpos = adr2pos(ins.getTargetAddress());
|
||||
walkCode(stats, newpos, stack, scope, abc, autoFill);
|
||||
} catch (ConvertException ex) {
|
||||
return false;
|
||||
}
|
||||
@@ -2457,7 +2469,7 @@ public class AVM2Code implements Cloneable {
|
||||
}
|
||||
try {
|
||||
int newpos = adr2pos(pos2adr(pos) + ins.operands[i]);
|
||||
int newpos = adr2pos(pos2adr(pos) + ins.operands[i]);
|
||||
if (!walkCode(stats, newpos, stack, scope, abc, autoFill)) {
|
||||
return false;
|
||||
}
|
||||
} catch (ConvertException ex) {
|
||||
@@ -2470,10 +2482,10 @@ public class AVM2Code implements Cloneable {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public CodeStats getStats(ABC abc, MethodBody body, int initScope, boolean autoFill) {
|
||||
CodeStats stats = new CodeStats(this);
|
||||
stats.initscope = initScope;
|
||||
stats.initscope = initScope;
|
||||
if (!walkCode(stats, 0, 0, initScope, abc, autoFill)) {
|
||||
return null;
|
||||
}
|
||||
int scopePos = -1;
|
||||
@@ -2490,7 +2502,7 @@ public class AVM2Code implements Cloneable {
|
||||
visited.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!walkCode(stats, adr2pos(ex.target), 1, scopePos, abc, autoFill)) {
|
||||
return null;
|
||||
}
|
||||
int maxIp = 0;
|
||||
@@ -2516,7 +2528,7 @@ public class AVM2Code implements Cloneable {
|
||||
stats.instructionStats[i].seen = false;
|
||||
}
|
||||
// Rerun rest with new scopePos, stackPos
|
||||
// Rerun rest with new scopePos, stackPos
|
||||
if (!walkCode(stats, nextIp, origStackPos + 1/*magic!*/, scopePos - 1 /*magic!*/, abc, autoFill)) {
|
||||
return null;
|
||||
}
|
||||
scopePos--;
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIn
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.HasNext2Ins;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.DecLocalPIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.IncLocalPIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.FilteredCheckAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item;
|
||||
@@ -70,6 +71,8 @@ import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.Loop;
|
||||
import com.jpexs.decompiler.graph.ScopeStack;
|
||||
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.ExitItem;
|
||||
import com.jpexs.decompiler.graph.model.GotoItem;
|
||||
import com.jpexs.decompiler.graph.model.IfItem;
|
||||
@@ -138,56 +141,119 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforePrintGraph(BaseLocalData localData, String path, Set<GraphPart> allParts, List<Loop> loops) {
|
||||
Map<Integer, Integer> ignoredSwitches = getIgnoredSwitches(allParts);
|
||||
Map<Integer, Set<Integer>> setLocalPosToGetLocalPos = calculateLocalRegsUsage(new HashSet<Integer>(ignoredSwitches.values()), path, allParts);
|
||||
protected void beforePrintGraph(BaseLocalData localData, String path, Set<GraphPart> allParts, List<Loop> loops) throws InterruptedException {
|
||||
AVM2LocalData avm2LocalData = ((AVM2LocalData) localData);
|
||||
avm2LocalData.codeStats = avm2LocalData.code.getStats(avm2LocalData.abc, avm2LocalData.methodBody, avm2LocalData.methodBody.init_scope_depth, false);
|
||||
getIgnoredSwitches((AVM2LocalData) localData, allParts);
|
||||
Set<Integer> integerSwitchesIps = new HashSet<>();
|
||||
for (GraphPart p : ((AVM2LocalData) localData).ignoredSwitches.values()) {
|
||||
integerSwitchesIps.add(p.end);
|
||||
}
|
||||
Map<Integer, Set<Integer>> setLocalPosToGetLocalPos = calculateLocalRegsUsage(integerSwitchesIps, path, allParts);
|
||||
avm2LocalData.setLocalPosToGetLocalPos = setLocalPosToGetLocalPos;
|
||||
|
||||
}
|
||||
|
||||
private Map<Integer, Integer> getIgnoredSwitches(Set<GraphPart> allParts) {
|
||||
Map<Integer, Integer> ignoredSwitches = new HashMap<>();
|
||||
int finStart;
|
||||
private void getIgnoredSwitches(AVM2LocalData localData, Set<GraphPart> allParts) throws InterruptedException {
|
||||
|
||||
for (int e = 0; e < body.exceptions.length; e++) {
|
||||
if (body.exceptions[e].isFinally()) {
|
||||
{
|
||||
{
|
||||
AVM2Instruction jmpIns = avm2code.code.get(code.adr2pos(avm2code.fixAddrAfterDebugLine(body.exceptions[e].end)));
|
||||
ABCException ex = body.exceptions[e];
|
||||
if (!ex.isFinally()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (jmpIns.definition instanceof JumpIns) {
|
||||
finStart = code.adr2pos(avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytesLength() + jmpIns.operands[0]);
|
||||
|
||||
GraphPart fpart = null;
|
||||
for (GraphPart p : allParts) {
|
||||
if (p.start == finStart) {
|
||||
fpart = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int swPos = -1;
|
||||
for (int f = finStart; f < avm2code.code.size(); f++) {
|
||||
if (avm2code.code.get(f).definition instanceof LookupSwitchIns) {
|
||||
AVM2Instruction swins = avm2code.code.get(f);
|
||||
if (swins.operands.length >= 3) {
|
||||
if (swins.operands[0] == swins.getBytesLength()) {
|
||||
if (code.adr2pos(code.pos2adr(f) + swins.operands[2]) < finStart) {
|
||||
swPos = f;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ignoredSwitches.put(e, swPos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
GraphPart finallyTryTargetPart = null;
|
||||
int targetIp = code.adr2pos(ex.target);
|
||||
for (GraphPart p : allParts) {
|
||||
if (targetIp >= p.start && targetIp <= p.end) {
|
||||
finallyTryTargetPart = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GraphPart finallyPart = finallyTryTargetPart.nextParts.size() > 0 ? finallyTryTargetPart.nextParts.get(0) : null;
|
||||
|
||||
TranslateStack finallyTryTargetStack = (TranslateStack) new TranslateStack("try_target");
|
||||
|
||||
AVM2LocalData localData2 = new AVM2LocalData(localData);
|
||||
localData2.scopeStack = new ScopeStack();
|
||||
|
||||
List<GraphTargetItem> targetOutput = translatePart(localData2, finallyTryTargetPart, finallyTryTargetStack, 0 /*??*/, "try_target");
|
||||
|
||||
final int FINALLY_KIND_STACK_BASED = 0;
|
||||
final int FINALLY_KIND_REGISTER_BASED = 1;
|
||||
final int FINALLY_KIND_INLINED = 2;
|
||||
final int FINALLY_KIND_UNKNOWN = -1;
|
||||
|
||||
int switchedReg = -1;
|
||||
int finallyKind = FINALLY_KIND_UNKNOWN;
|
||||
if (finallyTryTargetStack.size() == 1) {
|
||||
finallyKind = FINALLY_KIND_STACK_BASED;
|
||||
} else if (targetOutput.size() >= 2
|
||||
&& (targetOutput.get(targetOutput.size() - 1) instanceof SetLocalAVM2Item)
|
||||
&& (targetOutput.get(targetOutput.size() - 2) instanceof SetLocalAVM2Item)) {
|
||||
switchedReg = ((SetLocalAVM2Item) targetOutput.get(targetOutput.size() - 1)).regIndex;
|
||||
finallyKind = FINALLY_KIND_REGISTER_BASED;
|
||||
} else if (!targetOutput.isEmpty() && (targetOutput.get(targetOutput.size() - 1) instanceof ThrowAVM2Item)) {
|
||||
//inlined to single part
|
||||
//TODO: maybe replace all instances of exit nodes of try block
|
||||
finallyKind = FINALLY_KIND_INLINED;
|
||||
} else {
|
||||
//probably inlined code in more parts, cannot do :-(
|
||||
}
|
||||
|
||||
if (finallyKind == FINALLY_KIND_STACK_BASED) {
|
||||
|
||||
/*
|
||||
Search for a lookupswitch which first pops from the stack
|
||||
*/
|
||||
List<Integer> foundIps = new ArrayList<>();
|
||||
List<GraphPart> foundParts = new ArrayList<>();
|
||||
int stackAfter = localData.codeStats.instructionStats[finallyTryTargetPart.end].stackpos_after;
|
||||
|
||||
//int stackAfter = localData.codeStats.instructionStats[finallyPart.start].stackpos;
|
||||
findAllPops(localData, stackAfter, finallyPart, foundIps, foundParts, new HashSet<>());
|
||||
int switchIp = -1;
|
||||
GraphPart switchPart = null;
|
||||
for (int i = 0; i < foundIps.size(); i++) {
|
||||
int ip = foundIps.get(i);
|
||||
if (avm2code.code.get(ip).definition instanceof LookupSwitchIns) {
|
||||
switchIp = ip;
|
||||
switchPart = foundParts.get(i);
|
||||
}
|
||||
}
|
||||
if (switchIp > -1 && switchPart != null) {
|
||||
for (GraphPart r : finallyPart.refs) {
|
||||
for (int ip = r.end; ip >= r.start; ip--) {
|
||||
AVM2Instruction ins = avm2code.code.get(ip);
|
||||
if (ins.definition instanceof JumpIns) {
|
||||
continue;
|
||||
} else if (ins.definition instanceof PushByteIns) {
|
||||
int val = ins.operands[0];
|
||||
if (val < 0 || val > switchPart.nextParts.size() - 2) {
|
||||
localData.finallyJumps.put(r, switchPart.nextParts.get(0)); //default branch
|
||||
} else {
|
||||
localData.finallyJumps.put(r, switchPart.nextParts.get(1 + val));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//return in finally block is joined after switch decision
|
||||
for (GraphPart p : switchPart.nextParts) {
|
||||
for (GraphPart r : p.refs) {
|
||||
if (r != switchPart) {
|
||||
localData.finallyJumps.put(r, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
localData.ignoredSwitches.put(e, switchPart);
|
||||
} else {
|
||||
//there is probably return in all branches and no other way outside finally
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return ignoredSwitches;
|
||||
}
|
||||
|
||||
public Map<Integer, Set<Integer>> calculateLocalRegsUsage(Set<Integer> ignoredSwitches, String path, Set<GraphPart> allParts) {
|
||||
@@ -345,315 +411,231 @@ public class AVM2Graph extends Graph {
|
||||
for (GraphPart p : allBlocks) {
|
||||
if (avm2code.pos2adr(p.start) >= ex.start && avm2code.pos2adr(p.end) <= ex.end && target != null) {
|
||||
//Logger.getLogger(Graph.class.getName()).fine("ADDING throwpart " + target + " to " + p);
|
||||
p.throwParts.add(target);
|
||||
target.refs.add(p);
|
||||
//p.throwParts.add(target);
|
||||
//target.refs.add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void findNearestPartOutsideTry(AVM2LocalData localData, GraphPart part, int tryEndIp, Set<GraphPart> visited, Set<GraphPart> result) {
|
||||
if (visited.contains(part)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (part.start >= tryEndIp || part.end >= tryEndIp) {
|
||||
result.add(part);
|
||||
return;
|
||||
}
|
||||
|
||||
if (localData.finallyJumps.containsKey(part)) {
|
||||
GraphPart afterSwitchPart = localData.finallyJumps.get(part);
|
||||
GraphPart switchPart = null;
|
||||
for (GraphPart r : afterSwitchPart.refs) {
|
||||
if (localData.ignoredSwitches.containsValue(r)) {
|
||||
switchPart = r;
|
||||
}
|
||||
}
|
||||
|
||||
if (switchPart != null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (GraphPart n : part.nextParts) {
|
||||
findNearestPartOutsideTry(localData, n, tryEndIp, visited, result);
|
||||
}
|
||||
}
|
||||
|
||||
private Set<GraphPart> findNearestPartOutsideTry(AVM2LocalData localData, GraphPart start, int tryEndIp) {
|
||||
Set<GraphPart> result = new HashSet<>();
|
||||
findNearestPartOutsideTry(localData, start, tryEndIp, new HashSet<>(), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void findAllPops(AVM2LocalData localData, int stackLevel, GraphPart part, List<Integer> foundIps, List<GraphPart> foundParts, Set<GraphPart> visited) {
|
||||
if (visited.contains(part)) {
|
||||
return;
|
||||
}
|
||||
visited.add(part);
|
||||
for (int ip = part.start; ip <= part.end; ip++) {
|
||||
if (localData.codeStats.instructionStats[ip].stackpos_after == stackLevel - 1) {
|
||||
foundIps.add(ip);
|
||||
foundParts.add(part);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (GraphPart n : part.nextParts) {
|
||||
findAllPops(localData, stackLevel, n, foundIps, foundParts, visited);
|
||||
}
|
||||
}
|
||||
|
||||
private List<GraphTargetItem> checkTry(List<GraphTargetItem> output, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, AVM2LocalData localData, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, Set<GraphPart> allParts, TranslateStack stack, int staticOperation, String path) throws InterruptedException {
|
||||
if (localData.parsedExceptions == null) {
|
||||
localData.parsedExceptions = new ArrayList<>();
|
||||
}
|
||||
List<ABCException> parsedExceptions = localData.parsedExceptions;
|
||||
if (localData.finallyJumps == null) {
|
||||
localData.finallyJumps = new HashMap<>();
|
||||
}
|
||||
if (localData.ignoredSwitches == null) {
|
||||
localData.ignoredSwitches = new HashMap<>();
|
||||
}
|
||||
long addr = avm2code.getAddrThroughJumpAndDebugLine(avm2code.pos2adr(part.start));
|
||||
long maxEndAddr = -1;
|
||||
List<ABCException> catchedExceptions = new ArrayList<>();
|
||||
ABCException finallyException = null;
|
||||
int endIp = -1;
|
||||
int finallyIndex = -1;
|
||||
for (int e = 0; e < body.exceptions.length; e++) {
|
||||
if (addr == avm2code.getAddrThroughJumpAndDebugLine(body.exceptions[e].start)) {
|
||||
if (!parsedExceptions.contains(body.exceptions[e])) {
|
||||
long endAddr = avm2code.getAddrThroughJumpAndDebugLine(body.exceptions[e].end);
|
||||
if (endAddr > maxEndAddr) {
|
||||
catchedExceptions.clear();
|
||||
finallyException = null;
|
||||
finallyIndex = -1;
|
||||
maxEndAddr = avm2code.getAddrThroughJumpAndDebugLine(body.exceptions[e].end);
|
||||
endIp = avm2code.adr2pos(maxEndAddr);
|
||||
catchedExceptions.add(body.exceptions[e]);
|
||||
} else if (endAddr == maxEndAddr) {
|
||||
catchedExceptions.add(body.exceptions[e]);
|
||||
}
|
||||
if (body.exceptions[e].isFinally()) {
|
||||
finallyException = body.exceptions[e];
|
||||
finallyIndex = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (catchedExceptions.size() > 0) {
|
||||
parsedExceptions.addAll(catchedExceptions);
|
||||
if (finallyException != null) {
|
||||
catchedExceptions.remove(finallyException);
|
||||
}
|
||||
List<GraphTargetItem> tryCommands = new ArrayList<>();
|
||||
List<List<GraphTargetItem>> catchCommands = new ArrayList<>();
|
||||
List<GraphTargetItem> finallyCommands = new ArrayList<>();
|
||||
|
||||
GraphPart afterPart = null;
|
||||
for (GraphPart p : allParts) {
|
||||
if (endIp >= p.start && endIp <= p.end) {
|
||||
afterPart = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
stack.clear(); //If the original code (before check()) had "if" in it, there would be something on stack
|
||||
|
||||
for (ABCException ex : catchedExceptions) {
|
||||
|
||||
TranslateStack st2 = (TranslateStack) stack.clone();
|
||||
st2.clear();
|
||||
st2.add(new ExceptionAVM2Item(ex));
|
||||
|
||||
GraphPart catchPart = null;
|
||||
for (GraphPart p : allParts) {
|
||||
if (p.start == avm2code.adr2pos(ex.target)) {
|
||||
catchPart = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
AVM2LocalData localData2 = new AVM2LocalData(localData);
|
||||
localData2.scopeStack = new ScopeStack();
|
||||
|
||||
List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
|
||||
stopPart2.add(afterPart);
|
||||
|
||||
List<GraphTargetItem> currentCatchCommands = printGraph(foundGotos, partCodes, partCodePos, localData2, st2, allParts, null, catchPart, stopPart2, loops, staticOperation, path);
|
||||
if (!currentCatchCommands.isEmpty() && (currentCatchCommands.get(0) instanceof SetLocalAVM2Item)) {
|
||||
if (currentCatchCommands.get(0).value.getNotCoerced() instanceof ExceptionAVM2Item) {
|
||||
currentCatchCommands.remove(0);
|
||||
}
|
||||
}
|
||||
catchCommands.add(currentCatchCommands);
|
||||
}
|
||||
|
||||
if (finallyException == null) {
|
||||
List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
|
||||
stopPart2.add(afterPart);
|
||||
tryCommands = printGraph(foundGotos, partCodes, partCodePos, localData, stack, allParts, null, part, stopPart2, loops, staticOperation, path);
|
||||
}
|
||||
|
||||
if (finallyException != null) {
|
||||
afterPart = null;
|
||||
GraphPart finallyTryTargetPart = null;
|
||||
int targetPos = avm2code.adr2pos(finallyException.target);
|
||||
for (GraphPart p : allParts) {
|
||||
if (p.start == targetPos) {
|
||||
finallyTryTargetPart = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GraphPart finallyPart = finallyTryTargetPart.nextParts.isEmpty() ? null : finallyTryTargetPart.nextParts.get(0);
|
||||
|
||||
List<GraphPart> tryStopPart = new ArrayList<>(stopPart);
|
||||
if (finallyPart != null) {
|
||||
tryStopPart.add(finallyPart);
|
||||
}
|
||||
tryCommands = printGraph(foundGotos, partCodes, partCodePos, localData, stack, allParts, null, part, tryStopPart, loops, staticOperation, path);
|
||||
makeAllCommands(tryCommands, stack);
|
||||
processIfs(tryCommands);
|
||||
|
||||
//there should be §§push(-1) left
|
||||
if (!tryCommands.isEmpty()
|
||||
&& (tryCommands.get(tryCommands.size() - 1) instanceof PushItem)
|
||||
&& (tryCommands.get(tryCommands.size() - 1).value instanceof IntegerValueAVM2Item)) {
|
||||
tryCommands.remove(tryCommands.size() - 1);
|
||||
}
|
||||
|
||||
List<GraphPart> finallyStopPart = new ArrayList<>(stopPart);
|
||||
GraphPart switchPart = localData.ignoredSwitches.containsKey(finallyIndex) ? localData.ignoredSwitches.get(finallyIndex) : null;
|
||||
if (switchPart != null) {
|
||||
finallyStopPart.add(switchPart);
|
||||
}
|
||||
if (finallyPart != null) {
|
||||
finallyCommands = printGraph(foundGotos, partCodes, partCodePos, localData, stack, allParts, null, finallyPart, finallyStopPart, loops, staticOperation, path);
|
||||
}
|
||||
if (switchPart != null) {
|
||||
finallyCommands.addAll(translatePart(localData, switchPart, stack, staticOperation, path));
|
||||
afterPart = switchPart.nextParts.get(0); //take the default branch
|
||||
}
|
||||
stack.pop();
|
||||
|
||||
if (tryCommands.size() == 1
|
||||
&& (tryCommands.get(0) instanceof TryAVM2Item)
|
||||
&& catchCommands.isEmpty()
|
||||
&& ((TryAVM2Item) tryCommands.get(0)).finallyCommands.isEmpty()) {
|
||||
catchCommands = ((TryAVM2Item) tryCommands.get(0)).catchCommands;
|
||||
catchedExceptions = ((TryAVM2Item) tryCommands.get(0)).catchExceptions;
|
||||
tryCommands = ((TryAVM2Item) tryCommands.get(0)).tryCommands;
|
||||
}
|
||||
}
|
||||
if (catchCommands.isEmpty() && finallyCommands.isEmpty() && tryCommands.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
List<GraphTargetItem> ret = new ArrayList<>();
|
||||
ret.add(new TryAVM2Item(tryCommands, catchedExceptions, catchCommands, finallyCommands, "TODO"));
|
||||
|
||||
if (afterPart != null) {
|
||||
ret.addAll(printGraph(foundGotos, partCodes, partCodePos, localData, stack, allParts, null, afterPart, stopPart, loops, staticOperation, path));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<GraphTargetItem> check(List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, GraphSource code, BaseLocalData localData, Set<GraphPart> allParts, TranslateStack stack, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<GraphTargetItem> output, Loop currentLoop, int staticOperation, String path) throws InterruptedException {
|
||||
List<GraphTargetItem> ret = null;
|
||||
|
||||
AVM2LocalData aLocalData = (AVM2LocalData) localData;
|
||||
if (aLocalData.parsedExceptions == null) {
|
||||
aLocalData.parsedExceptions = new ArrayList<>();
|
||||
}
|
||||
List<ABCException> parsedExceptions = aLocalData.parsedExceptions;
|
||||
if (aLocalData.finallyJumps == null) {
|
||||
aLocalData.finallyJumps = new HashMap<>();
|
||||
}
|
||||
Map<Integer, List<Integer>> finallyJumps = aLocalData.finallyJumps;
|
||||
if (aLocalData.ignoredSwitches == null) {
|
||||
aLocalData.ignoredSwitches = new HashMap<>();
|
||||
}
|
||||
Map<Integer, Integer> ignoredSwitches = aLocalData.ignoredSwitches;
|
||||
if (aLocalData.ignoredSwitches2 == null) {
|
||||
aLocalData.ignoredSwitches2 = new ArrayList<>();
|
||||
}
|
||||
List<Integer> ignoredSwitches2 = aLocalData.ignoredSwitches2;
|
||||
int ip = part.start;
|
||||
long addr = avm2code.fixAddrAfterDebugLine(avm2code.pos2adr(part.start));
|
||||
long maxend = -1;
|
||||
List<Integer> catchedFinallys = new ArrayList<>();
|
||||
List<ABCException> catchedExceptions = new ArrayList<>();
|
||||
for (int e = 0; e < body.exceptions.length; e++) {
|
||||
if (addr == avm2code.fixAddrAfterDebugLine(body.exceptions[e].start)) {
|
||||
//Add finally only when the list is empty
|
||||
if (!body.exceptions[e].isFinally() || catchedExceptions.isEmpty()) {
|
||||
if (!parsedExceptions.contains(body.exceptions[e])) {
|
||||
if (((body.exceptions[e].end) > maxend)) {
|
||||
catchedExceptions.clear();
|
||||
catchedFinallys.clear();
|
||||
maxend = avm2code.fixAddrAfterDebugLine(body.exceptions[e].end);
|
||||
catchedExceptions.add(body.exceptions[e]);
|
||||
} else if (avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) == maxend) {
|
||||
catchedExceptions.add(body.exceptions[e]);
|
||||
}
|
||||
catchedFinallys.add(e);
|
||||
|
||||
}
|
||||
} else if (body.exceptions[e].isFinally()) {
|
||||
parsedExceptions.add(body.exceptions[e]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (catchedExceptions.size() > 0) {
|
||||
parsedExceptions.addAll(catchedExceptions);
|
||||
int endpos = code.adr2pos(avm2code.fixAddrAfterDebugLine(catchedExceptions.get(0).end));
|
||||
int endposStartBlock = code.adr2pos(catchedExceptions.get(0).end);
|
||||
|
||||
String finCatchName = "";
|
||||
List<List<GraphTargetItem>> catchedCommands = new ArrayList<>();
|
||||
if (avm2code.code.get(endpos).definition instanceof JumpIns) {
|
||||
long afterCatchAddr = avm2code.pos2adr(endpos + 1) + avm2code.code.get(endpos).operands[0];
|
||||
int afterCatchPos = avm2code.adr2pos(afterCatchAddr);
|
||||
final AVM2Graph t = this;
|
||||
Collections.sort(catchedExceptions, new Comparator<ABCException>() {
|
||||
@Override
|
||||
public int compare(ABCException o1, ABCException o2) {
|
||||
return (int) (t.avm2code.fixAddrAfterDebugLine(o1.target) - t.avm2code.fixAddrAfterDebugLine(o2.target));
|
||||
}
|
||||
});
|
||||
|
||||
List<GraphTargetItem> finallyCommands = new ArrayList<>();
|
||||
boolean hasFinally = false;
|
||||
int returnPos = afterCatchPos;
|
||||
int finStart;
|
||||
for (int e = 0; e < body.exceptions.length; e++) {
|
||||
if (body.exceptions[e].isFinally()) {
|
||||
if (addr == avm2code.fixAddrAfterDebugLine(body.exceptions[e].start)) {
|
||||
if (afterCatchPos + 1 == code.adr2pos(avm2code.fixAddrAfterDebugLine(body.exceptions[e].end))) {
|
||||
catchedFinallys.add(e);
|
||||
AVM2Instruction jmpIns = avm2code.code.get(code.adr2pos(avm2code.fixAddrAfterDebugLine(body.exceptions[e].end)));
|
||||
|
||||
if (jmpIns.definition instanceof JumpIns) {
|
||||
finStart = code.adr2pos(avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytesLength() + jmpIns.operands[0]);
|
||||
|
||||
GraphPart fpart = null;
|
||||
for (GraphPart p : allParts) {
|
||||
if (p.start == finStart) {
|
||||
fpart = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
TranslateStack st = (TranslateStack) stack.clone();
|
||||
st.clear();
|
||||
int swPos = -1;
|
||||
for (int f = finStart; f < avm2code.code.size(); f++) {
|
||||
if (avm2code.code.get(f).definition instanceof LookupSwitchIns) {
|
||||
AVM2Instruction swins = avm2code.code.get(f);
|
||||
if (swins.operands.length >= 3) {
|
||||
if (swins.operands[0] == swins.getBytesLength()) {
|
||||
if (code.adr2pos(code.pos2adr(f) + swins.operands[2]) < finStart) {
|
||||
//st.push(new ExceptionAVM2Item(body.exceptions[e]));
|
||||
GraphPart fepart = null;
|
||||
for (GraphPart p : allParts) {
|
||||
if (p.start == f + 1) {
|
||||
fepart = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//this.code.code.get(f).ignored = true;
|
||||
//ignoredSwitches.add(f);
|
||||
swPos = f;
|
||||
|
||||
List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
|
||||
stopPart2.add(fepart);
|
||||
//finallyCommands = printGraph(new ArrayList<GraphPart>(), localData, stack, allParts, parent, fpart, stopPart2, loops, staticOperation, path);
|
||||
returnPos = f + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//ignoredSwitches.add(-1);
|
||||
//int igs_size=ignoredSwitches.size();
|
||||
Map<Integer, List<Integer>> oldFinallyJumps = new HashMap<>(finallyJumps);
|
||||
finallyJumps.clear();
|
||||
ignoredSwitches.put(e, swPos);
|
||||
st.push(new PopItem(null, aLocalData.lineStartInstruction));
|
||||
finallyCommands = printGraph(foundGotos, partCodes, partCodePos, localData, st, allParts, parent, fpart, null, loops, staticOperation, path);
|
||||
//ignoredSwitches.remove(igs_size-1);
|
||||
finallyJumps.putAll(oldFinallyJumps);
|
||||
if (!finallyJumps.containsKey(e)) {
|
||||
finallyJumps.put(e, new ArrayList<>());
|
||||
}
|
||||
finallyJumps.get(e).add(finStart);
|
||||
hasFinally = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GraphPart retPart = null;
|
||||
for (GraphPart p : allParts) {
|
||||
if (p.start == returnPos) {
|
||||
retPart = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
List<GraphPart> catchParts = new ArrayList<>();
|
||||
for (int e = 0; e < catchedExceptions.size(); e++) {
|
||||
int eendpos;
|
||||
if (e < catchedExceptions.size() - 1) {
|
||||
eendpos = code.adr2pos(avm2code.fixAddrAfterDebugLine(catchedExceptions.get(e + 1).target)) - 2;
|
||||
} else {
|
||||
eendpos = afterCatchPos - 1;
|
||||
}
|
||||
|
||||
GraphPart npart = null;
|
||||
int findpos = code.adr2pos(catchedExceptions.get(e).target);
|
||||
for (GraphPart p : allParts) {
|
||||
if (p.start == findpos) {
|
||||
npart = p;
|
||||
catchParts.add(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GraphPart nepart = null;
|
||||
for (GraphPart p : allParts) {
|
||||
if (p.start == eendpos + 1) {
|
||||
nepart = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
TranslateStack st2 = (TranslateStack) stack.clone();
|
||||
st2.clear();
|
||||
st2.add(new ExceptionAVM2Item(catchedExceptions.get(e)));
|
||||
AVM2LocalData localData2 = new AVM2LocalData(aLocalData);
|
||||
localData2.scopeStack = new ScopeStack(localData2.scriptIndex);
|
||||
List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
|
||||
stopPart2.add(nepart);
|
||||
if (retPart != null) {
|
||||
stopPart2.add(retPart);
|
||||
}
|
||||
|
||||
List<GraphTargetItem> ncatchedCommands = printGraph(foundGotos, partCodes, partCodePos, localData2, st2, allParts, parent, npart, stopPart2, loops, staticOperation, path);
|
||||
//hack for findGotos - FIXME
|
||||
if (hasFinally && !ncatchedCommands.isEmpty()) {
|
||||
for (int k = 0; k < ncatchedCommands.size(); k++) {
|
||||
if (ncatchedCommands.get(k) instanceof GotoItem) {
|
||||
GotoItem gi = (GotoItem) ncatchedCommands.get(k);
|
||||
for (GotoItem g : foundGotos) {
|
||||
if (gi.labelName.equals(g.labelName) && g.targetCommands != null) {
|
||||
if (!g.targetCommands.isEmpty()) {
|
||||
if (g.targetCommands.get(0) instanceof PushItem) {
|
||||
if (g.targetCommands.get(0).value instanceof IntegerValueAVM2Item) {
|
||||
if (((IntegerValueAVM2Item) g.targetCommands.get(0).value).value == -1) {
|
||||
ncatchedCommands.remove(gi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (catchedExceptions.get(e).isFinally() && (catchedExceptions.size() > 1 || hasFinally)) {
|
||||
catchedExceptions.remove(e);
|
||||
e--;
|
||||
} else {
|
||||
catchedCommands.add(ncatchedCommands);
|
||||
if (retPart != null && avm2code.code.get(retPart.start).isExit() && !(!ncatchedCommands.isEmpty() && (ncatchedCommands.get(ncatchedCommands.size() - 1) instanceof ExitItem))) {
|
||||
avm2code.code.get(retPart.start).translate(localData, st2, ncatchedCommands, staticOperation, path);
|
||||
}
|
||||
if (catchedExceptions.get(e).isFinally()) {
|
||||
//endposStartBlock = -1;
|
||||
if (!ncatchedCommands.isEmpty() && (ncatchedCommands.get(0) instanceof SetLocalAVM2Item)) {
|
||||
SetLocalAVM2Item sl = (SetLocalAVM2Item) ncatchedCommands.get(0);
|
||||
if (sl.value.getNotCoerced() instanceof ExceptionAVM2Item) {
|
||||
finCatchName = AVM2Item.localRegName(new HashMap<>(), sl.regIndex);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//No kill ins
|
||||
if (!ncatchedCommands.isEmpty() && (ncatchedCommands.get(0) instanceof SetLocalAVM2Item)) {
|
||||
SetLocalAVM2Item sl = (SetLocalAVM2Item) ncatchedCommands.get(0);
|
||||
if (sl.value.getThroughDuplicate().getNotCoerced() instanceof ExceptionAVM2Item) {
|
||||
ncatchedCommands.remove(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GraphPart nepart = null;
|
||||
|
||||
for (GraphPart p : allParts) {
|
||||
if (p.start == endposStartBlock) {
|
||||
nepart = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
List<GraphPart> stopPart2 = new ArrayList<>();//stopPart);
|
||||
if (nepart != null) {
|
||||
stopPart2.add(nepart);
|
||||
}
|
||||
stopPart2.addAll(catchParts);
|
||||
|
||||
if (retPart != null) {
|
||||
stopPart2.add(retPart);
|
||||
}
|
||||
TranslateStack st = (TranslateStack) stack.clone();
|
||||
st.clear();
|
||||
List<GraphTargetItem> tryCommands = printGraph(foundGotos, partCodes, partCodePos, localData, st, allParts, parent, part, stopPart2, loops, staticOperation, path);
|
||||
if (retPart != null && avm2code.code.get(retPart.start).isExit() && !(!tryCommands.isEmpty() && (tryCommands.get(tryCommands.size() - 1) instanceof ExitItem))) {
|
||||
avm2code.code.get(retPart.start).translate(localData, st, tryCommands, staticOperation, path);
|
||||
}
|
||||
output.clear();
|
||||
stack.clear();
|
||||
makeAllCommands(tryCommands, st);
|
||||
output.add(new TryAVM2Item(tryCommands, catchedExceptions, catchedCommands, finallyCommands, finCatchName));
|
||||
for (int fin_e : catchedFinallys) {
|
||||
if (finallyJumps.containsKey(fin_e)) {
|
||||
finallyJumps.get(fin_e).clear();
|
||||
}
|
||||
//.remove((Integer) finStart);
|
||||
}
|
||||
ip = returnPos;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (ip != part.start) {
|
||||
part = null;
|
||||
for (GraphPart p : allParts) {
|
||||
List<GraphPart> ps = p.getSubParts();
|
||||
for (GraphPart p2 : ps) {
|
||||
if (p2.start == ip) {
|
||||
part = p2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = new ArrayList<>();
|
||||
ret.addAll(output);
|
||||
GraphTargetItem lop = checkLoop(new ArrayList<GraphTargetItem>(), part, stopPart, loops);
|
||||
if (lop == null) {
|
||||
TranslateStack st = (TranslateStack) stack.clone();
|
||||
st.clear();
|
||||
|
||||
ret.addAll(printGraph(foundGotos, partCodes, partCodePos, localData, st, allParts, null, part, stopPart, loops, staticOperation, path));
|
||||
} else {
|
||||
ret.add(lop);
|
||||
}
|
||||
ret = checkTry(output, foundGotos, partCodes, partCodePos, aLocalData, part, stopPart, loops, allParts, stack, staticOperation, path);
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((avm2code.code.get(part.end).definition instanceof LookupSwitchIns) && (ignoredSwitches.containsValue(part.end) || ignoredSwitches2.contains(part.end))) {
|
||||
ret = new ArrayList<>();
|
||||
ret.addAll(output);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//Detect switch
|
||||
if ((part.nextParts.size() == 2) && (!stack.isEmpty()) && (stack.peek() instanceof StrictEqAVM2Item)) {
|
||||
GraphSourceItem switchStartItem = code.get(part.start);
|
||||
|
||||
@@ -737,7 +719,6 @@ public class AVM2Graph extends Graph {
|
||||
defaultPart = defaultPart.nextParts.get(0);
|
||||
}
|
||||
|
||||
|
||||
ret = new ArrayList<>();
|
||||
ret.addAll(output);
|
||||
Reference<GraphPart> nextRef = new Reference<>(null);
|
||||
@@ -758,13 +739,37 @@ public class AVM2Graph extends Graph {
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<GraphPart> getNextParts(BaseLocalData localData, GraphPart part) {
|
||||
AVM2LocalData aLocalData = (AVM2LocalData) localData;
|
||||
/*if (aLocalData.finallyJumps.containsKey(part)) {
|
||||
List<GraphPart> ret = new ArrayList<>();
|
||||
ret.add(aLocalData.finallyJumps.get(part));
|
||||
return ret;
|
||||
}*/
|
||||
return super.getNextParts(localData, part);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GraphPart checkPart(TranslateStack stack, BaseLocalData localData, GraphPart prev, GraphPart next, Set<GraphPart> allParts) {
|
||||
AVM2LocalData aLocalData = (AVM2LocalData) localData;
|
||||
if (aLocalData.finallyJumps == null) {
|
||||
aLocalData.finallyJumps = new HashMap<>();
|
||||
}
|
||||
Map<Integer, List<Integer>> finallyJumps = aLocalData.finallyJumps;
|
||||
if (aLocalData.ignoredSwitches == null) {
|
||||
aLocalData.ignoredSwitches = new HashMap<>();
|
||||
}
|
||||
|
||||
if (prev != null) {
|
||||
if (aLocalData.ignoredSwitches.containsValue(prev)) {
|
||||
return null;
|
||||
}
|
||||
if (aLocalData.finallyJumps.containsKey(prev)) {
|
||||
return aLocalData.finallyJumps.get(prev);
|
||||
}
|
||||
}
|
||||
|
||||
/*Map<Integer, List<Integer>> finallyJumps = aLocalData.finallyJumps;
|
||||
if (aLocalData.ignoredSwitches == null) {
|
||||
aLocalData.ignoredSwitches = new HashMap<>();
|
||||
}
|
||||
@@ -786,7 +791,7 @@ public class AVM2Graph extends Graph {
|
||||
nip = branches.get(1 + val);
|
||||
}
|
||||
for (GraphPart p : allParts) {
|
||||
if (avm2code.fixIPAfterDebugLine(p.start) == avm2code.fixIPAfterDebugLine(nip)) {
|
||||
if (avm2code.getIpThroughJumpAndDebugLine(p.start) == avm2code.getIpThroughJumpAndDebugLine(nip)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
@@ -801,14 +806,14 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
|
||||
int pos = next.start;
|
||||
long addr = avm2code.fixAddrAfterDebugLine(avm2code.pos2adr(pos));
|
||||
long addr = avm2code.getAddrThroughJumpAndDebugLine(avm2code.pos2adr(pos));
|
||||
for (int e = 0; e < body.exceptions.length; e++) {
|
||||
if (body.exceptions[e].isFinally()) {
|
||||
if (addr == avm2code.fixAddrAfterDebugLine(body.exceptions[e].start)) {
|
||||
if (addr == avm2code.getAddrThroughJumpAndDebugLine(body.exceptions[e].start)) {
|
||||
if (true) { //afterCatchPos + 1 == code.adr2pos(this.code.fixAddrAfterDebugLine(body.exceptions[e].end))) {
|
||||
AVM2Instruction jmpIns = avm2code.code.get(avm2code.adr2pos(avm2code.fixAddrAfterDebugLine(body.exceptions[e].end)));
|
||||
AVM2Instruction jmpIns = avm2code.code.get(avm2code.adr2pos(avm2code.getAddrThroughJumpAndDebugLine(body.exceptions[e].end)));
|
||||
if (jmpIns.definition instanceof JumpIns) {
|
||||
int finStart = avm2code.adr2pos(avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytesLength() + jmpIns.operands[0]);
|
||||
int finStart = avm2code.adr2pos(avm2code.getAddrThroughJumpAndDebugLine(body.exceptions[e].end) + jmpIns.getBytesLength() + jmpIns.operands[0]);
|
||||
if (!finallyJumps.containsKey(e)) {
|
||||
finallyJumps.put(e, new ArrayList<>());
|
||||
}
|
||||
@@ -832,8 +837,7 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}*/
|
||||
return next;
|
||||
}
|
||||
|
||||
@@ -1050,6 +1054,7 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalProcess(List<GraphTargetItem> list, int level, FinalProcessLocalData localData, String path) throws InterruptedException {
|
||||
|
||||
@@ -1061,13 +1066,6 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
}
|
||||
|
||||
/*for (int i = 0; i < list.size(); i++) {
|
||||
|
||||
if (list.get(i) instanceof WhileItem) {
|
||||
WhileItem w = (WhileItem) list.get(i);
|
||||
|
||||
}
|
||||
}*/
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (list.get(i) instanceof SetLocalAVM2Item) {
|
||||
SetLocalAVM2Item ri = (SetLocalAVM2Item) list.get(i);
|
||||
@@ -1105,30 +1103,42 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
}
|
||||
|
||||
if (i + 2 < list.size()) {
|
||||
if (isIntegerOrPopInteger(list.get(i + 1)) && (list.get(i + 2) instanceof ReturnValueAVM2Item)
|
||||
&& (list.get(i + 2).value instanceof LocalRegAVM2Item)
|
||||
&& (((LocalRegAVM2Item) list.get(i + 2).value).regIndex == ri.regIndex)) {
|
||||
ReturnValueAVM2Item r = (ReturnValueAVM2Item) list.get(i + 2);
|
||||
r.value = ri.value;
|
||||
list.remove(i + 1);
|
||||
list.remove(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
if (isIntegerOrPopInteger(list.get(i + 1)) && (list.get(i + 2) instanceof ThrowAVM2Item)
|
||||
&& (list.get(i + 2).value instanceof LocalRegAVM2Item)
|
||||
&& (((LocalRegAVM2Item) list.get(i + 2).value).regIndex == ri.regIndex)) {
|
||||
ThrowAVM2Item t = (ThrowAVM2Item) list.get(i + 2);
|
||||
t.value = ri.value;
|
||||
list.remove(i + 1);
|
||||
list.remove(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
} else if (i + 1 < list.size() && usages.isEmpty()) {
|
||||
if (isIntegerOrPopInteger(list.get(i + 1))) {
|
||||
list.remove(i + 1);
|
||||
//§§push(int) in every return/throw in try..finally block
|
||||
//there may be multiple pushes as finnaly clauses may be nested
|
||||
int numPushes = 0;
|
||||
while (i + 1 + numPushes < list.size() && isIntegerOrPopInteger(list.get(i + 1 + numPushes))) {
|
||||
numPushes++;
|
||||
}
|
||||
if (numPushes > 0) {
|
||||
if (i + 1 + numPushes < list.size()) {
|
||||
if (numPushes > 0 && (list.get(i + 1 + numPushes) instanceof ReturnValueAVM2Item)
|
||||
&& (list.get(i + 1 + numPushes).value instanceof LocalRegAVM2Item)
|
||||
&& (((LocalRegAVM2Item) list.get(i + 1 + numPushes).value).regIndex == ri.regIndex)) {
|
||||
ReturnValueAVM2Item r = (ReturnValueAVM2Item) list.get(i + 1 + numPushes);
|
||||
r.value = ri.value;
|
||||
for (int n = 0; n < numPushes; n++) {
|
||||
list.remove(i + 1);
|
||||
}
|
||||
list.remove(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
if (numPushes > 0 && (list.get(i + 1 + numPushes) instanceof ThrowAVM2Item)
|
||||
&& (list.get(i + 1 + numPushes).value instanceof LocalRegAVM2Item)
|
||||
&& (((LocalRegAVM2Item) list.get(i + 1 + numPushes).value).regIndex == ri.regIndex)) {
|
||||
ThrowAVM2Item t = (ThrowAVM2Item) list.get(i + 1 + numPushes);
|
||||
t.value = ri.value;
|
||||
for (int n = 0; n < numPushes; n++) {
|
||||
list.remove(i + 1);
|
||||
}
|
||||
list.remove(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
} else if (i + numPushes < list.size() && usages.isEmpty()) {
|
||||
for (int n = 0; n < numPushes; n++) {
|
||||
list.remove(i + 1);
|
||||
}
|
||||
list.remove(i);
|
||||
i--;
|
||||
continue;
|
||||
@@ -1136,6 +1146,20 @@ public class AVM2Graph extends Graph {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//§§push(int) before every continue/returnvoid in try..finally block
|
||||
//there may be multiple pushes as finnaly clauses may be nested
|
||||
//TODO: handle this better - actually remove only really needed
|
||||
if ((list.get(i) instanceof ContinueItem) || (list.get(i) instanceof BreakItem) || (list.get(i) instanceof ReturnVoidAVM2Item)) {
|
||||
for (int j = i - 1; j >= 0; j--) {
|
||||
if (isIntegerOrPopInteger(list.get(j))) {
|
||||
list.remove(j);
|
||||
i--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<GraphTargetItem> ret = list;
|
||||
@@ -1241,4 +1265,12 @@ public class AVM2Graph extends Graph {
|
||||
switchItem.switchedObject = setLocal.value;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean partIsSwitch(GraphPart part) {
|
||||
if (part.end < 0) {
|
||||
return false;
|
||||
}
|
||||
return avm2code.code.get(part.end).definition instanceof LookupSwitchIns;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.abc.types;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
@@ -445,7 +446,7 @@ public final class MethodBody implements Cloneable {
|
||||
|
||||
public boolean autoFillStats(ABC abc, int initScope, boolean hasThis) {
|
||||
//System.out.println("--------------");
|
||||
//System.out.println("--------------");
|
||||
CodeStats stats = getCode().getStats(abc, this, initScope, true);
|
||||
if (stats == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
import com.jpexs.decompiler.flash.BaseLocalData;
|
||||
@@ -53,6 +54,7 @@ import com.jpexs.decompiler.graph.model.ContinueItem;
|
||||
import com.jpexs.decompiler.graph.model.DefaultItem;
|
||||
import com.jpexs.decompiler.graph.model.GotoItem;
|
||||
import com.jpexs.decompiler.graph.model.IfItem;
|
||||
import com.jpexs.decompiler.graph.model.ScriptEndItem;
|
||||
import com.jpexs.decompiler.graph.model.SwitchItem;
|
||||
import com.jpexs.decompiler.graph.model.WhileItem;
|
||||
import com.jpexs.helpers.Helper;
|
||||
@@ -159,6 +161,21 @@ public class ActionGraph extends Graph {
|
||||
@Override
|
||||
protected void finalProcess(List<GraphTargetItem> list, int level, FinalProcessLocalData localData, String path) throws InterruptedException {
|
||||
|
||||
if (level == 0) {
|
||||
List<GraphTargetItem> removed = new ArrayList<>();
|
||||
for (int i = list.size() - 1; i >= 0; i--) {
|
||||
if (list.get(i) instanceof ScriptEndItem) {
|
||||
continue;
|
||||
}
|
||||
if (list.get(i) instanceof FunctionActionItem) {
|
||||
removed.add(0, list.remove(i));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
list.addAll(0, removed);
|
||||
}
|
||||
|
||||
if (insideDoInitAction) {
|
||||
ActionScript2ClassDetector detector = new ActionScript2ClassDetector();
|
||||
detector.checkClass(list, path);
|
||||
|
||||
@@ -238,7 +238,7 @@ public class Graph {
|
||||
|
||||
GraphPartQueue newParts = new GraphPartQueue();
|
||||
loopnext:
|
||||
for (GraphPart nextRaw : part.nextParts) {
|
||||
for (GraphPart nextRaw : getNextParts(localData, part)) {
|
||||
|
||||
GraphPart next = checkPart(null, localData, part, nextRaw, null);
|
||||
if (next == null) {
|
||||
@@ -276,7 +276,7 @@ public class Graph {
|
||||
}
|
||||
|
||||
public GraphPart getNextCommonPart(BaseLocalData localData, GraphPart part, List<Loop> loops) throws InterruptedException {
|
||||
return getCommonPart(localData, part, part.nextParts, loops);
|
||||
return getCommonPart(localData, part, getNextParts(localData, part), loops);
|
||||
}
|
||||
|
||||
//TODO: Make this faster!
|
||||
@@ -374,7 +374,7 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
|
||||
loopi:
|
||||
/*loopi:
|
||||
for (int i = 0; i < parts.size(); i++) {
|
||||
for (int j = 0; j < parts.size(); j++) {
|
||||
if (j == i) {
|
||||
@@ -386,7 +386,7 @@ public class Graph {
|
||||
continue loopi;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
List<Set<GraphPart>> reachable = new ArrayList<>();
|
||||
Set<GraphPart> allReachable = new LinkedHashSet<>();
|
||||
for (GraphPart p : parts) {
|
||||
@@ -410,7 +410,7 @@ public class Graph {
|
||||
continue;
|
||||
}
|
||||
visited.add(p);
|
||||
int commonLevel = 1;
|
||||
int commonLevel = 0;
|
||||
for (Set<GraphPart> r : reachable) {
|
||||
if (r.contains(p)) {
|
||||
commonLevel++;
|
||||
@@ -426,6 +426,9 @@ public class Graph {
|
||||
//System.err.println("maxclevel = " + maxCommonLevel);
|
||||
//System.err.println("maxclevelpart = " + maxCommonLevelPart);
|
||||
|
||||
if (maxCommonLevel <= 1) {
|
||||
return null;
|
||||
}
|
||||
return maxCommonLevelPart;
|
||||
}
|
||||
|
||||
@@ -440,7 +443,7 @@ public class Graph {
|
||||
for (int i = part.start; i <= part.end; i++) {
|
||||
GraphSourceItem src = code.get(i);
|
||||
if (src.isJump()) {
|
||||
part = part.nextParts.get(0);
|
||||
part = getNextParts(localData, part).get(0);
|
||||
if(st.isEmpty()){
|
||||
startPart = part;
|
||||
}
|
||||
@@ -480,11 +483,11 @@ public class Graph {
|
||||
System.err.println("parts:");
|
||||
for (GraphPart p : allParts) {
|
||||
System.err.print(p);
|
||||
if (!p.nextParts.isEmpty()) {
|
||||
if (!getNextParts(localData, p).isEmpty()) {
|
||||
System.err.print(", next: ");
|
||||
}
|
||||
boolean first = true;
|
||||
for (GraphPart n : p.nextParts) {
|
||||
for (GraphPart n : getNextParts(localData, p)) {
|
||||
if (!first) {
|
||||
System.err.print(",");
|
||||
}
|
||||
@@ -552,7 +555,7 @@ public class Graph {
|
||||
return new FinalProcessLocalData(loops);
|
||||
}
|
||||
|
||||
protected void beforePrintGraph(BaseLocalData localData, String path, Set<GraphPart> allParts, List<Loop> loops) {
|
||||
protected void beforePrintGraph(BaseLocalData localData, String path, Set<GraphPart> allParts, List<Loop> loops) throws InterruptedException {
|
||||
|
||||
}
|
||||
|
||||
@@ -604,7 +607,7 @@ public class Graph {
|
||||
|
||||
|
||||
/**/
|
||||
//if (ref.nextParts)
|
||||
//if (getNextParts(localData, ref))
|
||||
private void getBackEdges(BaseLocalData localData, List<Loop> loops) throws InterruptedException {
|
||||
clearLoops(loops);
|
||||
for (Loop el : loops) {
|
||||
@@ -843,7 +846,7 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
|
||||
private void processIfs(List<GraphTargetItem> list) {
|
||||
protected void processIfs(List<GraphTargetItem> list) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
GraphTargetItem item = list.get(i);
|
||||
if ((item instanceof LoopItem) && (item instanceof Block)) {
|
||||
@@ -1192,7 +1195,7 @@ public class Graph {
|
||||
//loopContinues.add(part);
|
||||
}
|
||||
|
||||
if (part.nextParts.size() == 2) {
|
||||
if (part.nextParts.size() == 2 && !partIsSwitch(part)) {
|
||||
|
||||
List<GraphPart> nps;/* = new ArrayList<>(part.nextParts);
|
||||
for(int i=0;i<nps.size();i++){
|
||||
@@ -1217,7 +1220,7 @@ public class Graph {
|
||||
if (next != null) {
|
||||
getLoops(localData, next, loops, stopPart, false, level, visited);
|
||||
}
|
||||
} else if (part.nextParts.size() > 2) {
|
||||
} else if (part.nextParts.size() > 2 || partIsSwitch(part)) {
|
||||
GraphPart next = getNextCommonPart(localData, part, loops);
|
||||
|
||||
for (GraphPart p : part.nextParts) {
|
||||
@@ -1411,6 +1414,10 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
|
||||
protected List<GraphPart> getNextParts(BaseLocalData localData, GraphPart part) {
|
||||
return part.nextParts;
|
||||
}
|
||||
|
||||
protected List<GraphTargetItem> printGraph(List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, BaseLocalData localData, TranslateStack stack, Set<GraphPart> allParts, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<GraphTargetItem> ret, int staticOperation, String path, int recursionLevel) throws InterruptedException {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
@@ -1428,7 +1435,7 @@ public class Graph {
|
||||
//try {
|
||||
|
||||
if (debugPrintGraph) {
|
||||
System.err.println("PART " + part + " nextsize:" + part.nextParts.size());
|
||||
System.err.println("PART " + part + " nextsize:" + getNextParts(localData, part).size());
|
||||
}
|
||||
|
||||
/*while (((part != null) && (part.getHeight() == 1)) && (code.size() > part.start) && (code.get(part.start).isJump())) { //Parts with only jump in it gets ignored
|
||||
@@ -1436,9 +1443,9 @@ public class Graph {
|
||||
if (part == stopPart) {
|
||||
return ret;
|
||||
}
|
||||
GraphTargetItem lop = checkLoop(part.nextParts.get(0), stopPart, loops);
|
||||
GraphTargetItem lop = checkLoop(getNextParts(localData, part).get(0), stopPart, loops);
|
||||
if (lop == null) {
|
||||
part = part.nextParts.get(0);
|
||||
part = getNextParts(localData, part).get(0);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@@ -1584,8 +1591,11 @@ public class Graph {
|
||||
parts = ((GraphPartMulti) part).parts;
|
||||
} else {
|
||||
parts.add(part);
|
||||
while (part.nextParts.size() == 1 && part.nextParts.get(0).refs.size() == 1) {
|
||||
part = part.nextParts.get(0);
|
||||
while (getNextParts(localData, part).size() == 1 && getNextParts(localData, part).get(0).refs.size() == 1) {
|
||||
if (stopPart.contains(getNextParts(localData, part).get(0))) { //it might be referenced with try statement
|
||||
break;
|
||||
}
|
||||
part = getNextParts(localData, part).get(0);
|
||||
parts.add(part);
|
||||
}
|
||||
}
|
||||
@@ -1594,7 +1604,7 @@ public class Graph {
|
||||
int start = p.start;
|
||||
|
||||
output.addAll(code.translatePart(p, localData, stack, start, end, staticOperation, path));
|
||||
if ((end >= code.size() - 1) && p.nextParts.isEmpty()) {
|
||||
if ((end >= code.size() - 1) && getNextParts(localData, p).isEmpty()) {
|
||||
output.add(new ScriptEndItem());
|
||||
}
|
||||
}
|
||||
@@ -1614,7 +1624,7 @@ public class Graph {
|
||||
//********************************END PART DECOMPILING
|
||||
if (parseNext) {
|
||||
|
||||
if (part.nextParts.size() > 2) {
|
||||
if (getNextParts(localData, part).size() > 2 || partIsSwitch(part)) {
|
||||
GraphTargetItem originalSwitchedItem = stack.pop();
|
||||
makeAllCommands(currentRet, stack);
|
||||
GraphTargetItem switchedItem = originalSwitchedItem;
|
||||
@@ -1742,11 +1752,11 @@ public class Graph {
|
||||
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);
|
||||
GraphPart defaultPart = hasExpr ? getNextParts(localData, part).get(1 + defaultBranch) : getNextParts(localData, part).get(0);
|
||||
List<GraphPart> caseBodyParts = new ArrayList<>();
|
||||
for (int i = 1; i < part.nextParts.size(); i++) {
|
||||
for (int i = 1; i < getNextParts(localData, part).size(); i++) {
|
||||
if (!hasExpr) {
|
||||
if (part.nextParts.get(i) == defaultPart) {
|
||||
if (getNextParts(localData, part).get(i) == defaultPart) {
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
@@ -1763,7 +1773,7 @@ public class Graph {
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
caseBodyParts.add(part.nextParts.get(i));
|
||||
caseBodyParts.add(getNextParts(localData, part).get(i));
|
||||
pos++;
|
||||
}
|
||||
Reference<GraphPart> nextRef = new Reference<>(null);
|
||||
@@ -1783,7 +1793,7 @@ public class Graph {
|
||||
pos++;
|
||||
} //else
|
||||
GraphPart nextOnePart = null;
|
||||
if (part.nextParts.size() == 2) {
|
||||
if (getNextParts(localData, part).size() == 2 && !partIsSwitch(part)) {
|
||||
GraphTargetItem expr = stack.pop();
|
||||
/*if (expr instanceof LogicalOpItem) {
|
||||
expr = ((LogicalOpItem) expr).invert();
|
||||
@@ -1793,7 +1803,7 @@ public class Graph {
|
||||
if (nextOnePart == null) {
|
||||
|
||||
List<GraphPart> nps;
|
||||
nps = part.nextParts;
|
||||
nps = getNextParts(localData, part);
|
||||
boolean isEmpty = nps.get(0) == nps.get(1);
|
||||
|
||||
GraphPart next = getCommonPart(localData, part, nps, loops);
|
||||
@@ -1896,11 +1906,16 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
} //else
|
||||
if (part.nextParts.size() == 1) {
|
||||
nextOnePart = part.nextParts.get(0);
|
||||
if (getNextParts(localData, part).size() == 1) {
|
||||
nextOnePart = getNextParts(localData, part).get(0);
|
||||
}
|
||||
|
||||
if (getNextParts(localData, part).isEmpty()) {
|
||||
makeAllCommands(currentRet, stack);
|
||||
}
|
||||
|
||||
if (nextOnePart != null) {
|
||||
printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, part, part.nextParts.get(0), stopPart, loops, currentRet, staticOperation, path, recursionLevel + 1);
|
||||
printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, part, getNextParts(localData, part).get(0), stopPart, loops, currentRet, staticOperation, path, recursionLevel + 1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2415,29 +2430,17 @@ public class Graph {
|
||||
if (p instanceof FunctionActionItem) {
|
||||
commands.add(clen, p);
|
||||
} else {
|
||||
if (isExit) {
|
||||
/*if (isExit) {
|
||||
//ASC2 leaves some function calls unpopped on stack before returning from a method
|
||||
commands.add(clen, p);
|
||||
} else {
|
||||
} else {*/
|
||||
commands.add(clen, new PushItem(p));
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void removeEdgeToFromList(List<GraphPartEdge> edges, GraphPart to) {
|
||||
for (int i = edges.size() - 1; i >= 0; i--) {
|
||||
if (edges.get(i).to.equals(to)) {
|
||||
edges.remove(i);
|
||||
}
|
||||
}
|
||||
while (isPartEmpty(to) && !to.nextParts.isEmpty()) {
|
||||
to = to.nextParts.get(0);
|
||||
removeEdgeToFromList(edges, to);
|
||||
}
|
||||
}
|
||||
|
||||
protected SwitchItem handleSwitch(GraphTargetItem switchedObject,
|
||||
GraphSourceItem switchStartItem, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> allParts, TranslateStack stack, List<GraphPart> stopPart, List<Loop> loops, BaseLocalData localData, int staticOperation, String path,
|
||||
List<GraphTargetItem> caseValuesMap, GraphPart defaultPart, List<GraphPart> caseBodyParts, Reference<GraphPart> nextRef, Reference<GraphTargetItem> tiRef) throws InterruptedException {
|
||||
@@ -2570,16 +2573,12 @@ public class Graph {
|
||||
|
||||
for (int i = 0; i < caseBodies.size(); i++) {
|
||||
List<GraphTargetItem> currentCaseCommands = new ArrayList<>();
|
||||
GraphPart nextCase = next;
|
||||
if (next != null) {
|
||||
if (i < caseBodies.size() - 1) {
|
||||
if (!caseBodies.get(i).leadsTo(localData, this, code, caseBodies.get(i + 1), loops)) {
|
||||
currentCaseCommands.add(new BreakItem(null, localData.lineStartInstruction, currentLoop.id));
|
||||
} else {
|
||||
nextCase = caseBodies.get(i + 1);
|
||||
}
|
||||
if (i < caseBodies.size() - 1) {
|
||||
if (!caseBodies.get(i).leadsTo(localData, this, code, caseBodies.get(i + 1), loops)) {
|
||||
currentCaseCommands.add(new BreakItem(null, localData.lineStartInstruction, currentLoop.id));
|
||||
}
|
||||
}
|
||||
|
||||
List<GraphPart> stopPart2x = new ArrayList<>(stopPart);
|
||||
for (GraphPart b : caseBodies) {
|
||||
if (b != caseBodies.get(i)) {
|
||||
@@ -2638,4 +2637,8 @@ public class Graph {
|
||||
return new SwitchItem(null, switchStartItem, currentLoop, switchedObject, caseValuesMap, caseCommands, valuesMapping);
|
||||
|
||||
}
|
||||
|
||||
protected boolean partIsSwitch(GraphPart part) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2006,6 +2006,8 @@ public class ActionScript2Test extends ActionScript2TestBase {
|
||||
+ "case \"C\":\r\n"
|
||||
+ "trace(\"Ret 5\");\r\n"
|
||||
+ "return 5;\r\n"
|
||||
+ "default:\r\n"
|
||||
+ "continue;\r\n"
|
||||
+ "}\r\n"
|
||||
+ "}\r\n"
|
||||
+ "trace(\"Final\");\r\n"
|
||||
|
||||
@@ -1415,6 +1415,7 @@ public class ActionScript3Test extends ActionScriptTestBase {
|
||||
+ "{\r\n"
|
||||
+ "trace(\"a\");\r\n"
|
||||
+ "}\r\n"
|
||||
+ "continue;\r\n"
|
||||
+ "}\r\n"
|
||||
+ "catch(e:EOFError)\r\n"
|
||||
+ "{\r\n"
|
||||
|
||||
BIN
libsrc/ffdec_lib/testdata/cross_compile/bin/Main.air.swf
vendored
Normal file
BIN
libsrc/ffdec_lib/testdata/cross_compile/bin/Main.air.swf
vendored
Normal file
Binary file not shown.
BIN
libsrc/ffdec_lib/testdata/cross_compile/bin/Main.flex.swf
vendored
Normal file
BIN
libsrc/ffdec_lib/testdata/cross_compile/bin/Main.flex.swf
vendored
Normal file
Binary file not shown.
BIN
libsrc/ffdec_lib/testdata/cross_compile/bin/Main.flex_apache.swf
vendored
Normal file
BIN
libsrc/ffdec_lib/testdata/cross_compile/bin/Main.flex_apache.swf
vendored
Normal file
Binary file not shown.
BIN
libsrc/ffdec_lib/testdata/cross_compile/bin/Main.swftools.swf
vendored
Normal file
BIN
libsrc/ffdec_lib/testdata/cross_compile/bin/Main.swftools.swf
vendored
Normal file
Binary file not shown.
BIN
libsrc/ffdec_lib/testdata/cross_compile/bin/expressInstall.swf
vendored
Normal file
BIN
libsrc/ffdec_lib/testdata/cross_compile/bin/expressInstall.swf
vendored
Normal file
Binary file not shown.
40
libsrc/ffdec_lib/testdata/cross_compile/bin/index.html
vendored
Normal file
40
libsrc/ffdec_lib/testdata/cross_compile/bin/index.html
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>asc2</title>
|
||||
<meta name="description" content="" />
|
||||
|
||||
<script src="js/swfobject.js"></script>
|
||||
<script>
|
||||
var flashvars = {
|
||||
};
|
||||
var params = {
|
||||
menu: "false",
|
||||
scale: "noScale",
|
||||
allowFullscreen: "true",
|
||||
allowScriptAccess: "always",
|
||||
bgcolor: "",
|
||||
wmode: "direct" // can cause issues with FP settings & webcam
|
||||
};
|
||||
var attributes = {
|
||||
id:"asc2"
|
||||
};
|
||||
swfobject.embedSWF(
|
||||
"asc2.swf",
|
||||
"altContent", "100%", "100%", "10.0.0",
|
||||
"expressInstall.swf",
|
||||
flashvars, params, attributes);
|
||||
</script>
|
||||
<style>
|
||||
html, body { height:100%; overflow:hidden; }
|
||||
body { margin:0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="altContent">
|
||||
<h1>asc2</h1>
|
||||
<p><a href="http://www.adobe.com/go/getflashplayer">Get Adobe Flash player</a></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
4
libsrc/ffdec_lib/testdata/cross_compile/bin/js/swfobject.js
vendored
Normal file
4
libsrc/ffdec_lib/testdata/cross_compile/bin/js/swfobject.js
vendored
Normal file
File diff suppressed because one or more lines are too long
3
libsrc/ffdec_lib/testdata/cross_compile/build_air_debug.bat
vendored
Normal file
3
libsrc/ffdec_lib/testdata/cross_compile/build_air_debug.bat
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
set COMPILERKIND=air
|
||||
call c:\air\bin\mxmlc.bat -warnings=false -debug=true -output bin/Main.%COMPILERKIND%.swf src/Main.as 1> buildlog.%COMPILERKIND%.txt 2>&1
|
||||
6
libsrc/ffdec_lib/testdata/cross_compile/build_debug.bat
vendored
Normal file
6
libsrc/ffdec_lib/testdata/cross_compile/build_debug.bat
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
@echo off
|
||||
call build_air_debug.bat
|
||||
call build_flex_debug.bat
|
||||
call build_flex_apache_debug.bat
|
||||
call build_swftools_debug.bat
|
||||
pause
|
||||
3
libsrc/ffdec_lib/testdata/cross_compile/build_flex_apache_debug.bat
vendored
Normal file
3
libsrc/ffdec_lib/testdata/cross_compile/build_flex_apache_debug.bat
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
set COMPILERKIND=flex_apache
|
||||
call c:\flex_apache\bin\mxmlc.bat -warnings=false -debug=true -output bin/Main.%COMPILERKIND%.swf src/Main.as 1> buildlog.%COMPILERKIND%.txt 2>&1
|
||||
3
libsrc/ffdec_lib/testdata/cross_compile/build_flex_debug.bat
vendored
Normal file
3
libsrc/ffdec_lib/testdata/cross_compile/build_flex_debug.bat
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
set COMPILERKIND=flex
|
||||
c:\flex\bin\mxmlc.exe -warnings=false -debug=true -output bin/Main.%COMPILERKIND%.swf src/Main.as 1> buildlog.%COMPILERKIND%.txt 2>&1
|
||||
19
libsrc/ffdec_lib/testdata/cross_compile/build_stub.bat
vendored
Normal file
19
libsrc/ffdec_lib/testdata/cross_compile/build_stub.bat
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
@echo off
|
||||
set ISDEBUG=false
|
||||
if "%1" == "debug" goto blockset
|
||||
goto block2
|
||||
:blockset
|
||||
set ISDEBUG=true
|
||||
:block2
|
||||
set COMPILERPATH=%2
|
||||
set COMPILERKIND=%3
|
||||
rem if not exist %COMPILERPATH% goto notex
|
||||
%COMPILERPATH% -warnings=false -debug=%ISDEBUG% -output bin/Main.%COMPILERKIND%.swf src/Main.as > buildlog.%COMPILERKIND%.txt
|
||||
if errorlevel==1 goto failed
|
||||
goto end
|
||||
:notex
|
||||
echo Flex/AIR SDK not found. Download and unpack Flex/AIR SDK into some directory and add it to PATH variable
|
||||
goto end
|
||||
:failed
|
||||
pause
|
||||
:end
|
||||
4
libsrc/ffdec_lib/testdata/cross_compile/build_swftools_debug.bat
vendored
Normal file
4
libsrc/ffdec_lib/testdata/cross_compile/build_swftools_debug.bat
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
@echo off
|
||||
set COMPILERKIND=swftools
|
||||
cd src
|
||||
c:\swftools\as3compile.exe Main.as -o ..\bin\Main.%COMPILERKIND%.swf 1> ../buildlog.%COMPILERKIND%.txt 2>&1
|
||||
3
libsrc/ffdec_lib/testdata/cross_compile/buildlog.air.txt
vendored
Normal file
3
libsrc/ffdec_lib/testdata/cross_compile/buildlog.air.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
Loading configuration: c:\air\frameworks\flex-config.xml
|
||||
|
||||
2753 bytes written to C:\Dropbox\Programovani\JavaSE\FFDec\libsrc\ffdec_lib\testdata\cross_compile\bin\Main.air.swf in 0,459 seconds
|
||||
2
libsrc/ffdec_lib/testdata/cross_compile/buildlog.flex.txt
vendored
Normal file
2
libsrc/ffdec_lib/testdata/cross_compile/buildlog.flex.txt
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
Loading configuration file C:\flex\frameworks\flex-config.xml
|
||||
C:\Dropbox\Programovani\JavaSE\FFDec\libsrc\ffdec_lib\testdata\asc2\bin\Main.flex.swf (1083 bytes)
|
||||
2
libsrc/ffdec_lib/testdata/cross_compile/buildlog.flex_apache.txt
vendored
Normal file
2
libsrc/ffdec_lib/testdata/cross_compile/buildlog.flex_apache.txt
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
Loading configuration file C:\flex_apache\frameworks\flex-config.xml
|
||||
C:\Dropbox\Programovani\JavaSE\FFDec\libsrc\ffdec_lib\testdata\cross_compile\bin\Main.flex_apache.swf (3617 bytes)
|
||||
4
libsrc/ffdec_lib/testdata/cross_compile/buildlog.swftools.txt
vendored
Normal file
4
libsrc/ffdec_lib/testdata/cross_compile/buildlog.swftools.txt
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
Stack mismatch at pos 61
|
||||
Should be: 1:1, is: 0:1
|
||||
Stack mismatch at pos 61
|
||||
Should be: 1:1, is: 0:1
|
||||
95
libsrc/ffdec_lib/testdata/cross_compile/cross_compile.as3proj
vendored
Normal file
95
libsrc/ffdec_lib/testdata/cross_compile/cross_compile.as3proj
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<project version="2">
|
||||
<!-- Output SWF options -->
|
||||
<output>
|
||||
<movie outputType="Application" />
|
||||
<movie input="" />
|
||||
<movie path="bin\Main.flex.swf" />
|
||||
<movie fps="30" />
|
||||
<movie width="800" />
|
||||
<movie height="600" />
|
||||
<movie version="25" />
|
||||
<movie minorVersion="0" />
|
||||
<movie platform="Flash Player" />
|
||||
<movie background="#FFFFFF" />
|
||||
</output>
|
||||
<!-- Other classes to be compiled into your SWF -->
|
||||
<classpaths>
|
||||
<class path="src" />
|
||||
</classpaths>
|
||||
<!-- Build options -->
|
||||
<build>
|
||||
<option accessible="False" />
|
||||
<option advancedTelemetry="False" />
|
||||
<option allowSourcePathOverlap="False" />
|
||||
<option benchmark="False" />
|
||||
<option es="False" />
|
||||
<option inline="False" />
|
||||
<option locale="" />
|
||||
<option loadConfig="" />
|
||||
<option optimize="True" />
|
||||
<option omitTraces="True" />
|
||||
<option showActionScriptWarnings="True" />
|
||||
<option showBindingWarnings="True" />
|
||||
<option showInvalidCSS="True" />
|
||||
<option showDeprecationWarnings="True" />
|
||||
<option showUnusedTypeSelectorWarnings="True" />
|
||||
<option strict="True" />
|
||||
<option useNetwork="True" />
|
||||
<option useResourceBundleMetadata="True" />
|
||||
<option warnings="True" />
|
||||
<option verboseStackTraces="False" />
|
||||
<option linkReport="" />
|
||||
<option loadExterns="" />
|
||||
<option staticLinkRSL="True" />
|
||||
<option additional="" />
|
||||
<option compilerConstants="" />
|
||||
<option minorVersion="" />
|
||||
</build>
|
||||
<!-- SWC Include Libraries -->
|
||||
<includeLibraries>
|
||||
<!-- example: <element path="..." /> -->
|
||||
</includeLibraries>
|
||||
<!-- SWC Libraries -->
|
||||
<libraryPaths>
|
||||
<!-- example: <element path="..." /> -->
|
||||
</libraryPaths>
|
||||
<!-- External Libraries -->
|
||||
<externalLibraryPaths>
|
||||
<!-- example: <element path="..." /> -->
|
||||
</externalLibraryPaths>
|
||||
<!-- Runtime Shared Libraries -->
|
||||
<rslPaths>
|
||||
<!-- example: <element path="..." /> -->
|
||||
</rslPaths>
|
||||
<!-- Intrinsic Libraries -->
|
||||
<intrinsics>
|
||||
<!-- example: <element path="..." /> -->
|
||||
</intrinsics>
|
||||
<!-- Assets to embed into the output SWF -->
|
||||
<library>
|
||||
<!-- example: <asset path="..." id="..." update="..." glyphs="..." mode="..." place="..." sharepoint="..." /> -->
|
||||
</library>
|
||||
<!-- Class files to compile (other referenced classes will automatically be included) -->
|
||||
<compileTargets>
|
||||
<compile path="src\Main.as" />
|
||||
</compileTargets>
|
||||
<!-- Paths to exclude from the Project Explorer tree -->
|
||||
<hiddenPaths>
|
||||
<hidden path="obj" />
|
||||
</hiddenPaths>
|
||||
<!-- Executed before build -->
|
||||
<preBuildCommand />
|
||||
<!-- Executed after build -->
|
||||
<postBuildCommand alwaysRun="False">build_air_debug.bat
|
||||
build_flex_apache_debug.bat
|
||||
build_swftools_debug.bat</postBuildCommand>
|
||||
<!-- Other project options -->
|
||||
<options>
|
||||
<option showHiddenPaths="False" />
|
||||
<option testMovie="Default" />
|
||||
<option testMovieCommand="" />
|
||||
</options>
|
||||
<!-- Plugin storage -->
|
||||
<storage />
|
||||
</project>
|
||||
48
libsrc/ffdec_lib/testdata/cross_compile/obj/cross_compileConfig.old
vendored
Normal file
48
libsrc/ffdec_lib/testdata/cross_compile/obj/cross_compileConfig.old
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--This Adobe Flex compiler configuration file was generated by a tool.-->
|
||||
<!--Any modifications you make may be lost.-->
|
||||
<flex-config>
|
||||
<target-player>25.0</target-player>
|
||||
<benchmark>false</benchmark>
|
||||
<static-link-runtime-shared-libraries>true</static-link-runtime-shared-libraries>
|
||||
<compiler>
|
||||
<define append="true">
|
||||
<name>CONFIG::debug</name>
|
||||
<value>true</value>
|
||||
</define>
|
||||
<define append="true">
|
||||
<name>CONFIG::release</name>
|
||||
<value>false</value>
|
||||
</define>
|
||||
<define append="true">
|
||||
<name>CONFIG::timeStamp</name>
|
||||
<value>'31.01.2021'</value>
|
||||
</define>
|
||||
<define append="true">
|
||||
<name>CONFIG::air</name>
|
||||
<value>false</value>
|
||||
</define>
|
||||
<define append="true">
|
||||
<name>CONFIG::mobile</name>
|
||||
<value>false</value>
|
||||
</define>
|
||||
<define append="true">
|
||||
<name>CONFIG::desktop</name>
|
||||
<value>false</value>
|
||||
</define>
|
||||
<verbose-stacktraces>true</verbose-stacktraces>
|
||||
<source-path append="true">
|
||||
<path-element>C:\Dropbox\Programovani\JavaSE\FFDec\libsrc\ffdec_lib\testdata\cross_compile\src</path-element>
|
||||
<path-element>C:\Program Files (x86)\FlashDevelop\Library\AS3\classes</path-element>
|
||||
</source-path>
|
||||
</compiler>
|
||||
<file-specs>
|
||||
<path-element>C:\Dropbox\Programovani\JavaSE\FFDec\libsrc\ffdec_lib\testdata\cross_compile\src\Main.as</path-element>
|
||||
</file-specs>
|
||||
<default-background-color>#FFFFFF</default-background-color>
|
||||
<default-frame-rate>30</default-frame-rate>
|
||||
<default-size>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</default-size>
|
||||
</flex-config>
|
||||
48
libsrc/ffdec_lib/testdata/cross_compile/obj/cross_compileConfig.xml
vendored
Normal file
48
libsrc/ffdec_lib/testdata/cross_compile/obj/cross_compileConfig.xml
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--This Adobe Flex compiler configuration file was generated by a tool.-->
|
||||
<!--Any modifications you make may be lost.-->
|
||||
<flex-config>
|
||||
<target-player>25.0</target-player>
|
||||
<benchmark>false</benchmark>
|
||||
<static-link-runtime-shared-libraries>true</static-link-runtime-shared-libraries>
|
||||
<compiler>
|
||||
<define append="true">
|
||||
<name>CONFIG::debug</name>
|
||||
<value>true</value>
|
||||
</define>
|
||||
<define append="true">
|
||||
<name>CONFIG::release</name>
|
||||
<value>false</value>
|
||||
</define>
|
||||
<define append="true">
|
||||
<name>CONFIG::timeStamp</name>
|
||||
<value>'31.01.2021'</value>
|
||||
</define>
|
||||
<define append="true">
|
||||
<name>CONFIG::air</name>
|
||||
<value>false</value>
|
||||
</define>
|
||||
<define append="true">
|
||||
<name>CONFIG::mobile</name>
|
||||
<value>false</value>
|
||||
</define>
|
||||
<define append="true">
|
||||
<name>CONFIG::desktop</name>
|
||||
<value>false</value>
|
||||
</define>
|
||||
<verbose-stacktraces>true</verbose-stacktraces>
|
||||
<source-path append="true">
|
||||
<path-element>C:\Dropbox\Programovani\JavaSE\FFDec\libsrc\ffdec_lib\testdata\cross_compile\src</path-element>
|
||||
<path-element>C:\Program Files (x86)\FlashDevelop\Library\AS3\classes</path-element>
|
||||
</source-path>
|
||||
</compiler>
|
||||
<file-specs>
|
||||
<path-element>C:\Dropbox\Programovani\JavaSE\FFDec\libsrc\ffdec_lib\testdata\cross_compile\src\Main.as</path-element>
|
||||
</file-specs>
|
||||
<default-background-color>#FFFFFF</default-background-color>
|
||||
<default-frame-rate>30</default-frame-rate>
|
||||
<default-size>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</default-size>
|
||||
</flex-config>
|
||||
34
libsrc/ffdec_lib/testdata/cross_compile/src/Main.as
vendored
Normal file
34
libsrc/ffdec_lib/testdata/cross_compile/src/Main.as
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
package
|
||||
{
|
||||
import flash.display.MovieClip;
|
||||
import flash.events.Event;
|
||||
import tests.*;
|
||||
|
||||
/**
|
||||
* ...
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class Main extends MovieClip
|
||||
{
|
||||
TestTryCatch;
|
||||
TestTryCatchIfInTry;
|
||||
TestTryCatchLoop;
|
||||
TestTryCatchExceptionUsage
|
||||
TestTryFinally;
|
||||
TestTryFinallyDirectReturnInFinally;
|
||||
TestTryFinallyLoop;
|
||||
TestTryFinallyLoopInFinally;
|
||||
TestTryFinallyMultipleCatch;
|
||||
TestTryFinallyReturn;
|
||||
TestTryFinallyReturnInFinally;
|
||||
TestTryFinallyReturnNested;
|
||||
TestTryFinallyReturnVoid;
|
||||
|
||||
public function Main()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
26
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryCatch.as
vendored
Normal file
26
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryCatch.as
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
package tests
|
||||
{
|
||||
/**
|
||||
* ...
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TestTryCatch
|
||||
{
|
||||
|
||||
public function run() : void
|
||||
{
|
||||
trace("before try");
|
||||
try
|
||||
{
|
||||
trace("in try");
|
||||
}
|
||||
catch (e:Error)
|
||||
{
|
||||
trace("in catch");
|
||||
}
|
||||
trace("after");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
26
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryCatchExceptionUsage.as
vendored
Normal file
26
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryCatchExceptionUsage.as
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
package tests
|
||||
{
|
||||
/**
|
||||
* ...
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TestTryCatchExceptionUsage
|
||||
{
|
||||
|
||||
public function run() : void
|
||||
{
|
||||
trace("before try");
|
||||
try
|
||||
{
|
||||
trace("in try");
|
||||
}
|
||||
catch (e:Error)
|
||||
{
|
||||
trace("catched exception: "+e.message);
|
||||
}
|
||||
trace("after");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
32
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryCatchIfInTry.as
vendored
Normal file
32
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryCatchIfInTry.as
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
package tests
|
||||
{
|
||||
/**
|
||||
* ...
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TestTryCatchIfInTry
|
||||
{
|
||||
|
||||
public function run() : void
|
||||
{
|
||||
var a:Boolean = true;
|
||||
trace("before");
|
||||
try
|
||||
{
|
||||
if (a)
|
||||
{
|
||||
trace("ret");
|
||||
return;
|
||||
}
|
||||
trace("in try");
|
||||
}
|
||||
catch (e:Error)
|
||||
{
|
||||
trace("in catch");
|
||||
}
|
||||
trace("after");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
39
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryCatchLoop.as
vendored
Normal file
39
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryCatchLoop.as
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
package tests
|
||||
{
|
||||
import flash.errors.EOFError;
|
||||
|
||||
/**
|
||||
* ...
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TestTryCatchLoop
|
||||
{
|
||||
|
||||
public function run() : void
|
||||
{
|
||||
var j:* = undefined;
|
||||
for (var i:* = 0; i < 100; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
for (j = 0; j < 20; j++)
|
||||
{
|
||||
trace("a");
|
||||
}
|
||||
}
|
||||
catch (e:EOFError)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
catch (e:Error)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
trace("after_try");
|
||||
}
|
||||
trace("end");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
30
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinally.as
vendored
Normal file
30
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinally.as
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
package tests
|
||||
{
|
||||
/**
|
||||
* ...
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TestTryFinally
|
||||
{
|
||||
|
||||
public function run() : void
|
||||
{
|
||||
trace("before try");
|
||||
try
|
||||
{
|
||||
trace("in try");
|
||||
}
|
||||
catch (e:Error)
|
||||
{
|
||||
trace("in catch");
|
||||
}
|
||||
finally
|
||||
{
|
||||
trace("in finally");
|
||||
}
|
||||
trace("after");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
34
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyDirectReturnInFinally.as
vendored
Normal file
34
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyDirectReturnInFinally.as
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
package tests
|
||||
{
|
||||
/**
|
||||
* ...
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TestTryFinallyDirectReturnInFinally
|
||||
{
|
||||
|
||||
public function run() : String
|
||||
{
|
||||
|
||||
var str:String = "xxx";
|
||||
try
|
||||
{
|
||||
}
|
||||
catch (e:Error)
|
||||
{
|
||||
trace("error");
|
||||
}
|
||||
finally
|
||||
{
|
||||
trace("hi ");
|
||||
if (5 == 4)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
return "hu" + str;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
38
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyLoop.as
vendored
Normal file
38
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyLoop.as
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
package tests
|
||||
{
|
||||
/**
|
||||
* ...
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TestTryFinallyLoop
|
||||
{
|
||||
|
||||
public function run() : void
|
||||
{
|
||||
for (var i:int = 0; i < 10; i++)
|
||||
{
|
||||
trace("before try");
|
||||
try
|
||||
{
|
||||
trace("in try");
|
||||
if (i == 5)
|
||||
{
|
||||
trace("continue for");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch (e:Error)
|
||||
{
|
||||
trace("in catch");
|
||||
}
|
||||
finally
|
||||
{
|
||||
trace("in finally");
|
||||
}
|
||||
trace("after");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
38
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyLoopInFinally.as
vendored
Normal file
38
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyLoopInFinally.as
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
package tests
|
||||
{
|
||||
/**
|
||||
* ...
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TestTryFinallyLoopInFinally
|
||||
{
|
||||
|
||||
public function run() : void
|
||||
{
|
||||
for (var i:int = 0; i < 10; i++)
|
||||
{
|
||||
trace("before try");
|
||||
try
|
||||
{
|
||||
trace("in try");
|
||||
}
|
||||
catch (e:Error)
|
||||
{
|
||||
trace("in catch");
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (i == 5)
|
||||
{
|
||||
trace("continue for");
|
||||
continue;
|
||||
}
|
||||
trace("in finally");
|
||||
}
|
||||
trace("after");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
35
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyMultipleCatch.as
vendored
Normal file
35
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyMultipleCatch.as
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
package tests
|
||||
{
|
||||
import flash.errors.EOFError;
|
||||
/**
|
||||
* ...
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TestTryFinallyMultipleCatch
|
||||
{
|
||||
|
||||
public function run() : void
|
||||
{
|
||||
trace("before try");
|
||||
try
|
||||
{
|
||||
trace("in try");
|
||||
}
|
||||
catch (e:Error)
|
||||
{
|
||||
trace("in catch Error");
|
||||
}
|
||||
catch (e:EOFError)
|
||||
{
|
||||
trace("in catch EOFError");
|
||||
}
|
||||
finally
|
||||
{
|
||||
trace("in finally");
|
||||
}
|
||||
trace("after");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
42
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyReturn.as
vendored
Normal file
42
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyReturn.as
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
package tests
|
||||
{
|
||||
/**
|
||||
* ...
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TestTryFinallyReturn
|
||||
{
|
||||
|
||||
public function run() : String
|
||||
{
|
||||
trace("before try");
|
||||
try
|
||||
{
|
||||
trace("in try");
|
||||
var a:int = 5;
|
||||
if (a > 4)
|
||||
{
|
||||
return "RET";
|
||||
}
|
||||
trace("between");
|
||||
if (a < 3)
|
||||
{
|
||||
return "RE2";
|
||||
}
|
||||
trace("in try2");
|
||||
}
|
||||
catch (e:Error)
|
||||
{
|
||||
trace("in catch");
|
||||
}
|
||||
finally
|
||||
{
|
||||
trace("in finally");
|
||||
}
|
||||
trace("after");
|
||||
return "RETFINAL";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
44
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyReturnInFinally.as
vendored
Normal file
44
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyReturnInFinally.as
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
package tests
|
||||
{
|
||||
/**
|
||||
* ...
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TestTryFinallyReturnInFinally
|
||||
{
|
||||
|
||||
public function run() : String
|
||||
{
|
||||
trace("before try");
|
||||
try
|
||||
{
|
||||
trace("in try");
|
||||
var a:int = 5;
|
||||
if (a > 4)
|
||||
{
|
||||
return "RET";
|
||||
}
|
||||
}
|
||||
catch (e:Error)
|
||||
{
|
||||
trace("in catch");
|
||||
}
|
||||
finally
|
||||
{
|
||||
trace("in finally");
|
||||
if (a > 6){
|
||||
return "FINRET1";
|
||||
}
|
||||
trace("xx");
|
||||
if (a > 5){
|
||||
return "FINRET2";
|
||||
}
|
||||
trace("nofinret");
|
||||
}
|
||||
trace("after");
|
||||
return "RETEXIT";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
43
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyReturnNested.as
vendored
Normal file
43
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyReturnNested.as
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
package tests
|
||||
{
|
||||
/**
|
||||
* ...
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TestTryFinallyReturnNested
|
||||
{
|
||||
|
||||
public function run() : String
|
||||
{
|
||||
try
|
||||
{
|
||||
trace("before try2");
|
||||
try
|
||||
{
|
||||
trace("in try2");
|
||||
var a:int = 5;
|
||||
if (a > 4)
|
||||
{
|
||||
return "RET";
|
||||
}
|
||||
}
|
||||
catch (e:Error)
|
||||
{
|
||||
trace("in catch");
|
||||
}
|
||||
finally
|
||||
{
|
||||
trace("in finally2");
|
||||
}
|
||||
trace("after");
|
||||
}
|
||||
finally
|
||||
{
|
||||
trace("in finally1");
|
||||
}
|
||||
return "RETFINAL";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
36
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyReturnVoid.as
vendored
Normal file
36
libsrc/ffdec_lib/testdata/cross_compile/src/tests/TestTryFinallyReturnVoid.as
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
package tests
|
||||
{
|
||||
/**
|
||||
* ...
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TestTryFinallyReturnVoid
|
||||
{
|
||||
|
||||
public function run() : void
|
||||
{
|
||||
trace("before try");
|
||||
try
|
||||
{
|
||||
trace("in try");
|
||||
var a:int = 5;
|
||||
if (a > 4)
|
||||
{
|
||||
return;
|
||||
}
|
||||
trace("in try2");
|
||||
}
|
||||
catch (e:Error)
|
||||
{
|
||||
trace("in catch");
|
||||
}
|
||||
finally
|
||||
{
|
||||
trace("in finally");
|
||||
}
|
||||
trace("after");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -249,6 +249,10 @@
|
||||
<label>core.lexers</label>
|
||||
<location>libsrc/ffdec_lib/lexers</location>
|
||||
</source-folder>
|
||||
<source-folder style="packages">
|
||||
<label>core.graphviz</label>
|
||||
<location>libsrc/ffdec_lib/graphviz</location>
|
||||
</source-folder>
|
||||
<source-file>
|
||||
<location>build.xml</location>
|
||||
</source-file>
|
||||
|
||||
Reference in New Issue
Block a user