gnash-commit
[Top][All Lists]
Advanced

[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:




reply via email to

[Prev in Thread] Current Thread [Next in Thread]