Benjamin Otte
2007-Apr-12 05:07 UTC
[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
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@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@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@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@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@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@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@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@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.@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@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@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@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@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@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@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@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 */
Possibly Parallel Threads
- Branch 'as' - 9 commits - libswfdec/swfdec_as_context.c libswfdec/swfdec_as_frame.c libswfdec/swfdec_as_frame.h libswfdec/swfdec_as_function.c libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_stack.c libswfdec/swfdec_as_stack.h
- Branch 'as' - 14 commits - libswfdec-gtk/swfdec_playback_alsa.c 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
- Branch 'as' - 8 commits - libswfdec/Makefile.am libswfdec/swfdec_as_array.c libswfdec/swfdec_as_context.c libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_math.c libswfdec/swfdec_as_math.h libswfdec/swfdec_as_strings.c libswfdec/swfdec_as_types.c
- Branch 'as' - 9 commits - configure.ac libswfdec/swfdec_as_context.c libswfdec/swfdec_as_frame.c libswfdec/swfdec_as_frame.h libswfdec/swfdec_as_function.h libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_object.c libswfdec/swfdec_as_object.h
- Branch 'as' - 25 commits - libswfdec/Makefile.am libswfdec/swfdec_as_boolean.c libswfdec/swfdec_as_boolean.h 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