[Swfdec] Branch 'as' - 15 commits - libswfdec/swfdec_as_context.c libswfdec/swfdec_as_context.h libswfdec/swfdec_as_frame.c libswfdec/swfdec_as_frame.h libswfdec/swfdec_as_function.c libswfdec/swfdec_as_function.h libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_object.c libswfdec/swfdec_as_object.h libswfdec/swfdec_as_types.c libswfdec/swfdec_as_types.h libswfdec/swfdec_button_movie.c libswfdec/swfdec_connection.c libswfdec/swfdec_debugger.c libswfdec/swfdec_listener.c libswfdec/swfdec_movie.c libswfdec/swfdec_net_stream.c libswfdec/swfdec_script.c libswfdec/swfdec_xml.c player/swfdec_debug_widget.c

Benjamin Otte company at kemper.freedesktop.org
Thu Apr 12 05:07:01 PDT 2007


 libswfdec/swfdec_as_context.c   |   29 ++--
 libswfdec/swfdec_as_context.h   |    5 
 libswfdec/swfdec_as_frame.c     |   47 +++++-
 libswfdec/swfdec_as_frame.h     |    7 -
 libswfdec/swfdec_as_function.c  |   12 +
 libswfdec/swfdec_as_function.h  |    4 
 libswfdec/swfdec_as_interpret.c |  270 +++++++++++++++++++---------------------
 libswfdec/swfdec_as_object.c    |   31 ++++
 libswfdec/swfdec_as_object.h    |    3 
 libswfdec/swfdec_as_types.c     |   24 ++-
 libswfdec/swfdec_as_types.h     |    4 
 libswfdec/swfdec_button_movie.c |    2 
 libswfdec/swfdec_connection.c   |    2 
 libswfdec/swfdec_debugger.c     |   25 +--
 libswfdec/swfdec_listener.c     |    2 
 libswfdec/swfdec_movie.c        |    2 
 libswfdec/swfdec_net_stream.c   |    4 
 libswfdec/swfdec_script.c       |    9 -
 libswfdec/swfdec_xml.c          |    2 
 player/swfdec_debug_widget.c    |    2 
 20 files changed, 285 insertions(+), 201 deletions(-)

New commits:
diff-tree 02593459b3315d147733872fef67bdb8fb5396d0 (from f47891d0c97c9679dc4234c83866948ace3d1d50)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 12 14:06:35 2007 +0200

    ensxure printing an action always returns a string, even if its just "error"

diff --git a/libswfdec/swfdec_debugger.c b/libswfdec/swfdec_debugger.c
index 71b3ee7..1daf62a 100644
--- a/libswfdec/swfdec_debugger.c
+++ b/libswfdec/swfdec_debugger.c
@@ -70,10 +70,8 @@ swfdec_debugger_print_push (ScriptParser
       case 0: /* string */
 	{
 	  const char *s = swfdec_bits_skip_string (&bits);
-	  if (!s) {
-	    g_string_free (string, TRUE);
-	    return NULL;
-	  }
+	  if (!s)
+	    goto error;
 	  g_string_append_c (string, '"');
 	  g_string_append (string, s);
 	  g_string_append_c (string, '"');
@@ -108,15 +106,13 @@ swfdec_debugger_print_push (ScriptParser
 
 	  if (!parser->constant_pool) {
 	    SWFDEC_ERROR ("no constant pool");
-	    g_string_free (string, TRUE);
-	    return NULL;
+	    goto error;
 	  }
 	  id = type == 8 ? swfdec_bits_get_u8 (&bits) : swfdec_bits_get_u16 (&bits);
 	  s = swfdec_constant_pool_get (parser->constant_pool, id);
 	  if (!s) {
 	    SWFDEC_ERROR ("constant pool size too small");
-	    g_string_free (string, TRUE);
-	    return NULL;
+	    goto error;
 	  }
 	  g_string_append_c (string, '"');
 	  g_string_append (string, s);
@@ -125,10 +121,14 @@ swfdec_debugger_print_push (ScriptParser
 	break;
       default:
 	SWFDEC_ERROR ("Push: type %u not implemented", type);
-	return NULL;
+	goto error;
     }
   }
   return g_string_free (string, FALSE);
+
+error:
+  g_string_free (string, TRUE);
+  return "erroneous action Push";
 }
 
 /* NB: constant pool actions are special in that they are called at init time */
@@ -140,15 +140,14 @@ swfdec_debugger_add_command (gconstpoint
   SwfdecDebuggerCommand command;
 
   command.code = bytecode;
-  if (action == 0x96) {
-    /* PUSH */
+  if (action == SWFDEC_AS_ACTION_PUSH) {
     command.description = swfdec_debugger_print_push (parser, data, len);
   } else {
     command.description = swfdec_script_print_action (action, data, len);
   }
+  g_assert (command.description != NULL);
   g_array_append_val (parser->commands, command);
-  if (action == 0x88) {
-    /* constant pool */
+  if (action == SWFDEC_AS_ACTION_CONSTANT_POOL) {
     if (parser->constant_pool)
       swfdec_constant_pool_free (parser->constant_pool);
     parser->constant_pool = swfdec_constant_pool_new_from_action (data, len);
diff-tree f47891d0c97c9679dc4234c83866948ace3d1d50 (from 36576d269d6927d4d2403f98c5dce4e0998b805f)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 12 14:06:09 2007 +0200

    return a valid string in _print_action () all the time, never return NULL

diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index f5fd334..06b9d75 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -129,15 +129,16 @@ swfdec_script_print_action (guint action
 
   if (action & 0x80) {
     if (spec->print == NULL) {
-      SWFDEC_ERROR ("action %u %s has no print statement",
-	  action, spec->name ? spec->name : "Unknown");
-      return NULL;
+      SWFDEC_ERROR ("action %u 0x%02X %s has no print statement",
+	  action, action, spec->name ? spec->name : "Unknown");
+      return g_strdup_printf ("erroneous action %s",
+	  spec->name ? spec->name : "Unknown");
     }
     return spec->print (action, data, len);
   } else {
     if (spec->name == NULL) {
       SWFDEC_ERROR ("action %u is unknown", action);
-      return NULL;
+      return g_strdup_printf ("unknown Action 0x%02X", action);
     }
     return g_strdup (spec->name);
   }
diff-tree 36576d269d6927d4d2403f98c5dce4e0998b805f (from 0a383b0939aff7f9b7b4d6922e53645f1151874f)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 12 13:52:00 2007 +0200

    implement calling valueOf when converting to number

diff --git a/libswfdec/swfdec_as_types.c b/libswfdec/swfdec_as_types.c
index 4731c97..889fceb 100644
--- a/libswfdec/swfdec_as_types.c
+++ b/libswfdec/swfdec_as_types.c
@@ -99,6 +99,7 @@ const char *swfdec_as_strings[] = {
   SWFDEC_AS_CONSTANT_STRING ("function"),
   SWFDEC_AS_CONSTANT_STRING ("object"),
   SWFDEC_AS_CONSTANT_STRING ("toString"),
+  SWFDEC_AS_CONSTANT_STRING ("valueOf"),
   /* add more here */
   NULL
 };
@@ -204,8 +205,15 @@ swfdec_as_value_to_number (SwfdecAsConte
 	  return NAN;
       }
     case SWFDEC_TYPE_AS_ASOBJECT:
-      SWFDEC_ERROR ("FIXME");
-      return NAN;
+      {
+	SwfdecAsValue ret;
+	swfdec_as_object_call (SWFDEC_AS_VALUE_GET_OBJECT (value), SWFDEC_AS_STR_VALUEOF,
+	    0, NULL, &ret);
+	if (SWFDEC_AS_VALUE_IS_NUMBER (&ret))
+	  return SWFDEC_AS_VALUE_GET_NUMBER (&ret);
+	else
+	  return NAN;
+      }
     default:
       g_assert_not_reached ();
       return NAN;
diff --git a/libswfdec/swfdec_as_types.h b/libswfdec/swfdec_as_types.h
index b114bae..2cfe796 100644
--- a/libswfdec/swfdec_as_types.h
+++ b/libswfdec/swfdec_as_types.h
@@ -166,6 +166,7 @@ extern const char *swfdec_as_strings[];
 #define SWFDEC_AS_STR_FUNCTION		SWFDEC_AS_STR_CONSTANT(66)
 #define SWFDEC_AS_STR_OBJECT		SWFDEC_AS_STR_CONSTANT(67)
 #define SWFDEC_AS_STR_TOSTRING		SWFDEC_AS_STR_CONSTANT(68)
+#define SWFDEC_AS_STR_VALUEOF		SWFDEC_AS_STR_CONSTANT(69)
 
 /* all existing actions */
 typedef enum {
diff-tree 0a383b0939aff7f9b7b4d6922e53645f1151874f (from 7b3c6b319a51bf19205f6314d9b171243f9af88a)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 12 13:51:41 2007 +0200

    use current scale not user set scale when computing click area

diff --git a/player/swfdec_debug_widget.c b/player/swfdec_debug_widget.c
index 4c7ebcc..953b918 100644
--- a/player/swfdec_debug_widget.c
+++ b/player/swfdec_debug_widget.c
@@ -60,7 +60,7 @@ swfdec_debug_widget_button_press (GtkWid
     return FALSE;
 
   if (event->button == 1 && swfdec_gtk_widget_get_interactive (widget)) {
-    double scale = swfdec_gtk_widget_get_scale (widget);
+    double scale = swfdec_gtk_widget_get_current_scale (widget);
     SwfdecPlayer *player = swfdec_gtk_widget_get_player (widget);
     switch (event->type) {
       case GDK_BUTTON_PRESS:
diff-tree 7b3c6b319a51bf19205f6314d9b171243f9af88a (from 096cfd1d49808ca78c06a2db0f3fe4ac9cd94dc6)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 12 13:39:08 2007 +0200

    remove debugging g_print

diff --git a/libswfdec/swfdec_as_context.c b/libswfdec/swfdec_as_context.c
index e88c30d..e38d9ba 100644
--- a/libswfdec/swfdec_as_context.c
+++ b/libswfdec/swfdec_as_context.c
@@ -386,7 +386,6 @@ start:
   pc = frame->pc;
 
   while (TRUE) {
-    g_print ("pc is %p\n", pc);
     if (pc == endpc) {
       swfdec_as_context_return (context);
       goto start;
diff-tree 096cfd1d49808ca78c06a2db0f3fe4ac9cd94dc6 (from 605184459c5be15046a75e42ef912f0d12a7ecf6)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 12 13:38:28 2007 +0200

    copy the name of the calling script

diff --git a/libswfdec/swfdec_as_frame.c b/libswfdec/swfdec_as_frame.c
index 36db616..ee6c8ca 100644
--- a/libswfdec/swfdec_as_frame.c
+++ b/libswfdec/swfdec_as_frame.c
@@ -104,11 +104,12 @@ swfdec_as_frame_new (SwfdecAsObject *thi
   if (!swfdec_as_context_use_mem (context, size))
     return NULL;
   frame = g_object_new (SWFDEC_TYPE_AS_FRAME, NULL);
-  SWFDEC_DEBUG ("new frame");
   swfdec_as_object_add (SWFDEC_AS_OBJECT (frame), context, size);
   frame->next = context->frame;
   context->frame = frame;
   frame->script = swfdec_script_ref (script);
+  frame->function_name = script->name;
+  SWFDEC_DEBUG ("new frame for function %s", frame->function_name);
   frame->pc = script->buffer->data;
   frame->stack = stack;
   frame->scope = thisp;
diff-tree 605184459c5be15046a75e42ef912f0d12a7ecf6 (from 3c696bc51ec288dfe931bc23b1e297d4b7e169da)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 12 13:38:16 2007 +0200

    break on 0 action before invoking the debugger

diff --git a/libswfdec/swfdec_as_context.c b/libswfdec/swfdec_as_context.c
index 46b8889..e88c30d 100644
--- a/libswfdec/swfdec_as_context.c
+++ b/libswfdec/swfdec_as_context.c
@@ -386,6 +386,7 @@ start:
   pc = frame->pc;
 
   while (TRUE) {
+    g_print ("pc is %p\n", pc);
     if (pc == endpc) {
       swfdec_as_context_return (context);
       goto start;
@@ -395,6 +396,13 @@ start:
       goto error;
     }
 
+    /* decode next action */
+    action = *pc;
+    if (action == 0) {
+      swfdec_as_context_return (context);
+      goto start;
+    }
+    /* invoke debugger if there is one */
     if (step) {
       frame->pc = pc;
       (* step) (context);
@@ -403,11 +411,8 @@ start:
 	goto start;
       }
     }
-    /* decode next action */
-    action = *pc;
+    /* prepare action */
     spec = swfdec_as_actions + action;
-    if (action == 0)
-      break;
     if (action & 0x80) {
       if (pc + 2 >= endpc) {
 	SWFDEC_ERROR ("action %u length value out of range", action);
@@ -445,6 +450,7 @@ start:
 #ifndef G_DISABLE_ASSERT
     check = (spec->add >= 0 && spec->remove >= 0) ? stack->cur + spec->add - spec->remove : NULL;
 #endif
+    /* execute action */
     spec->exec[version] (context, action, data, len);
     if (frame == context->frame) {
 #ifndef G_DISABLE_ASSERT
diff-tree 3c696bc51ec288dfe931bc23b1e297d4b7e169da (from 847c11c34cc23a33097931e2b4022ba1c585b94b)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 12 13:22:18 2007 +0200

    refacotr function calls and return value handling

diff --git a/libswfdec/swfdec_as_object.c b/libswfdec/swfdec_as_object.c
index 9c6e56e..747b071 100644
--- a/libswfdec/swfdec_as_object.c
+++ b/libswfdec/swfdec_as_object.c
@@ -313,12 +313,41 @@ swfdec_as_object_run (SwfdecAsObject *ob
     swfdec_as_context_run (object->context);
 }
 
+/**
+ * swfdec_as_object_call:
+ * @object: a #SwfdecAsObject
+ * @name: garbage-collected string naming the function to call. 
+ * @argc: number of arguments to provide to function
+ * @argv: arguments or %NULL when @argc is 0
+ * @return_value: location to take the return value of the call or %NULL to 
+ *                ignore the return value.
+ *
+ * Calls the function named @name on the given object. This function is 
+ * essentially equal to the folloeing Actionscript code: 
+ * <informalexample><programlisting>
+ * @return_value = @object. at name (@argv[0], ..., @argv[argc-1]);
+ * </programlisting></informalexample>
+ **/
 void
-swfdec_as_object_call (SwfdecAsObject *object, const char *name, guint argc, SwfdecAsValue *argv)
+swfdec_as_object_call (SwfdecAsObject *object, const char *name, guint argc, 
+    SwfdecAsValue *argv, SwfdecAsValue *return_value)
 {
+  SwfdecAsValue tmp;
+  SwfdecAsFunction *fun;
+
   g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
   g_return_if_fail (name != NULL);
   g_return_if_fail (argc == 0 || argv != NULL);
+
+  if (return_value)
+    SWFDEC_AS_VALUE_SET_UNDEFINED (return_value);
+  swfdec_as_object_get (object, name, &tmp);
+  if (!SWFDEC_AS_VALUE_IS_OBJECT (&tmp))
+    return;
+  fun = (SwfdecAsFunction *) SWFDEC_AS_VALUE_GET_OBJECT (&tmp);
+  if (!SWFDEC_IS_AS_FUNCTION (fun))
+    return;
+  swfdec_as_function_call (fun, object, argc, argv, return_value ? return_value : &tmp);
 }
 
 gboolean
diff --git a/libswfdec/swfdec_as_object.h b/libswfdec/swfdec_as_object.h
index b843011..0876bbb 100644
--- a/libswfdec/swfdec_as_object.h
+++ b/libswfdec/swfdec_as_object.h
@@ -130,7 +130,8 @@ gboolean	swfdec_as_object_has_function	(
 void		swfdec_as_object_call		(SwfdecAsObject *       object,
 						 const char *		name,
 						 guint			argc,
-						 SwfdecAsValue *	argv);
+						 SwfdecAsValue *	argv,
+						 SwfdecAsValue *	return_value);
 
 G_END_DECLS
 #endif
diff --git a/libswfdec/swfdec_as_types.c b/libswfdec/swfdec_as_types.c
index ee8c403..4731c97 100644
--- a/libswfdec/swfdec_as_types.c
+++ b/libswfdec/swfdec_as_types.c
@@ -98,6 +98,7 @@ const char *swfdec_as_strings[] = {
   SWFDEC_AS_CONSTANT_STRING ("movieclip"),
   SWFDEC_AS_CONSTANT_STRING ("function"),
   SWFDEC_AS_CONSTANT_STRING ("object"),
+  SWFDEC_AS_CONSTANT_STRING ("toString"),
   /* add more here */
   NULL
 };
@@ -138,8 +139,15 @@ swfdec_as_value_to_string (SwfdecAsConte
 	return ret;
       }
     case SWFDEC_TYPE_AS_ASOBJECT:
-      SWFDEC_ERROR ("FIXME");
-      return SWFDEC_AS_STR_OBJECT_OBJECT;
+      {
+	SwfdecAsValue ret;
+	swfdec_as_object_call (SWFDEC_AS_VALUE_GET_OBJECT (value), SWFDEC_AS_STR_TOSTRING,
+	    0, NULL, &ret);
+	if (SWFDEC_AS_VALUE_IS_STRING (&ret))
+	  return SWFDEC_AS_VALUE_GET_STRING (&ret);
+	else
+	  return SWFDEC_AS_STR_OBJECT_OBJECT;
+      }
     default:
       g_assert_not_reached ();
       return SWFDEC_AS_STR_EMPTY;
diff --git a/libswfdec/swfdec_as_types.h b/libswfdec/swfdec_as_types.h
index a65772a..b114bae 100644
--- a/libswfdec/swfdec_as_types.h
+++ b/libswfdec/swfdec_as_types.h
@@ -165,6 +165,7 @@ extern const char *swfdec_as_strings[];
 #define SWFDEC_AS_STR_MOVIECLIP		SWFDEC_AS_STR_CONSTANT(65)
 #define SWFDEC_AS_STR_FUNCTION		SWFDEC_AS_STR_CONSTANT(66)
 #define SWFDEC_AS_STR_OBJECT		SWFDEC_AS_STR_CONSTANT(67)
+#define SWFDEC_AS_STR_TOSTRING		SWFDEC_AS_STR_CONSTANT(68)
 
 /* all existing actions */
 typedef enum {
diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index 15267b6..a16a4f9 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -109,7 +109,7 @@ swfdec_button_movie_execute (SwfdecButto
     swfdec_event_list_execute (movie->button->events, 
 	SWFDEC_AS_OBJECT (SWFDEC_MOVIE (movie)->parent), condition, 0);
   name = swfdec_button_condition_get_name (condition);
-  swfdec_as_object_call (SWFDEC_AS_OBJECT (movie), name, 0, NULL);
+  swfdec_as_object_call (SWFDEC_AS_OBJECT (movie), name, 0, NULL, NULL);
 }
 
 #define CONTENT_IN_FRAME(content, frame) \
diff --git a/libswfdec/swfdec_connection.c b/libswfdec/swfdec_connection.c
index d55c916..e10e53b 100644
--- a/libswfdec/swfdec_connection.c
+++ b/libswfdec/swfdec_connection.c
@@ -76,7 +76,7 @@ swfdec_connection_onstatus (SwfdecConnec
   }
   SWFDEC_AS_VALUE_SET_OBJECT (&value, info);
   swfdec_as_object_unroot (info);
-  swfdec_as_object_call (SWFDEC_AS_OBJECT (conn), SWFDEC_AS_STR_STATUS, 1, &value);
+  swfdec_as_object_call (SWFDEC_AS_OBJECT (conn), SWFDEC_AS_STR_STATUS, 1, &value, NULL);
 }
 
 SwfdecConnection *
diff --git a/libswfdec/swfdec_listener.c b/libswfdec/swfdec_listener.c
index b4495e7..b2021f0 100644
--- a/libswfdec/swfdec_listener.c
+++ b/libswfdec/swfdec_listener.c
@@ -135,7 +135,7 @@ swfdec_listener_execute	(SwfdecListener 
 	listener->entries[i].removed = FALSE;
       }
       listener->entries[i].blocked_by = NULL;
-      swfdec_as_object_call (obj, event, 0, NULL);
+      swfdec_as_object_call (obj, event, 0, NULL, NULL);
     }
   }
 }
diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index 3b6a726..e627130 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -410,7 +410,7 @@ swfdec_movie_execute_script (SwfdecMovie
   }
   name = swfdec_event_type_get_name (condition);
   if (name != NULL)
-    swfdec_as_object_call (SWFDEC_AS_OBJECT (movie), name, 0, NULL);
+    swfdec_as_object_call (SWFDEC_AS_OBJECT (movie), name, 0, NULL, NULL);
 }
 
 static void
diff --git a/libswfdec/swfdec_net_stream.c b/libswfdec/swfdec_net_stream.c
index 4fa1a32..fc19af2 100644
--- a/libswfdec/swfdec_net_stream.c
+++ b/libswfdec/swfdec_net_stream.c
@@ -46,7 +46,7 @@ swfdec_net_stream_onstatus (SwfdecNetStr
   swfdec_as_object_set (object, SWFDEC_AS_STR_LEVEL, &val);
 
   SWFDEC_AS_VALUE_SET_OBJECT (&val, object);
-  swfdec_as_object_call (SWFDEC_AS_OBJECT (stream), SWFDEC_AS_STR_ON_STATUS, 1, &val);
+  swfdec_as_object_call (SWFDEC_AS_OBJECT (stream), SWFDEC_AS_STR_ON_STATUS, 1, &val, NULL);
 }
 
 static void swfdec_net_stream_update_playing (SwfdecNetStream *stream);
@@ -113,7 +113,7 @@ swfdec_net_stream_video_goto (SwfdecNetS
 	SWFDEC_ERROR ("could not parse data tag");
       } else {
 	swfdec_as_object_call (SWFDEC_AS_OBJECT (stream), 
-	    SWFDEC_AS_VALUE_GET_STRING (&name), 1, &value);
+	    SWFDEC_AS_VALUE_GET_STRING (&name), 1, &value, NULL);
       }
     }
   }
diff --git a/libswfdec/swfdec_xml.c b/libswfdec/swfdec_xml.c
index c931c6b..057c64c 100644
--- a/libswfdec/swfdec_xml.c
+++ b/libswfdec/swfdec_xml.c
@@ -47,7 +47,7 @@ swfdec_xml_ondata (SwfdecXml *xml)
   } else {
     SWFDEC_AS_VALUE_SET_UNDEFINED (&val);
   }
-  swfdec_as_object_call (SWFDEC_AS_OBJECT (xml), SWFDEC_AS_STR_ON_DATA, 1, &val);
+  swfdec_as_object_call (SWFDEC_AS_OBJECT (xml), SWFDEC_AS_STR_ON_DATA, 1, &val, NULL);
 }
 
 static void
diff-tree 847c11c34cc23a33097931e2b4022ba1c585b94b (from 19645bbd08100a4684ace9256ed47edbfc629aa8)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 12 12:27:41 2007 +0200

    rework handling of return values
    
    function calls now take a pointer to a return value. That value is
    set to UNDEFINED right now and can then be overwritten by subsequent
    return actions.

diff --git a/libswfdec/swfdec_as_context.c b/libswfdec/swfdec_as_context.c
index 185ae0a..46b8889 100644
--- a/libswfdec/swfdec_as_context.c
+++ b/libswfdec/swfdec_as_context.c
@@ -387,7 +387,7 @@ start:
 
   while (TRUE) {
     if (pc == endpc) {
-      swfdec_as_context_return (context, NULL);
+      swfdec_as_context_return (context);
       goto start;
     }
     if (pc < startpc || pc >= endpc) {
@@ -471,19 +471,12 @@ error:
 }
 
 void
-swfdec_as_context_return (SwfdecAsContext *context, SwfdecAsValue *retval)
+swfdec_as_context_return (SwfdecAsContext *context)
 {
   g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context));
   g_return_if_fail (context->frame != NULL);
-  g_return_if_fail (retval == NULL || SWFDEC_IS_AS_VALUE (retval));
 
   context->frame = context->frame->next;
-  swfdec_as_stack_ensure_left (context->frame->stack, 1);
-  if (retval) {
-    *swfdec_as_stack_push (context->frame->stack) = *retval;
-  } else {
-    SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_push (context->frame->stack));
-  }
 }
 
 void
diff --git a/libswfdec/swfdec_as_context.h b/libswfdec/swfdec_as_context.h
index b4b2777..ca1b818 100644
--- a/libswfdec/swfdec_as_context.h
+++ b/libswfdec/swfdec_as_context.h
@@ -90,8 +90,7 @@ void		swfdec_as_string_mark		(const char
 void		swfdec_as_context_gc		(SwfdecAsContext *	context);
 
 void		swfdec_as_context_run		(SwfdecAsContext *	context);
-void		swfdec_as_context_return	(SwfdecAsContext *	context,
-						 SwfdecAsValue *	retval);
+void		swfdec_as_context_return	(SwfdecAsContext *	context);
 void		swfdec_as_context_trace		(SwfdecAsContext *	context,
 						 const char *		string);
 
diff --git a/libswfdec/swfdec_as_frame.h b/libswfdec/swfdec_as_frame.h
index 8d806bf..a89c7ee 100644
--- a/libswfdec/swfdec_as_frame.h
+++ b/libswfdec/swfdec_as_frame.h
@@ -40,6 +40,7 @@ struct _SwfdecAsFrame {
 
   SwfdecAsFrame *	next;		/* next frame (FIXME: keep a list in the context instead?) */
   char *		function_name;	/* name of function */
+  SwfdecAsValue *	return_value;	/* pointer to where to store the return value */
   /* normal execution */
   SwfdecScript *	script;		/* script being executed */
   SwfdecAsObject *	scope;		/* scope object coming after this: an Object */
diff --git a/libswfdec/swfdec_as_function.c b/libswfdec/swfdec_as_function.c
index 65540d2..653efea 100644
--- a/libswfdec/swfdec_as_function.c
+++ b/libswfdec/swfdec_as_function.c
@@ -107,13 +107,16 @@ swfdec_as_function_new_native (SwfdecAsC
 }
 
 void
-swfdec_as_function_call (SwfdecAsFunction *function, SwfdecAsObject *thisp, guint n_args)
+swfdec_as_function_call (SwfdecAsFunction *function, SwfdecAsObject *thisp, guint n_args,
+    SwfdecAsValue *args, SwfdecAsValue *return_value)
 {
   SwfdecAsContext *context;
   SwfdecAsFrame *frame;
 
   g_return_if_fail (SWFDEC_IS_AS_FUNCTION (function));
   g_return_if_fail (SWFDEC_IS_AS_OBJECT (thisp));
+  g_return_if_fail (n_args == 0 || args != NULL);
+  g_return_if_fail (return_value != NULL);
 
   context = thisp->context;
   if (context->frame) {
@@ -122,9 +125,9 @@ swfdec_as_function_call (SwfdecAsFunctio
   } else {
     n_args = 0;
   }
+  SWFDEC_AS_VALUE_SET_UNDEFINED (return_value);
   /* now do different things depending on if we're a native function or not */
   if (function->native) {
-    SwfdecAsValue retval = { 0, };
     if (n_args < function->min_args) {
       SwfdecAsStack *stack = context->frame->stack;
       if (n_args == 0) {
@@ -139,10 +142,11 @@ swfdec_as_function_call (SwfdecAsFunctio
     frame = swfdec_as_frame_new_native (thisp);
     g_assert (function->name);
     frame->function_name = function->name;
-    function->native (context, thisp, n_args, NULL, &retval);
-    swfdec_as_context_return (context, &retval);
+    function->native (context, thisp, n_args, args, return_value);
+    swfdec_as_context_return (context);
   } else {
     frame = swfdec_as_frame_new (thisp, function->script);
+    frame->return_value = return_value;
     /* FIXME: do the preloading here */
   }
 }
diff --git a/libswfdec/swfdec_as_function.h b/libswfdec/swfdec_as_function.h
index d39c645..77ca819 100644
--- a/libswfdec/swfdec_as_function.h
+++ b/libswfdec/swfdec_as_function.h
@@ -66,7 +66,9 @@ SwfdecAsFunction *	swfdec_as_function_ne
 
 void			swfdec_as_function_call		(SwfdecAsFunction *	function,
 							 SwfdecAsObject *	thisp,
-							 guint			n_args);
+							 guint			n_args,
+							 SwfdecAsValue *	args,
+							 SwfdecAsValue *	return_value);
 
 
 
diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index cc2bf34..11ae005 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -658,6 +658,8 @@ swfdec_action_call (SwfdecAsContext *cx,
   SwfdecAsFunction *fun;
   SwfdecAsObject *thisp;
   SwfdecAsFrame *frame = cx->frame;
+  SwfdecAsValue retval;
+  guint i;
 
   if (!SWFDEC_AS_VALUE_IS_OBJECT (swfdec_as_stack_peek (frame->stack, 1)) ||
       !SWFDEC_AS_VALUE_IS_OBJECT (swfdec_as_stack_peek (frame->stack, 2)))
@@ -667,7 +669,20 @@ swfdec_action_call (SwfdecAsContext *cx,
     goto error;
   thisp = SWFDEC_AS_VALUE_GET_OBJECT (swfdec_as_stack_peek (frame->stack, 2));
   swfdec_as_stack_pop_n (frame->stack, 2);
-  swfdec_as_function_call (fun, thisp, n_args);
+  /* swap arguments on the stack */
+  /* FIXME: can we somehow keep this order please, it might be interesting for debuggers */
+  for (i = 0; i < n_args / 2; i++) {
+    SwfdecAsValue tmp = *swfdec_as_stack_peek (frame->stack, i + 1);
+    *swfdec_as_stack_peek (frame->stack, i + 1) = *swfdec_as_stack_peek (frame->stack, n_args - i);
+    *swfdec_as_stack_peek (frame->stack, n_args - i) = tmp;
+  }
+  swfdec_as_function_call (fun, thisp, n_args, swfdec_as_stack_peek (frame->stack, n_args), &retval);
+  if (n_args) {
+    swfdec_as_stack_pop_n (frame->stack, n_args - 1);
+    *swfdec_as_stack_peek (frame->stack, 1) = retval;
+  } else {
+    *swfdec_as_stack_push (frame->stack) = retval;
+  }
   return;
 
 error:
diff-tree 19645bbd08100a4684ace9256ed47edbfc629aa8 (from 63635ba4c29a8ecb3de4314f4586ed85c90266d7)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 12 11:28:47 2007 +0200

    implement RandomNumber action
    
    Also add a GRand to SwfdecAsContext so we can set/get the seed to reproduce
    stuff.

diff --git a/libswfdec/swfdec_as_context.c b/libswfdec/swfdec_as_context.c
index d8a0859..185ae0a 100644
--- a/libswfdec/swfdec_as_context.c
+++ b/libswfdec/swfdec_as_context.c
@@ -266,6 +266,7 @@ swfdec_as_context_dispose (GObject *obje
   g_assert (g_hash_table_size (context->objects) == 0);
   g_hash_table_destroy (context->objects);
   g_hash_table_destroy (context->strings);
+  g_rand_free (context->rand);
 
   G_OBJECT_CLASS (swfdec_as_context_parent_class)->dispose (object);
 }
@@ -305,6 +306,7 @@ swfdec_as_context_init (SwfdecAsContext 
 	(char *) swfdec_as_strings[i]);
   }
   context->global = swfdec_as_object_new (context);
+  context->rand = g_rand_new ();
 }
 
 /*** STRINGS ***/
diff --git a/libswfdec/swfdec_as_context.h b/libswfdec/swfdec_as_context.h
index e75f729..b4b2777 100644
--- a/libswfdec/swfdec_as_context.h
+++ b/libswfdec/swfdec_as_context.h
@@ -48,6 +48,7 @@ struct _SwfdecAsContext {
 
   SwfdecAsContextState	state;		/* our current state */
   SwfdecAsObject *	global;		/* the global object */
+  GRand *		rand;		/* random number generator */
 
   /* bookkeeping for GC */
   gsize			memory;		/* memory currently in use */
diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index 9e052c4..cc2bf34 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -981,23 +981,22 @@ swfdec_action_push_duplicate (SwfdecAsCo
   *swfdec_as_stack_push (cx->frame->stack) = *swfdec_as_stack_peek (cx->frame->stack, 1);
 }
 
-#if 0
 static void
 swfdec_action_random_number (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
-  gint32 max, result;
+  gint32 max;
+  SwfdecAsValue *val;
 
-  if (!JS_ValueToECMAInt32 (cx, cx->fp->sp[-1], &max))
-    return JS_FALSE;
+  val = swfdec_as_stack_peek (cx->frame->stack, 1);
+  max = swfdec_as_value_to_integer (cx, val);
   
   if (max <= 0)
-    result = 0;
+    SWFDEC_AS_VALUE_SET_NUMBER (val, 0);
   else
-    result = g_random_int_range (0, max);
-
-  return JS_NewNumberValue(cx, result, &cx->fp->sp[-1]);
+    SWFDEC_AS_VALUE_SET_NUMBER (val, g_rand_int_range (cx->rand, 0, max));
 }
 
+#if 0
 static void
 swfdec_action_old_compare (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
@@ -2159,8 +2158,10 @@ const SwfdecActionSpec swfdec_as_actions
   [0x2a] = { "Throw", NULL },
   [0x2b] = { "Cast", NULL },
   [0x2c] = { "Implements", NULL },
+#endif
   /* version 4 */
   [0x30] = { "RandomNumber", NULL, 1, 1, { NULL, swfdec_action_random_number, swfdec_action_random_number, swfdec_action_random_number, swfdec_action_random_number } },
+#if 0
   [0x31] = { "MBStringLength", NULL },
   [0x32] = { "CharToAscii", NULL },
   [0x33] = { "AsciiToChar", NULL },
diff-tree 63635ba4c29a8ecb3de4314f4586ed85c90266d7 (from d0b2d60131cc86f9bbeae1b75978198c607c69c2)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 12 11:18:04 2007 +0200

    implement Greater and Less2 actions

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index e95796e..9e052c4 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -797,48 +797,45 @@ swfdec_action_add2 (SwfdecAsContext *cx,
   }
 }
 
-#if 0
 static void
 swfdec_action_new_comparison_6 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
-  jsval lval, rval;
   double d, d2;
 
-  rval = cx->fp->sp[-1];
-  lval = cx->fp->sp[-2];
-  cx->fp->sp--;
-  d = swfdec_value_to_number (cx, lval);
-  d2 = swfdec_value_to_number (cx, rval);
+  d2 = swfdec_as_value_to_number (cx, swfdec_as_stack_peek (cx->frame->stack, 1));
+  d = swfdec_as_value_to_number (cx, swfdec_as_stack_peek (cx->frame->stack, 2));
+  swfdec_as_stack_pop (cx->frame->stack);
   if (action == 0x48)
-    cx->fp->sp[-1] = BOOLEAN_TO_JSVAL (d < d2);
+    SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx->frame->stack, 1), d < d2);
   else 
-    cx->fp->sp[-1] = BOOLEAN_TO_JSVAL (d > d2);
-  return JS_TRUE;
+    SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx->frame->stack, 1), d > d2);
 }
 
 static void
 swfdec_action_new_comparison_7 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
-  jsval lval, rval;
+  SwfdecAsValue *lval, *rval;
 
-  rval = cx->fp->sp[-1];
-  lval = cx->fp->sp[-2];
-  cx->fp->sp--;
-  if (JSVAL_IS_VOID (rval) || JSVAL_IS_VOID (lval)) {
-    cx->fp->sp[-1] = JSVAL_VOID;
-  } else if (JSVAL_IS_STRING(lval) && JSVAL_IS_STRING(rval)) {
-    int comp = JS_CompareStrings (JSVAL_TO_STRING (lval), JSVAL_TO_STRING (rval));
-    cx->fp->sp[-1] = BOOLEAN_TO_JSVAL (action == 0x48 ? comp < 0 : comp > 0);
+  rval = swfdec_as_stack_peek (cx->frame->stack, 1);
+  lval = swfdec_as_stack_peek (cx->frame->stack, 2);
+  if (SWFDEC_AS_VALUE_IS_UNDEFINED (rval) || SWFDEC_AS_VALUE_IS_UNDEFINED (lval)) {
+    swfdec_as_stack_pop (cx->frame->stack);
+    SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx->frame->stack, 1));
+  } else if (SWFDEC_AS_VALUE_IS_STRING (rval) || SWFDEC_AS_VALUE_IS_STRING (lval)) {
+    int comp = strcmp (SWFDEC_AS_VALUE_GET_STRING (rval), SWFDEC_AS_VALUE_GET_STRING (lval));
+    swfdec_as_stack_pop (cx->frame->stack);
+    SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx->frame->stack, 1), action == 0x48 ? comp < 0 : comp > 0);
   } else {
     double d, d2;
-    if (!JS_ValueToNumber(cx, lval, &d) ||
-        !JS_ValueToNumber(cx, rval, &d2))
-	return JS_FALSE;
-    cx->fp->sp[-1] = BOOLEAN_TO_JSVAL (action == 0x48 ? d < d2 : d > d2);
+    d2 = swfdec_as_value_to_number (cx, rval);
+    d = swfdec_as_value_to_number (cx, lval);
+    swfdec_as_stack_pop (cx->frame->stack);
+    if (action == 0x48)
+      SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx->frame->stack, 1), d < d2);
+    else 
+      SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx->frame->stack, 1), d > d2);
   }
-  return JS_TRUE;
 }
-#endif
 
 static void
 swfdec_action_not_4 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
@@ -2191,9 +2188,7 @@ const SwfdecActionSpec swfdec_as_actions
   [0x46] = { "Enumerate", NULL },
 #endif
   [SWFDEC_AS_ACTION_ADD2] = { "Add2", NULL, 2, 1, { NULL, NULL, swfdec_action_add2, swfdec_action_add2, swfdec_action_add2 } },
-#if 0
-  [0x48] = { "Less2", NULL, 2, 1, { NULL, NULL, swfdec_action_new_comparison_6, swfdec_action_new_comparison_6, swfdec_action_new_comparison_7 } },
-#endif
+  [SWFDEC_AS_ACTION_LESS2] = { "Less2", NULL, 2, 1, { NULL, NULL, swfdec_action_new_comparison_6, swfdec_action_new_comparison_6, swfdec_action_new_comparison_7 } },
   [SWFDEC_AS_ACTION_EQUALS2] = { "Equals2", NULL, 2, 1, { NULL, NULL, swfdec_action_equals2, swfdec_action_equals2, swfdec_action_equals2 } },
   [SWFDEC_AS_ACTION_TO_NUMBER] = { "ToNumber", NULL, 1, 1, { NULL, NULL, swfdec_action_to_number, swfdec_action_to_number, swfdec_action_to_number } },
   [SWFDEC_AS_ACTION_TO_STRING] = { "ToString", NULL, 1, 1, { NULL, NULL, swfdec_action_to_string, swfdec_action_to_string, swfdec_action_to_string } },
@@ -2218,13 +2213,15 @@ const SwfdecActionSpec swfdec_as_actions
   [0x65] = { "BitURShift", NULL, 2, 1, { NULL, NULL, swfdec_action_shift, swfdec_action_shift, swfdec_action_shift } },
   /* version 6 */
   [0x66] = { "StrictEquals", NULL },
-  [0x67] = { "Greater", NULL, 2, 1, { NULL, NULL, NULL, swfdec_action_new_comparison_6, swfdec_action_new_comparison_7 } },
-  [0x68] = { "StringGreater", NULL },
+#endif
+  [SWFDEC_AS_ACTION_GREATER] = { "Greater", NULL, 2, 1, { NULL, NULL, NULL, swfdec_action_new_comparison_6, swfdec_action_new_comparison_7 } },
+  [SWFDEC_AS_ACTION_STRING_GREATER] = { "StringGreater", NULL },
   /* version 7 */
+#if 0
   [0x69] = { "Extends", NULL, 2, 0, { NULL, NULL, NULL, NULL, swfdec_action_extends } },
+#endif
 
   /* version 3 */
-#endif
   [SWFDEC_AS_ACTION_GOTO_FRAME] = { "GotoFrame", swfdec_action_print_goto_frame, 0, 0, { swfdec_action_goto_frame, swfdec_action_goto_frame, swfdec_action_goto_frame, swfdec_action_goto_frame, swfdec_action_goto_frame } },
 #if 0
   [0x83] = { "GetURL", swfdec_action_print_get_url, 0, 0, { swfdec_action_get_url, swfdec_action_get_url, swfdec_action_get_url, swfdec_action_get_url, swfdec_action_get_url } },
diff --git a/libswfdec/swfdec_as_types.h b/libswfdec/swfdec_as_types.h
index 10f3a9c..a65772a 100644
--- a/libswfdec/swfdec_as_types.h
+++ b/libswfdec/swfdec_as_types.h
@@ -243,7 +243,7 @@ typedef enum {
   SWFDEC_AS_ACTION_BIT_URSHIFT = 0x65,
   SWFDEC_AS_ACTION_STRICT_EQUALS = 0x66,
   SWFDEC_AS_ACTION_GREATER = 0x67,
-  SWFDEC_AS_ACTION_STRING_FREATER = 0x68,
+  SWFDEC_AS_ACTION_STRING_GREATER = 0x68,
   SWFDEC_AS_ACTION_EXTENDS = 0x69,
   SWFDEC_AS_ACTION_GOTO_FRAME = 0x81,
   SWFDEC_AS_ACTION_GET_URL = 0x83,
diff-tree d0b2d60131cc86f9bbeae1b75978198c607c69c2 (from 5ff1c3070d3f85f152c6a1d4045904c3ced10266)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 12 11:07:50 2007 +0200

    implement Equals2

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index 7dcd442..e95796e 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -1031,57 +1031,58 @@ swfdec_action_old_compare (SwfdecAsConte
   }
   return JS_TRUE;
 }
+#endif
 
 static void
 swfdec_action_equals2 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
-  jsval rval, lval;
-  int ltag, rtag;
-  void cond;
-
-  rval = cx->fp->sp[-1];
-  lval = cx->fp->sp[-2];
-  ltag = JSVAL_TAG(lval);
-  rtag = JSVAL_TAG(rval);
-  if (ltag == rtag) {
-    if (ltag == JSVAL_STRING) {
-      cond = js_CompareStrings (JSVAL_TO_STRING (lval), JSVAL_TO_STRING (rval)) == 0;
-    } else if (ltag == JSVAL_DOUBLE) {
-      cond = *JSVAL_TO_DOUBLE(lval) == *JSVAL_TO_DOUBLE(rval);
-    } else {
-      cond = lval == rval;
+  SwfdecAsValue *rval, *lval;
+  SwfdecAsType ltype, rtype;
+  gboolean cond;
+
+  rval = swfdec_as_stack_peek (cx->frame->stack, 1);
+  lval = swfdec_as_stack_peek (cx->frame->stack, 2);
+  ltype = lval->type;
+  rtype = rval->type;
+  if (ltype == rtype) {
+    switch (ltype) {
+      case SWFDEC_TYPE_AS_UNDEFINED:
+      case SWFDEC_TYPE_AS_NULL:
+	cond = TRUE;
+	break;
+      case SWFDEC_TYPE_AS_BOOLEAN:
+	cond = SWFDEC_AS_VALUE_GET_BOOLEAN (lval) == SWFDEC_AS_VALUE_GET_BOOLEAN (rval);
+	break;
+      case SWFDEC_TYPE_AS_NUMBER:
+	cond = SWFDEC_AS_VALUE_GET_NUMBER (lval) == SWFDEC_AS_VALUE_GET_NUMBER (rval);
+	break;
+      case SWFDEC_TYPE_AS_STRING:
+	cond = SWFDEC_AS_VALUE_GET_STRING (lval) == SWFDEC_AS_VALUE_GET_STRING (rval);
+	break;
+      case SWFDEC_TYPE_AS_ASOBJECT:
+	cond = SWFDEC_AS_VALUE_GET_OBJECT (lval) == SWFDEC_AS_VALUE_GET_OBJECT (rval);
+	break;
+      default:
+	g_assert_not_reached ();
+	cond = FALSE;
+	break;
     }
   } else {
-    if (JSVAL_IS_NULL(lval) || JSVAL_IS_VOID(lval)) {
-      cond = (JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval));
-    } else if (JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval)) {
-      cond = JS_FALSE;
+    if (ltype == SWFDEC_TYPE_AS_UNDEFINED || ltype == SWFDEC_TYPE_AS_NULL) {
+      cond = (rtype == SWFDEC_TYPE_AS_UNDEFINED || rtype == SWFDEC_TYPE_AS_NULL);
+    } else if (rtype == SWFDEC_TYPE_AS_UNDEFINED || rtype == SWFDEC_TYPE_AS_NULL) {
+      cond = FALSE;
     } else {
-      if (ltag == JSVAL_OBJECT) {
-	if (!OBJ_DEFAULT_VALUE (cx, JSVAL_TO_OBJECT(lval), 0, &lval))
-	  return JS_FALSE;
-	ltag = JSVAL_TAG(lval);
-      } else if (rtag == JSVAL_OBJECT) {
-	if (!OBJ_DEFAULT_VALUE (cx, JSVAL_TO_OBJECT(rval), 0, &rval))
-	  return JS_FALSE;
-	rtag = JSVAL_TAG(rval);
-      }
-      if (ltag == JSVAL_STRING && rtag == JSVAL_STRING) {
-	cond = js_CompareStrings (JSVAL_TO_STRING (lval), JSVAL_TO_STRING (rval)) == 0;
-      } else {
-	double d, d2;
-	if (!JS_ValueToNumber (cx, lval, &d) ||
-	    !JS_ValueToNumber (cx, rval, &d2))
-	  return JS_FALSE;
-	cond = d == d2;
-      }
+      SWFDEC_WARNING ("FIXME: test equality operations between non-equal types");
+      double l, r;
+      r = swfdec_as_value_to_number (cx, rval);
+      l = swfdec_as_value_to_number (cx, lval);
+      cond = r == l;
     }
   }
-  cx->fp->sp--;
-  cx->fp->sp[-1] = BOOLEAN_TO_JSVAL (cond);
-  return JS_TRUE;
+  swfdec_as_stack_pop (cx->frame->stack);
+  SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx->frame->stack, 1), cond);
 }
-#endif
 
 static void
 swfdec_action_set_target (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
@@ -2192,8 +2193,8 @@ const SwfdecActionSpec swfdec_as_actions
   [SWFDEC_AS_ACTION_ADD2] = { "Add2", NULL, 2, 1, { NULL, NULL, swfdec_action_add2, swfdec_action_add2, swfdec_action_add2 } },
 #if 0
   [0x48] = { "Less2", NULL, 2, 1, { NULL, NULL, swfdec_action_new_comparison_6, swfdec_action_new_comparison_6, swfdec_action_new_comparison_7 } },
-  [0x49] = { "Equals2", NULL, 2, 1, { NULL, NULL, swfdec_action_equals2, swfdec_action_equals2, swfdec_action_equals2 } },
 #endif
+  [SWFDEC_AS_ACTION_EQUALS2] = { "Equals2", NULL, 2, 1, { NULL, NULL, swfdec_action_equals2, swfdec_action_equals2, swfdec_action_equals2 } },
   [SWFDEC_AS_ACTION_TO_NUMBER] = { "ToNumber", NULL, 1, 1, { NULL, NULL, swfdec_action_to_number, swfdec_action_to_number, swfdec_action_to_number } },
   [SWFDEC_AS_ACTION_TO_STRING] = { "ToString", NULL, 1, 1, { NULL, NULL, swfdec_action_to_string, swfdec_action_to_string, swfdec_action_to_string } },
   [SWFDEC_AS_ACTION_PUSH_DUPLICATE] = { "PushDuplicate", NULL, 1, 2, { NULL, NULL, swfdec_action_push_duplicate, swfdec_action_push_duplicate, swfdec_action_push_duplicate } },
diff-tree 5ff1c3070d3f85f152c6a1d4045904c3ced10266 (from 75d5878407131d54858da7a2443c9ff5e793c86c)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 12 10:54:08 2007 +0200

    implement Increment and Decrement

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index b876331..7dcd442 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -882,27 +882,25 @@ swfdec_action_if (SwfdecAsContext *cx, g
     cx->frame->pc += 5 + GINT16_FROM_LE (*((gint16*) data)); 
 }
 
-#if 0
 static void
 swfdec_action_decrement (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
-  double d;
+  SwfdecAsValue *val;
 
-  d = swfdec_value_to_number (cx, cx->fp->sp[-1]);
-  d--;
-  return JS_NewNumberValue (cx, d, &cx->fp->sp[-1]);
+  val = swfdec_as_stack_peek (cx->frame->stack, 1);
+  SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_as_value_to_number (cx, val) + 1);
 }
 
 static void
 swfdec_action_increment (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
-  double d;
+  SwfdecAsValue *val;
 
-  d = swfdec_value_to_number (cx, cx->fp->sp[-1]);
-  d++;
-  return JS_NewNumberValue (cx, d, &cx->fp->sp[-1]);
+  val = swfdec_as_stack_peek (cx->frame->stack, 1);
+  SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_as_value_to_number (cx, val) + 1);
 }
 
+#if 0
 static void
 swfdec_action_get_url (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
@@ -2202,10 +2200,8 @@ const SwfdecActionSpec swfdec_as_actions
   [SWFDEC_AS_ACTION_SWAP] = { "Swap", NULL, 2, 2, { NULL, NULL, swfdec_action_swap, swfdec_action_swap, swfdec_action_swap } },
   [SWFDEC_AS_ACTION_GET_MEMBER] = { "GetMember", NULL, 2, 1, { NULL, swfdec_action_get_member, swfdec_action_get_member, swfdec_action_get_member, swfdec_action_get_member } },
   [SWFDEC_AS_ACTION_SET_MEMBER] = { "SetMember", NULL, 3, 0, { NULL, swfdec_action_set_member, swfdec_action_set_member, swfdec_action_set_member, swfdec_action_set_member } },
-#if 0
-  [0x50] = { "Increment", NULL, 1, 1, { NULL, NULL, swfdec_action_increment, swfdec_action_increment, swfdec_action_increment } },
-  [0x51] = { "Decrement", NULL, 1, 1, { NULL, NULL, swfdec_action_decrement, swfdec_action_decrement, swfdec_action_decrement } },
-#endif
+  [SWFDEC_AS_ACTION_INCREMENT] = { "Increment", NULL, 1, 1, { NULL, NULL, swfdec_action_increment, swfdec_action_increment, swfdec_action_increment } },
+  [SWFDEC_AS_ACTION_DECREMENT] = { "Decrement", NULL, 1, 1, { NULL, NULL, swfdec_action_decrement, swfdec_action_decrement, swfdec_action_decrement } },
   [SWFDEC_AS_ACTION_CALL_METHOD] = { "CallMethod", NULL, -1, 1, { NULL, NULL, swfdec_action_call_method, swfdec_action_call_method, swfdec_action_call_method } },
 #if 0
   [0x53] = { "NewMethod", NULL, -1, 1, { NULL, NULL, swfdec_action_new_method, swfdec_action_new_method, swfdec_action_new_method } },
diff-tree 75d5878407131d54858da7a2443c9ff5e793c86c (from 1f5c7b93200bf3416a9ebad2ef079f46348a76c6)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 12 10:51:22 2007 +0200

    implement SetTarget and SetTarget2

diff --git a/libswfdec/swfdec_as_frame.c b/libswfdec/swfdec_as_frame.c
index da19217..36db616 100644
--- a/libswfdec/swfdec_as_frame.c
+++ b/libswfdec/swfdec_as_frame.c
@@ -57,6 +57,8 @@ swfdec_as_frame_mark (SwfdecAsObject *ob
   swfdec_as_object_mark (SWFDEC_AS_OBJECT (frame->next));
   swfdec_as_object_mark (frame->scope);
   swfdec_as_object_mark (frame->var_object);
+  if (frame->target)
+    swfdec_as_object_mark (frame->target);
   for (i = 0; i < frame->n_registers; i++) {
     swfdec_as_value_mark (&frame->registers[i]);
   }
@@ -143,24 +145,54 @@ swfdec_as_frame_new_native (SwfdecAsObje
 SwfdecAsObject *
 swfdec_as_frame_find_variable (SwfdecAsFrame *frame, const SwfdecAsValue *variable)
 {
-  SwfdecAsObject *ret = NULL;
+  SwfdecAsObject *cur, *ret = NULL;
   guint i;
 
   g_return_val_if_fail (SWFDEC_IS_AS_FRAME (frame), NULL);
   g_return_val_if_fail (SWFDEC_IS_AS_VALUE (variable), NULL);
 
+  cur = SWFDEC_AS_OBJECT (frame);
   for (i = 0; i < 256 && frame != NULL; i++) {
-    ret = swfdec_as_object_find_variable (frame->scope, variable);
-    if (ret)
-      break;
-    if (!SWFDEC_IS_AS_FRAME (frame->scope))
+    if (!SWFDEC_IS_AS_FRAME (cur))
       break;
-    frame = SWFDEC_AS_FRAME (frame->scope);
+    ret = swfdec_as_object_find_variable (cur, variable);
+    if (ret)
+      return ret;
+    cur = SWFDEC_AS_FRAME (cur)->scope;
   }
+  g_assert (cur);
   if (i == 256) {
     swfdec_as_context_abort (SWFDEC_AS_OBJECT (frame)->context, "Scope recursion limit exceeded");
     return NULL;
   }
+  /* we've walked the scope chain down until the last object now.
+   * The last 2 objects in the scope chain are the current target and the global object */
+  if (frame->target) {
+    ret = swfdec_as_object_find_variable (frame->target, variable);
+  } else {
+    ret = swfdec_as_object_find_variable (cur, variable);
+  }
+  if (ret)
+    return ret;
+  ret = swfdec_as_object_find_variable (cur->context->global, variable);
   return ret;
 }
 
+/**
+ * swfdec_as_frame_set_target:
+ * @frame: a #SwfdecAsFrame
+ * @target: the new object to use as target or %NULL to unset
+ *
+ * Sets the new target to be used in this @frame. The target is a legacy 
+ * Actionscript concept that is similar to "with". If you don't have to,
+ * you shouldn't use this function.
+ **/
+void
+swfdec_as_frame_set_target (SwfdecAsFrame *frame, SwfdecAsObject *target)
+{
+  g_return_if_fail (SWFDEC_IS_AS_FRAME (frame));
+  g_return_if_fail (target == NULL || SWFDEC_IS_AS_OBJECT (target));
+
+  frame->target = target;
+}
+
diff --git a/libswfdec/swfdec_as_frame.h b/libswfdec/swfdec_as_frame.h
index c9d8b08..8d806bf 100644
--- a/libswfdec/swfdec_as_frame.h
+++ b/libswfdec/swfdec_as_frame.h
@@ -42,7 +42,8 @@ struct _SwfdecAsFrame {
   char *		function_name;	/* name of function */
   /* normal execution */
   SwfdecScript *	script;		/* script being executed */
-  SwfdecAsObject *	scope;		/* scope object coming after this or NULL */
+  SwfdecAsObject *	scope;		/* scope object coming after this: an Object */
+  SwfdecAsObject *	target;		/* target to use instead of last object in scope chain */
   SwfdecAsObject *	var_object;	/* new variables go here */
   SwfdecAsValue *	registers;	/* the registers */
   guint			n_registers;	/* number of allocated registers */
@@ -66,6 +67,9 @@ SwfdecAsFrame *	swfdec_as_frame_new_nati
 SwfdecAsObject *swfdec_as_frame_find_variable	(SwfdecAsFrame *	frame,
 						 const SwfdecAsValue *	variable);
 
+void		swfdec_as_frame_set_target	(SwfdecAsFrame *	frame,
+						 SwfdecAsObject *	target);
+
 
 G_END_DECLS
 #endif
diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index 3989186..b876331 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -1083,65 +1083,43 @@ swfdec_action_equals2 (SwfdecAsContext *
   cx->fp->sp[-1] = BOOLEAN_TO_JSVAL (cond);
   return JS_TRUE;
 }
-
-static void
-swfdec_action_do_set_target (SwfdecAsContext *cx, JSObject *target)
-{
-  JSObject *with;
-  
-  /* FIXME: this whole function stops working the moment it's used together 
-   * with With */
-  with = js_NewObject(cx, &js_WithClass, target, cx->fp->scopeChain);
-  if (!with)
-    return JS_FALSE;
-  cx->fp->scopeChain = with;
-  return JS_TRUE;
-}
-
-static void
-swfdec_action_do_unset_target (SwfdecAsContext *cx)
-{
-  if (JS_GetClass (cx->fp->scopeChain) != &js_WithClass) {
-    SWFDEC_ERROR ("Cannot unset target: scope chain contains no with object");
-    return JS_TRUE;
-  }
-  cx->fp->scopeChain = JS_GetParent (cx, cx->fp->scopeChain);
-  return JS_TRUE;
-}
+#endif
 
 static void
 swfdec_action_set_target (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
-  jsval target;
-
   if (!memchr (data, 0, len)) {
     SWFDEC_ERROR ("SetTarget action does not specify a string");
-    return JS_FALSE;
+    return;
   }
-  if (*data == '\0')
-    return swfdec_action_do_unset_target (cx);
-  target = swfdec_js_eval (cx, NULL, (const char *) data);
-  if (!JSVAL_IS_OBJECT (target) || JSVAL_IS_NULL (target)) {
-    SWFDEC_WARNING ("target is not an object");
-    return JS_TRUE;
+  if (*data == '\0') {
+    swfdec_as_frame_set_target (cx->frame, NULL);
+  } else {
+    SwfdecAsValue target;
+    swfdec_as_context_eval (cx, NULL, (const char *) data, &target);
+    if (!SWFDEC_AS_VALUE_IS_OBJECT (&target)) {
+      SWFDEC_WARNING ("target is not an object");
+      return;
+    } 
+    /* FIXME: allow non-movieclips as targets? */
+    swfdec_as_frame_set_target (cx->frame, SWFDEC_AS_VALUE_GET_OBJECT (&target));
   }
-  return swfdec_action_do_set_target (cx, JSVAL_TO_OBJECT (target));
 }
 
 static void
 swfdec_action_set_target2 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
-  jsval val;
-  
-  val = cx->fp->sp[-1];
-  cx->fp->sp--;
-  if (!JSVAL_IS_OBJECT (val) || JSVAL_IS_NULL (val)) {
+  SwfdecAsValue *val;
+  val = swfdec_as_stack_peek (cx->frame->stack, 1);
+  if (!SWFDEC_AS_VALUE_IS_OBJECT (val)) {
     SWFDEC_WARNING ("target is not an object");
-    return JS_TRUE;
-  }
-  return swfdec_action_do_set_target (cx, JSVAL_TO_OBJECT (val));
+    return;
+  } 
+  /* FIXME: allow non-movieclips as targets? */
+  swfdec_as_frame_set_target (cx->frame, SWFDEC_AS_VALUE_GET_OBJECT (val));
 }
 
+#if 0
 static void
 swfdec_action_start_drag (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
@@ -1858,17 +1836,19 @@ swfdec_action_print_store_register (guin
   }
   return g_strdup_printf ("StoreRegister %u", (guint) *data);
 }
+#endif
 
 static char *
 swfdec_action_print_set_target (guint action, const guint8 *data, guint len)
 {
   if (!memchr (data, 0, len)) {
     SWFDEC_ERROR ("SetTarget action does not specify a string");
-    return JS_FALSE;
+    return NULL;
   }
   return g_strconcat ("SetTarget ", data, NULL);
 }
 
+#if 0
 static char *
 swfdec_action_print_define_function (guint action, const guint8 *data, guint len)
 {
@@ -2166,8 +2146,8 @@ const SwfdecActionSpec swfdec_as_actions
 #endif
   [SWFDEC_AS_ACTION_GET_VARIABLE] = { "GetVariable", NULL, 1, 1, { NULL, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable } },
   [SWFDEC_AS_ACTION_SET_VARIABLE] = { "SetVariable", NULL, 2, 0, { NULL, swfdec_action_set_variable, swfdec_action_set_variable, swfdec_action_set_variable, swfdec_action_set_variable } },
+  [SWFDEC_AS_ACTION_SET_TARGET2] = { "SetTarget2", NULL, 1, 0, { swfdec_action_set_target2, swfdec_action_set_target2, swfdec_action_set_target2, swfdec_action_set_target2, swfdec_action_set_target2 } },
 #if 0
-  [0x20] = { "SetTarget2", NULL, 1, 0, { swfdec_action_set_target2, swfdec_action_set_target2, swfdec_action_set_target2, swfdec_action_set_target2, swfdec_action_set_target2 } },
   [0x21] = { "StringAdd", NULL, 2, 1, { NULL, swfdec_action_string_add, swfdec_action_string_add, swfdec_action_string_add, swfdec_action_string_add } },
 #endif
   [0x22] = { "GetProperty", NULL, 2, 1, { NULL, swfdec_action_get_property, swfdec_action_get_property, swfdec_action_get_property, swfdec_action_get_property } },
@@ -2257,9 +2237,7 @@ const SwfdecActionSpec swfdec_as_actions
   [SWFDEC_AS_ACTION_CONSTANT_POOL] = { "ConstantPool", swfdec_action_print_constant_pool, 0, 0, { NULL, NULL, swfdec_action_constant_pool, swfdec_action_constant_pool, swfdec_action_constant_pool } },
   /* version 3 */
   [SWFDEC_AS_ACTION_WAIT_FOR_FRAME] = { "WaitForFrame", swfdec_action_print_wait_for_frame, 0, 0, { swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame } },
-#if 0
-  [0x8b] = { "SetTarget", swfdec_action_print_set_target, 0, 0, { swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target } },
-#endif
+  [SWFDEC_AS_ACTION_SET_TARGET] = { "SetTarget", swfdec_action_print_set_target, 0, 0, { swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target } },
   [SWFDEC_AS_ACTION_GOTO_LABEL] = { "GotoLabel", swfdec_action_print_goto_label, 0, 0, { swfdec_action_goto_label, swfdec_action_goto_label, swfdec_action_goto_label, swfdec_action_goto_label, swfdec_action_goto_label } },
 #if 0
   /* version 4 */
diff-tree 1f5c7b93200bf3416a9ebad2ef079f46348a76c6 (from bf5b82f30cd63edfe3e508e785583e6e4356cde9)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 12 10:51:08 2007 +0200

    We have a global object now

diff --git a/libswfdec/swfdec_as_context.c b/libswfdec/swfdec_as_context.c
index 9756fc9..d8a0859 100644
--- a/libswfdec/swfdec_as_context.c
+++ b/libswfdec/swfdec_as_context.c
@@ -225,6 +225,8 @@ swfdec_as_context_mark_roots (gpointer k
 static void
 swfdec_as_context_do_mark (SwfdecAsContext *context)
 {
+  if (context->global)
+    swfdec_as_object_mark (context->global);
   g_hash_table_foreach (context->objects, swfdec_as_context_mark_roots, NULL);
 }
 
@@ -302,6 +304,7 @@ swfdec_as_context_init (SwfdecAsContext 
     g_hash_table_insert (context->strings, (char *) swfdec_as_strings[i] + 1, 
 	(char *) swfdec_as_strings[i]);
   }
+  context->global = swfdec_as_object_new (context);
 }
 
 /*** STRINGS ***/
diff --git a/libswfdec/swfdec_as_context.h b/libswfdec/swfdec_as_context.h
index 72f5ec1..e75f729 100644
--- a/libswfdec/swfdec_as_context.h
+++ b/libswfdec/swfdec_as_context.h
@@ -47,6 +47,7 @@ struct _SwfdecAsContext {
   GObject		object;
 
   SwfdecAsContextState	state;		/* our current state */
+  SwfdecAsObject *	global;		/* the global object */
 
   /* bookkeeping for GC */
   gsize			memory;		/* memory currently in use */


More information about the Swfdec mailing list