[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash ChangeLog server/Function.cpp server/Func...
From: |
Sandro Santilli |
Subject: |
[Gnash-commit] gnash ChangeLog server/Function.cpp server/Func... |
Date: |
Sun, 25 Jun 2006 16:53:04 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Sandro Santilli <strk> 06/06/25 16:53:04
Modified files:
. : ChangeLog
server : Function.cpp Function.h Makefile.am
action_buffer.cpp action_buffer.h
server/swf : ASHandlers.cpp ASHandlers.h
Added files:
server : ActionExec.cpp ActionExec.h
Log message:
* server/ActionExec.cpp, server/ActionExec.h,
server/Makefile.am: new class for action_buffer
execution context.
* server/Function.cpp, server/Function.h:
use action_buffer by const pointers .
* server/action_buffer.cpp, server/action_buffer.h:
added utility functions to read data from the buffer
to eventually use a stream instead.
* server/swf/ASHandlers.cpp, server/swf/ASHandlers.h:
SWFHandlers made a singleton (hopefully fixes the static
initialization problem), used a fixed-size vector
for SWFHandlers::_handlers (faster). Ported some
ActionHandlers from ActionExec (work unfinished).
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.430&r2=1.431
http://cvs.savannah.gnu.org/viewcvs/gnash/server/Function.cpp?cvsroot=gnash&r1=1.18&r2=1.19
http://cvs.savannah.gnu.org/viewcvs/gnash/server/Function.h?cvsroot=gnash&r1=1.10&r2=1.11
http://cvs.savannah.gnu.org/viewcvs/gnash/server/Makefile.am?cvsroot=gnash&r1=1.48&r2=1.49
http://cvs.savannah.gnu.org/viewcvs/gnash/server/action_buffer.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/server/action_buffer.h?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/server/ActionExec.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/ActionExec.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/swf/ASHandlers.cpp?cvsroot=gnash&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/gnash/server/swf/ASHandlers.h?cvsroot=gnash&r1=1.1&r2=1.2
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.430
retrieving revision 1.431
diff -u -b -r1.430 -r1.431
--- ChangeLog 24 Jun 2006 17:56:35 -0000 1.430
+++ ChangeLog 25 Jun 2006 16:53:04 -0000 1.431
@@ -1,3 +1,19 @@
+2006-06-25 Sandro Santilli <address@hidden>
+
+ * server/ActionExec.cpp, server/ActionExec.h,
+ server/Makefile.am: new class for action_buffer
+ execution context.
+ * server/Function.cpp, server/Function.h:
+ use action_buffer by const pointers .
+ * server/action_buffer.cpp, server/action_buffer.h:
+ added utility functions to read data from the buffer
+ to eventually use a stream instead.
+ * server/swf/ASHandlers.cpp, server/swf/ASHandlers.h:
+ SWFHandlers made a singleton (hopefully fixes the static
+ initialization problem), used a fixed-size vector
+ for SWFHandlers::_handlers (faster). Ported some
+ ActionHandlers from ActionExec (work unfinished).
+
2006-06-24 Sandro Santilli <address@hidden>
* server/movie_def_impl.h, server/movie_definition.h,
Index: server/Function.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/Function.cpp,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -b -r1.18 -r1.19
--- server/Function.cpp 21 Jun 2006 23:06:41 -0000 1.18
+++ server/Function.cpp 25 Jun 2006 16:53:04 -0000 1.19
@@ -182,7 +182,8 @@
}
-function_as_object::function_as_object(action_buffer* ab, as_environment* env,
+function_as_object::function_as_object(const action_buffer* ab,
+ as_environment* env,
size_t start, const std::vector<with_stack_entry>& with_stack)
:
as_object(getFunctionPrototype()),
Index: server/Function.h
===================================================================
RCS file: /sources/gnash/gnash/server/Function.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- server/Function.h 21 Jun 2006 20:56:38 -0000 1.10
+++ server/Function.h 25 Jun 2006 16:53:04 -0000 1.11
@@ -61,7 +61,7 @@
public:
/// Action buffer containing the function definition
- action_buffer* m_action_buffer;
+ const action_buffer* m_action_buffer;
/// @@ might need some kind of ref count here, but beware cycles
as_environment* m_env;
@@ -135,7 +135,8 @@
/// environment, rather than the environment where they
/// were defined.
///
- function_as_object(action_buffer* ab, as_environment* env,
+ function_as_object(const action_buffer* ab,
+ as_environment* env,
size_t start,
const std::vector<with_stack_entry>& with_stack);
Index: server/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/Makefile.am,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -b -r1.48 -r1.49
--- server/Makefile.am 20 Jun 2006 11:12:36 -0000 1.48
+++ server/Makefile.am 25 Jun 2006 16:53:04 -0000 1.49
@@ -137,6 +137,7 @@
string.cpp \
action.cpp \
action_buffer.cpp \
+ ActionExec.cpp \
button.cpp \
dlist.cpp \
edit_text_character.cpp \
@@ -168,6 +169,7 @@
noinst_HEADERS = $(as_incls) \
action.h \
action_buffer.h \
+ ActionExec.h \
array.h \
as_value.h \
as_environment.h \
Index: server/action_buffer.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/action_buffer.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- server/action_buffer.cpp 21 Jun 2006 09:06:01 -0000 1.2
+++ server/action_buffer.cpp 25 Jun 2006 16:53:04 -0000 1.3
@@ -39,6 +39,7 @@
#endif
#include "action_buffer.h"
+#include "ActionExec.h"
#include "Function.h" // for function_as_object
#include "log.h"
#include "stream.h"
@@ -64,46 +65,14 @@
namespace gnash {
-// Vitaly: SWF::SWFHandlers::_handlers & SWF::SWFHandlers::_property_names
-// are used at creation "SWFHandlers ash" and consequently they should be
certain here
-std::map<action_type, ActionHandler> SWF::SWFHandlers::_handlers;
-std::vector<std::string> SWF::SWFHandlers::_property_names;
-
-static SWFHandlers ash;
-
-// Utility. Try to convert str to a number. If successful,
-// put the result in *result, and return true. If not
-// successful, put 0 in *result, and return false.
-static bool string_to_number(double* result, const char* str)
-{
- char* tail = 0;
- *result = strtod(str, &tail);
- if (tail == str || *tail != 0)
- {
- // Failed conversion to Number.
- return false;
- }
- return true;
-}
-
-fscommand_callback s_fscommand_handler = NULL;
-
-// External interface.
-void register_fscommand_callback(fscommand_callback handler)
-{
- s_fscommand_handler = handler;
-}
-
-
-
-// Disassemble one instruction to the log.
-static void
-log_disasm(const unsigned char* instruction_data);
+static const SWFHandlers& ash = SWFHandlers::instance();
action_buffer::action_buffer()
:
m_decl_dict_processed_at(-1)
{
+ static int count=0;
+ printf("Action buffer %d created\n", ++count);
}
@@ -112,20 +81,20 @@
{
// Read action bytes.
for (;;) {
- int instruction_start = m_buffer.size();
+ size_t instruction_start = m_buffer.size();
- int pc = m_buffer.size();
+ size_t pc = m_buffer.size();
- int action_id = in->read_u8();
+ uint8_t action_id = in->read_u8();
m_buffer.push_back(action_id);
if (action_id & 0x80) {
// Action contains extra data. Read it.
- int length = in->read_u16();
+ uint16_t length = in->read_u16();
m_buffer.push_back(length & 0x0FF);
m_buffer.push_back((length >> 8) & 0x0FF);
- for (int i = 0; i < length; i++) {
- unsigned char b = in->read_u8();
+ for (uint16_t i = 0; i < length; i++) {
+ uint8_t b = in->read_u8();
m_buffer.push_back(b);
}
}
@@ -133,10 +102,11 @@
dbglogfile.setStamp(false);
log_action("PC index: %d:\t", pc);
if (dbglogfile.getActionDump()) {
- log_disasm(&m_buffer[instruction_start]);
+ log_disasm(instruction_start);
}
- if (action_id == 0) {
+ if (action_id == SWF::ACTION_END)
+ {
// end of action buffer.
break;
}
@@ -144,37 +114,18 @@
}
-/*private*/
-// Interpret the decl_dict opcode. Don't read stop_pc or
-// later. A dictionary is some static strings embedded in the
-// action buffer; there should only be one dictionary per
-// action buffer.
-//
-// NOTE: Normally the dictionary is declared as the first
-// action in an action buffer, but I've seen what looks like
-// some form of copy protection that amounts to:
-//
-// <start of action buffer>
-// push true
-// branch_if_true label
-// decl_dict [0] // this is never executed, but has lots of
orphan data declared in the opcode
-// label: // (embedded inside the previous opcode; looks like an invalid
jump)
-// ... "protected" code here, including the real decl_dict opcode ...
-// <end of the dummy decl_dict [0] opcode>
-//
-// So we just interpret the first decl_dict we come to, and
-// cache the results. If we ever hit a different decl_dict in
-// the same action_buffer, then we log an error and ignore it.
+/*public*/
void
-action_buffer::process_decl_dict(int start_pc, int stop_pc)
+action_buffer::process_decl_dict(size_t start_pc, size_t stop_pc) const
{
- assert(stop_pc <= (int) m_buffer.size());
+ assert(stop_pc <= m_buffer.size());
if (m_decl_dict_processed_at == start_pc) {
// We've already processed this decl_dict.
- int count = m_buffer[start_pc + 3] | (m_buffer[start_pc + 4] << 8);
+#ifndef NDEBUG
+ int count = read_int16(start_pc+3);
assert((int) m_dictionary.size() == count);
- UNUSED(count);
+#endif
return;
}
@@ -189,13 +140,13 @@
m_decl_dict_processed_at = start_pc;
// Actual processing.
- int i = start_pc;
- int length = m_buffer[i + 1] | (m_buffer[i + 2] << 8);
- int count = m_buffer[i + 3] | (m_buffer[i + 4] << 8);
+ size_t i = start_pc;
+ int16 length = read_int16(i+1);
+ int16 count = read_int16(i+3);
i += 2;
- UNUSED(length);
-
+ log_msg("Start at %d, stop at %d, length read was %d, count read was
%d",
+ start_pc, stop_pc, length, count);
assert(start_pc + 3 + length == stop_pc);
m_dictionary.resize(count);
@@ -223,35 +174,36 @@
}
}
-
// Interpret the actions in this action buffer, and evaluate
// them in the given environment. Execute our whole buffer,
// without any arguments passed in.
void
-action_buffer::execute(as_environment* env)
+action_buffer::execute(as_environment* env) const
{
+ assert(env);
+
int local_stack_top = env->get_local_frame_top();
env->add_frame_barrier();
- std::vector<with_stack_entry> empty_with_stack;
- execute(env, 0, m_buffer.size(), NULL, empty_with_stack, false /* not
function2 */);
+ ActionExec exec(*this, *env);
+ exec();
env->set_local_frame_top(local_stack_top);
}
-#if 1
+#if 0
/*private*/
void
action_buffer::doActionDefineFunction(as_environment* env,
std::vector<with_stack_entry>& with_stack,
- size_t pc,
+ size_t this_pc,
size_t* next_pc)
{
// Create a new function_as_object
function_as_object* func = new function_as_object(this, env, *next_pc,
with_stack);
- size_t i = pc;
+ size_t i = this_pc;
i += 3;
// Extract name.
@@ -294,13 +246,13 @@
void
action_buffer::doActionDefineFunction2(as_environment* env,
std::vector<with_stack_entry>& with_stack,
- size_t pc,
+ size_t this_pc,
size_t* next_pc)
{
function_as_object* func = new function_as_object(this, env,
*next_pc, with_stack);
func->set_is_function2();
- size_t i = pc;
+ size_t i = this_pc;
i += 3;
// Extract name.
@@ -363,509 +315,22 @@
action_buffer::execute(
as_environment* env,
size_t start_pc,
- size_t exec_bytes,
- as_value* /* retval */ , //should we drop this parameter ?
+ size_t exec_bytes, // used when invoked as a function call
+ as_value* retval, // used when invoked as a function call
const std::vector<with_stack_entry>& initial_with_stack,
- bool is_function2)
+ bool is_function2) const
{
- action_init(); // @@ stick this somewhere else; need some global
static init function
-
assert(env);
-
- std::vector<with_stack_entry> with_stack(initial_with_stack);
-
-#if 0
- // Check the time
- if (periodic_events.expired()) {
- periodic_events.poll_event_handlers(env);
- }
-#endif
-
- movie* original_target = env->get_target();
- UNUSED(original_target); // Avoid warnings.
-
- size_t stop_pc = start_pc + exec_bytes;
-
- for (size_t pc = start_pc; pc < stop_pc; ) {
- // Cleanup any expired "with" blocks.
- while ( with_stack.size() > 0
- && pc >= with_stack.back().end_pc() ) {
- // Drop this stack element
- with_stack.resize(with_stack.size() - 1);
- }
-
- // Get the opcode.
- int action_id = m_buffer[pc];
- if ((action_id & 0x80) == 0) {
- if (dbglogfile.getActionDump()) {
- log_action("\nEX:\t");
- log_disasm(&m_buffer[pc]);
- }
-
- // IF_VERBOSE_ACTION(log_msg("Action ID is: 0x%x\n", action_id));
-
- ash.execute((action_type)action_id, *env);
- pc++; // advance to next action.
- } else {
-
- if (dbglogfile.getActionDump()) {
- log_action("\nEX:\t");
- log_disasm(&m_buffer[pc]);
- }
-
- // Action containing extra data.
- size_t length = m_buffer[pc + 1] | (m_buffer[pc + 2] << 8);
- size_t next_pc = pc + length + 3;
-
- switch (action_id) {
- default:
- break;
-
- case SWF::ACTION_GOTOFRAME: // goto frame
- {
- int frame = m_buffer[pc + 3] | (m_buffer[pc + 4] << 8);
- // 0-based already?
- //// Convert from 1-based to 0-based
- //frame--;
- env->get_target()->goto_frame(frame);
- break;
- }
-
- case SWF::ACTION_GETURL: // get url
- {
- // If this is an FSCommand, then call the callback
- // handler, if any.
-
- // Two strings as args.
- const char* url = (const char*) &(m_buffer[pc + 3]);
- size_t url_len = strlen(url);
- const char* target = (const char*) &(m_buffer[pc + 3 +
url_len + 1]);
-
- // If the url starts with an "http" or "https",
- // then we want to load it into a web browser.
- if (strncmp(url, "http", 4) == 0) {
-// if (windowid) {
-// Atom mAtom = 486;
-// Display *mDisplay = XOpenDisplay(NULL);
-// XLockDisplay(mDisplay);
-// XChangeProperty (mDisplay, windowid,
mAtom,
-// XA_STRING, 8,
PropModeReplace,
-// (unsigned char *)url,
-// url_len);
-
-// XUnlockDisplay(mDisplay);
-// XCloseDisplay(mDisplay);
-// } else {
- string command = "firefox -remote \"openurl(";
- command += url;
- command += ")\"";
- dbglogfile << "Launching URL... " << command << endl;
-// movie *target = env->get_target();
-// target->get_url(url);
- system(command.c_str());
-// }
- break;
- }
-
- // If the url starts with "FSCommand:", then this is
- // a message for the host app.
- if (strncmp(url, "FSCommand:", 10) == 0) {
- if (s_fscommand_handler) {
- // Call into the app.
-
(*s_fscommand_handler)(env->get_target()->get_root_interface(), url + 10,
target);
- }
- } else {
-#ifdef EXTERN_MOVIE
-// log_error("get url: target=%s, url=%s\n",
target, url);
-
- tu_string tu_target = target;
- movie* target_movie = env->find_target(tu_target);
- if (target_movie != NULL) {
- movie *root_movie =
env->get_target()->get_root_movie();
- attach_extern_movie(url, target_movie, root_movie);
- } else {
- log_error("get url: target %s not found\n", target);
- }
-#endif // EXTERN_MOVIE
- }
-
- break;
- }
-
- case SWF::ACTION_SETREGISTER: // store_register
- {
- int reg = m_buffer[pc + 3];
- // Save top of stack in specified register.
- if (is_function2) {
- *(env->local_register_ptr(reg)) = env->top(0);
-
- log_action("-------------- local register[%d] =
'%s'\n",
- reg,
- env->top(0).to_string());
- } else if (reg >= 0 && reg < 4) {
- env->m_global_register[reg] = env->top(0);
-
- log_action("-------------- global register[%d] =
'%s'\n",
- reg,
- env->top(0).to_string());
- } else {
- log_error("store_register[%d] -- register out of
bounds!", reg);
- }
-
- break;
- }
-
- case SWF::ACTION_CONSTANTPOOL: // decl_dict: declare dictionary
- {
- //int i = pc;
- //int count = m_buffer[pc + 3] | (m_buffer[pc + 4] << 8);
- //i += 2;
-
- process_decl_dict(pc, next_pc);
-
- break;
- }
-
- case SWF::ACTION_WAITFORFRAME: // wait for frame
- {
- // If we haven't loaded a specified frame yet, then we're
supposed to skip
- // some specified number of actions.
- //
- // Since we don't load incrementally, just ignore this opcode.
- break;
- }
-
- case SWF::ACTION_SETTARGET: // set target
- {
- // Change the movie we're working on.
- const char* target_name = (const char*) &m_buffer[pc + 3];
- movie *new_target;
-
- // if the string is blank, we set target to the root movie
- // TODO - double check this is correct?
- if (target_name[0] == '\0')
- new_target = env->find_target((tu_string)"/");
- else
- new_target = env->find_target((tu_string)target_name);
-
- if (new_target == NULL) {
- log_action("ERROR: Couldn't find movie \"%s\" to set
target to!"
- " Not setting target at all...",
- (const char *)target_name);
- }
- else
- env->set_target(new_target);
-
- break;
- }
-
- case SWF::ACTION_GOTOLABEL: // go to labeled frame,
goto_frame_lbl
- {
- char* frame_label = (char*) &m_buffer[pc + 3];
- movie *target = env->get_target();
- target->goto_labeled_frame(frame_label);
- break;
- }
-
- case SWF::ACTION_WAITFORFRAMEEXPRESSION: // wait for frame
expression (?)
- {
- // Pop the frame number to wait for; if it's not loaded skip
the
- // specified number of actions.
- //
- // Since we don't support incremental loading, pop our arg and
- // don't do anything.
- env->drop(1);
- break;
- }
-
- case SWF::ACTION_DEFINEFUNCTION2: // 0x8E
- doActionDefineFunction2(env, with_stack, pc, &next_pc);
- break;
-
- case SWF::ACTION_WITH: // with
- {
- int frame = m_buffer[pc + 3] | (m_buffer[pc + 4] << 8);
- UNUSED(frame);
- log_action("-------------- with block start: stack size is
%zd\n", with_stack.size());
- if (with_stack.size() < 8) {
- int block_length = m_buffer[pc + 3] | (m_buffer[pc
+ 4] << 8);
- int block_end = next_pc + block_length;
- as_object* with_obj = env->top(0).to_object();
- with_stack.push_back(with_stack_entry(with_obj,
block_end));
- }
- env->drop(1);
- break;
- }
- case SWF::ACTION_PUSHDATA: // push_data
- {
- size_t i = pc;
- while (i - pc < length) {
- int type = m_buffer[3 + i];
- i++;
- if (type == 0) {
- // string
- const char* str = (const char*) &m_buffer[3 + i];
- i += strlen(str) + 1;
- env->push(str);
-
- log_action("-------------- pushed '%s'", str);
- } else if (type == 1) {
- // float (little-endian)
- union {
- float f;
- uint32_t i;
- } u;
- compiler_assert(sizeof(u) == sizeof(u.i));
-
- memcpy(&u.i, &m_buffer[3 + i], 4);
- u.i = swap_le32(u.i);
- i += 4;
-
- env->push(u.f);
- log_action("-------------- pushed '%g'", u.f);
- } else if (type == 2) {
- as_value nullvalue;
- nullvalue.set_null();
- env->push(nullvalue);
-
- log_action("-------------- pushed NULL");
- } else if (type == 3) {
- env->push(as_value());
-
- log_action("-------------- pushed UNDEFINED");
- } else if (type == 4) {
- // contents of register
- int reg = m_buffer[3 + i];
- UNUSED(reg);
- i++;
- if (is_function2) {
- env->push(*(env->local_register_ptr(reg)));
- log_action("-------------- pushed local
register[%d] = '%s'\n",
- reg,
- env->top(0).to_string());
- } else if (reg < 0 || reg >= 4) {
- env->push(as_value());
- log_error("push register[%d] -- register out of
bounds!\n", reg);
- } else {
- env->push(env->m_global_register[reg]);
- log_action("-------------- pushed global
register[%d] = '%s'\n",
- reg,
- env->top(0).to_string());
- }
-
- } else if (type == 5) {
- bool bool_val = m_buffer[3 + i] ? true : false;
- i++;
-// log_msg("bool(%d)\n",
bool_val);
- env->push(bool_val);
-
- log_action("-------------- pushed %s",
- (bool_val ? "true" : "false"));
- } else if (type == 6) {
- // double
- // wacky format: 45670123
- union {
- double d;
- uint64 i;
- struct {
- uint32_t lo;
- uint32_t hi;
- } sub;
- } u;
- compiler_assert(sizeof(u) == sizeof(u.i));
-
- memcpy(&u.sub.hi, &m_buffer[3 + i], 4);
- memcpy(&u.sub.lo, &m_buffer[3 + i + 4], 4);
- u.i = swap_le64(u.i);
- i += 8;
-
- env->push(u.d);
-
- log_action("-------------- pushed double %g", u.d);
- } else if (type == 7) {
- // int32
- int32_t val = m_buffer[3 + i]
- | (m_buffer[3 + i + 1] << 8)
- | (m_buffer[3 + i + 2] << 16)
- | (m_buffer[3 + i + 3] << 24);
- i += 4;
-
- env->push(val);
-
- log_action("-------------- pushed int32 %d",val);
- } else if (type == 8) {
- int id = m_buffer[3 + i];
- i++;
- if (id < (int) m_dictionary.size()) {
- env->push(m_dictionary[id]);
-
- log_action("-------------- pushed '%s'",
- m_dictionary[id]);
- } else {
- log_error("dict_lookup(%d) is out of bounds!\n",
id);
- env->push(0);
- log_action("-------------- pushed 0");
- }
- } else if (type == 9) {
- int id = m_buffer[3 + i] | (m_buffer[4 + i] << 8);
- i += 2;
- if (id < (int) m_dictionary.size()) {
- env->push(m_dictionary[id]);
- log_action("-------------- pushed '%s'\n",
m_dictionary[id]);
- } else {
- log_error("dict_lookup(%d) is out of bounds!\n",
id);
- env->push(0);
-
- log_action("-------------- pushed 0");
- }
- }
- }
-
- break;
- }
- case SWF::ACTION_BRANCHALWAYS: // branch always (goto)
- {
- int16_t offset = m_buffer[pc + 3] | (m_buffer[pc + 4]
<< 8);
- next_pc += offset;
- // @@ TODO range checks
- break;
- }
- case SWF::ACTION_GETURL2: // get url 2
- {
- int method = m_buffer[pc + 3];
- UNUSED(method);
-
- const char* target = env->top(0).to_string();
- const char* url = env->top(1).to_string();
-
- // If the url starts with "FSCommand:", then this is
- // a message for the host app.
- if (strncmp(url, "FSCommand:", 10) == 0) {
- if (s_fscommand_handler) {
- // Call into the app.
-
(*s_fscommand_handler)(env->get_target()->get_root_interface(), url + 10,
target);
- }
- } else {
-#ifdef EXTERN_MOVIE
-// log_error("get url2: target=%s, url=%s\n", target, url);
-
- movie* target_movie = env->find_target(env->top(0));
- if (target_movie != NULL) {
- movie* root_movie =
env->get_target()->get_root_movie();
- attach_extern_movie(url, target_movie, root_movie);
- } else {
- log_error("get url2: target %s not found\n", target);
- }
-#endif // EXTERN_MOVIE
- }
- env->drop(2);
- break;
- }
-
- case SWF::ACTION_DEFINEFUNCTION: // declare function
- doActionDefineFunction(env, with_stack, pc, &next_pc);
- break;
-
- case SWF::ACTION_BRANCHIFTRUE: // branch if true
- {
- int16_t offset = m_buffer[pc + 3] | (m_buffer[pc + 4]
<< 8);
-
- bool test = env->top(0).to_bool();
- env->drop(1);
- if (test) {
- next_pc += offset;
-
- if (next_pc > stop_pc) {
- log_error("branch to offset %d -- this section only
runs to %d\n",
- next_pc,
- stop_pc);
- }
- }
- break;
- }
- case SWF::ACTION_CALLFRAME: // call frame
- {
- // Note: no extra data in this instruction!
- assert(env->m_target);
- env->m_target->call_frame_actions(env->top(0));
- env->drop(1);
-
- break;
- }
-
- case SWF::ACTION_GOTOEXPRESSION: // goto frame expression,
goto_frame_exp
- {
- // From Alexi's SWF ref:
- //
- // Pop a value or a string and jump to the specified
- // frame. When a string is specified, it can include a
- // path to a sprite as in:
- //
- // /Test:55
- //
- // When f_play is ON, the action is to play as soon as
- // that frame is reached. Otherwise, the
- // frame is shown in stop mode.
-
- unsigned char play_flag = m_buffer[pc + 3];
- movie::play_state state = play_flag ? movie::PLAY :
movie::STOP;
-
- movie* target = env->get_target();
- bool success = false;
-
- if (env->top(0).get_type() == as_value::UNDEFINED) {
- // No-op.
- } else if (env->top(0).get_type() == as_value::STRING) {
- // @@ TODO: parse possible sprite path...
-
- // Also, if the frame spec is actually a number (not a
label), then
- // we need to do the conversion...
-
- const char* frame_label = env->top(0).to_string();
- if (target->goto_labeled_frame(frame_label)) {
- success = true;
- } else {
- // Couldn't find the label. Try converting to a
number.
- double num;
- if (string_to_number(&num, env->top(0).to_string())) {
- int frame_number = int(num);
- target->goto_frame(frame_number);
- success = true;
- }
- // else no-op.
- }
- } else if (env->top(0).get_type() == as_value::OBJECT) {
- // This is a no-op; see test_goto_frame.swf
- } else if (env->top(0).get_type() == as_value::NUMBER) {
- // Frame numbers appear to be 0-based! @@ Verify.
- int frame_number = int(env->top(0).to_number());
- target->goto_frame(frame_number);
- success = true;
- }
-
- if (success) {
- target->set_play_state(state);
- }
-
- env->drop(1);
- break;
- }
- }
- pc = next_pc;
- }
- }
-
- env->set_target(original_target);
+ ActionExec exec(*this, *env, start_pc, exec_bytes, retval,
+ initial_with_stack, is_function2);
+ exec();
}
-//
-// Disassembler
-//
-
// Disassemble one instruction to the log.
-void
-log_disasm(const unsigned char* instruction_data)
+static void
+disasm(const unsigned char* instruction_data)
{
+
as_arg_t fmt = ARG_HEX;
action_type action_id = (action_type)instruction_data[0];
unsigned char num[10];
@@ -1078,7 +543,52 @@
dbglogfile.setStamp(true);
}
+// Disassemble one instruction to the log.
+void
+action_buffer::log_disasm(size_t pc) const
+{
+ const unsigned char* instruction_data =
+ (const unsigned char *)&m_buffer[pc];
+ disasm(instruction_data);
+}
+
+
+float
+action_buffer::read_float_little(size_t pc) const
+{
+ union {
+ float f;
+ uint32_t i;
+ } u;
+ compiler_assert(sizeof(u) == sizeof(u.i));
+ memcpy(&u.i, &m_buffer[pc], 4);
+ u.i = swap_le32(u.i);
+ return u.f;
+}
+
+double
+action_buffer::read_double_wacky(size_t pc) const
+{
+ // double
+ // wacky format: 45670123
+ union {
+ double d;
+ uint64 i;
+ struct {
+ uint32_t lo;
+ uint32_t hi;
+ } sub;
+ } u;
+
+ compiler_assert(sizeof(u) == sizeof(u.i));
+ // this works, but is pretty dirty
+ memcpy(&u.sub.hi, &m_buffer[pc], 4);
+ memcpy(&u.sub.lo, &m_buffer[pc + 4], 4);
+ u.i = swap_le64(u.i);
+
+ return u.d;
+}
};
Index: server/action_buffer.h
===================================================================
RCS file: /sources/gnash/gnash/server/action_buffer.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- server/action_buffer.h 21 Jun 2006 14:18:58 -0000 1.3
+++ server/action_buffer.h 25 Jun 2006 16:53:04 -0000 1.4
@@ -54,21 +54,34 @@
//#include "log.h"
#include "with_stack_entry.h"
+// Forward declarations
namespace gnash {
+ struct as_environment;
+ struct as_value;
+ namespace SWF {
+ class ActionHandler;
+ }
+}
-// Forward declarations
-//struct movie;
-struct as_environment;
-//class as_object;
-struct as_value;
-//class function_as_object;
-/// Base class for actions.
+namespace gnash {
+
+class ActionExec;
+
+/// A code segment.
+//
+/// This currently holds the actions in a memory
+/// buffer, but I'm workin toward making this unneeded
+/// so to eventually use a gnash::stream directly and
+/// avoid full loads. (not before profiling!).
+//
class action_buffer
{
public:
+ friend class ActionExec;
+
action_buffer();
/// Read action bytes from input stream
@@ -81,42 +94,148 @@
/// Execute our whole buffer,
/// without any arguments passed in.
///
- void execute(as_environment* env);
+ /// FIXME: obsolete this, use ActionExec instead.
+ ///
+ void execute(as_environment* env) const;
/// Interpret the specified subset of the actions in our buffer.
//
/// Caller is responsible for cleaning up our local
/// stack frame (it may have passed its arguments in via the
/// local stack frame).
+ ///
+ /// FIXME: obsolete this, use ActionExec instead.
+ ///
void execute(
as_environment* env,
size_t start_pc,
size_t exec_bytes,
as_value* retval, // we should probably drop this parameter
const std::vector<with_stack_entry>& initial_with_stack,
- bool is_function2);
+ bool is_function2) const;
- bool is_null()
+ bool is_null() const
{
return m_buffer.size() < 1 || m_buffer[0] == 0;
}
- int get_length() const { return m_buffer.size(); }
+ // kept for backward compatibility, should drop and see
+ // what breaks.
+ size_t get_length() const { return size(); }
+
+ size_t size() const { return m_buffer.size(); }
+
+ uint8_t operator[] (size_t off) const
+ {
+ assert(off < m_buffer.size() );
+ return m_buffer[off];
+ }
+
+ /// Disassemble instruction at given offset to the log.
+ void log_disasm(size_t pc) const;
+
+ /// Get a null-terminated string from given offset
+ //
+ /// Useful to hide complexity of underlying buffer access.
+ ///
+ const char* read_string(size_t pc) const
+ {
+ return (const char*)(&m_buffer[pc]);
+ }
+
+ /// Get an integer value from given offset
+ //
+ /// Useful to hide complexity of underlying buffer access.
+ ///
+ int16_t read_int16(size_t pc) const
+ {
+ int ret = m_buffer[pc] | (m_buffer[pc + 1] << 8);
+ return ret;
+ }
+
+ /// Read a 32-bit integer starting at given offset.
+ //
+ /// Useful to hide complexity of underlying buffer access.
+ ///
+ int32_t read_int32(size_t pc) const
+ {
+ int32_t val = m_buffer[pc]
+ | (m_buffer[pc + 1] << 8)
+ | (m_buffer[pc + 2] << 16)
+ | (m_buffer[pc + 3] << 24);
+ return val;
+ }
+
+ /// Read a little-endian 32-bit float starting at given offset
+ //
+ /// Useful to hide complexity of underlying buffer access.
+ ///
+ float read_float_little(size_t pc) const;
+
+ /// Read a 64-bit double starting at given offset.
+ //
+ /// wacky format: 45670123
+ /// Useful to hide complexity of underlying buffer access.
+ ///
+ double read_double_wacky(size_t pc) const;
+
+ /// Return number of entries in the constant pool
+ size_t dictionary_size() const
+ {
+ return m_dictionary.size();
+ }
+
+ /// Return a value from the constant pool
+ const char* dictionary_get(size_t n) const
+ {
+ return m_dictionary[n];
+ }
+
+ /// \brief
+ /// Interpret the SWF::ACTION_CONSTANTPOOL opcode.
+ //
+ /// Don't read stop_pc or later.
+ ///
+ /// A dictionary is some static strings embedded in the
+ /// action buffer; there should only be one dictionary per
+ /// action buffer.
+ ///
+ /// NOTE: Normally the dictionary is declared as the first
+ /// action in an action buffer, but I've seen what looks like
+ /// some form of copy protection that amounts to:
+ ///
+ /// <start of action buffer>
+ /// push true
+ /// branch_if_true label
+ /// decl_dict [0] // this is never executed, but has lots
of orphan data declared in the opcode
+ /// label: // (embedded inside the previous opcode; looks like an
invalid jump)
+ /// ... "protected" code here, including the real decl_dict
opcode ...
+ /// <end of the dummy decl_dict [0] opcode>
+ ///
+ /// So we just interpret the first decl_dict we come to, and
+ /// cache the results. If we ever hit a different decl_dict in
+ /// the same action_buffer, then we log an error and ignore it.
+ ///
+ void process_decl_dict(size_t start_pc, size_t stop_pc) const;
private:
+
// Don't put these as values in std::vector<>! They contain
// internal pointers and cannot be moved or copied.
// If you need to keep an array of them, keep pointers
// to new'd instances.
action_buffer(const action_buffer& a) { assert(0); }
- void process_decl_dict(int start_pc, int stop_pc);
+ /// the code itself, as read from the SWF
+ std::vector<uint8_t> m_buffer;
+
+ /// The dictionary
+ mutable std::vector<const char*> m_dictionary;
- // data:
- std::vector<unsigned char> m_buffer;
- std::vector<const char*> m_dictionary;
- int m_decl_dict_processed_at;
+ /// FIXME: move to ActionExec
+ mutable int m_decl_dict_processed_at;
+#if 0
void doActionNew(as_environment* env,
std::vector<with_stack_entry>& with_stack);
@@ -148,6 +267,7 @@
void doActionDelete2(as_environment* env,
std::vector<with_stack_entry>& with_stack);
+#endif
};
Index: server/swf/ASHandlers.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/swf/ASHandlers.cpp,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- server/swf/ASHandlers.cpp 21 Jun 2006 23:06:41 -0000 1.12
+++ server/swf/ASHandlers.cpp 25 Jun 2006 16:53:04 -0000 1.13
@@ -38,32 +38,43 @@
#include "config.h"
#endif
-#include <string>
-#include <map>
-#include <vector>
-
#include "log.h"
#include "swf.h"
#include "ASHandlers.h"
#include "movie_definition.h"
-//#include "action.h"
#include "array.h"
#include "Function.h"
#include "tu_random.h"
#include "fn_call.h"
+#include "ActionExec.h"
+
+#include <string>
+#include <map>
+#include <vector>
using namespace std;
+// Forward declarations
namespace gnash {
+ extern fscommand_callback s_fscommand_handler;
+}
-/// SWF format parsing classes
+namespace gnash {
namespace SWF { // gnash::SWF
-// std::map<action_type, ActionHandler> SWFHandlers::_handlers;
-// std::vector<std::string> SWFHandlers::_property_names;
+SWFHandlers::container_type SWFHandlers::_handlers(255);
+std::vector<std::string> SWFHandlers::_property_names;
+
+
+static void unsupported_action_handler(ActionExec& thread)
+{
+ log_error("Unsupported action handler invoked");
+}
ActionHandler::ActionHandler()
- : _debug(false), _stack_args(0), _arg_format(ARG_NONE)
+ : _debug(false), _stack_args(0), _arg_format(ARG_NONE),
+ _callback(unsupported_action_handler),
+ _name("unsupported")
{
// GNASH_REPORT_FUNCTION;
}
@@ -114,16 +125,17 @@
// GNASH_REPORT_FUNCTION;
}
-bool
-ActionHandler::execute(as_environment &env)
+void
+ActionHandler::execute(ActionExec& thread) const
{
// GNASH_REPORT_FUNCTION;
- return _callback(env);
+ return _callback(thread);
}
SWFHandlers::SWFHandlers()
{
// GNASH_REPORT_FUNCTION;
+ _property_names.reserve(32);
_property_names.push_back("_x");
_property_names.push_back("_y");
_property_names.push_back("_xscale");
@@ -358,214 +370,336 @@
// GNASH_REPORT_FUNCTION;
}
-bool
-SWFHandlers::execute(action_type type, as_environment &env)
+const SWFHandlers&
+SWFHandlers::instance()
{
-// GNASH_REPORT_FUNCTION;
- return _handlers[type].execute(env);
+ static SWFHandlers* _instance = new SWFHandlers();
+ return *_instance;
}
bool
-SWFHandlers::ActionEnd(as_environment &end)
+SWFHandlers::execute(action_type type, ActionExec& thread) const
{
// GNASH_REPORT_FUNCTION;
+
+ if ( _handlers[type].getName() == "unsupported" ) return false;
+ _handlers[type].execute(thread);
return true;
}
-bool
-SWFHandlers::ActionNextFrame(as_environment &env)
+
+void
+SWFHandlers::ActionEnd(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+
+ //as_environment& env = thread.env;
+#ifndef NDEBUG
+ const action_buffer& code = thread.code;
+ assert( code[thread.pc] == SWF::ACTION_END );
+#endif
+
+ dbglogfile << __PRETTY_FUNCTION__ << ": CHECKME: was broken" << endl;
+ thread.next_pc=thread.stop_pc;
+}
+void
+SWFHandlers::ActionNextFrame(ActionExec& thread)
+{
+// GNASH_REPORT_FUNCTION;
+
+ as_environment& env = thread.env;
+ const action_buffer& code = thread.code;
+
+ assert( code[thread.pc] == SWF::ACTION_NEXTFRAME );
env.get_target()->goto_frame(env.get_target()->get_current_frame() + 1);
- return true;
}
-bool
-SWFHandlers::ActionPrevFrame(as_environment &env)
+void
+SWFHandlers::ActionPrevFrame(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+
+ as_environment& env = thread.env;
+ const action_buffer& code = thread.code;
+
+ assert( code[thread.pc] == SWF::ACTION_PREVFRAME );
env.get_target()->goto_frame(env.get_target()->get_current_frame() - 1);
- return true;
}
-bool
-SWFHandlers::ActionPlay(as_environment &env)
+void
+SWFHandlers::ActionPlay(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+
+ as_environment& env = thread.env;
+ const action_buffer& code = thread.code;
+
+ assert( code[thread.pc] == SWF::ACTION_PLAY );
env.get_target()->set_play_state(movie::PLAY);
- return true;
}
-bool
-SWFHandlers::ActionStop(as_environment &env)
+void
+SWFHandlers::ActionStop(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+
+ as_environment& env = thread.env;
+ const action_buffer& code = thread.code;
+
+ assert( code[thread.pc] == SWF::ACTION_STOP );
env.get_target()->set_play_state(movie::STOP);
- return true;
}
-bool
-SWFHandlers::ActionToggleQuality(as_environment &env)
+void
+SWFHandlers::ActionToggleQuality(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+
+ as_environment& env = thread.env;
+ const action_buffer& code = thread.code;
+
+ assert( code[thread.pc] == SWF::ACTION_TOGGLEQUALITY );
dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
}
-bool
-SWFHandlers::ActionStopSounds(as_environment &env)
+void
+SWFHandlers::ActionStopSounds(ActionExec& thread)
{
+// GNASH_REPORT_FUNCTION;
+
+ as_environment& env = thread.env;
+ const action_buffer& code = thread.code;
+
+ assert( code[thread.pc] == SWF::ACTION_STOPSOUNDS );
sound_handler* s = get_sound_handler();
if (s != NULL)
{
s->stop_all_sounds();
}
- return true;
}
-bool
-SWFHandlers::ActionGotoFrame(as_environment &env)
+void
+SWFHandlers::ActionGotoFrame(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
- dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
+
+ as_environment& env = thread.env;
+ const action_buffer& code = thread.code;
+
+ assert( code[thread.pc] == SWF::ACTION_GOTOFRAME );
+
+ int frame = code[thread.pc + 3] | (code[thread.pc + 4] << 8);
+
+ // 0-based already?
+ //// Convert from 1-based to 0-based
+ //frame--;
+ env.get_target()->goto_frame(frame);
+ thread.next_pc = thread.stop_pc;
}
-bool
-SWFHandlers::ActionGetUrl(as_environment &env)
+void
+SWFHandlers::ActionGetUrl(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
- dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
+ as_environment& env = thread.env;
+ const action_buffer& code = thread.code;
+
+ assert( code[thread.pc] == SWF::ACTION_GETURL );
+
+ size_t& pc = thread.pc;
+
+ // If this is an FSCommand, then call the callback
+ // handler, if any.
+
+ // Two strings as args.
+ const char* url = code.read_string(pc+3);
+ size_t url_len = strlen(url);
+ const char* target = code.read_string(pc+3);
+
+ // If the url starts with an "http" or "https",
+ // then we want to load it into a web browser.
+ if (strncmp(url, "http", 4) == 0)
+ {
+// if (windowid) {
+// Atom mAtom = 486;
+// Display *mDisplay = XOpenDisplay(NULL);
+// XLockDisplay(mDisplay);
+// XChangeProperty (mDisplay, windowid,
mAtom,
+// XA_STRING, 8,
PropModeReplace,
+// (unsigned char *)url,
+// url_len);
+
+// XUnlockDisplay(mDisplay);
+// XCloseDisplay(mDisplay);
+// } else {
+ string command = "firefox -remote \"openurl(";
+ command += url;
+ command += ")\"";
+ dbglogfile << "Launching URL... " << command << endl;
+// movie *target = env.get_target();
+// target->get_url(url);
+ system(command.c_str());
+// }
+ return;
+ }
+
+ // If the url starts with "FSCommand:", then this is
+ // a message for the host app.
+ else if (strncmp(url, "FSCommand:", 10) == 0)
+ {
+ if (s_fscommand_handler) {
+ // Call into the app.
+
(*s_fscommand_handler)(env.get_target()->get_root_interface(), url + 10,
target);
+ }
+ }
+ else
+ {
+#ifdef EXTERN_MOVIE
+// log_error("get url: target=%s, url=%s\n", target, url);
+
+ tu_string tu_target = target;
+ movie* target_movie = env.find_target(tu_target);
+ if (target_movie != NULL) {
+ movie *root_movie = env.get_target()->get_root_movie();
+ attach_extern_movie(url, target_movie, root_movie);
+ } else {
+ log_error("get url: target %s not found\n", target);
+ }
+#endif // EXTERN_MOVIE
+ }
+
}
-bool
-SWFHandlers::ActionWaitForFrame(as_environment &env)
+void
+SWFHandlers::ActionWaitForFrame(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
- dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
+ // If we haven't loaded a specified frame yet, then we're supposed
+ // to skip some specified number of actions.
+ //
+ // Since we don't load incrementally, just ignore this opcode.
+
+ dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented (no need until we
play while reading)" << endl;
}
-bool
-SWFHandlers::ActionSetTarget(as_environment &env)
+void
+SWFHandlers::ActionSetTarget(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
}
-bool
-SWFHandlers::ActionGotoLabel(as_environment &env)
+void
+SWFHandlers::ActionGotoLabel(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
}
-bool
-SWFHandlers::ActionAdd(as_environment &env)
+void
+SWFHandlers::ActionAdd(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(1) += env.top(0);
env.drop(1);
-
- return true;
}
-bool
-SWFHandlers::ActionSubtract(as_environment &env)
+void
+SWFHandlers::ActionSubtract(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(1) -= env.top(0);
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionMultiply(as_environment &env)
+void
+SWFHandlers::ActionMultiply(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(1) *= env.top(0);
env.drop(1);
-
- return true;
}
-bool
-SWFHandlers::ActionDivide(as_environment &env)
+void
+SWFHandlers::ActionDivide(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(1) /= env.top(0);
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionEqual(as_environment &env)
+void
+SWFHandlers::ActionEqual(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(1).set_bool(env.top(1) == env.top(0));
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionLessThan(as_environment &env)
+void
+SWFHandlers::ActionLessThan(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(1).set_bool(env.top(1) < env.top(0));
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionLogicalAnd(as_environment &env)
+void
+SWFHandlers::ActionLogicalAnd(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(1).set_bool(env.top(1).to_bool() && env.top(0).to_bool());
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionLogicalOr(as_environment &env)
+void
+SWFHandlers::ActionLogicalOr(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(1).set_bool(env.top(1).to_bool() && env.top(0).to_bool());
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionLogicalNot(as_environment &env)
+void
+SWFHandlers::ActionLogicalNot(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(0).set_bool(! env.top(0).to_bool());
- return true;
}
-bool
-SWFHandlers::ActionStringEq(as_environment &env)
+void
+SWFHandlers::ActionStringEq(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(1).set_bool(env.top(1).to_tu_string() ==
env.top(0).to_tu_string());
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionStringLength(as_environment &env)
+void
+SWFHandlers::ActionStringLength(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
int version = env.get_target()->get_movie_definition()->get_version();
env.top(0).set_int(env.top(0).to_tu_string_versioned(version).utf8_length());
- return true;
}
-bool
-SWFHandlers::ActionSubString(as_environment &env)
+void
+SWFHandlers::ActionSubString(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
int size = int(env.top(0).to_number());
int base = int(env.top(1).to_number()) - 1; // 1-based indices
int version = env.get_target()->get_movie_definition()->get_version();
@@ -584,13 +718,13 @@
env.drop(2);
env.top(0).set_tu_string(new_string);
- return true;
}
-bool
-SWFHandlers::ActionPop(as_environment &env)
+void
+SWFHandlers::ActionPop(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
if ( ! env.stack_size() )
{
// Malformed SWF
@@ -600,21 +734,21 @@
{
env.drop(1);
}
- return true;
}
-bool
-SWFHandlers::ActionInt(as_environment &env)
+void
+SWFHandlers::ActionInt(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(0).set_int(int(floor(env.top(0).to_number())));
- return true;
}
-bool
-SWFHandlers::ActionGetVariable(as_environment &env)
+void
+SWFHandlers::ActionGetVariable(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
as_value var_name = env.pop();
tu_string var_string = var_name.to_tu_string();
@@ -630,25 +764,24 @@
variable.to_tu_string().c_str(),
(void*)variable.to_object());
}
-
- return true;
}
-bool
-SWFHandlers::ActionSetVariable(as_environment &env)
+void
+SWFHandlers::ActionSetVariable(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.set_variable(env.top(1).to_tu_string(), env.top(0));
log_action("\n-- set var: %s", env.top(1).to_string());
env.drop(2);
- return true;
}
-bool
-SWFHandlers::ActionSetTargetExpression(as_environment &env)
+void
+SWFHandlers::ActionSetTargetExpression(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
const char * target_name = env.top(0).to_string();
env.drop(1); // pop the target name off the stack
movie *new_target;
@@ -668,25 +801,24 @@
} else {
env.set_target(new_target);
}
-
- return true;
}
-bool
-SWFHandlers::ActionStringConcat(as_environment &env)
+void
+SWFHandlers::ActionStringConcat(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
int version = env.get_target()->get_movie_definition()->get_version();
env.top(1).convert_to_string_versioned(version);
env.top(1).string_concat(env.top(0).to_tu_string_versioned(version));
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionGetProperty(as_environment &env)
+void
+SWFHandlers::ActionGetProperty(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
movie *target = env.find_target(env.top(1));
int prop_number = (int)env.top(0).to_number();
if (target) {
@@ -701,13 +833,13 @@
env.top(1) = as_value();
}
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionSetProperty(as_environment &env)
+void
+SWFHandlers::ActionSetProperty(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
movie *target = env.find_target(env.top(2));
int prop_number = (int)env.top(1).to_number();
@@ -723,44 +855,44 @@
}
env.drop(3);
- return true;
}
-bool
-SWFHandlers::ActionDuplicateClip(as_environment &env)
+void
+SWFHandlers::ActionDuplicateClip(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.get_target()->clone_display_object(
env.top(2).to_tu_string(),
env.top(1).to_tu_string(),
(int) env.top(0).to_number());
env.drop(3);
- return true;
}
-bool
-SWFHandlers::ActionRemoveClip(as_environment &env)
+void
+SWFHandlers::ActionRemoveClip(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.get_target()->remove_display_object(env.top(0).to_tu_string());
env.drop(1);
- return true;
}
/// \brief Trace messages from the Flash movie using trace();
-bool
-SWFHandlers::ActionTrace(as_environment &env)
+void
+SWFHandlers::ActionTrace(ActionExec& thread)
{
//// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
dbglogfile << env.top(0).to_string() << endl;
env.drop(1);
- return false;
}
-bool
-SWFHandlers::ActionStartDragMovie(as_environment &env)
+void
+SWFHandlers::ActionStartDragMovie(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
movie::drag_state st;
st.m_character = env.find_target(env.top(0));
@@ -787,39 +919,39 @@
root_movie->set_drag_state(st);
}
- return true;
}
-bool
-SWFHandlers::ActionStopDragMovie(as_environment &env)
+void
+SWFHandlers::ActionStopDragMovie(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
movie *root_movie = env.get_target()->get_root_movie();
assert(root_movie);
root_movie->stop_drag();
- return true;
}
-bool
-SWFHandlers::ActionStringCompare(as_environment &env)
+void
+SWFHandlers::ActionStringCompare(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(1).set_bool(env.top(1).to_tu_string() < env.top(0).to_tu_string());
- return true;
}
-bool
-SWFHandlers::ActionThrow(as_environment &env)
+void
+SWFHandlers::ActionThrow(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ //as_environment& env = thread.env;
dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
}
-bool
-SWFHandlers::ActionCastOp(as_environment &env)
+void
+SWFHandlers::ActionCastOp(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
// Get the "super" function
function_as_object* super = env.top(0).to_as_function();
@@ -836,7 +968,7 @@
env.drop(1);
env.top(0) = as_value();
- return false;
+ return;
}
env.drop(1);
@@ -845,147 +977,317 @@
} else {
env.top(0) = as_value();
}
-
- return true;
}
-bool
-SWFHandlers::ActionImplementsOp(as_environment &env)
+void
+SWFHandlers::ActionImplementsOp(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
}
-bool
-SWFHandlers::ActionRandom(as_environment &env)
+void
+SWFHandlers::ActionRandom(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
int max = int(env.top(0).to_number());
if (max < 1) max = 1;
env.top(0).set_int(tu_random::next_random() % max);
- return true;
}
-bool
-SWFHandlers::ActionMbLength(as_environment &env)
+void
+SWFHandlers::ActionMbLength(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
}
-bool
-SWFHandlers::ActionOrd(as_environment &env)
+void
+SWFHandlers::ActionOrd(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(0).set_int(env.top(0).to_string()[0]);
- return true;
}
-bool
-SWFHandlers::ActionChr(as_environment &env)
+void
+SWFHandlers::ActionChr(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
char buf[2];
buf[0] = int(env.top(0).to_number());
buf[1] = 0;
env.top(0).set_string(buf);
- return true;
}
-bool
-SWFHandlers::ActionGetTimer(as_environment &env)
+void
+SWFHandlers::ActionGetTimer(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.push(floorf(env.m_target->get_timer() * 1000.0f));
- return true;
}
-bool
-SWFHandlers::ActionMbSubString(as_environment &env)
+void
+SWFHandlers::ActionMbSubString(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
}
-bool
-SWFHandlers::ActionMbOrd(as_environment &env)
+void
+SWFHandlers::ActionMbOrd(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
}
-bool
-SWFHandlers::ActionMbChr(as_environment &env)
+void
+SWFHandlers::ActionMbChr(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
}
-bool
-SWFHandlers::ActionWaitForFrameExpression(as_environment &env)
+void
+SWFHandlers::ActionWaitForFrameExpression(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
}
-bool
-SWFHandlers::ActionPushData(as_environment &env)
+void
+SWFHandlers::ActionPushData(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
- dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
+ as_environment& env = thread.env;
+
+ const action_buffer& code = thread.code;
+
+ size_t pc = thread.pc;
+ int16_t length = code.read_int16(pc+1);
+ assert( length >= 0 );
+
+ log_action("-------------- push len=%d", length);
+
+ //---------------
+ size_t i = pc;
+ while (i - pc < length) {
+ uint8_t type = code[3 + i];
+ log_action("-------------- push type=%d", type);
+ i++;
+ if (type == 0) {
+ // string
+ const char* str = code.read_string(i+3);
+ i += strlen(str) + 1;
+ env.push(str);
+
+ log_action("-------------- pushed '%s'", str);
+ } else if (type == 1) {
+
+ float f = code.read_float_little(i+3);
+ i += 4;
+ env.push(f);
+ log_action("-------------- pushed '%g'", f);
+ } else if (type == 2) {
+ as_value nullvalue;
+ nullvalue.set_null();
+ env.push(nullvalue);
+
+ log_action("-------------- pushed NULL");
+ } else if (type == 3) {
+ env.push(as_value());
+
+ log_action("-------------- pushed UNDEFINED");
+ } else if (type == 4) {
+ // contents of register
+ int reg = code[3 + i];
+ i++;
+ if ( thread.isFunction2() ) {
+ env.push(*(env.local_register_ptr(reg)));
+ log_action("-------------- pushed local register[%d] =
'%s'\n",
+ reg,
+ env.top(0).to_string());
+ } else if (reg < 0 || reg >= 4) {
+ env.push(as_value());
+ log_error("push register[%d] -- register out of
bounds!\n", reg);
+ } else {
+ env.push(env.m_global_register[reg]);
+ log_action("-------------- pushed global register[%d] =
'%s'\n",
+ reg,
+ env.top(0).to_string());
+ }
+
+ } else if (type == 5) {
+ bool bool_val = code[i+3] ? true : false;
+ i++;
+// log_msg("bool(%d)\n", bool_val);
+ env.push(bool_val);
+
+ log_action("-------------- pushed %s",
+ (bool_val ? "true" : "false"));
+ } else if (type == 6) {
+ double d = code.read_double_wacky(i+3);
+ i += 8;
+ env.push(d);
+
+ log_action("-------------- pushed double %g", d);
+ } else if (type == 7) {
+ // int32
+ int32_t val = code.read_int32(i+3);
+ i += 4;
+
+ env.push(val);
+
+ log_action("-------------- pushed int32 %d",val);
+ } else if (type == 8) {
+ int id = code[3 + i];
+ i++;
+ if ( id < (int) code.dictionary_size() ) {
+ env.push( code.dictionary_get(id) );
+
+ log_action("-------------- pushed '%s'",
+ code.dictionary_get(id));
+ } else {
+ log_error("dict_lookup(%d) is out of bounds!\n", id);
+ env.push(0);
+ log_action("-------------- pushed 0");
+ }
+ } else if (type == 9) {
+ int id = code.read_int16(i+3);
+ i += 2;
+ if ( id < (int) code.dictionary_size() ) {
+ env.push( code.dictionary_get(id) );
+ log_action("-------------- pushed '%s'\n",
+ code.dictionary_get(id) );
+ } else {
+ log_error("dict_lookup(%d) is out of bounds!\n", id);
+ env.push(0);
+
+ log_action("-------------- pushed 0");
+ }
+ }
+ }
}
-bool
-SWFHandlers::ActionBranchAlways(as_environment &env)
+void
+SWFHandlers::ActionBranchAlways(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
- dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
+// as_environment& env = thread.env;
+// dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
+
+ int16_t offset = thread.code.read_int16(thread.pc+3);
+ thread.next_pc += offset;
+ // @@ TODO range checks
}
-bool
-SWFHandlers::ActionGetUrl2(as_environment &env)
+void
+SWFHandlers::ActionGetUrl2(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
- dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
+ as_environment& env = thread.env;
+ const action_buffer& code = thread.code;
+
+ assert( code[thread.pc] == SWF::ACTION_GETURL );
+
+ const char* target = env.top(0).to_string();
+ const char* url = env.top(1).to_string();
+
+ // If the url starts with "FSCommand:", then this is
+ // a message for the host app.
+ if (strncmp(url, "FSCommand:", 10) == 0)
+ {
+ if (s_fscommand_handler)
+ {
+ // Call into the app.
+
(*s_fscommand_handler)(env.get_target()->get_root_interface(), url + 10,
target);
+ }
+ }
+ else
+ {
+#ifdef EXTERN_MOVIE
+// log_error("get url2: target=%s, url=%s\n", target, url);
+
+ movie* target_movie = env.find_target(env.top(0));
+ if (target_movie != NULL)
+ {
+ movie* root_movie = env.get_target()->get_root_movie();
+ attach_extern_movie(url, target_movie, root_movie);
+ }
+ else
+ {
+ log_error("get url2: target %s not found\n", target);
+ }
+#endif // EXTERN_MOVIE
+ }
+ env.drop(2);
}
-bool
-SWFHandlers::ActionBranchIfTrue(as_environment &env)
+void
+SWFHandlers::ActionBranchIfTrue(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
- dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
+
+ as_environment& env = thread.env;
+ const action_buffer& code = thread.code;
+
+ // Alias these
+ size_t& pc = thread.pc;
+ size_t& next_pc = thread.next_pc;
+ size_t& stop_pc = thread.stop_pc;
+
+ //dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
+
+ int16_t offset = code.read_int16(pc+3);
+
+ bool test = env.top(0).to_bool();
+ env.drop(1);
+ if (test)
+ {
+ next_pc += offset;
+
+ if (next_pc > stop_pc)
+ {
+ log_error("branch to offset %d -- "
+ " this section only runs to %d. "
+ " Malformed SWF !.\n",
+ next_pc,
+ stop_pc);
+ }
+ }
}
-bool
-SWFHandlers::ActionCallFrame(as_environment &env)
+void
+SWFHandlers::ActionCallFrame(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
}
-bool
-SWFHandlers::ActionGotoExpression(as_environment &env)
+void
+SWFHandlers::ActionGotoExpression(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
}
-bool
-SWFHandlers::ActionDeleteVar(as_environment &env)
+void
+SWFHandlers::ActionDeleteVar(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
+
as_value var = env.pop();
as_value object = env.top(0);
if (object.get_type() == as_value::OBJECT)
@@ -999,18 +1301,18 @@
// TODO: remove a member from object if it
there is
env.top(0).set_bool(true);
- return true;
+ return;
}
}
env.top(0).set_bool(false);
- return false;
}
-bool
-SWFHandlers::ActionDelete(as_environment &env)
+void
+SWFHandlers::ActionDelete(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
as_value var = env.top(0);
as_value oldval = env.get_variable_raw(var.to_tu_string());
@@ -1024,24 +1326,23 @@
} else {
env.top(0).set_bool(false);
}
-
- return true;
}
-bool
-SWFHandlers::ActionVarEquals(as_environment &env)
+void
+SWFHandlers::ActionVarEquals(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
as_value value = env.pop();
as_value varname = env.pop();
env.set_local(varname.to_tu_string(), value);
- return true;
}
-bool
-SWFHandlers::ActionCallFunction(as_environment &env)
+void
+SWFHandlers::ActionCallFunction(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
as_value function;
if (env.top(0).get_type() == as_value::STRING) {
// Function is a string; lookup the function.
@@ -1068,32 +1369,33 @@
env.drop(nargs + 1);
env.top(0) = result;
-
- return true;
}
-bool
-SWFHandlers::ActionReturn(as_environment &env)
+void
+SWFHandlers::ActionReturn(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
+ as_value* retval = thread.retval;
+
// Put top of stack in the provided return slot, if
// it's not NULL.
- as_value *retval = 0;
if (retval) {
*retval = env.top(0);
}
env.drop(1);
// Skip the rest of this buffer (return from this action_buffer).
-// pc = stop_pc;
- dbglogfile << __PRETTY_FUNCTION__ << ": FIXME: Set the PC pointer here!!"
<< endl;
- return false;
+ thread.next_pc = thread.stop_pc;
+
+ //dbglogfile << __PRETTY_FUNCTION__ << ": FIXME: Set the PC pointer
here!!" << endl;
}
-bool
-SWFHandlers::ActionModulo(as_environment &env)
+void
+SWFHandlers::ActionModulo(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
as_value result;
double y = env.pop().to_number();
double x = env.pop().to_number();
@@ -1104,13 +1406,13 @@
// env.drop(1);
// log_error("modulo x=%f, y=%f, z=%f\n",x,y,result.to_number());
env.push(result);
- return true;
}
-bool
-SWFHandlers::ActionNew(as_environment &env)
+void
+SWFHandlers::ActionNew(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
// doActionNew(env, with_stack);
as_value classname = env.pop();
@@ -1165,23 +1467,23 @@
log_msg("new object at %p\n", new_obj.to_object());
#endif
- return true;
}
-bool
-SWFHandlers::ActionVar(as_environment &env)
+void
+SWFHandlers::ActionVar(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
const tu_string &varname = env.top(0).to_tu_string();
env.declare_local(varname);
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionInitArray(as_environment &env)
+void
+SWFHandlers::ActionInitArray(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
int array_size = (int) env.pop().to_number();
//log_msg("xxx init array: size = %d, top of stack = %d\n", array_size,
env.get_top_index());//xxxxx
@@ -1207,13 +1509,13 @@
//as_global_trace(fn_call(NULL, NULL, env, 1, env.get_top_index()));
//xxxx
- return false;
}
-bool
-SWFHandlers::ActionInitObject(as_environment &env)
+void
+SWFHandlers::ActionInitObject(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
//
// SWFACTION_PUSH
// [000] Constant: 1 "obj"
@@ -1242,13 +1544,13 @@
//env.drop(nmembers*2);
env.push(new_obj);
- return true;
}
-bool
-SWFHandlers::ActionTypeOf(as_environment &env)
+void
+SWFHandlers::ActionTypeOf(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
switch(env.top(0).get_type()) {
case as_value::UNDEFINED:
env.top(0).set_string("undefined");
@@ -1275,28 +1577,31 @@
log_error("typeof unknown type: %02X\n", env.top(0).get_type());
break;
}
- return true;
}
-bool
-SWFHandlers::ActionTargetPath(as_environment &env)
+void
+SWFHandlers::ActionTargetPath(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
}
-bool
-SWFHandlers::ActionEnumerate(as_environment &env)
+void
+SWFHandlers::ActionEnumerate(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
as_value var_name = env.pop();
const tu_string& var_string = var_name.to_tu_string();
as_value variable = env.get_variable(var_string);
+ // @@ shouldn't we return *only* after pushing the nullvalue
+ // below ?
if (variable.to_object() == NULL) {
- return false;
+ dbglogfile << __PRETTY_FUNCTION__ << ": CHECKME: are we required to
always push at least a NULL value ?" << endl;
+ return;
}
const as_object* object = (as_object*) (variable.to_object());
@@ -1336,14 +1641,13 @@
++it;
};
}
-
- return true;
}
-bool
-SWFHandlers::ActionNewAdd(as_environment &env)
+void
+SWFHandlers::ActionNewAdd(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
int version = env.get_target()->get_movie_definition()->get_version();
if (env.top(0).get_type() == as_value::STRING
|| env.top(1).get_type() == as_value::STRING) {
@@ -1353,71 +1657,70 @@
env.top(1) += env.top(0);
}
env.drop(1);
-
- return true;
}
-bool
-SWFHandlers::ActionNewLessThan(as_environment &env)
+void
+SWFHandlers::ActionNewLessThan(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
if (env.top(1).get_type() == as_value::STRING) {
env.top(1).set_bool(env.top(1).to_tu_string() <
env.top(0).to_tu_string());
} else {
env.top(1).set_bool(env.top(1) < env.top(0));
}
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionNewEquals(as_environment &env)
+void
+SWFHandlers::ActionNewEquals(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(1).set_bool(env.top(1) == env.top(0));
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionToNumber(as_environment &env)
+void
+SWFHandlers::ActionToNumber(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(0).convert_to_number();
- return true;
}
-bool
-SWFHandlers::ActionToString(as_environment &env)
+void
+SWFHandlers::ActionToString(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
int version = env.get_target()->get_movie_definition()->get_version();
env.top(0).convert_to_string_versioned(version);
- return true;
}
-bool
-SWFHandlers::ActionDup(as_environment &env)
+void
+SWFHandlers::ActionDup(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.push(env.top(0));
- return true;
}
-bool
-SWFHandlers::ActionSwap(as_environment &env)
+void
+SWFHandlers::ActionSwap(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
as_value temp = env.top(1);
env.top(1) = env.top(0);
env.top(0) = temp;
- return true;
}
-bool
-SWFHandlers::ActionGetMember(as_environment &env)
+void
+SWFHandlers::ActionGetMember(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
// Some corner case behaviors depend on the SWF file version.
int version = env.get_target()->get_movie_definition()->get_version();
@@ -1432,7 +1735,7 @@
// "to an as_object: %s\n",
target.to_string()));
env.top(1).set_undefined();
env.drop(1);
- return false;
+ return;
}
log_action(" ActionGetMember: target: %s (object %p)\n",
@@ -1454,13 +1757,13 @@
}
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionSetMember(as_environment &env)
+void
+SWFHandlers::ActionSetMember(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
as_object* obj = env.top(2).to_object();
if (obj) {
obj->set_member(env.top(1).to_tu_string(), env.top(0));
@@ -1476,34 +1779,34 @@
env.top(0).to_tu_string().c_str());
}
env.drop(3);
- return true;
}
-bool
-SWFHandlers::ActionIncrement(as_environment &env)
+void
+SWFHandlers::ActionIncrement(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(0) += 1;
- return true;
}
-bool
-SWFHandlers::ActionDecrement(as_environment &env)
+void
+SWFHandlers::ActionDecrement(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(0) -= 1;
- return true;
}
-bool
-SWFHandlers::ActionCallMethod(as_environment &env)
+void
+SWFHandlers::ActionCallMethod(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
as_value result;
// Some corner case behaviors depend on the SWF file version.
- //int version = env->get_target()->get_movie_definition()->get_version();
+ //int version = env.get_target()->get_movie_definition()->get_version();
// Get name of the method
const tu_string &method_name = env.top(0).to_tu_string();
@@ -1544,23 +1847,24 @@
env.top(0) = result;
// This is to check stack status after call method
- //log_msg("at doActionCallMethod() end, stack: \n"); env->dump_stack();
+ //log_msg("at doActionCallMethod() end, stack: \n"); env.dump_stack();
- return true;
}
-bool
-SWFHandlers::ActionNewMethod(as_environment &env)
+void
+SWFHandlers::ActionNewMethod(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
}
-bool
-SWFHandlers::ActionInstanceOf(as_environment &env)
+void
+SWFHandlers::ActionInstanceOf(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
+
// Get the "super" function
function_as_object* super = env.top(0).to_as_function();
@@ -1577,80 +1881,80 @@
env.drop(1);
env.top(0) = as_value(false);
- return false;
+ return;
}
env.drop(1);
env.top(0) = as_value(instance->instanceOf(super));
- return true;
}
-bool
-SWFHandlers::ActionEnum2(as_environment &env)
+void
+SWFHandlers::ActionEnum2(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
}
-bool
-SWFHandlers::ActionBitwiseAnd(as_environment &env)
+void
+SWFHandlers::ActionBitwiseAnd(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(1) &= env.top(0);
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionBitwiseOr(as_environment &env)
+void
+SWFHandlers::ActionBitwiseOr(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(1) |= env.top(0);
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionBitwiseXor(as_environment &env)
+void
+SWFHandlers::ActionBitwiseXor(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(1) ^= env.top(0);
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionShiftLeft(as_environment &env)
+void
+SWFHandlers::ActionShiftLeft(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(1).asr(env.top(0));
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionShiftRight(as_environment &env)
+void
+SWFHandlers::ActionShiftRight(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(1).lsr(env.top(0));
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionShiftRight2(as_environment &env)
+void
+SWFHandlers::ActionShiftRight2(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(1).lsr(env.top(0));
env.drop(1);
- return false;
}
-bool
-SWFHandlers::ActionStrictEq(as_environment &env)
+void
+SWFHandlers::ActionStrictEq(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
if (env.top(1).get_type() != env.top(0).get_type()) {
// Types don't match.
env.top(1).set_bool(false);
@@ -1659,80 +1963,183 @@
env.top(1).set_bool(env.top(1) == env.top(0));
env.drop(1);
}
- return true;
}
-bool
-SWFHandlers::ActionGreater(as_environment &env)
+void
+SWFHandlers::ActionGreater(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
if (env.top(1).get_type() == as_value::STRING) {
env.top(1).set_bool(env.top(1).to_tu_string() >
env.top(0).to_tu_string());
} else {
env.top(1).set_bool(env.top(1).to_number() > env.top(0).to_number());
}
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionStringGreater(as_environment &env)
+void
+SWFHandlers::ActionStringGreater(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+ as_environment& env = thread.env;
env.top(1).set_bool(env.top(1).to_tu_string() > env.top(0).to_tu_string());
env.drop(1);
- return true;
}
-bool
-SWFHandlers::ActionExtends(as_environment &env)
+void
+SWFHandlers::ActionExtends(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
}
-bool
-SWFHandlers::ActionConstantPool(as_environment &env)
+void
+SWFHandlers::ActionConstantPool(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
- dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
- return false;
+ thread.code.process_decl_dict(thread.pc, thread.next_pc);
}
-bool
-SWFHandlers::ActionDefineFunction2(as_environment &env)
+void
+SWFHandlers::ActionDefineFunction2(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
- return false;
+
+ as_environment& env = thread.env;
+ const action_buffer& code = thread.code;
+
+ function_as_object* func = new function_as_object(
+ &code, &env, thread.next_pc, thread.with_stack);
+ func->set_is_function2();
+
+ size_t i = thread.pc;
+ i += 3;
+
+ // Extract name.
+ // @@ security: watch out for possible missing terminator here!
+ tu_string name = (const char*) code.read_string(i);
+ i += name.length() + 1;
+
+ // Get number of arguments.
+ int nargs = code.read_int16(i);
+ i += 2;
+
+ // Get the count of local registers used by this function.
+ uint8 register_count = code[i];
+ i += 1;
+ func->set_local_register_count(register_count);
+
+ // Flags, for controlling register assignment of implicit args.
+ uint16 flags = code.read_int16(i);
+ i += 2;
+ func->set_function2_flags(flags);
+
+ // Get the register assignments and names of the arguments.
+ for (int n = 0; n < nargs; n++)
+ {
+ uint8 arg_register = code[i];
+ ++i;
+
+ // @@ security: watch out for possible missing terminator here!
+ func->add_arg(arg_register, code.read_string(i));
+ i += func->m_args.back().m_name.length() + 1;
+ }
+
+ // Get the length of the actual function code.
+ int16_t length = code.read_int16(thread.pc);
+ assert( length >= 0 );
+ i += 2;
+ func->set_length(length);
+
+ // Skip the function body (don't interpret it now).
+ assert (thread.next_pc == thread.pc + length);
+ //thread.next_pc += length; // this shoudn't be needed
+
+ // If we have a name, then save the function in this
+ // environment under that name.
+ as_value function_value(func);
+ if (name.length() > 0) {
+ // @@ NOTE: should this be m_target->set_variable()???
+ env.set_member(name, function_value);
+ }
+
+ // Also leave it on the stack.
+ env.push_val(function_value);
}
-bool
-SWFHandlers::ActionTry(as_environment &env)
+void
+SWFHandlers::ActionTry(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
- return false;
+ dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
}
-bool
-SWFHandlers::ActionWith(as_environment &env)
+void
+SWFHandlers::ActionWith(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
- return false;
+ dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
}
-bool
-SWFHandlers::ActionDefineFunction(as_environment &env)
+void
+SWFHandlers::ActionDefineFunction(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
- return false;
+
+ as_environment& env = thread.env;
+ const action_buffer& code = thread.code;
+
+ //int16_t tag_length = code.read_int16(thread.pc);
+ //assert( tag_length >= 0 );
+
+ // Create a new function_as_object
+ function_as_object* func = new function_as_object(
+ &code, &env, thread.next_pc, thread.with_stack);
+
+ size_t i = thread.pc + 3;
+
+ // Extract name.
+ // @@ security: watch out for possible missing terminator here!
+ tu_string name = code.read_string(i);
+ i += name.length() + 1;
+
+ // Get number of arguments.
+ int nargs = code.read_int16(i);
+ i += 2;
+
+ // Get the names of the arguments.
+ for (int n = 0; n < nargs; n++) {
+ // @@ security: watch out for possible missing terminator here!
+ func->add_arg(0, code.read_string(i));
+ i += func->m_args.back().m_name.length() + 1;
+ }
+
+ // Get the length of the actual function code.
+ int length = code.read_int16(i);
+ i += 2;
+ func->set_length(length);
+
+ // Skip the function body (don't interpret it now).
+ thread.next_pc += length;
+
+ // If we have a name, then save the function in this
+ // environment under that name.
+ as_value function_value(func);
+ if (name.length() > 0) {
+ // @@ NOTE: should this be m_target->set_variable()???
+ env.set_member(name, function_value);
+ }
+
+ // Also leave it on the stack.
+ env.push_val(function_value);
}
-bool
-SWFHandlers::ActionSetRegister(as_environment &env)
+void
+SWFHandlers::ActionSetRegister(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
- return false;
+ dbglogfile << __PRETTY_FUNCTION__ << ": unimplemented!" << endl;
}
} // namespace gnash::SWF
Index: server/swf/ASHandlers.h
===================================================================
RCS file: /sources/gnash/gnash/server/swf/ASHandlers.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- server/swf/ASHandlers.h 15 May 2006 03:21:07 -0000 1.1
+++ server/swf/ASHandlers.h 25 Jun 2006 16:53:04 -0000 1.2
@@ -41,10 +41,16 @@
#include <string>
#include <map>
#include <vector>
-#include "action.h"
+#include "action.h" // we should get rid of this probably
#include "swf.h"
#include "log.h"
+
+// Forward declarations
+namespace gnash {
+ class ActionExec;
+}
+
namespace gnash {
/// SWF format parsing classes
@@ -63,7 +69,8 @@
ARG_FUNCTION2
} as_arg_t;
-typedef bool (*action_callback_t)(as_environment &env);
+typedef void (*action_callback_t)(ActionExec& thread);
+//as_environment &env, action_buffer& code, size_t& PC);
class ActionHandler
{
public:
@@ -76,137 +83,174 @@
ActionHandler(action_type type, std::string name,
action_callback_t func, as_arg_t format, int nargs);
~ActionHandler();
- bool execute(as_environment &env);
- void toggleDebug(bool state) { _debug = state; }
- action_type getType() { return _type; }
- std::string getName() { return _name; }
- int getNumArgs() { return _stack_args; }
- as_arg_t getArgFormat() { return _arg_format; }
+
+ /// Execute the action
+ void execute(ActionExec& thread) const;
+
+ void toggleDebug(bool state) const { _debug = state; }
+ action_type getType() const { return _type; }
+ std::string getName() const { return _name; }
+ int getNumArgs() const { return _stack_args; }
+ as_arg_t getArgFormat() const { return _arg_format; }
private:
action_type _type;
std::string _name;
action_callback_t _callback;
- bool _debug;
+ mutable bool _debug;
int _stack_args; // the number of args to pop from the stack
as_arg_t _arg_format;
};
+/// A singleton containing the supported SWF Action handlers.
class SWFHandlers
{
public:
- SWFHandlers();
- ~SWFHandlers();
- bool execute(action_type type, as_environment &env);
+
+ /// TODO: use a vector as we can have at most 254 actions
+ /// (127 w/out length, 127 with length, the high bit is
+ /// used to distinguish the two types)
+ //typedef std::map<action_type, ActionHandler> container_type;
+
+ // Indexed by action id
+ typedef std::vector<ActionHandler> container_type;
+
+ /// Return the singleton instance of SWFHandlers class
+ static const SWFHandlers& instance();
+
+ /// Execute the action identified by 'type' action type
+ bool execute(action_type type, ActionExec& thread) const;
+
void toggleDebug(bool state) { _debug = state; }
- static bool ActionEnd(as_environment &end);
- static bool ActionNextFrame(as_environment &env);
- static bool ActionPrevFrame(as_environment &env);
- static bool ActionPlay(as_environment &env);
- static bool ActionStop(as_environment &env);
- static bool ActionToggleQuality(as_environment &env);
- static bool ActionStopSounds(as_environment &env);
- static bool ActionGotoFrame(as_environment &env);
- static bool ActionGetUrl(as_environment &env);
- static bool ActionWaitForFrame(as_environment &env);
- static bool ActionSetTarget(as_environment &env);
- static bool ActionGotoLabel(as_environment &env);
- static bool ActionAdd(as_environment &env);
- static bool ActionSubtract(as_environment &env);
- static bool ActionMultiply(as_environment &env);
- static bool ActionDivide(as_environment &env);
- static bool ActionEqual(as_environment &env);
- static bool ActionLessThan(as_environment &env);
- static bool ActionLogicalAnd(as_environment &env);
- static bool ActionLogicalOr(as_environment &env);
- static bool ActionLogicalNot(as_environment &env);
- static bool ActionStringEq(as_environment &env);
- static bool ActionStringLength(as_environment &env);
- static bool ActionSubString(as_environment &env);
- static bool ActionPop(as_environment &env);
- static bool ActionInt(as_environment &env);
- static bool ActionGetVariable(as_environment &env);
- static bool ActionSetVariable(as_environment &env);
- static bool ActionSetTargetExpression(as_environment &env);
- static bool ActionStringConcat(as_environment &env);
- static bool ActionGetProperty(as_environment &env);
- static bool ActionSetProperty(as_environment &env);
- static bool ActionDuplicateClip(as_environment &env);
- static bool ActionRemoveClip(as_environment &env);
- static bool ActionTrace(as_environment &env);
- static bool ActionStartDragMovie(as_environment &env);
- static bool ActionStopDragMovie(as_environment &env);
- static bool ActionStringCompare(as_environment &env);
- static bool ActionThrow(as_environment &env);
- static bool ActionCastOp(as_environment &env);
- static bool ActionImplementsOp(as_environment &env);
- static bool ActionRandom(as_environment &env);
- static bool ActionMbLength(as_environment &env);
- static bool ActionOrd(as_environment &env);
- static bool ActionChr(as_environment &env);
- static bool ActionGetTimer(as_environment &env);
- static bool ActionMbSubString(as_environment &env);
- static bool ActionMbOrd(as_environment &env);
- static bool ActionMbChr(as_environment &env);
- static bool ActionWaitForFrameExpression(as_environment &env);
- static bool ActionPushData(as_environment &env);
- static bool ActionBranchAlways(as_environment &env);
- static bool ActionGetUrl2(as_environment &env);
- static bool ActionBranchIfTrue(as_environment &env);
- static bool ActionCallFrame(as_environment &env);
- static bool ActionGotoExpression(as_environment &env);
- static bool ActionDeleteVar(as_environment &env);
- static bool ActionDelete(as_environment &env);
- static bool ActionVarEquals(as_environment &env);
- static bool ActionCallFunction(as_environment &env);
- static bool ActionReturn(as_environment &env);
- static bool ActionModulo(as_environment &env);
- static bool ActionNew(as_environment &env);
- static bool ActionVar(as_environment &env);
- static bool ActionInitArray(as_environment &env);
- static bool ActionInitObject(as_environment &env);
- static bool ActionTypeOf(as_environment &env);
- static bool ActionTargetPath(as_environment &env);
- static bool ActionEnumerate(as_environment &env);
- static bool ActionNewAdd(as_environment &env);
- static bool ActionNewLessThan(as_environment &env);
- static bool ActionNewEquals(as_environment &env);
- static bool ActionToNumber(as_environment &env);
- static bool ActionToString(as_environment &env);
- static bool ActionDup(as_environment &env);
- static bool ActionSwap(as_environment &env);
- static bool ActionGetMember(as_environment &env);
- static bool ActionSetMember(as_environment &env);
- static bool ActionIncrement(as_environment &env);
- static bool ActionDecrement(as_environment &env);
- static bool ActionCallMethod(as_environment &env);
- static bool ActionNewMethod(as_environment &env);
- static bool ActionInstanceOf(as_environment &env);
- static bool ActionEnum2(as_environment &env);
- static bool ActionBitwiseAnd(as_environment &env);
- static bool ActionBitwiseOr(as_environment &env);
- static bool ActionBitwiseXor(as_environment &env);
- static bool ActionShiftLeft(as_environment &env);
- static bool ActionShiftRight(as_environment &env);
- static bool ActionShiftRight2(as_environment &env);
- static bool ActionStrictEq(as_environment &env);
- static bool ActionGreater(as_environment &env);
- static bool ActionStringGreater(as_environment &env);
- static bool ActionExtends(as_environment &env);
- static bool ActionConstantPool(as_environment &env);
- static bool ActionDefineFunction2(as_environment &env);
- static bool ActionTry(as_environment &env);
- static bool ActionWith(as_environment &env);
- static bool ActionDefineFunction(as_environment &env);
- static bool ActionSetRegister(as_environment &env);
-
- int size() { return (int)_handlers.size(); }
- action_type lastType() { return
_handlers[ACTION_GOTOEXPRESSION].getType(); }
- ActionHandler &operator [](action_type x) { return _handlers[x]; }
+ static void ActionEnd(ActionExec& thread);
+ static void ActionNextFrame(ActionExec& thread);
+ static void ActionPrevFrame(ActionExec& thread);
+ static void ActionPlay(ActionExec& thread);
+ static void ActionStop(ActionExec& thread);
+ static void ActionToggleQuality(ActionExec& thread);
+ static void ActionStopSounds(ActionExec& thread);
+ static void ActionGotoFrame(ActionExec& thread);
+ static void ActionGetUrl(ActionExec& thread);
+ static void ActionWaitForFrame(ActionExec& thread);
+ static void ActionSetTarget(ActionExec& thread);
+ static void ActionGotoLabel(ActionExec& thread);
+ static void ActionAdd(ActionExec& thread);
+ static void ActionSubtract(ActionExec& thread);
+ static void ActionMultiply(ActionExec& thread);
+ static void ActionDivide(ActionExec& thread);
+ static void ActionEqual(ActionExec& thread);
+ static void ActionLessThan(ActionExec& thread);
+ static void ActionLogicalAnd(ActionExec& thread);
+ static void ActionLogicalOr(ActionExec& thread);
+ static void ActionLogicalNot(ActionExec& thread);
+ static void ActionStringEq(ActionExec& thread);
+ static void ActionStringLength(ActionExec& thread);
+ static void ActionSubString(ActionExec& thread);
+ static void ActionPop(ActionExec& thread);
+ static void ActionInt(ActionExec& thread);
+ static void ActionGetVariable(ActionExec& thread);
+ static void ActionSetVariable(ActionExec& thread);
+ static void ActionSetTargetExpression(ActionExec& thread);
+ static void ActionStringConcat(ActionExec& thread);
+ static void ActionGetProperty(ActionExec& thread);
+ static void ActionSetProperty(ActionExec& thread);
+ static void ActionDuplicateClip(ActionExec& thread);
+ static void ActionRemoveClip(ActionExec& thread);
+ static void ActionTrace(ActionExec& thread);
+ static void ActionStartDragMovie(ActionExec& thread);
+ static void ActionStopDragMovie(ActionExec& thread);
+ static void ActionStringCompare(ActionExec& thread);
+ static void ActionThrow(ActionExec& thread);
+ static void ActionCastOp(ActionExec& thread);
+ static void ActionImplementsOp(ActionExec& thread);
+ static void ActionRandom(ActionExec& thread);
+ static void ActionMbLength(ActionExec& thread);
+ static void ActionOrd(ActionExec& thread);
+ static void ActionChr(ActionExec& thread);
+ static void ActionGetTimer(ActionExec& thread);
+ static void ActionMbSubString(ActionExec& thread);
+ static void ActionMbOrd(ActionExec& thread);
+ static void ActionMbChr(ActionExec& thread);
+ static void ActionWaitForFrameExpression(ActionExec& thread);
+ static void ActionPushData(ActionExec& thread);
+ static void ActionBranchAlways(ActionExec& thread);
+ static void ActionGetUrl2(ActionExec& thread);
+ static void ActionBranchIfTrue(ActionExec& thread);
+ static void ActionCallFrame(ActionExec& thread);
+ static void ActionGotoExpression(ActionExec& thread);
+ static void ActionDeleteVar(ActionExec& thread);
+ static void ActionDelete(ActionExec& thread);
+ static void ActionVarEquals(ActionExec& thread);
+ static void ActionCallFunction(ActionExec& thread);
+ static void ActionReturn(ActionExec& thread);
+ static void ActionModulo(ActionExec& thread);
+ static void ActionNew(ActionExec& thread);
+ static void ActionVar(ActionExec& thread);
+ static void ActionInitArray(ActionExec& thread);
+ static void ActionInitObject(ActionExec& thread);
+ static void ActionTypeOf(ActionExec& thread);
+ static void ActionTargetPath(ActionExec& thread);
+ static void ActionEnumerate(ActionExec& thread);
+ static void ActionNewAdd(ActionExec& thread);
+ static void ActionNewLessThan(ActionExec& thread);
+ static void ActionNewEquals(ActionExec& thread);
+ static void ActionToNumber(ActionExec& thread);
+ static void ActionToString(ActionExec& thread);
+ static void ActionDup(ActionExec& thread);
+ static void ActionSwap(ActionExec& thread);
+ static void ActionGetMember(ActionExec& thread);
+ static void ActionSetMember(ActionExec& thread);
+ static void ActionIncrement(ActionExec& thread);
+ static void ActionDecrement(ActionExec& thread);
+ static void ActionCallMethod(ActionExec& thread);
+ static void ActionNewMethod(ActionExec& thread);
+ static void ActionInstanceOf(ActionExec& thread);
+ static void ActionEnum2(ActionExec& thread);
+ static void ActionBitwiseAnd(ActionExec& thread);
+ static void ActionBitwiseOr(ActionExec& thread);
+ static void ActionBitwiseXor(ActionExec& thread);
+ static void ActionShiftLeft(ActionExec& thread);
+ static void ActionShiftRight(ActionExec& thread);
+ static void ActionShiftRight2(ActionExec& thread);
+ static void ActionStrictEq(ActionExec& thread);
+ static void ActionGreater(ActionExec& thread);
+ static void ActionStringGreater(ActionExec& thread);
+ static void ActionExtends(ActionExec& thread);
+ static void ActionConstantPool(ActionExec& thread);
+ static void ActionDefineFunction2(ActionExec& thread);
+ static void ActionTry(ActionExec& thread);
+ static void ActionWith(ActionExec& thread);
+ static void ActionDefineFunction(ActionExec& thread);
+ static void ActionSetRegister(ActionExec& thread);
+
+ size_t size() const { return _handlers.size(); }
+
+ action_type lastType() const
+ {
+ return ACTION_GOTOEXPRESSION;
+ //return _handlers[ACTION_GOTOEXPRESSION].getType();
+ }
+
+ const ActionHandler &operator[] (action_type x) const
+ {
+ //return const_cast<ActionHandler>(_handlers[x]);
+ return _handlers[x];
+ }
+
private:
+
bool _debug;
- static std::map<action_type, ActionHandler> _handlers;
+
+ static container_type _handlers;
+
static std::vector<std::string> _property_names;
+
+ // Use the ::instance() method to get a reference
+ SWFHandlers();
+
+ // You won't destroy a singleton
+ ~SWFHandlers();
+
};
Index: server/ActionExec.cpp
===================================================================
RCS file: server/ActionExec.cpp
diff -N server/ActionExec.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/ActionExec.cpp 25 Jun 2006 16:53:04 -0000 1.1
@@ -0,0 +1,633 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+// Linking Gnash statically or dynamically with other modules is making a
+// combined work based on Gnash. Thus, the terms and conditions of the GNU
+// General Public License cover the whole combination.
+//
+// As a special exception, the copyright holders of Gnash give you
+// permission to combine Gnash with free software programs or libraries
+// that are released under the GNU LGPL and with code included in any
+// release of Talkback distributed by the Mozilla Foundation. You may
+// copy and distribute such a system following the terms of the GNU GPL
+// for all but the LGPL-covered parts and Talkback, and following the
+// LGPL for the LGPL-covered parts.
+//
+// Note that people who make modified versions of Gnash are not obligated
+// to grant this special exception for their modified versions; it is their
+// choice whether to do so. The GNU General Public License gives permission
+// to release a modified version without this exception; this exception
+// also makes it possible to release a modified version which carries
+// forward this exception.
+//
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ActionExec.h"
+#include "action_buffer.h"
+#include "Function.h" // for function_as_object
+#include "log.h"
+#include "stream.h"
+
+#include "swf.h"
+#include "ASHandlers.h"
+#include "as_environment.h"
+
+#include <typeinfo>
+
+#if !defined(_WIN32) && !defined(WIN32)
+# include <pthread.h>
+#endif
+
+#include <string>
+#include <stdlib.h> // for strtod
+
+using namespace gnash;
+using namespace SWF;
+using std::string;
+using std::endl;
+
+
+namespace gnash {
+
+static const SWFHandlers& ash = SWFHandlers::instance();
+
+// External interface (to be moved under swf/ASHandlers)
+fscommand_callback s_fscommand_handler = NULL;
+void register_fscommand_callback(fscommand_callback handler)
+{
+ s_fscommand_handler = handler;
+}
+
+// Utility. Try to convert str to a number. If successful,
+// put the result in *result, and return true. If not
+// successful, put 0 in *result, and return false.
+static bool string_to_number(double* result, const char* str)
+{
+ char* tail = 0;
+ *result = strtod(str, &tail);
+ if (tail == str || *tail != 0)
+ {
+ // Failed conversion to Number.
+ return false;
+ }
+ return true;
+}
+
+
+
+
+ActionExec::ActionExec(const action_buffer& abuf, as_environment& newEnv,
+ size_t nStartPC, size_t exec_bytes, as_value* retval,
+ const std::vector<with_stack_entry>& initial_with_stack,
+ bool nIsFunction2)
+ :
+ code(abuf),
+ pc(nStartPC),
+ stop_pc(nStartPC+exec_bytes),
+ next_pc(nStartPC),
+ env(newEnv),
+ retval(retval),
+ with_stack(initial_with_stack),
+ _function2_var(nIsFunction2)
+{
+}
+
+ActionExec::ActionExec(const action_buffer& abuf, as_environment& newEnv)
+ :
+ code(abuf),
+ pc(0),
+ stop_pc(code.size()),
+ next_pc(0),
+ env(newEnv),
+ retval(0),
+ with_stack(),
+ _function2_var(false)
+{
+}
+
+void
+ActionExec::operator() ()
+{
+ action_init(); // @@ stick this somewhere else; need some global
static init function
+
+#if 0
+ // Check the time
+ if (periodic_events.expired()) {
+ periodic_events.poll_event_handlers(&env);
+ }
+#endif
+
+ movie* original_target = env.get_target();
+ UNUSED(original_target); // Avoid warnings.
+
+ while (pc<stop_pc)
+ {
+
+ // Cleanup any expired "with" blocks.
+ while ( with_stack.size() > 0
+ && pc >= with_stack.back().end_pc() ) {
+ // Drop this stack element
+ with_stack.resize(with_stack.size() - 1);
+ }
+
+ // Get the opcode.
+ uint8_t action_id = code[pc];
+
+ if (dbglogfile.getActionDump()) {
+ log_action("\nEX:\t");
+ code.log_disasm(pc);
+ }
+
+ // Set default next_pc offset, control flow action handlers
+ // will be able to reset it.
+ if ((action_id & 0x80) == 0) {
+ // action with no extra data
+ next_pc = pc+1;
+ } else {
+ // action with extra data
+ int16_t length = code.read_int16(pc+1);
+ assert( length >= 0 );
+ next_pc = pc + length + 3;
+ }
+
+ if ( action_id == SWF::ACTION_RETURN ) {
+ break;
+ }
+
+ if ( action_id == SWF::ACTION_END ) {
+ log_msg("At ACTION_END pc=%d, stop_pc=%d", pc, stop_pc);
+ break;
+ }
+
+ ash.execute((action_type)action_id, *this);
+
+ // Control flow actions will change the PC (next_pc)
+ pc = next_pc;
+
+//
+// The following handlers implementations must be moved
+// to swf/ASHandlers. Are kept for reference
+//
+#if 0 // {
+ if ( ! ash.execute((action_type)action_id, *this) )
+ {
+ // Action handler not yet ported to new layout
+
+#if 0
+ switch (action_id) {
+
+ case SWF::ACTION_GOTOFRAME: // goto frame
+ {
+ int frame = code.read_int16(pc+3);
+ // 0-based already?
+ //// Convert from 1-based to 0-based
+ //frame--;
+ env.get_target()->goto_frame(frame);
+ break;
+ }
+
+#if 0
+ case SWF::ACTION_GETURL: // get url
+ {
+ // If this is an FSCommand, then call the callback
+ // handler, if any.
+
+ // Two strings as args.
+ const char* url = code.read_string(pc+3);
+ size_t url_len = strlen(url);
+ const char* target = code.read_string(pc+3+url_len+1);
+
+ // If the url starts with an "http" or "https",
+ // then we want to load it into a web browser.
+ if (strncmp(url, "http", 4) == 0) {
+// if (windowid) {
+// Atom mAtom = 486;
+// Display *mDisplay = XOpenDisplay(NULL);
+// XLockDisplay(mDisplay);
+// XChangeProperty (mDisplay, windowid,
mAtom,
+// XA_STRING, 8,
PropModeReplace,
+// (unsigned char *)url,
+// url_len);
+
+// XUnlockDisplay(mDisplay);
+// XCloseDisplay(mDisplay);
+// } else {
+ string command = "firefox -remote \"openurl(";
+ command += url;
+ command += ")\"";
+ dbglogfile << "Launching URL... " << command << endl;
+// movie *target = env.get_target();
+// target->get_url(url);
+ system(command.c_str());
+// }
+ break;
+ }
+
+ // If the url starts with "FSCommand:", then this is
+ // a message for the host app.
+ if (strncmp(url, "FSCommand:", 10) == 0) {
+ if (s_fscommand_handler) {
+ // Call into the app.
+
(*s_fscommand_handler)(env.get_target()->get_root_interface(), url + 10,
target);
+ }
+ } else {
+#ifdef EXTERN_MOVIE
+// log_error("get url: target=%s, url=%s\n",
target, url);
+
+ tu_string tu_target = target;
+ movie* target_movie = env.find_target(tu_target);
+ if (target_movie != NULL) {
+ movie *root_movie =
env.get_target()->get_root_movie();
+ attach_extern_movie(url, target_movie, root_movie);
+ } else {
+ log_error("get url: target %s not found\n", target);
+ }
+#endif // EXTERN_MOVIE
+ }
+
+ break;
+ }
+#endif
+
+ case SWF::ACTION_SETREGISTER: // store_register
+ {
+ int reg = code[pc + 3];
+ // Save top of stack in specified register.
+ if ( isFunction2() ) {
+ *(env.local_register_ptr(reg)) = env.top(0);
+
+ log_action("-------------- local register[%d] =
'%s'\n",
+ reg,
+ env.top(0).to_string());
+ } else if (reg >= 0 && reg < 4) {
+ env.m_global_register[reg] = env.top(0);
+
+ log_action("-------------- global register[%d] =
'%s'\n",
+ reg,
+ env.top(0).to_string());
+ } else {
+ log_error("store_register[%d] -- register out of
bounds!", reg);
+ }
+
+ break;
+ }
+
+#if 0
+ case SWF::ACTION_CONSTANTPOOL: // decl_dict: declare dictionary
+ {
+ //int i = pc;
+ //int count = code[pc + 3] | (code[pc + 4] << 8);
+ //i += 2;
+
+ code.process_decl_dict(pc, next_pc);
+
+ break;
+ }
+#endif
+
+#if 0
+ case SWF::ACTION_WAITFORFRAME: // wait for frame
+ {
+ // If we haven't loaded a specified frame yet, then we're
supposed to skip
+ // some specified number of actions.
+ //
+ // Since we don't load incrementally, just ignore this opcode.
+ break;
+ }
+#endif
+
+ case SWF::ACTION_SETTARGET: // set target
+ {
+ // Change the movie we're working on.
+ const char* target_name = code.read_string(pc+3);
+ movie *new_target;
+
+ // if the string is blank, we set target to the root movie
+ // TODO - double check this is correct?
+ if (target_name[0] == '\0')
+ new_target = env.find_target((tu_string)"/");
+ else
+ new_target = env.find_target((tu_string)target_name);
+
+ if (new_target == NULL) {
+ log_action("ERROR: Couldn't find movie \"%s\" to set
target to!"
+ " Not setting target at all...",
+ (const char *)target_name);
+ }
+ else
+ env.set_target(new_target);
+
+ break;
+ }
+
+ case SWF::ACTION_GOTOLABEL: // go to labeled frame,
goto_frame_lbl
+ {
+ const char* frame_label = code.read_string(pc+3);
+ movie *target = env.get_target();
+ target->goto_labeled_frame(frame_label);
+ break;
+ }
+
+ case SWF::ACTION_WAITFORFRAMEEXPRESSION: // wait for frame
expression (?)
+ {
+ // Pop the frame number to wait for; if it's not loaded skip
the
+ // specified number of actions.
+ //
+ // Since we don't support incremental loading, pop our arg and
+ // don't do anything.
+ env.drop(1);
+ break;
+ }
+
+#if 0
+ case SWF::ACTION_DEFINEFUNCTION2: // 0x8E
+ code.doActionDefineFunction2(env, with_stack, pc, &next_pc);
+ break;
+#endif
+
+ case SWF::ACTION_WITH: // with
+ {
+ int frame = code.read_int16(pc+3);
+ UNUSED(frame);
+ log_action("-------------- with block start: stack size is
%zd\n", with_stack.size());
+ if (with_stack.size() < 8) {
+ int block_length = code.read_int16(pc+3);
+ int block_end = next_pc + block_length;
+ as_object* with_obj = env.top(0).to_object();
+ with_stack.push_back(with_stack_entry(with_obj,
block_end));
+ }
+ env.drop(1);
+ break;
+ }
+#if 0
+ case SWF::ACTION_PUSHDATA: // push_data
+ {
+ size_t i = pc;
+ while (i - pc < length) {
+ int type = code[3 + i];
+ i++;
+ if (type == 0) {
+ // string
+ const char* str = code.read_string(i+3);
+ i += strlen(str) + 1;
+ env.push(str);
+
+ log_action("----string---- pushed '%s'", str);
+ } else if (type == 1) {
+
+ float f = code.read_float_little(i+3);
+ i += 4;
+ env.push(f);
+ log_action("----float----- pushed '%g'", f);
+ } else if (type == 2) {
+ as_value nullvalue;
+ nullvalue.set_null();
+ env.push(nullvalue);
+
+ log_action("----null------ pushed NULL");
+ } else if (type == 3) {
+ env.push(as_value());
+
+ log_action("----undef----- pushed UNDEFINED");
+ } else if (type == 4) {
+ // contents of register
+ int reg = code[3 + i];
+ i++;
+ if ( isFunction2() ) {
+ env.push(*(env.local_register_ptr(reg)));
+ log_action("-------------- pushed local
register[%d] = '%s'\n",
+ reg,
+ env.top(0).to_string());
+ } else if (reg < 0 || reg >= 4) {
+ env.push(as_value());
+ log_error("push register[%d] -- register out of
bounds!\n", reg);
+ } else {
+ env.push(env.m_global_register[reg]);
+ log_action("-------------- pushed global
register[%d] = '%s'\n",
+ reg,
+ env.top(0).to_string());
+ }
+
+ } else if (type == 5) {
+ bool bool_val = code[i+3] ? true : false;
+ i++;
+// log_msg("bool(%d)\n", bool_val);
+ env.push(bool_val);
+
+ log_action("---bool------- pushed %s",
+ (bool_val ? "true" : "false"));
+ } else if (type == 6) {
+ double d = code.read_double_wacky(i+3);
+ i += 8;
+ env.push(d);
+
+ log_action("-------------- pushed double %g", u.d);
+ } else if (type == 7) {
+ // int32
+ int32_t val = code.read_int32(i+3);
+ i += 4;
+
+ env.push(val);
+
+ log_action("-------------- pushed int32 %d",val);
+ } else if (type == 8) {
+ int id = code[3 + i];
+ i++;
+ if (id < (int) code.m_dictionary.size()) {
+ env.push(code.m_dictionary[id]);
+
+ log_action("----dict------ pushed '%s'",
+ code.m_dictionary[id]);
+ } else {
+ log_error("dict_lookup(%d) is out of bounds!\n",
id);
+ env.push(0);
+ log_action("-------------- pushed 0");
+ }
+ } else if (type == 9) {
+ int id = code.read_int16(i+3);
+ i += 2;
+ if (id < (int) code.m_dictionary.size()) {
+ env.push(code.m_dictionary[id]);
+ log_action("-------------- pushed '%s'\n",
code.m_dictionary[id]);
+ } else {
+ log_error("dict_lookup(%d) is out of bounds!\n",
id);
+ env.push(0);
+
+ log_action("-------------- pushed 0");
+ }
+ }
+ }
+
+ break;
+ }
+#endif
+ case SWF::ACTION_BRANCHALWAYS: // branch always (goto)
+ {
+ int16_t offset = code.read_int16(pc+3);
+ next_pc += offset;
+ // @@ TODO range checks
+ break;
+ }
+#if 0
+ case SWF::ACTION_GETURL2: // get url 2
+ {
+ int method = code[pc + 3];
+ UNUSED(method);
+
+ const char* target = env.top(0).to_string();
+ const char* url = env.top(1).to_string();
+
+ // If the url starts with "FSCommand:", then this is
+ // a message for the host app.
+ if (strncmp(url, "FSCommand:", 10) == 0) {
+ if (s_fscommand_handler) {
+ // Call into the app.
+
(*s_fscommand_handler)(env.get_target()->get_root_interface(), url + 10,
target);
+ }
+ } else {
+#ifdef EXTERN_MOVIE
+// log_error("get url2: target=%s, url=%s\n", target, url);
+
+ movie* target_movie = env.find_target(env.top(0));
+ if (target_movie != NULL) {
+ movie* root_movie =
env.get_target()->get_root_movie();
+ attach_extern_movie(url, target_movie, root_movie);
+ } else {
+ log_error("get url2: target %s not found\n", target);
+ }
+#endif // EXTERN_MOVIE
+ }
+ env.drop(2);
+ break;
+ }
+#endif
+
+#if 0
+ case SWF::ACTION_DEFINEFUNCTION: // declare function
+ doActionDefineFunction(env, with_stack, pc, &next_pc);
+ break;
+#endif
+
+ case SWF::ACTION_BRANCHIFTRUE: // branch if true
+ {
+ int16_t offset = code.read_int16(pc+3);
+
+ bool test = env.top(0).to_bool();
+ env.drop(1);
+ if (test) {
+ next_pc += offset;
+
+ if (next_pc > stop_pc) {
+ log_error("branch to offset %d -- this section only
runs to %d\n",
+ next_pc,
+ stop_pc);
+ }
+ }
+ break;
+ }
+ case SWF::ACTION_CALLFRAME: // call frame
+ {
+ // Note: no extra data in this instruction!
+ assert(env.m_target);
+ env.m_target->call_frame_actions(env.top(0));
+ env.drop(1);
+
+ break;
+ }
+
+ case SWF::ACTION_GOTOEXPRESSION: // goto frame expression,
goto_frame_exp
+ {
+ // From Alexi's SWF ref:
+ //
+ // Pop a value or a string and jump to the specified
+ // frame. When a string is specified, it can include a
+ // path to a sprite as in:
+ //
+ // /Test:55
+ //
+ // When f_play is ON, the action is to play as soon as
+ // that frame is reached. Otherwise, the
+ // frame is shown in stop mode.
+
+ unsigned char play_flag = code[pc + 3];
+ movie::play_state state = play_flag ? movie::PLAY :
movie::STOP;
+
+ movie* target = env.get_target();
+ bool success = false;
+
+ if (env.top(0).get_type() == as_value::UNDEFINED) {
+ // No-op.
+ } else if (env.top(0).get_type() == as_value::STRING) {
+ // @@ TODO: parse possible sprite path...
+
+ // Also, if the frame spec is actually a number (not a
label), then
+ // we need to do the conversion...
+
+ const char* frame_label = env.top(0).to_string();
+ if (target->goto_labeled_frame(frame_label)) {
+ success = true;
+ } else {
+ // Couldn't find the label. Try converting to a
number.
+ double num;
+ if (string_to_number(&num, env.top(0).to_string())) {
+ int frame_number = int(num);
+ target->goto_frame(frame_number);
+ success = true;
+ }
+ // else no-op.
+ }
+ } else if (env.top(0).get_type() == as_value::OBJECT) {
+ // This is a no-op; see test_goto_frame.swf
+ } else if (env.top(0).get_type() == as_value::NUMBER) {
+ // Frame numbers appear to be 0-based! @@ Verify.
+ int frame_number = int(env.top(0).to_number());
+ target->goto_frame(frame_number);
+ success = true;
+ }
+
+ if (success) {
+ target->set_play_state(state);
+ }
+
+ env.drop(1);
+ break;
+ }
+
+ default:
+ log_error("Missing handler for action %d", action_id);
+ break;
+
+ }
+#endif
+ }
+#endif // } // End of kept-for reference block
+
+ }
+
+ env.set_target(original_target);
+}
+
+
+};
+
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: server/ActionExec.h
===================================================================
RCS file: server/ActionExec.h
diff -N server/ActionExec.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/ActionExec.h 25 Jun 2006 16:53:04 -0000 1.1
@@ -0,0 +1,110 @@
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+// Linking Gnash statically or dynamically with other modules is making a
+// combined work based on Gnash. Thus, the terms and conditions of the GNU
+// General Public License cover the whole combination.
+//
+// As a special exception, the copyright holders of Gnash give you
+// permission to combine Gnash with free software programs or libraries
+// that are released under the GNU LGPL and with code included in any
+// release of Talkback distributed by the Mozilla Foundation. You may
+// copy and distribute such a system following the terms of the GNU GPL
+// for all but the LGPL-covered parts and Talkback, and following the
+// LGPL for the LGPL-covered parts.
+//
+// Note that people who make modified versions of Gnash are not obligated
+// to grant this special exception for their modified versions; it is their
+// choice whether to do so. The GNU General Public License gives permission
+// to release a modified version without this exception; this exception
+// also makes it possible to release a modified version which carries
+// forward this exception.
+//
+
+#ifndef GNASH_ACTIONEXEC_H
+#define GNASH_ACTIONEXEC_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "with_stack_entry.h"
+
+#include <vector>
+
+// Forward declarations
+namespace gnash {
+ class action_buffer;
+ class as_environment;
+ class as_value;
+}
+
+namespace gnash {
+
+/// Executor of an action_buffer
+class ActionExec {
+
+public:
+
+ const action_buffer& code;
+
+ /// Program counter (offset of current action tag)
+ size_t pc;
+
+ /// End of current function execution
+ size_t stop_pc;
+
+ /// Offset to next action tag
+ size_t next_pc;
+
+ as_environment& env;
+
+ as_value* retval;
+ std::vector<with_stack_entry> with_stack;
+ bool _function2_var;
+
+ ActionExec(const action_buffer& abuf, as_environment& newEnv);
+
+ ActionExec(
+ const action_buffer& abuf, // the action buffer
+ as_environment& newEnv,
+ size_t nStartPC, // where to start execution
+ size_t nExecBytes, // Number of bytes to run
+ // this is probably a redundant
+ // information, as an ActionEnd
+ // should tell us when to stop.
+ // We'll keep this parameter as
+ // an SWF integrity checker.
+ as_value* nRetval, // where to return a value, if this
+ // is a function call (??)
+ const std::vector<with_stack_entry>& initial_with_stack,
+ bool nIsFunction2 // again, this is only for use with functions
+ );
+
+ bool isFunction2() { return _function2_var; }
+
+ void operator() ();
+
+};
+
+} // namespace gnash
+
+#endif // GNASH_ACTIONEXEC_H
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End: