[Swfdec-commits] 6 commits - swfdec/swfdec_as_context.c swfdec/swfdec_as_frame.c swfdec/swfdec_as_frame_internal.h swfdec/swfdec_as_interpret.c test/trace vivified/code

Pekka Lampila medar at kemper.freedesktop.org
Fri Apr 25 06:38:59 PDT 2008


 swfdec/swfdec_as_context.c                   |    2 
 swfdec/swfdec_as_frame.c                     |   18 +
 swfdec/swfdec_as_frame_internal.h            |    8 
 swfdec/swfdec_as_interpret.c                 |   66 +----
 test/trace/Makefile.am                       |   27 ++
 test/trace/definelocal-overwrite-5.swf       |binary
 test/trace/definelocal-overwrite-5.swf.trace |    3 
 test/trace/definelocal-overwrite-6.swf       |binary
 test/trace/definelocal-overwrite-6.swf.trace |    3 
 test/trace/definelocal-overwrite-7.swf       |binary
 test/trace/definelocal-overwrite-7.swf.trace |    3 
 test/trace/definelocal-overwrite-8.swf       |binary
 test/trace/definelocal-overwrite-8.swf.trace |    3 
 test/trace/definelocal-overwrite.as          |   10 
 test/trace/definelocal-scope-5.swf           |binary
 test/trace/definelocal-scope-5.swf.trace     |    8 
 test/trace/definelocal-scope-6.swf           |binary
 test/trace/definelocal-scope-6.swf.trace     |    8 
 test/trace/definelocal-scope-7.swf           |binary
 test/trace/definelocal-scope-7.swf.trace     |    8 
 test/trace/definelocal-scope-8.swf           |binary
 test/trace/definelocal-scope-8.swf.trace     |    8 
 test/trace/definelocal-scope.as              |   37 ++
 test/trace/too-many-blocks-5.swf             |binary
 test/trace/too-many-blocks-5.swf.trace       |    4 
 test/trace/too-many-blocks-6.swf             |binary
 test/trace/too-many-blocks-6.swf.trace       |    4 
 test/trace/too-many-blocks-7.swf             |binary
 test/trace/too-many-blocks-7.swf.trace       |    4 
 test/trace/too-many-blocks-8.swf             |binary
 test/trace/too-many-blocks-8.swf.trace       |    4 
 test/trace/too-many-blocks.as                |   25 +
 vivified/code/Makefile.am                    |    2 
 vivified/code/vivi_code_asm_try.c            |  341 +++++++++++++++++++++++++++
 vivified/code/vivi_code_asm_try.h            |   84 ++++++
 vivified/code/vivi_disassembler.c            |   56 ++++
 36 files changed, 684 insertions(+), 52 deletions(-)

New commits:
commit f6de7efe91acf624df8a7c5de1386dc713058ccc
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Apr 25 16:37:28 2008 +0300

    Implement ViviCodeAsmTry and deassembler for it

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index 2c22c85..8a642cd 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -28,6 +28,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_asm_pool.c \
 	vivi_code_asm_push.c \
 	vivi_code_asm_store.c \
+	vivi_code_asm_try.c \
 	vivi_code_asm_with.c \
 	vivi_code_assembler.c \
 	vivi_code_assignment.c \
@@ -100,6 +101,7 @@ noinst_HEADERS = \
 	vivi_code_asm_pool.h \
 	vivi_code_asm_push.h \
 	vivi_code_asm_store.h \
+	vivi_code_asm_try.h \
 	vivi_code_asm_with.h \
 	vivi_code_assembler.h \
 	vivi_code_assignment.h \
diff --git a/vivified/code/vivi_code_asm_try.c b/vivified/code/vivi_code_asm_try.c
new file mode 100644
index 0000000..3782582
--- /dev/null
+++ b/vivified/code/vivi_code_asm_try.c
@@ -0,0 +1,341 @@
+/* Vivified
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <swfdec/swfdec_as_interpret.h>
+#include <swfdec/swfdec_bits.h>
+
+#include "vivi_code_asm_try.h"
+#include "vivi_code_asm.h"
+#include "vivi_code_emitter.h"
+#include "vivi_code_error.h"
+#include "vivi_code_printer.h"
+
+static gboolean
+vivi_code_asm_try_resolve (ViviCodeEmitter *emitter, SwfdecBuffer *buffer,
+    gsize offset, gpointer data, GError **error)
+{
+  ViviCodeAsmTry *try_ = VIVI_CODE_ASM_TRY (data);
+  gssize catch_start_offset, finally_start_offset, end_offset;
+  gsize write_offset, diff;
+
+  write_offset = offset;
+
+  if (try_->use_register) {
+    offset += 1;
+  } else {
+    offset += strlen (try_->variable_name) + 1;
+  }
+
+  catch_start_offset =
+    vivi_code_emitter_get_label_offset (emitter, try_->catch_start);
+  if (catch_start_offset < 0) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_MISSING_LABEL,
+	"no label \"%s\"", vivi_code_label_get_name (try_->catch_start));
+    return FALSE;
+  }
+
+  finally_start_offset =
+    vivi_code_emitter_get_label_offset (emitter, try_->finally_start);
+  if (finally_start_offset < 0) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_MISSING_LABEL,
+	"no label \"%s\"", vivi_code_label_get_name (try_->finally_start));
+    return FALSE;
+  }
+
+  end_offset = vivi_code_emitter_get_label_offset (emitter, try_->end);
+  if (end_offset < 0) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_MISSING_LABEL,
+	"no label \"%s\"", vivi_code_label_get_name (try_->end));
+    return FALSE;
+  }
+
+  if ((gsize)catch_start_offset < offset) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_SIZE,
+	"catch start before try");
+    return FALSE;
+  }
+
+  if (finally_start_offset < catch_start_offset) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_SIZE,
+	"finally start before catch start");
+    return FALSE;
+  }
+
+  if (end_offset < finally_start_offset) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_SIZE,
+	"end before finally start");
+    return FALSE;
+  }
+
+  // try size
+  diff = catch_start_offset - offset;
+  if (diff > G_MAXUINT16) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_SIZE,
+	"catch start too far away");
+    return FALSE;
+  }
+
+  buffer->data[write_offset - 5] = diff >> 8;
+  buffer->data[write_offset - 6] = diff;
+
+  // catch size
+  diff = finally_start_offset - catch_start_offset;
+  if (diff > G_MAXUINT16) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_SIZE,
+	"finally start too far away");
+    return FALSE;
+  }
+
+  buffer->data[write_offset - 3] = diff >> 8;
+  buffer->data[write_offset - 4] = diff;
+
+  // finally size
+  diff = end_offset - finally_start_offset;
+  if (diff > G_MAXUINT16) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_SIZE,
+	"end too far away");
+    return FALSE;
+  }
+
+  buffer->data[write_offset - 1] = diff >> 8;
+  buffer->data[write_offset - 2] = diff;
+
+  return TRUE;
+}
+
+static gboolean
+vivi_code_asm_try_emit (ViviCodeAsm *code, ViviCodeEmitter *emitter,
+    GError **error)
+{
+  ViviCodeAsmTry *try_ = VIVI_CODE_ASM_TRY (code);
+  SwfdecBots *emit = vivi_code_emitter_get_bots (emitter);
+  guint flags;
+
+  swfdec_bots_put_u8 (emit, SWFDEC_AS_ACTION_TRY);
+  swfdec_bots_put_u16 (emit,
+      8 + (try_->use_register ? 0 : strlen (try_->variable_name)));
+
+  flags = try_->reserved_flags << 3;
+  if (try_->has_catch) {
+    flags |= (1 << 0);
+  } else {
+    flags &= ~(1 << 0);
+  }
+  if (try_->has_finally) {
+    flags |= (1 << 1);
+  } else {
+    flags &= ~(1 << 1);
+  }
+  if (try_->use_register) {
+    flags |= (1 << 2);
+  } else {
+    flags &= ~(1 << 2);
+  }
+  swfdec_bots_put_u8 (emit, flags);
+
+  swfdec_bots_put_u16 (emit, 0); /* try size */
+  swfdec_bots_put_u16 (emit, 0); /* catch size */
+  swfdec_bots_put_u16 (emit, 0); /* finally size */
+  vivi_code_emitter_add_later (emitter, vivi_code_asm_try_resolve, code);
+
+  if (try_->use_register) {
+    swfdec_bots_put_u8 (emit, try_->register_number);
+  } else {
+    swfdec_bots_put_string (emit, try_->variable_name);
+  }
+
+  return TRUE;
+}
+
+static void
+vivi_code_asm_try_asm_init (ViviCodeAsmInterface *iface)
+{
+  iface->emit = vivi_code_asm_try_emit;
+}
+
+G_DEFINE_TYPE_WITH_CODE (ViviCodeAsmTry, vivi_code_asm_try, VIVI_TYPE_CODE_ASM_CODE,
+    G_IMPLEMENT_INTERFACE (VIVI_TYPE_CODE_ASM, vivi_code_asm_try_asm_init))
+
+static void
+vivi_code_asm_try_print (ViviCodeToken *token, ViviCodePrinter *printer)
+{
+  ViviCodeAsmTry *try_ = VIVI_CODE_ASM_TRY (token);
+  guint i;
+
+  vivi_code_printer_print (printer, "try ");
+
+  if (try_->has_catch)
+    vivi_code_printer_print (printer, "has_catch ");
+
+  if (try_->has_finally)
+    vivi_code_printer_print (printer, "has_finally ");
+
+  if (try_->use_register)
+    vivi_code_printer_print (printer, "use_register ");
+
+  for (i = 0; i < 5; i++) {
+    if (try_->reserved_flags & (1 << i)) {
+      char *str = g_strdup_printf ("reserverd%i ", i + 1);
+      vivi_code_printer_print (printer, str);
+      g_free (str);
+    }
+  }
+
+  if (try_->use_register) {
+    char *str = g_strdup_printf ("%i", try_->register_number);
+    vivi_code_printer_print (printer, str);
+    g_free (str);
+  } else {
+    vivi_code_printer_print (printer, try_->variable_name);
+  }
+  vivi_code_printer_print (printer, " ");
+
+  vivi_code_printer_print (printer,
+      vivi_code_label_get_name (try_->catch_start));
+  vivi_code_printer_print (printer, " ");
+
+  vivi_code_printer_print (printer,
+      vivi_code_label_get_name (try_->finally_start));
+  vivi_code_printer_print (printer, " ");
+
+  vivi_code_printer_print (printer, vivi_code_label_get_name (try_->end));
+
+  vivi_code_printer_new_line (printer, FALSE);
+}
+
+static void
+vivi_code_asm_try_dispose (GObject *object)
+{
+  ViviCodeAsmTry *try_ = VIVI_CODE_ASM_TRY (object);
+
+  if (!try_->use_register)
+    g_free (try_->variable_name);
+
+  g_object_unref (try_->catch_start);
+  g_object_unref (try_->finally_start);
+  g_object_unref (try_->end);
+
+  G_OBJECT_CLASS (vivi_code_asm_try_parent_class)->dispose (object);
+}
+
+static void
+vivi_code_asm_try_class_init (ViviCodeAsmTryClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeAsmCodeClass *code_class = VIVI_CODE_ASM_CODE_CLASS (klass);
+
+  object_class->dispose = vivi_code_asm_try_dispose;
+
+  token_class->print = vivi_code_asm_try_print;
+
+  code_class->bytecode = SWFDEC_AS_ACTION_TRY;
+}
+
+static void
+vivi_code_asm_try_init (ViviCodeAsmTry *try_)
+{
+}
+
+static ViviCodeAsmTry *
+vivi_code_asm_try_new_internal (gboolean has_catch, gboolean has_finally,
+    ViviCodeLabel *catch_start, ViviCodeLabel *finally_start,
+    ViviCodeLabel *end)
+{
+  ViviCodeAsmTry *ret;
+
+  g_return_val_if_fail (VIVI_IS_CODE_LABEL (catch_start), NULL);
+  g_return_val_if_fail (VIVI_IS_CODE_LABEL (finally_start), NULL);
+  g_return_val_if_fail (VIVI_IS_CODE_LABEL (end), NULL);
+
+  ret = g_object_new (VIVI_TYPE_CODE_ASM_TRY, NULL);
+  ret->catch_start = g_object_ref (catch_start);
+  ret->finally_start = g_object_ref (finally_start);
+  ret->end = g_object_ref (end);
+
+  ret->has_catch = has_catch;
+  ret->has_finally = has_finally;
+  ret->reserved_flags = 0;
+
+  return ret;
+}
+
+ViviCodeAsm *
+vivi_code_asm_try_new_variable (const char *name, gboolean has_catch,
+   gboolean has_finally, ViviCodeLabel *catch_start,
+   ViviCodeLabel *finally_start, ViviCodeLabel *end)
+{
+  ViviCodeAsmTry *try_;
+
+  g_return_val_if_fail (name != NULL, NULL);
+
+  try_ = vivi_code_asm_try_new_internal (has_catch, has_finally, catch_start,
+      finally_start, end);
+  try_->use_register = FALSE;
+  try_->variable_name = g_strdup (name);
+
+  return VIVI_CODE_ASM (try_);
+}
+
+ViviCodeAsm *
+vivi_code_asm_try_new_register (guint register_number, gboolean has_catch,
+    gboolean has_finally, ViviCodeLabel *catch_start,
+    ViviCodeLabel *finally_start, ViviCodeLabel *end)
+{
+  ViviCodeAsmTry *try_;
+
+  g_return_val_if_fail (register_number < 256, NULL);
+
+  try_ = vivi_code_asm_try_new_internal (has_catch, has_finally, catch_start,
+      finally_start, end);
+  try_->use_register = TRUE;
+  try_->register_number = register_number;
+
+  return VIVI_CODE_ASM (try_);
+}
+
+void
+vivi_code_asm_try_set_reserved_flags (ViviCodeAsmTry *try_, guint flags)
+{
+  g_return_if_fail (VIVI_IS_CODE_ASM_TRY (try_));
+  g_return_if_fail (flags < (1 << 5));
+
+  try_->reserved_flags = flags;
+}
+
+void
+vivi_code_asm_try_set_variable_name (ViviCodeAsmTry *try_, const char *name)
+{
+  g_return_if_fail (VIVI_IS_CODE_ASM_TRY (try_));
+  g_return_if_fail (name != NULL);
+
+  if (!try_->use_register) {
+    g_free (try_->variable_name);
+  } else {
+    try_->use_register = FALSE;
+  }
+
+  try_->variable_name = g_strdup (name);
+}
diff --git a/vivified/code/vivi_code_asm_try.h b/vivified/code/vivi_code_asm_try.h
new file mode 100644
index 0000000..c40afcf
--- /dev/null
+++ b/vivified/code/vivi_code_asm_try.h
@@ -0,0 +1,84 @@
+/* Vivified
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _VIVI_CODE_ASM_TRY_H_
+#define _VIVI_CODE_ASM_TRY_H_
+
+#include <vivified/code/vivi_code_asm.h>
+#include <vivified/code/vivi_code_asm_code.h>
+#include <vivified/code/vivi_code_label.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ViviCodeAsmTry ViviCodeAsmTry;
+typedef struct _ViviCodeAsmTryClass ViviCodeAsmTryClass;
+
+#define VIVI_TYPE_CODE_ASM_TRY                    (vivi_code_asm_try_get_type())
+#define VIVI_IS_CODE_ASM_TRY(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_ASM_TRY))
+#define VIVI_IS_CODE_ASM_TRY_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_ASM_TRY))
+#define VIVI_CODE_ASM_TRY(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_ASM_TRY, ViviCodeAsmTry))
+#define VIVI_CODE_ASM_TRY_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_ASM_TRY, ViviCodeAsmTryClass))
+#define VIVI_CODE_ASM_TRY_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_ASM_TRTRY ViviCodeAsmTryClass))
+
+struct _ViviCodeAsmTry
+{
+  ViviCodeAsmCode	code;
+
+  gboolean		has_catch;
+  gboolean		has_finally;
+  gboolean		use_register;
+  guint			reserved_flags;
+  union {
+    guint		register_number;
+    char *		variable_name;
+  };
+  ViviCodeLabel *	catch_start;
+  ViviCodeLabel *	finally_start;
+  ViviCodeLabel *	end;
+};
+
+struct _ViviCodeAsmTryClass
+{
+  ViviCodeAsmCodeClass	code_class;
+};
+
+GType			vivi_code_asm_try_get_type	  	(void);
+
+ViviCodeAsm *		vivi_code_asm_try_new_variable		(const char *		name,
+								 gboolean		has_catch,
+								 gboolean		has_finally,
+								 ViviCodeLabel *	catch_start,
+								 ViviCodeLabel *	finally_start,
+								 ViviCodeLabel *	end);
+ViviCodeAsm *		vivi_code_asm_try_new_register		(guint			register_number,
+								 gboolean		has_catch,
+								 gboolean		has_finally,
+								 ViviCodeLabel *	catch_start,
+								 ViviCodeLabel *	finally_start,
+								 ViviCodeLabel *	end);
+
+void			vivi_code_asm_try_set_reserved_flags	(ViviCodeAsmTry *	try_,
+								 guint			flags);
+
+void			vivi_code_asm_try_set_variable_name	(ViviCodeAsmTry *	try_,
+								 const char *		name);
+
+
+G_END_DECLS
+#endif
diff --git a/vivified/code/vivi_disassembler.c b/vivified/code/vivi_disassembler.c
index 2163d6d..69be97c 100644
--- a/vivified/code/vivi_disassembler.c
+++ b/vivified/code/vivi_disassembler.c
@@ -35,6 +35,7 @@
 #include "vivi_code_asm_pool.h"
 #include "vivi_code_asm_push.h"
 #include "vivi_code_asm_store.h"
+#include "vivi_code_asm_try.h"
 #include "vivi_code_asm_with.h"
 #include "vivi_code_assembler.h"
 #include "vivi_code_comment.h"
@@ -379,6 +380,60 @@ vivi_disassemble_script (SwfdecScript *script)
 	    g_object_unref (fun);
 	  }
 	  break;
+        case SWFDEC_AS_ACTION_TRY:
+	  {
+	    gboolean has_catch, has_finally, use_register;
+	    guint flags, try_size, catch_size, finally_size, register_number;
+	    char *name;
+	    ViviCodeLabel *catch_start, *finally_start, *end_label;
+	    ViviCodeAsm *try;
+
+	    flags = swfdec_bits_get_u8 (&bits);
+
+	    has_catch = flags & (1 << 0);
+	    has_finally = flags & (1 << 1);
+	    use_register = flags & (1 << 2);
+
+	    try_size = swfdec_bits_get_u16 (&bits);
+	    catch_size = swfdec_bits_get_u16 (&bits);
+	    finally_size = swfdec_bits_get_u16 (&bits);
+	    if (use_register) {
+	      register_number = swfdec_bits_get_u8 (&bits);
+	      name = NULL; // shut up compiler warnings
+	    } else {
+	      register_number = 0;
+	      name = swfdec_bits_get_string (&bits, script->version);
+	    }
+
+	    end_label = vivi_disassemble_labels_get_label (labels,
+		pc + try_size + catch_size + finally_size);
+	    if (finally_size > 0) {
+	      finally_start = vivi_disassemble_labels_get_label (labels,
+		  pc + try_size + catch_size);
+	    } else {
+	      finally_start = end_label;
+	    }
+	    if (catch_size > 0) {
+	      catch_start = vivi_disassemble_labels_get_label (labels,
+		  pc + try_size);
+	    } else {
+	      catch_start = finally_start;
+	    }
+
+	    if (use_register) {
+	      try = vivi_code_asm_try_new_register (register_number,
+		  has_catch, has_finally, catch_start, finally_start,
+		  end_label);
+	    } else {
+	      try = vivi_code_asm_try_new_variable (name, has_catch,
+		  has_finally, catch_start, finally_start, end_label);
+	      g_free (name);
+	    }
+	    vivi_code_asm_try_set_reserved_flags (VIVI_CODE_ASM_TRY (try),
+		flags >> 3);
+	    vivi_code_assembler_add_code (assembler, try);
+	  }
+	  break;
         case SWFDEC_AS_ACTION_GET_URL:
 	  vivi_disassemble_get_url (assembler, &bits, script->version);
 	  break;
@@ -388,7 +443,6 @@ vivi_disassemble_script (SwfdecScript *script)
         case SWFDEC_AS_ACTION_SET_TARGET:
         case SWFDEC_AS_ACTION_GOTO_LABEL:
         case SWFDEC_AS_ACTION_WAIT_FOR_FRAME2:
-        case SWFDEC_AS_ACTION_TRY:
         case SWFDEC_AS_ACTION_GET_URL2:
         case SWFDEC_AS_ACTION_CALL:
         case SWFDEC_AS_ACTION_GOTO_FRAME2:
commit 59908d27b24aae9c4cd3ac1dca1bc88444671297
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Apr 25 16:03:32 2008 +0300

    Add a test for DefineLocal with variables of the same name in the scope chain

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 6eaf546..395c1db 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -867,6 +867,15 @@ EXTRA_DIST = \
 	definelocal-overwrite-7.swf.trace \
 	definelocal-overwrite-8.swf \
 	definelocal-overwrite-8.swf.trace \
+	definelocal-scope.as \
+	definelocal-scope-5.swf \
+	definelocal-scope-5.swf.trace \
+	definelocal-scope-6.swf \
+	definelocal-scope-6.swf.trace \
+	definelocal-scope-7.swf \
+	definelocal-scope-7.swf.trace \
+	definelocal-scope-8.swf \
+	definelocal-scope-8.swf.trace \
 	definelocal-target.as \
 	definelocal-target-5.swf \
 	definelocal-target-5.swf.trace \
diff --git a/test/trace/definelocal-scope-5.swf b/test/trace/definelocal-scope-5.swf
new file mode 100644
index 0000000..51e3a97
Binary files /dev/null and b/test/trace/definelocal-scope-5.swf differ
diff --git a/test/trace/definelocal-scope-5.swf.trace b/test/trace/definelocal-scope-5.swf.trace
new file mode 100644
index 0000000..250b2b3
--- /dev/null
+++ b/test/trace/definelocal-scope-5.swf.trace
@@ -0,0 +1,8 @@
+0
+0
+0
+4
+0
+0
+0
+0
diff --git a/test/trace/definelocal-scope-6.swf b/test/trace/definelocal-scope-6.swf
new file mode 100644
index 0000000..d26f1f5
Binary files /dev/null and b/test/trace/definelocal-scope-6.swf differ
diff --git a/test/trace/definelocal-scope-6.swf.trace b/test/trace/definelocal-scope-6.swf.trace
new file mode 100644
index 0000000..250b2b3
--- /dev/null
+++ b/test/trace/definelocal-scope-6.swf.trace
@@ -0,0 +1,8 @@
+0
+0
+0
+4
+0
+0
+0
+0
diff --git a/test/trace/definelocal-scope-7.swf b/test/trace/definelocal-scope-7.swf
new file mode 100644
index 0000000..41bf4fa
Binary files /dev/null and b/test/trace/definelocal-scope-7.swf differ
diff --git a/test/trace/definelocal-scope-7.swf.trace b/test/trace/definelocal-scope-7.swf.trace
new file mode 100644
index 0000000..250b2b3
--- /dev/null
+++ b/test/trace/definelocal-scope-7.swf.trace
@@ -0,0 +1,8 @@
+0
+0
+0
+4
+0
+0
+0
+0
diff --git a/test/trace/definelocal-scope-8.swf b/test/trace/definelocal-scope-8.swf
new file mode 100644
index 0000000..94c72e6
Binary files /dev/null and b/test/trace/definelocal-scope-8.swf differ
diff --git a/test/trace/definelocal-scope-8.swf.trace b/test/trace/definelocal-scope-8.swf.trace
new file mode 100644
index 0000000..250b2b3
--- /dev/null
+++ b/test/trace/definelocal-scope-8.swf.trace
@@ -0,0 +1,8 @@
+0
+0
+0
+4
+0
+0
+0
+0
diff --git a/test/trace/definelocal-scope.as b/test/trace/definelocal-scope.as
new file mode 100644
index 0000000..eb3339f
--- /dev/null
+++ b/test/trace/definelocal-scope.as
@@ -0,0 +1,37 @@
+// makeswf -v 7 -s 200x150 -r 15 -o test-8.swf test-8.as
+
+var x1 = 0;
+var x2 = 0;
+var x3 = 0;
+var x4 = 0;
+var y1 = 0;
+var y2 = 0;
+var y3 = 0;
+var y4 = 0;
+var a = { x1: 1, x2: 1, x3: 1, y1: 1, y2: 1, y3: 1 };
+with (a) {
+  var b = { x1: 2, x2: 2, y1: 2, y2: 2 };
+  with (b) {
+    var c = { x1: 3, y1: 3 };
+    with (c) {
+      var x1 = 4;
+      var x2 = 4;
+      var x3 = 4;
+      var x4 = 4;
+      var y1;
+      var y2;
+      var y3;
+      var y4;
+    }
+  }
+}
+trace (x1);
+trace (x2);
+trace (x3);
+trace (x4);
+trace (y1);
+trace (y2);
+trace (y3);
+trace (y4);
+
+getURL ("FSCommand:quit", "");
commit 577df517e0452b8ce81a15af27bd8522f9054542
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Apr 25 15:59:28 2008 +0300

    Fixes to DefineLocal and DefineLocal2
    
    Make them check scope for existing variable with same name
    Make DefineLocal2 not overwrite existing values

diff --git a/swfdec/swfdec_as_context.c b/swfdec/swfdec_as_context.c
index 6c679de..397ebb7 100644
--- a/swfdec/swfdec_as_context.c
+++ b/swfdec/swfdec_as_context.c
@@ -1097,7 +1097,7 @@ swfdec_as_context_eval_set_property (SwfdecAsContext *cx,
       SWFDEC_ERROR ("no frame in eval_set?");
       return;
     }
-    swfdec_as_frame_set_variable (cx->frame, name, ret);
+    swfdec_as_frame_set_variable (cx->frame, name, ret, TRUE, FALSE);
   } else {
     swfdec_as_object_set_variable (obj, name, ret);
   }
diff --git a/swfdec/swfdec_as_frame.c b/swfdec/swfdec_as_frame.c
index d4bf392..52e311c 100644
--- a/swfdec/swfdec_as_frame.c
+++ b/swfdec/swfdec_as_frame.c
@@ -581,7 +581,7 @@ swfdec_as_frame_get_variable_and_flags (SwfdecAsFrame *frame, const char *variab
 
 void
 swfdec_as_frame_set_variable_and_flags (SwfdecAsFrame *frame, const char *variable,
-    const SwfdecAsValue *value, guint default_flags)
+    const SwfdecAsValue *value, guint default_flags, gboolean overwrite, gboolean local)
 {
   SwfdecAsObject *pobject, *set;
   GSList *walk;
@@ -593,12 +593,24 @@ swfdec_as_frame_set_variable_and_flags (SwfdecAsFrame *frame, const char *variab
   for (walk = frame->scope_chain; walk; walk = walk->next) {
     if (swfdec_as_object_get_variable_and_flags (walk->data, variable, NULL, NULL, &pobject) &&
 	pobject == walk->data) {
+      if (!overwrite)
+	return;
       set = walk->data;
       break;
     }
   }
-  if (set == NULL)
-    set = frame->target;
+  if (set == NULL) {
+    if (local && frame->is_local) {
+      set = SWFDEC_AS_OBJECT (frame);
+    } else {
+      set = frame->target;
+    }
+  }
+
+  if (!overwrite) {
+    if (swfdec_as_object_get_variable (set, variable, NULL))
+      return;
+  }
 
   swfdec_as_object_set_variable_and_flags (set, variable, value, default_flags);
 }
diff --git a/swfdec/swfdec_as_frame_internal.h b/swfdec/swfdec_as_frame_internal.h
index 0dc9a5e..712c3e6 100644
--- a/swfdec/swfdec_as_frame_internal.h
+++ b/swfdec/swfdec_as_frame_internal.h
@@ -79,13 +79,15 @@ SwfdecAsObject *swfdec_as_frame_get_variable_and_flags
 						 SwfdecAsValue *	value,
 						 guint *		flags,
 						 SwfdecAsObject **	pobject);
-#define swfdec_as_frame_set_variable(frame, variable, value) \
-  swfdec_as_frame_set_variable_and_flags (frame, variable, value, 0)
+#define swfdec_as_frame_set_variable(frame, variable, value, overwrite, local) \
+  swfdec_as_frame_set_variable_and_flags (frame, variable, value, 0, overwrite, local)
 void		swfdec_as_frame_set_variable_and_flags
 						(SwfdecAsFrame *	frame,
 						 const char *		variable,
 						 const SwfdecAsValue *	value,
-						 guint			default_flags);
+						 guint			default_flags,
+						 gboolean		overwrite,
+						 gboolean		local);
 SwfdecAsDeleteReturn
 		swfdec_as_frame_delete_variable	(SwfdecAsFrame *	frame,
 						 const char *		variable);
diff --git a/swfdec/swfdec_as_interpret.c b/swfdec/swfdec_as_interpret.c
index aa43941..de86447 100644
--- a/swfdec/swfdec_as_interpret.c
+++ b/swfdec/swfdec_as_interpret.c
@@ -656,7 +656,8 @@ swfdec_action_set_variable (SwfdecAsContext *cx, guint action, const guint8 *dat
 	rest = s;
       else
 	rest = swfdec_as_context_get_string (cx, rest);
-      swfdec_as_frame_set_variable (cx->frame, rest, swfdec_as_stack_peek (cx, 1));
+      swfdec_as_frame_set_variable (cx->frame, rest,
+	  swfdec_as_stack_peek (cx, 1), TRUE, FALSE);
     }
   }
   swfdec_as_stack_pop_n (cx, 2);
@@ -1993,17 +1994,11 @@ swfdec_action_target_path (SwfdecAsContext *cx, guint action, const guint8 *data
 static void
 swfdec_action_define_local (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
-  SwfdecAsObject *target;
   const char *name;
 
   name = swfdec_as_value_to_string (cx, swfdec_as_stack_peek (cx, 2));
-  if (cx->frame->is_local) {
-    target = SWFDEC_AS_OBJECT (cx->frame);
-  } else {
-    target = cx->frame->target;
-  }
-  swfdec_as_object_set_variable (target, name,
-      swfdec_as_stack_peek (cx, 1));
+  swfdec_as_frame_set_variable (cx->frame, name, swfdec_as_stack_peek (cx, 1),
+      TRUE, TRUE);
   swfdec_as_stack_pop_n (cx, 2);
 }
 
@@ -2011,16 +2006,10 @@ static void
 swfdec_action_define_local2 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
   SwfdecAsValue val = { 0, };
-  SwfdecAsObject *target;
   const char *name;
 
   name = swfdec_as_value_to_string (cx, swfdec_as_stack_peek (cx, 1));
-  if (cx->frame->is_local) {
-    target = SWFDEC_AS_OBJECT (cx->frame);
-  } else {
-    target = cx->frame->target;
-  }
-  swfdec_as_object_set_variable (target, name, &val);
+  swfdec_as_frame_set_variable (cx->frame, name, &val, FALSE, TRUE);
   swfdec_as_stack_pop (cx);
 }
 
commit 5094e894f4c45421d3d8036e9d970c3804debb52
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Apr 25 15:58:41 2008 +0300

    Add a test for whether DefineLocal and DefineLocal2 overwrite existing values

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 1e61aa6..6eaf546 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -858,6 +858,15 @@ EXTRA_DIST = \
 	definelocal-function-target-7.swf.trace \
 	definelocal-function-target-8.swf \
 	definelocal-function-target-8.swf.trace \
+	definelocal-overwrite.as \
+	definelocal-overwrite-5.swf \
+	definelocal-overwrite-5.swf.trace \
+	definelocal-overwrite-6.swf \
+	definelocal-overwrite-6.swf.trace \
+	definelocal-overwrite-7.swf \
+	definelocal-overwrite-7.swf.trace \
+	definelocal-overwrite-8.swf \
+	definelocal-overwrite-8.swf.trace \
 	definelocal-target.as \
 	definelocal-target-5.swf \
 	definelocal-target-5.swf.trace \
diff --git a/test/trace/definelocal-overwrite-5.swf b/test/trace/definelocal-overwrite-5.swf
new file mode 100644
index 0000000..c3b3d85
Binary files /dev/null and b/test/trace/definelocal-overwrite-5.swf differ
diff --git a/test/trace/definelocal-overwrite-5.swf.trace b/test/trace/definelocal-overwrite-5.swf.trace
new file mode 100644
index 0000000..bb5ee5c
--- /dev/null
+++ b/test/trace/definelocal-overwrite-5.swf.trace
@@ -0,0 +1,3 @@
+0
+0
+1
diff --git a/test/trace/definelocal-overwrite-6.swf b/test/trace/definelocal-overwrite-6.swf
new file mode 100644
index 0000000..806c72e
Binary files /dev/null and b/test/trace/definelocal-overwrite-6.swf differ
diff --git a/test/trace/definelocal-overwrite-6.swf.trace b/test/trace/definelocal-overwrite-6.swf.trace
new file mode 100644
index 0000000..bb5ee5c
--- /dev/null
+++ b/test/trace/definelocal-overwrite-6.swf.trace
@@ -0,0 +1,3 @@
+0
+0
+1
diff --git a/test/trace/definelocal-overwrite-7.swf b/test/trace/definelocal-overwrite-7.swf
new file mode 100644
index 0000000..10f6eec
Binary files /dev/null and b/test/trace/definelocal-overwrite-7.swf differ
diff --git a/test/trace/definelocal-overwrite-7.swf.trace b/test/trace/definelocal-overwrite-7.swf.trace
new file mode 100644
index 0000000..bb5ee5c
--- /dev/null
+++ b/test/trace/definelocal-overwrite-7.swf.trace
@@ -0,0 +1,3 @@
+0
+0
+1
diff --git a/test/trace/definelocal-overwrite-8.swf b/test/trace/definelocal-overwrite-8.swf
new file mode 100644
index 0000000..826559c
Binary files /dev/null and b/test/trace/definelocal-overwrite-8.swf differ
diff --git a/test/trace/definelocal-overwrite-8.swf.trace b/test/trace/definelocal-overwrite-8.swf.trace
new file mode 100644
index 0000000..bb5ee5c
--- /dev/null
+++ b/test/trace/definelocal-overwrite-8.swf.trace
@@ -0,0 +1,3 @@
+0
+0
+1
diff --git a/test/trace/definelocal-overwrite.as b/test/trace/definelocal-overwrite.as
new file mode 100644
index 0000000..54eec3b
--- /dev/null
+++ b/test/trace/definelocal-overwrite.as
@@ -0,0 +1,10 @@
+// makeswf -v 7 -s 200x150 -r 15 -o test-8.swf test-8.as
+
+var x = 0;
+trace (x);
+var x;
+trace (x);
+var x = 1;
+trace (x);
+
+getURL ("FSCommand:quit", "");
commit 363b1a376bedc8cf68702fd40137f611aa067441
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Apr 25 14:46:44 2008 +0300

    Add a test for the recent block popping fix

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 78409c6..1e61aa6 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -3349,6 +3349,15 @@ EXTRA_DIST = \
 	tointeger-various-6.swf.trace \
 	tointeger-various-7.swf \
 	tointeger-various-7.swf.trace \
+	too-many-blocks.as \
+	too-many-blocks-5.swf \
+	too-many-blocks-5.swf.trace \
+	too-many-blocks-6.swf \
+	too-many-blocks-6.swf.trace \
+	too-many-blocks-7.swf \
+	too-many-blocks-7.swf.trace \
+	too-many-blocks-8.swf \
+	too-many-blocks-8.swf.trace \
 	totalframes.xml \
 	totalframes.swf \
 	totalframes.swf.trace \
diff --git a/test/trace/too-many-blocks-5.swf b/test/trace/too-many-blocks-5.swf
new file mode 100644
index 0000000..23c9ce5
Binary files /dev/null and b/test/trace/too-many-blocks-5.swf differ
diff --git a/test/trace/too-many-blocks-5.swf.trace b/test/trace/too-many-blocks-5.swf.trace
new file mode 100644
index 0000000..f58d53d
--- /dev/null
+++ b/test/trace/too-many-blocks-5.swf.trace
@@ -0,0 +1,4 @@
+0
+0
+0
+4
diff --git a/test/trace/too-many-blocks-6.swf b/test/trace/too-many-blocks-6.swf
new file mode 100644
index 0000000..a66af1a
Binary files /dev/null and b/test/trace/too-many-blocks-6.swf differ
diff --git a/test/trace/too-many-blocks-6.swf.trace b/test/trace/too-many-blocks-6.swf.trace
new file mode 100644
index 0000000..f58d53d
--- /dev/null
+++ b/test/trace/too-many-blocks-6.swf.trace
@@ -0,0 +1,4 @@
+0
+0
+0
+4
diff --git a/test/trace/too-many-blocks-7.swf b/test/trace/too-many-blocks-7.swf
new file mode 100644
index 0000000..5746cc4
Binary files /dev/null and b/test/trace/too-many-blocks-7.swf differ
diff --git a/test/trace/too-many-blocks-7.swf.trace b/test/trace/too-many-blocks-7.swf.trace
new file mode 100644
index 0000000..f58d53d
--- /dev/null
+++ b/test/trace/too-many-blocks-7.swf.trace
@@ -0,0 +1,4 @@
+0
+0
+0
+4
diff --git a/test/trace/too-many-blocks-8.swf b/test/trace/too-many-blocks-8.swf
new file mode 100644
index 0000000..7b36099
Binary files /dev/null and b/test/trace/too-many-blocks-8.swf differ
diff --git a/test/trace/too-many-blocks-8.swf.trace b/test/trace/too-many-blocks-8.swf.trace
new file mode 100644
index 0000000..f58d53d
--- /dev/null
+++ b/test/trace/too-many-blocks-8.swf.trace
@@ -0,0 +1,4 @@
+0
+0
+0
+4
diff --git a/test/trace/too-many-blocks.as b/test/trace/too-many-blocks.as
new file mode 100644
index 0000000..0f6eff0
--- /dev/null
+++ b/test/trace/too-many-blocks.as
@@ -0,0 +1,25 @@
+// makeswf -v 7 -s 200x150 -r 15 -o test-8.swf test-8.as
+
+var x1 = 0;
+var x2 = 0;
+var x3 = 0;
+var x4 = 0;
+var a = { x1: 1, x2: 1, x3: 1 };
+with (a) {
+  var b = { x1: 2, x2: 2 };
+  with (b) {
+    var c = { x1: 3 };
+    with (c) {
+      x1 = 4;
+      x2 = 4;
+      x3 = 4;
+      x4 = 4;
+    }
+  }
+}
+trace (x1);
+trace (x2);
+trace (x3);
+trace (x4);
+
+getURL ("FSCommand:quit", "");
commit e8dfffaf9a1a0c6fcf895bfad1bb581cfe818234
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Apr 25 14:18:16 2008 +0300

    Make catch block have it's own scope

diff --git a/swfdec/swfdec_as_interpret.c b/swfdec/swfdec_as_interpret.c
index 6a57185..aa43941 100644
--- a/swfdec/swfdec_as_interpret.c
+++ b/swfdec/swfdec_as_interpret.c
@@ -2550,6 +2550,8 @@ typedef struct {
     guint		register_number;
     char *		variable_name;
   };
+
+  SwfdecAsObject *	scope_object;
 } TryData;
 
 static void
@@ -2594,6 +2596,11 @@ swfdec_action_try_end_catch (SwfdecAsFrame *frame, gpointer data)
 
   cx = SWFDEC_AS_OBJECT (frame)->context;
 
+  g_assert (frame->scope_chain->data == try_data->scope_object);
+  frame->scope_chain =
+    g_slist_delete_link (frame->scope_chain, frame->scope_chain);
+  try_data->scope_object = NULL;
+
   if (swfdec_as_context_catch (cx, &val))
   {
     // we got an exception while in catch block:
@@ -2637,6 +2644,14 @@ swfdec_action_try_end_try (SwfdecAsFrame *frame, gpointer data)
     // we got an exception while in try block:
     // set the exception variable
     // add new block for catch and jump to it
+    try_data->scope_object = swfdec_as_object_new_empty (cx);
+    cx->frame->scope_chain = g_slist_prepend (cx->frame->scope_chain,
+	try_data->scope_object);
+
+    swfdec_as_frame_push_block (frame, try_data->catch_start,
+	try_data->catch_start + try_data->catch_size,
+	swfdec_action_try_end_catch, try_data);
+    frame->pc = try_data->catch_start;
 
     if (try_data->use_register)
     {
@@ -2649,35 +2664,9 @@ swfdec_action_try_end_try (SwfdecAsFrame *frame, gpointer data)
     }
     else
     {
-      // FIXME: this is duplicate of SetVariable
-      SwfdecAsObject *object;
-      const char *s, *rest;
-
-      s = swfdec_as_context_get_string (cx, try_data->variable_name);
-      if (swfdec_action_get_movie_by_path (cx, s, &object, &rest)) {
-	if (object && rest) {
-	  swfdec_as_object_set_variable (object,
-	      swfdec_as_context_get_string (cx, rest), &val);
-	} else {
-	  if (object) {
-	    rest = s;
-	  } else {
-	    rest = swfdec_as_context_get_string (cx, rest);
-	  }
-	  swfdec_as_frame_set_variable (frame, rest, &val);
-	}
-      }
-      else
-      {
-	SWFDEC_ERROR ("cannot set Error to variable %s",
-	    try_data->variable_name);
-      }
+      swfdec_as_object_set_variable (try_data->scope_object,
+	  swfdec_as_context_get_string (cx, try_data->variable_name), &val);
     }
-
-    swfdec_as_frame_push_block (frame, try_data->catch_start,
-	try_data->catch_start + try_data->catch_size,
-	swfdec_action_try_end_catch, try_data);
-    frame->pc = try_data->catch_start;
   }
   else
   {


More information about the Swfdec-commits mailing list