in modules/swfutils/src/java/flash/swf/MovieMetaData.java [599:1059]
public static void walkActions(ActionList c, int swfVersion, String[] pool, String className, List<Integer> profileOffsets)
{
// assumption: ActionContext c is always not null! try-catch-finally may be busted.
if (c == null) return;
Stack<Object> evalStack = new Stack<Object>();
HashMap<Object, Object> variables = new HashMap<Object, Object>();
// loop again, this time, we register all the actions...
int offset;
Action a;
for (int i=0; i < c.size(); i++)
{
offset = c.getOffset(i);
a = c.getAction(i);
switch (a.code)
{
// Flash 1 and 2 actions
case ActionConstants.sactionHasLength:
case ActionConstants.sactionNone:
case ActionConstants.sactionGotoFrame:
case ActionConstants.sactionGetURL:
case ActionConstants.sactionNextFrame:
case ActionConstants.sactionPrevFrame:
case ActionConstants.sactionPlay:
case ActionConstants.sactionStop:
case ActionConstants.sactionToggleQuality:
case ActionConstants.sactionStopSounds:
case ActionConstants.sactionWaitForFrame:
// Flash 3 Actions
case ActionConstants.sactionSetTarget:
case ActionConstants.sactionGotoLabel:
// no action
break;
// Flash 4 Actions
case ActionConstants.sactionAdd:
case ActionConstants.sactionSubtract:
case ActionConstants.sactionMultiply:
case ActionConstants.sactionDivide:
case ActionConstants.sactionEquals:
case ActionConstants.sactionLess:
case ActionConstants.sactionAnd:
case ActionConstants.sactionOr:
case ActionConstants.sactionStringEquals:
case ActionConstants.sactionStringAdd:
case ActionConstants.sactionStringLess:
case ActionConstants.sactionMBStringLength:
case ActionConstants.sactionGetProperty:
// pop, pop, push
pop(evalStack);
break;
case ActionConstants.sactionNot:
case ActionConstants.sactionStringLength:
case ActionConstants.sactionToInteger:
case ActionConstants.sactionCharToAscii:
case ActionConstants.sactionAsciiToChar:
case ActionConstants.sactionMBCharToAscii:
case ActionConstants.sactionMBAsciiToChar:
case ActionConstants.sactionRandomNumber:
// pop, push
break;
case ActionConstants.sactionGetVariable:
Object key = pop(evalStack);
if (variables.get(key) == null)
{
evalStack.push(key);
}
else
{
evalStack.push(variables.get(key));
}
break;
case ActionConstants.sactionStringExtract:
case ActionConstants.sactionMBStringExtract:
// pop, pop, pop, push
pop(evalStack);
pop(evalStack);
break;
case ActionConstants.sactionPush:
Push p = (Push) a;
Object o = p.value;
int type = Push.getTypeCode(o);
switch (type)
{
case Push.kPushStringType:
evalStack.push(o);
break;
case Push.kPushNullType:
evalStack.push("null");
break;
case Push.kPushUndefinedType:
evalStack.push("undefined");
break;
case Push.kPushRegisterType:
evalStack.push(registers[((Byte)o).intValue()&0xFF]);
break;
case Push.kPushConstant8Type:
case Push.kPushConstant16Type:
evalStack.push(pool[((Number) o).intValue()&0xFFFF]);
break;
case Push.kPushFloatType:
evalStack.push(o + "F");
break;
case Push.kPushBooleanType:
case Push.kPushDoubleType:
case Push.kPushIntegerType:
evalStack.push(o);
break;
default:
evalStack.push("type" + type);
break;
}
break;
case ActionConstants.sactionIf:
pop(evalStack);
break;
case ActionConstants.sactionPop:
case ActionConstants.sactionCall:
case ActionConstants.sactionGotoFrame2:
case ActionConstants.sactionSetTarget2:
case ActionConstants.sactionRemoveSprite:
case ActionConstants.sactionWaitForFrame2:
case ActionConstants.sactionTrace:
// pop
pop(evalStack);
break;
case ActionConstants.sactionJump:
case ActionConstants.sactionEndDrag:
// no action
break;
case ActionConstants.sactionSetVariable:
key = pop(evalStack);
Object val = pop(evalStack);
variables.put(key, val);
break;
case ActionConstants.sactionGetURL2:
// pop, pop
pop(evalStack);
pop(evalStack);
break;
case ActionConstants.sactionSetProperty:
case ActionConstants.sactionCloneSprite:
// pop, pop, pop
pop(evalStack);
pop(evalStack);
pop(evalStack);
break;
case ActionConstants.sactionStartDrag:
// pop, pop, pop, if the 3rd pop is non-zero, pop, pop, pop, pop
pop(evalStack);
pop(evalStack);
Object obj = pop(evalStack);
if (Integer.parseInt(obj.toString()) != 0)
{
pop(evalStack);
pop(evalStack);
pop(evalStack);
pop(evalStack);
}
break;
case ActionConstants.sactionGetTime:
// push
evalStack.push(dummy);
break;
// Flash 5 actions
case ActionConstants.sactionDelete:
pop(evalStack);
break;
case ActionConstants.sactionDefineLocal:
// pop, pop
val = pop(evalStack);
key = pop(evalStack);
variables.put(key, val);
break;
case ActionConstants.sactionDefineFunction:
case ActionConstants.sactionDefineFunction2:
DefineFunction f = (DefineFunction) a;
if (swfVersion > 6 && className != null)
{
if (f.name == null || f.name.length() == 0)
{
int depth = evalStack.size();
if (depth != 0)
{
o = evalStack.peek();
if (o == dummy)
{
f.name = "";
}
else if (o != null)
{
f.name = o.toString();
}
}
evalStack.push(dummy);
}
if ("null".equals(f.name))
{
f.name = "";
}
if (f.name == null || f.name.length() == 0)
{
// do nothing... it's an anonymous function!
}
else if (!className.endsWith(f.name))
{
f.name = className + "." + f.name;
}
else
{
f.name = className + ".[constructor]";
}
}
else
{
if (f.name == null || f.name.length() == 0)
{
StringBuilder buffer = new StringBuilder();
int depth = evalStack.size();
for (int k = depth - 1; k >= 0; k--)
{
o = evalStack.get(k);
if (o == dummy)
{
break;
}
else if (k == depth - 1)
{
buffer.append(o);
}
else
{
buffer.insert(0, '.');
buffer.insert(0, o);
}
}
f.name = buffer.toString();
if (f.name != null && f.name.indexOf(".prototype.") == -1)
{
f.name = "";
}
evalStack.push(dummy);
}
}
// evalActions(f.actions);
break;
case ActionConstants.sactionCallFunction:
Object function = pop(evalStack);
if (profileOffsets != null && "profile".equals(function))
{
profileOffsets.add(new Integer(offset - 13)); // Push 1
profileOffsets.add(new Integer(offset - 5)); // Push 'profile'
profileOffsets.add(new Integer(offset)); // CallFunction
profileOffsets.add(new Integer(offset + 1)); // Pop
}
int n = ((Number) pop(evalStack)).intValue();
for (int k = 0; k < n; k++)
{
pop(evalStack);
}
evalStack.push(dummy);
break;
case ActionConstants.sactionReturn:
// return function() { ... } doesn't push...
pop(evalStack);
break;
case ActionConstants.sactionModulo:
// pop, push
break;
case ActionConstants.sactionNewObject:
pop(evalStack);
int num = ((Number) pop(evalStack)).intValue();
for (int k = 0; k < num; k++)
{
pop(evalStack);
}
evalStack.push(dummy);
break;
case ActionConstants.sactionDefineLocal2:
case ActionConstants.sactionDelete2:
case ActionConstants.sactionAdd2:
case ActionConstants.sactionLess2:
// pop
pop(evalStack);
break;
case ActionConstants.sactionInitArray:
// pop, if the first pop is non-zero, keep popping
num = ((Number) pop(evalStack)).intValue();
for (int k = 0; k < num; k++)
{
pop(evalStack);
}
evalStack.push(dummy);
break;
case ActionConstants.sactionInitObject:
num = ((Number) pop(evalStack)).intValue() * 2;
for (int k = 0; k < num; k++)
{
pop(evalStack);
}
evalStack.push(dummy);
break;
case ActionConstants.sactionTargetPath:
case ActionConstants.sactionEnumerate:
case ActionConstants.sactionToNumber:
case ActionConstants.sactionToString:
case ActionConstants.sactionTypeOf:
// no action
break;
case ActionConstants.sactionStoreRegister:
StoreRegister r = (StoreRegister) a;
registers[r.register] = evalStack.peek();
break;
case ActionConstants.sactionEquals2:
// pop, pop, push
// if (evalStack.size() >= 2)
{
pop(evalStack);
}
break;
case ActionConstants.sactionPushDuplicate:
evalStack.push(dummy);
break;
case ActionConstants.sactionStackSwap:
// pop, pop, push, push
break;
case ActionConstants.sactionGetMember:
// pop, pop, concat, push
Object o1 = pop(evalStack);
Object o2 = pop(evalStack);
if (pool != null)
{
try
{
evalStack.push(pool[Integer.parseInt(o2.toString())] + "." + pool[Integer.parseInt(o1.toString())]);
}
catch (Exception ex)
{
if (o1 == dummy || o2 == dummy)
{
evalStack.push(dummy);
}
else
{
evalStack.push(o2 + "." + o1);
}
}
}
else
{
evalStack.push(o2 + "." + o1);
}
break;
case ActionConstants.sactionSetMember:
// pop, pop, pop
pop(evalStack);
pop(evalStack);
pop(evalStack);
break;
case ActionConstants.sactionIncrement:
case ActionConstants.sactionDecrement:
break;
case ActionConstants.sactionCallMethod:
pop(evalStack);
pop(evalStack);
Object obj2 = pop(evalStack);
if (obj2 instanceof String)
{
try {
n = Integer.parseInt((String) obj2);
}
catch (NumberFormatException ex)
{
n = 1;
}
}
else
{
n = ((Number) obj2).intValue();
}
for (int k = 0; k < n; k++)
{
pop(evalStack);
}
evalStack.push(dummy);
break;
case ActionConstants.sactionNewMethod:
/*Object meth =*/ pop(evalStack);
/*Object cls =*/ pop(evalStack);
num = ((Number) pop(evalStack)).intValue();
for (int k = 0; k < num; k++)
{
pop(evalStack);
}
evalStack.push(dummy);
break;
case ActionConstants.sactionWith:
// pop
pop(evalStack);
break;
case ActionConstants.sactionConstantPool:
pool = ((ConstantPool) a).pool;
// no action
break;
case ActionConstants.sactionStrictMode:
break;
case ActionConstants.sactionBitAnd:
case ActionConstants.sactionBitOr:
case ActionConstants.sactionBitLShift:
// pop, push
break;
case ActionConstants.sactionBitXor:
case ActionConstants.sactionBitRShift:
case ActionConstants.sactionBitURShift:
pop(evalStack);
break;
// Flash 6 actions
case ActionConstants.sactionInstanceOf:
pop(evalStack);
break;
case ActionConstants.sactionEnumerate2:
// pop, push, more pushes?
break;
case ActionConstants.sactionStrictEquals:
case ActionConstants.sactionGreater:
case ActionConstants.sactionStringGreater:
pop(evalStack);
break;
// FEATURE_EXCEPTIONS
case ActionConstants.sactionTry:
// do nothing
break;
case ActionConstants.sactionThrow:
pop(evalStack);
break;
// FEATURE_AS2_INTERFACES
case ActionConstants.sactionCastOp:
break;
case ActionConstants.sactionImplementsOp:
break;
// Reserved for Quicktime
case ActionConstants.sactionQuickTime:
break;
default:
break;
}
}
}