[Swfdec-commits] 15 commits - swfdec/swfdec_as_interpret.c swfdec/swfdec_bits.c swfdec/swfdec_bits.h swfdec/swfdec_bots.c swfdec/swfdec_bots.h test/trace vivified/code

Benjamin Otte company at kemper.freedesktop.org
Fri Apr 18 10:23:02 PDT 2008


 swfdec/swfdec_as_interpret.c                 |   12 
 swfdec/swfdec_bits.c                         |    6 
 swfdec/swfdec_bits.h                         |    1 
 swfdec/swfdec_bots.c                         |   25 +
 swfdec/swfdec_bots.h                         |    5 
 test/trace/Makefile.am                       |    5 
 test/trace/push-different-booleans.swf       |binary
 test/trace/push-different-booleans.swf.trace |    1 
 test/trace/push-weird.as                     |   15 +
 test/trace/push-weird.swf                    |binary
 test/trace/push-weird.swf.trace              |    4 
 vivified/code/Makefile.am                    |    5 
 vivified/code/decompiler.c                   |   38 ++
 vivified/code/vivi_code_asm.h                |    5 
 vivified/code/vivi_code_asm_code.c           |    2 
 vivified/code/vivi_code_asm_code_default.c   |    2 
 vivified/code/vivi_code_asm_push.c           |  396 +++++++++++++++++++++++++++
 vivified/code/vivi_code_asm_push.h           |  108 +++++++
 vivified/code/vivi_code_assembler.c          |    6 
 vivified/code/vivi_code_comment.c            |    4 
 vivified/code/vivi_code_comment.h            |    2 
 vivified/code/vivi_code_emitter.c            |   10 
 vivified/code/vivi_code_emitter.h            |    5 
 vivified/code/vivi_code_error.c              |   30 ++
 vivified/code/vivi_code_error.h              |   36 ++
 vivified/code/vivi_code_printer.c            |   49 +++
 vivified/code/vivi_code_printer.h            |    4 
 vivified/code/vivi_code_string.c             |   46 ---
 vivified/code/vivi_decompiler.c              |    6 
 vivified/code/vivi_decompiler.h              |    2 
 vivified/code/vivi_decompiler_block.c        |   12 
 vivified/code/vivi_disassembler.c            |  168 +++++++++++
 32 files changed, 923 insertions(+), 87 deletions(-)

New commits:
commit a28db0e9e1fde80a376eca7d72384f076624b3b9
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Apr 18 19:22:27 2008 +0200

    add some tests for abnormal data in push actions

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 75c3e24..0b8b0d7 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -2388,6 +2388,11 @@ EXTRA_DIST = \
 	propflags-set-prototype-8.swf.trace \
 	propflags-set-prototype-9.swf \
 	propflags-set-prototype-9.swf.trace \
+	push-different-booleans.swf \
+	push-different-booleans.swf.trace \
+	push-weird.as \
+	push-weird.swf \
+	push-weird.swf.trace \
 	rectangle-construct.as \
 	rectangle-construct-5.swf \
 	rectangle-construct-5.swf.trace \
diff --git a/test/trace/push-different-booleans.swf b/test/trace/push-different-booleans.swf
new file mode 100644
index 0000000..18bf2da
Binary files /dev/null and b/test/trace/push-different-booleans.swf differ
diff --git a/test/trace/push-different-booleans.swf.trace b/test/trace/push-different-booleans.swf.trace
new file mode 100644
index 0000000..27ba77d
--- /dev/null
+++ b/test/trace/push-different-booleans.swf.trace
@@ -0,0 +1 @@
+true
diff --git a/test/trace/push-weird.as b/test/trace/push-weird.as
new file mode 100644
index 0000000..81d9882
--- /dev/null
+++ b/test/trace/push-weird.as
@@ -0,0 +1,15 @@
+// makeswf -v 7 -s 200x150 -r 1 -o push-weird.swf push-weird.as
+
+asm {
+  pool "Hello World"
+  push pool 0
+  push type 42, type 23, undefined
+  trace
+  trace
+  push
+  trace
+  push big 0
+  trace
+};
+
+getURL ("fscommand:quit", "");
diff --git a/test/trace/push-weird.swf b/test/trace/push-weird.swf
new file mode 100644
index 0000000..ca8d645
Binary files /dev/null and b/test/trace/push-weird.swf differ
diff --git a/test/trace/push-weird.swf.trace b/test/trace/push-weird.swf.trace
new file mode 100644
index 0000000..68553a1
--- /dev/null
+++ b/test/trace/push-weird.swf.trace
@@ -0,0 +1,4 @@
+undefined
+Hello World
+undefined
+Hi World
commit e8cbd1ffd57e27ed517a58431dd0bacbeeee4830
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Apr 18 19:21:40 2008 +0200

    continue parsig after unknown push types

diff --git a/swfdec/swfdec_as_interpret.c b/swfdec/swfdec_as_interpret.c
index 44e4dc3..12e30e8 100644
--- a/swfdec/swfdec_as_interpret.c
+++ b/swfdec/swfdec_as_interpret.c
@@ -376,8 +376,8 @@ swfdec_action_push (SwfdecAsContext *cx, guint action, const guint8 *data, guint
 	  break;
 	}
       default:
-	SWFDEC_ERROR ("Push: type %u not implemented", type);
-	return;
+	SWFDEC_ERROR ("Push: unknown type %u, skipping", type);
+	break;
     }
   }
 }
@@ -3031,8 +3031,8 @@ swfdec_action_print_push (guint action, const guint8 *data, guint len)
 	g_string_append_printf (string, "Pool %u", swfdec_bits_get_u16 (&bits));
 	break;
       default:
-	SWFDEC_ERROR ("Push: type %u not implemented", type);
-	return NULL;
+	SWFDEC_ERROR ("Push: unknown type %u, skipping", type);
+	break;
     }
   }
   return g_string_free (string, FALSE);
diff --git a/vivified/code/vivi_decompiler.c b/vivified/code/vivi_decompiler.c
index 94e381c..023fceb 100644
--- a/vivified/code/vivi_decompiler.c
+++ b/vivified/code/vivi_decompiler.c
@@ -192,8 +192,8 @@ vivi_decompile_push (ViviDecompilerBlock *block, ViviDecompilerState *state,
 	  break;
 	}
       default:
-	vivi_decompiler_block_add_error (block, state, "Push: type %u not implemented", type);
-	return TRUE;
+	vivi_decompiler_block_add_error (block, state, "Push: type %u unknown, skipping", type);
+	break;
     }
     vivi_decompiler_state_push (state, val);
   }
diff --git a/vivified/code/vivi_disassembler.c b/vivified/code/vivi_disassembler.c
index c07a937..2ade0f3 100644
--- a/vivified/code/vivi_disassembler.c
+++ b/vivified/code/vivi_disassembler.c
@@ -93,8 +93,8 @@ vivi_disassemble_push (ViviCodeAssembler *assembler, SwfdecBits *bits, guint ver
 	vivi_code_asm_push_add_pool (push, swfdec_bits_get_u16 (bits));
 	break;
       default:
-	vivi_disassembler_warning (assembler, "Push: type %u not implemented", type);
-	goto fail;
+	vivi_disassembler_warning (assembler, "Push: unknown type %u, ignoring", type);
+	break;
     }
   }
 
commit d380bb3a528e547bce982e63cde24d4631b69d2c
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Apr 18 19:16:07 2008 +0200

    audit the rest of the code for swfdec_bits_get_s32()

diff --git a/vivified/code/vivi_code_asm_push.c b/vivified/code/vivi_code_asm_push.c
index ed87933..d6a3512 100644
--- a/vivified/code/vivi_code_asm_push.c
+++ b/vivified/code/vivi_code_asm_push.c
@@ -347,6 +347,21 @@ vivi_code_asm_push_get_double (ViviCodeAsmPush *push, guint id)
   return swfdec_bits_get_double (&bits);
 }
 
+int
+vivi_code_asm_push_get_integer (ViviCodeAsmPush *push, guint id)
+{
+  SwfdecBits bits;
+
+  g_return_val_if_fail (VIVI_IS_CODE_ASM_PUSH (push), FALSE);
+  g_return_val_if_fail (id < push->offsets->len, FALSE);
+
+  swfdec_bits_init_data (&bits, push->contents->data, swfdec_bots_get_bytes (push->contents));
+  swfdec_bits_skip_bytes (&bits, GPOINTER_TO_SIZE (g_ptr_array_index (push->offsets, id)));
+  g_return_val_if_fail (swfdec_bits_get_u8 (&bits) == VIVI_CODE_CONSTANT_INTEGER, FALSE);
+
+  return swfdec_bits_get_s32 (&bits);
+}
+
 gboolean
 vivi_code_asm_push_get_boolean (ViviCodeAsmPush *push, guint id)
 {
diff --git a/vivified/code/vivi_code_asm_push.h b/vivified/code/vivi_code_asm_push.h
index 72ca903..b93f845 100644
--- a/vivified/code/vivi_code_asm_push.h
+++ b/vivified/code/vivi_code_asm_push.h
@@ -77,6 +77,8 @@ guint			vivi_code_asm_push_get_register		(ViviCodeAsmPush *	push,
 								 guint			id);
 double			vivi_code_asm_push_get_double		(ViviCodeAsmPush *	push,
 								 guint			id);
+int			vivi_code_asm_push_get_integer		(ViviCodeAsmPush *	push,
+								 guint			id);
 gboolean		vivi_code_asm_push_get_boolean		(ViviCodeAsmPush *	push,
 								 guint			id);
 guint			vivi_code_asm_push_get_pool		(ViviCodeAsmPush *	push,
diff --git a/vivified/code/vivi_decompiler.c b/vivified/code/vivi_decompiler.c
index f95d393..94e381c 100644
--- a/vivified/code/vivi_decompiler.c
+++ b/vivified/code/vivi_decompiler.c
@@ -172,7 +172,7 @@ vivi_decompile_push (ViviDecompilerBlock *block, ViviDecompilerState *state,
 	val = vivi_code_number_new (swfdec_bits_get_double (&bits));
 	break;
       case 7: /* 32bit int */
-	val = vivi_code_number_new ((int) swfdec_bits_get_u32 (&bits));
+	val = vivi_code_number_new (swfdec_bits_get_s32 (&bits));
 	break;
       case 8: /* 8bit ConstantPool address */
       case 9: /* 16bit ConstantPool address */
diff --git a/vivified/code/vivi_disassembler.c b/vivified/code/vivi_disassembler.c
index 9e53fa2..c07a937 100644
--- a/vivified/code/vivi_disassembler.c
+++ b/vivified/code/vivi_disassembler.c
@@ -84,7 +84,7 @@ vivi_disassemble_push (ViviCodeAssembler *assembler, SwfdecBits *bits, guint ver
 	vivi_code_asm_push_add_double (push, swfdec_bits_get_double (bits));
 	break;
       case 7: /* 32bit int */
-	vivi_code_asm_push_add_integer (push, (gint32) swfdec_bits_get_u32 (bits));
+	vivi_code_asm_push_add_integer (push, swfdec_bits_get_s32 (bits));
 	break;
       case 8: /* 8bit ConstantPool address */
 	vivi_code_asm_push_add_pool (push, swfdec_bits_get_u8 (bits));
commit 45f740f8c97fda1e9eb624b7c84aa792462f4fb4
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Apr 18 19:12:31 2008 +0200

    swfdec_bits_get_s32() code audit done
    
    Yay for special casing one place :o

diff --git a/swfdec/swfdec_as_interpret.c b/swfdec/swfdec_as_interpret.c
index 40cb7ca..44e4dc3 100644
--- a/swfdec/swfdec_as_interpret.c
+++ b/swfdec/swfdec_as_interpret.c
@@ -353,7 +353,7 @@ swfdec_action_push (SwfdecAsContext *cx, guint action, const guint8 *data, guint
 	break;
       case 7: /* 32bit int */
 	SWFDEC_AS_VALUE_SET_INT (swfdec_as_stack_push (cx), 
-	    (int) swfdec_bits_get_u32 (&bits));
+	    swfdec_bits_get_s32 (&bits));
 	break;
       case 8: /* 8bit ConstantPool address */
       case 9: /* 16bit ConstantPool address */
@@ -3022,7 +3022,7 @@ swfdec_action_print_push (guint action, const guint8 *data, guint len)
 	g_string_append_printf (string, "%g", swfdec_bits_get_double (&bits));
 	break;
       case 7: /* 32bit int */
-	g_string_append_printf (string, "%d", swfdec_bits_get_u32 (&bits));
+	g_string_append_printf (string, "%d", swfdec_bits_get_s32 (&bits));
 	break;
       case 8: /* 8bit ConstantPool address */
 	g_string_append_printf (string, "Pool %u", swfdec_bits_get_u8 (&bits));
commit 52efc3635d19c9265fa693de1a0e0b0390803ce8
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Apr 18 19:08:39 2008 +0200

    more hacking on the asm stuff
    
    - s/decompiler_asm/disassembler/
    - disassemble push statements

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index 1bd0f63..c0fac3e 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -71,12 +71,12 @@ libvivified_compiler_la_SOURCES = \
 	vivi_compiler_empty_statement.c \
 	vivi_compiler_get_temporary.c \
 	vivi_compiler_goto_name.c \
-	vivi_decompiler_asm.c \
 	vivi_decompiler_block.c \
 	vivi_decompiler_duplicate.c \
 	vivi_decompiler_state.c \
 	vivi_decompiler_unknown.c \
 	vivi_decompiler.c \
+	vivi_disassembler.c \
 	vivi_parser.c \
 	vivi_parser_scanner.c
 
diff --git a/vivified/code/decompiler.c b/vivified/code/decompiler.c
index 9fbf88f..a8ebf8f 100644
--- a/vivified/code/decompiler.c
+++ b/vivified/code/decompiler.c
@@ -67,7 +67,7 @@ decode_script (gpointer scriptp, gpointer use_asm)
 
   g_print ("/* %s */\n", script->name);
   if (use_asm) {
-    token = VIVI_CODE_TOKEN (vivi_decompile_script_asm (script));
+    token = VIVI_CODE_TOKEN (vivi_disassemble_script (script));
   } else {
     token = VIVI_CODE_TOKEN (vivi_code_function_new_from_script (scriptp));
   }
diff --git a/vivified/code/vivi_code_asm_push.c b/vivified/code/vivi_code_asm_push.c
index 6d20c38..ed87933 100644
--- a/vivified/code/vivi_code_asm_push.c
+++ b/vivified/code/vivi_code_asm_push.c
@@ -22,6 +22,7 @@
 #endif
 
 #include <swfdec/swfdec_as_interpret.h>
+#include <swfdec/swfdec_bits.h>
 
 #include "vivi_code_asm_push.h"
 #include "vivi_code_asm.h"
@@ -54,10 +55,84 @@ vivi_code_asm_push_asm_init (ViviCodeAsmInterface *iface)
   iface->emit = vivi_code_asm_push_emit;
 }
 
-G_DEFINE_TYPE_WITH_CODE (ViviCodeAsmPush, vivi_code_asm_push, VIVI_TYPE_CODE_ASM_PUSH,
+G_DEFINE_TYPE_WITH_CODE (ViviCodeAsmPush, vivi_code_asm_push, VIVI_TYPE_CODE_ASM_CODE,
     G_IMPLEMENT_INTERFACE (VIVI_TYPE_CODE_ASM, vivi_code_asm_push_asm_init))
 
 static void
+vivi_code_asm_push_print (ViviCodeToken *token, ViviCodePrinter*printer)
+{
+  ViviCodeAsmPush *push = VIVI_CODE_ASM_PUSH (token);
+  SwfdecBits bits;
+  char *s, *s2;
+  gboolean first = TRUE;
+  guint type;
+
+  vivi_code_printer_print (printer, "push");
+  swfdec_bits_init_data (&bits, push->contents->data, swfdec_bots_get_bytes (push->contents));
+  while (swfdec_bits_left (&bits)) {
+    if (first) {
+      vivi_code_printer_print (printer, " ");
+      first = FALSE;
+    } else {
+      vivi_code_printer_print (printer, ", ");
+    }
+    type = swfdec_bits_get_u8 (&bits);
+    switch (type) {
+      case VIVI_CODE_CONSTANT_STRING:
+	s = swfdec_bits_get_string (&bits, 7);
+	s2 = vivi_code_escape_string (s);
+	g_free (s);
+	vivi_code_printer_print (printer, s2);
+	g_free (s2);
+	break;
+      case VIVI_CODE_CONSTANT_FLOAT:
+	s = g_strdup_printf ("%.ff", swfdec_bits_get_float (&bits));
+	vivi_code_printer_print (printer, s2);
+	g_free (s);
+	break;
+      case VIVI_CODE_CONSTANT_NULL:
+	vivi_code_printer_print (printer, "null");
+	break;
+      case VIVI_CODE_CONSTANT_UNDEFINED:
+	vivi_code_printer_print (printer, "undefined");
+	break;
+      case VIVI_CODE_CONSTANT_REGISTER:
+	s = g_strdup_printf ("reg %u", swfdec_bits_get_u8 (&bits));
+	vivi_code_printer_print (printer, s);
+	g_free (s);
+	break;
+      case VIVI_CODE_CONSTANT_BOOLEAN:
+	vivi_code_printer_print (printer, swfdec_bits_get_u8 (&bits) ? "true" : "false");
+	break;
+      case VIVI_CODE_CONSTANT_DOUBLE:
+	s = g_strdup_printf ("%.g", swfdec_bits_get_double (&bits));
+	vivi_code_printer_print (printer, s);
+	g_free (s);
+	break;
+      case VIVI_CODE_CONSTANT_INTEGER:
+	s = g_strdup_printf ("%d", swfdec_bits_get_s32 (&bits));
+	vivi_code_printer_print (printer, s);
+	g_free (s);
+	break;
+      case VIVI_CODE_CONSTANT_CONSTANT_POOL:
+	s = g_strdup_printf ("pool %u", swfdec_bits_get_u8 (&bits));
+	vivi_code_printer_print (printer, s);
+	g_free (s);
+	break;
+      case VIVI_CODE_CONSTANT_CONSTANT_POOL_BIG:
+	/* FIXME: allow differentiation between pool type for values < 256? */
+	s = g_strdup_printf ("pool %u", swfdec_bits_get_u16 (&bits));
+	vivi_code_printer_print (printer, s);
+	g_free (s);
+	break;
+      default:
+	g_assert_not_reached ();
+    }
+  }
+  vivi_code_printer_new_line (printer, FALSE);
+}
+
+static void
 vivi_code_asm_push_dispose (GObject *object)
 {
   ViviCodeAsmPush *push = VIVI_CODE_ASM_PUSH (object);
@@ -72,8 +147,11 @@ static void
 vivi_code_asm_push_class_init (ViviCodeAsmPushClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
 
   object_class->dispose = vivi_code_asm_push_dispose;
+
+  token_class->print = vivi_code_asm_push_print;
 }
 
 static void
@@ -209,3 +287,95 @@ vivi_code_asm_push_add_pool_big (ViviCodeAsmPush *push, guint id)
   swfdec_bots_put_u16 (push->contents, id);
 }
 
+const char *
+vivi_code_asm_push_get_string (ViviCodeAsmPush *push, guint id)
+{
+  SwfdecBits bits;
+
+  g_return_val_if_fail (VIVI_IS_CODE_ASM_PUSH (push), NULL);
+  g_return_val_if_fail (id < push->offsets->len, NULL);
+
+  swfdec_bits_init_data (&bits, push->contents->data, swfdec_bots_get_bytes (push->contents));
+  swfdec_bits_skip_bytes (&bits, GPOINTER_TO_SIZE (g_ptr_array_index (push->offsets, id)));
+  g_return_val_if_fail (swfdec_bits_get_u8 (&bits) == VIVI_CODE_CONSTANT_STRING, NULL);
+
+  return (char *) bits.ptr;
+}
+
+float
+vivi_code_asm_push_get_float (ViviCodeAsmPush *push, guint id)
+{
+  SwfdecBits bits;
+
+  g_return_val_if_fail (VIVI_IS_CODE_ASM_PUSH (push), 0.0f);
+  g_return_val_if_fail (id < push->offsets->len, 0.0f);
+
+  swfdec_bits_init_data (&bits, push->contents->data, swfdec_bots_get_bytes (push->contents));
+  swfdec_bits_skip_bytes (&bits, GPOINTER_TO_SIZE (g_ptr_array_index (push->offsets, id)));
+  g_return_val_if_fail (swfdec_bits_get_u8 (&bits) == VIVI_CODE_CONSTANT_FLOAT, 0.0f);
+
+  return swfdec_bits_get_float (&bits);
+}
+
+guint
+vivi_code_asm_push_get_register (ViviCodeAsmPush *push, guint id)
+{
+  SwfdecBits bits;
+
+  g_return_val_if_fail (VIVI_IS_CODE_ASM_PUSH (push), 0);
+  g_return_val_if_fail (id < push->offsets->len, 0);
+
+  swfdec_bits_init_data (&bits, push->contents->data, swfdec_bots_get_bytes (push->contents));
+  swfdec_bits_skip_bytes (&bits, GPOINTER_TO_SIZE (g_ptr_array_index (push->offsets, id)));
+  g_return_val_if_fail (swfdec_bits_get_u8 (&bits) == VIVI_CODE_CONSTANT_REGISTER, 0);
+
+  return swfdec_bits_get_u8 (&bits);
+}
+
+double
+vivi_code_asm_push_get_double (ViviCodeAsmPush *push, guint id)
+{
+  SwfdecBits bits;
+
+  g_return_val_if_fail (VIVI_IS_CODE_ASM_PUSH (push), 0.0);
+  g_return_val_if_fail (id < push->offsets->len, 0.0);
+
+  swfdec_bits_init_data (&bits, push->contents->data, swfdec_bots_get_bytes (push->contents));
+  swfdec_bits_skip_bytes (&bits, GPOINTER_TO_SIZE (g_ptr_array_index (push->offsets, id)));
+  g_return_val_if_fail (swfdec_bits_get_u8 (&bits) == VIVI_CODE_CONSTANT_DOUBLE, 0.0);
+
+  return swfdec_bits_get_double (&bits);
+}
+
+gboolean
+vivi_code_asm_push_get_boolean (ViviCodeAsmPush *push, guint id)
+{
+  SwfdecBits bits;
+
+  g_return_val_if_fail (VIVI_IS_CODE_ASM_PUSH (push), FALSE);
+  g_return_val_if_fail (id < push->offsets->len, FALSE);
+
+  swfdec_bits_init_data (&bits, push->contents->data, swfdec_bots_get_bytes (push->contents));
+  swfdec_bits_skip_bytes (&bits, GPOINTER_TO_SIZE (g_ptr_array_index (push->offsets, id)));
+  g_return_val_if_fail (swfdec_bits_get_u8 (&bits) == VIVI_CODE_CONSTANT_BOOLEAN, FALSE);
+
+  return swfdec_bits_get_u8 (&bits) ? TRUE : FALSE;
+}
+
+guint
+vivi_code_asm_push_get_pool (ViviCodeAsmPush *push, guint id)
+{
+  SwfdecBits bits;
+  guint type;
+
+  g_return_val_if_fail (VIVI_IS_CODE_ASM_PUSH (push), 0);
+  g_return_val_if_fail (id < push->offsets->len, 0);
+
+  swfdec_bits_init_data (&bits, push->contents->data, swfdec_bots_get_bytes (push->contents));
+  swfdec_bits_skip_bytes (&bits, GPOINTER_TO_SIZE (g_ptr_array_index (push->offsets, id)));
+  type = swfdec_bits_get_u8 (&bits);
+  g_return_val_if_fail (type == VIVI_CODE_CONSTANT_CONSTANT_POOL ||
+      type == VIVI_CODE_CONSTANT_CONSTANT_POOL_BIG, 0);
+
+  return type == VIVI_CODE_CONSTANT_CONSTANT_POOL ? swfdec_bits_get_u8 (&bits) : swfdec_bits_get_u16 (&bits);
+}
diff --git a/vivified/code/vivi_code_asm_push.h b/vivified/code/vivi_code_asm_push.h
index 194a9f3..72ca903 100644
--- a/vivified/code/vivi_code_asm_push.h
+++ b/vivified/code/vivi_code_asm_push.h
@@ -70,13 +70,17 @@ guint			vivi_code_asm_push_get_n_values		(ViviCodeAsmPush *	push);
 ViviCodeConstantType	vivi_code_asm_push_get_value_type     	(ViviCodeAsmPush *	push,
 								 guint			i);
 const char *		vivi_code_asm_push_get_string		(ViviCodeAsmPush *	push,
-								 guint			i);
-double			vivi_code_asm_push_get_number		(ViviCodeAsmPush *	push,
-								 guint			i);
-int			vivi_code_asm_push_get_integer		(ViviCodeAsmPush *	push,
-								 guint			i);
-int			vivi_code_asm_push_get_boolean		(ViviCodeAsmPush *	push,
-								 guint			i);
+								 guint			id);
+float			vivi_code_asm_push_get_float		(ViviCodeAsmPush *	push,
+								 guint			id);
+guint			vivi_code_asm_push_get_register		(ViviCodeAsmPush *	push,
+								 guint			id);
+double			vivi_code_asm_push_get_double		(ViviCodeAsmPush *	push,
+								 guint			id);
+gboolean		vivi_code_asm_push_get_boolean		(ViviCodeAsmPush *	push,
+								 guint			id);
+guint			vivi_code_asm_push_get_pool		(ViviCodeAsmPush *	push,
+								 guint			id);
 
 void			vivi_code_asm_push_add_string		(ViviCodeAsmPush *	push,
 								 const char *		string);
diff --git a/vivified/code/vivi_decompiler.h b/vivified/code/vivi_decompiler.h
index 1ac1212..43489d3 100644
--- a/vivified/code/vivi_decompiler.h
+++ b/vivified/code/vivi_decompiler.h
@@ -28,7 +28,7 @@ G_BEGIN_DECLS
 
 ViviCodeStatement *	vivi_decompile_script		(SwfdecScript *		script);
 
-ViviCodeStatement *	vivi_decompile_script_asm	(SwfdecScript *		script);
+ViviCodeStatement *	vivi_disassemble_script		(SwfdecScript *		script);
 
 
 G_END_DECLS
diff --git a/vivified/code/vivi_decompiler_asm.c b/vivified/code/vivi_decompiler_asm.c
deleted file mode 100644
index e24b0ae..0000000
--- a/vivified/code/vivi_decompiler_asm.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/* 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 <swfdec/swfdec_as_interpret.h>
-#include <swfdec/swfdec_bits.h>
-#include <swfdec/swfdec_script_internal.h>
-
-#include "vivi_decompiler.h"
-#include "vivi_code_assembler.h"
-#include "vivi_code_comment.h"
-#include "vivi_code_asm_code_default.h"
-
-#define vivi_decompiler_warning(assembler,...) G_STMT_START { \
-  char *__s = g_strdup_printf (__VA_ARGS__); \
-  ViviCodeStatement *comment = vivi_code_comment_new (__s); \
-  vivi_code_assembler_add_code(assembler, VIVI_CODE_ASM (comment)); \
-  g_object_unref (comment); \
-  g_free (__s); \
-}G_STMT_END
-
-static ViviCodeAsm * (* simple_commands[0x80]) (void) = {
-#define DEFAULT_ASM(a,b,c) [c] = vivi_code_asm_ ## b ## _new,
-#include "vivi_code_defaults.h"
-};
-
-
-ViviCodeStatement *
-vivi_decompile_script_asm (SwfdecScript *script)
-{
-  ViviCodeAssembler *assembler = VIVI_CODE_ASSEMBLER (vivi_code_assembler_new ());
-  GHashTable *bytecodes;
-  const guint8 *pc, *start, *end, *exit;
-  const guint8 *data;
-  guint code, len;
-  SwfdecBits bits;
-
-  start = script->buffer->data;
-  end = start + script->buffer->length;
-  exit = script->exit;
-  pc = script->main;
-
-  bytecodes = g_hash_table_new (g_direct_hash, g_direct_equal);
-
-  while (pc != exit) {
-    if (pc < start || pc >= end) {
-      vivi_decompiler_warning (assembler, "program counter out of range");
-      goto error;
-    }
-    code = pc[0];
-    if (code & 0x80) {
-      if (pc + 2 >= end) {
-	vivi_decompiler_warning (assembler, "bytecode 0x%02X length value out of range", code);
-	goto error;
-      }
-      data = pc + 3;
-      len = pc[1] | pc[2] << 8;
-      if (data + len > end) {
-	vivi_decompiler_warning (assembler, "bytecode 0x%02X length %u out of range", code, len);
-	goto error;
-      }
-      swfdec_bits_init_data (&bits, data, len);
-      switch (code) {
-	default:
-	  vivi_decompiler_warning (assembler, "unknown bytecode 0x%02X", code);
-	  pc = data + len;
-      }
-    } else {
-      if (simple_commands[code]) {
-	ViviCodeAsm *asmcode = simple_commands[code] ();
-	vivi_code_assembler_add_code (assembler, asmcode);
-	g_object_unref (asmcode);
-      } else {
-	vivi_decompiler_warning (assembler, "unknown bytecode 0x%02X", code);
-      }
-      pc++;
-    }
-  }
-
-error:
-  g_hash_table_destroy (bytecodes);
-  return VIVI_CODE_STATEMENT (assembler);
-}
-
diff --git a/vivified/code/vivi_disassembler.c b/vivified/code/vivi_disassembler.c
new file mode 100644
index 0000000..9e53fa2
--- /dev/null
+++ b/vivified/code/vivi_disassembler.c
@@ -0,0 +1,168 @@
+/* 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 <swfdec/swfdec_as_interpret.h>
+#include <swfdec/swfdec_bits.h>
+#include <swfdec/swfdec_script_internal.h>
+
+#include "vivi_decompiler.h"
+#include "vivi_code_asm_code_default.h"
+#include "vivi_code_asm_push.h"
+#include "vivi_code_assembler.h"
+#include "vivi_code_comment.h"
+
+#define vivi_disassembler_warning(assembler,...) G_STMT_START { \
+  char *__s = g_strdup_printf (__VA_ARGS__); \
+  ViviCodeStatement *comment = vivi_code_comment_new (__s); \
+  vivi_code_assembler_add_code (assembler, VIVI_CODE_ASM (comment)); \
+  g_object_unref (comment); \
+  g_free (__s); \
+}G_STMT_END
+
+static ViviCodeAsm * (* simple_commands[0x80]) (void) = {
+#define DEFAULT_ASM(a,b,c) [c] = vivi_code_asm_ ## b ## _new,
+#include "vivi_code_defaults.h"
+};
+
+static void
+vivi_disassemble_push (ViviCodeAssembler *assembler, SwfdecBits *bits, guint version)
+{
+  ViviCodeAsmPush *push;
+  guint type;
+
+  push = VIVI_CODE_ASM_PUSH (vivi_code_asm_push_new ());
+  while (swfdec_bits_left (bits)) {
+    type = swfdec_bits_get_u8 (bits);
+    switch (type) {
+      case 0: /* string */
+	{
+	  char *s = swfdec_bits_get_string (bits, version);
+	  if (s == NULL) {
+	    vivi_disassembler_warning (assembler, "could not read string");
+	    goto fail;
+	  }
+	  vivi_code_asm_push_add_string (push, s);
+	  g_free (s);
+	  break;
+	}
+      case 1: /* float */
+	vivi_code_asm_push_add_float (push, swfdec_bits_get_float (bits));
+	break;
+      case 2: /* null */
+	vivi_code_asm_push_add_null (push);
+	break;
+      case 3: /* undefined */
+	vivi_code_asm_push_add_undefined (push);
+	break;
+      case 4: /* register */
+	vivi_code_asm_push_add_register (push, swfdec_bits_get_u8 (bits));
+	break;
+      case 5: /* boolean */
+	vivi_code_asm_push_add_boolean (push, swfdec_bits_get_u8 (bits));
+	break;
+      case 6: /* double */
+	vivi_code_asm_push_add_double (push, swfdec_bits_get_double (bits));
+	break;
+      case 7: /* 32bit int */
+	vivi_code_asm_push_add_integer (push, (gint32) swfdec_bits_get_u32 (bits));
+	break;
+      case 8: /* 8bit ConstantPool address */
+	vivi_code_asm_push_add_pool (push, swfdec_bits_get_u8 (bits));
+	break;
+      case 9: /* 16bit ConstantPool address */
+	vivi_code_asm_push_add_pool (push, swfdec_bits_get_u16 (bits));
+	break;
+      default:
+	vivi_disassembler_warning (assembler, "Push: type %u not implemented", type);
+	goto fail;
+    }
+  }
+
+  vivi_code_assembler_add_code (assembler, VIVI_CODE_ASM (push));
+fail:
+  g_object_unref (push);
+}
+
+
+ViviCodeStatement *
+vivi_disassemble_script (SwfdecScript *script)
+{
+  ViviCodeAssembler *assembler = VIVI_CODE_ASSEMBLER (vivi_code_assembler_new ());
+  GHashTable *bytecodes;
+  const guint8 *pc, *start, *end, *exit;
+  const guint8 *data;
+  guint code, len;
+  SwfdecBits bits;
+
+  start = script->buffer->data;
+  end = start + script->buffer->length;
+  exit = script->exit;
+  pc = script->main;
+
+  bytecodes = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+  while (pc != exit) {
+    if (pc < start || pc >= end) {
+      vivi_disassembler_warning (assembler, "program counter out of range");
+      goto error;
+    }
+    code = pc[0];
+    if (code & 0x80) {
+      if (pc + 2 >= end) {
+	vivi_disassembler_warning (assembler, "bytecode 0x%02X length value out of range", code);
+	goto error;
+      }
+      data = pc + 3;
+      len = pc[1] | pc[2] << 8;
+      if (data + len > end) {
+	vivi_disassembler_warning (assembler, "bytecode 0x%02X length %u out of range", code, len);
+	goto error;
+      }
+      swfdec_bits_init_data (&bits, data, len);
+      switch (code) {
+	case SWFDEC_AS_ACTION_PUSH:
+	  vivi_disassemble_push (assembler, &bits, script->version);
+	  pc = data + len;
+	  break;
+	default:
+	  vivi_disassembler_warning (assembler, "unknown bytecode 0x%02X", code);
+	  pc = data + len;
+	  break;
+      }
+    } else {
+      if (simple_commands[code]) {
+	ViviCodeAsm *asmcode = simple_commands[code] ();
+	vivi_code_assembler_add_code (assembler, asmcode);
+	g_object_unref (asmcode);
+      } else {
+	vivi_disassembler_warning (assembler, "unknown bytecode 0x%02X", code);
+      }
+      pc++;
+    }
+  }
+
+error:
+  g_hash_table_destroy (bytecodes);
+  return VIVI_CODE_STATEMENT (assembler);
+}
+
commit af549dbc9bc0f7c0935b4fdb75076f114fef8fd9
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Apr 18 19:06:35 2008 +0200

    add swfdec_bits_get_s32()
    
    previously I used (int)swfdec_bits_get_u32(), but that only works if ints are
    32bit. Luckily they are on all current architectures, so it never failed.
    The code should still be audited and be changed to use get_s32() instead.

diff --git a/swfdec/swfdec_bits.c b/swfdec/swfdec_bits.c
index 10c1bcd..6ab8ca0 100644
--- a/swfdec/swfdec_bits.c
+++ b/swfdec/swfdec_bits.c
@@ -258,6 +258,12 @@ swfdec_bits_get_u32 (SwfdecBits * b)
   return r;
 }
 
+int
+swfdec_bits_get_s32 (SwfdecBits *b)
+{
+  return (gint32) swfdec_bits_get_u32 (b);
+}
+
 guint
 swfdec_bits_get_bu16 (SwfdecBits *b)
 {
diff --git a/swfdec/swfdec_bits.h b/swfdec/swfdec_bits.h
index 36e9a6a..21c3c79 100644
--- a/swfdec/swfdec_bits.h
+++ b/swfdec/swfdec_bits.h
@@ -49,6 +49,7 @@ guint swfdec_bits_get_u8 (SwfdecBits * b);
 guint swfdec_bits_get_u16 (SwfdecBits * b);
 int swfdec_bits_get_s16 (SwfdecBits * b);
 guint swfdec_bits_get_u32 (SwfdecBits * b);
+int swfdec_bits_get_s32 (SwfdecBits * b);
 guint swfdec_bits_get_bu16 (SwfdecBits *b);
 guint swfdec_bits_get_bu24 (SwfdecBits *b);
 guint swfdec_bits_get_bu32 (SwfdecBits *b);
commit 5fc1f24ff032bd355960c2fa07f9e092e052811b
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Apr 18 19:06:06 2008 +0200

    make the escape_string function public
    
    this includes putting it in a sane place

diff --git a/vivified/code/vivi_code_printer.c b/vivified/code/vivi_code_printer.c
index 33ff64b..738069f 100644
--- a/vivified/code/vivi_code_printer.c
+++ b/vivified/code/vivi_code_printer.c
@@ -21,6 +21,8 @@
 #include "config.h"
 #endif
 
+#include <string.h>
+
 #include "vivi_code_printer.h"
 
 G_DEFINE_ABSTRACT_TYPE (ViviCodePrinter, vivi_code_printer, G_TYPE_OBJECT)
@@ -131,3 +133,50 @@ vivi_code_printer_get_indentation (ViviCodePrinter *printer)
 
   return printer->indentation;
 }
+
+char *
+vivi_code_escape_string (const char *s)
+{
+  GString *str;
+  char *next;
+
+  g_return_val_if_fail (s != NULL, NULL);
+
+  str = g_string_new ("\"");
+  while ((next = strpbrk (s, "\"\\\b\f\n\r\t\v"))) {
+    g_string_append_len (str, s, next - s);
+    switch (*next) {
+      case '"':
+	g_string_append (str, "\\\"");
+	break;
+      case '\\':
+	g_string_append (str, "\\\\");
+	break;
+      case '\b':
+	g_string_append (str, "\\b");
+	break;
+      case '\f':
+	g_string_append (str, "\\f");
+	break;
+      case '\n':
+	g_string_append (str, "\\n");
+	break;
+      case '\r':
+	g_string_append (str, "\\r");
+	break;
+      case '\t':
+	g_string_append (str, "\\t");
+	break;
+      case '\v':
+	g_string_append (str, "\\v");
+	break;
+      default:
+	g_assert_not_reached ();
+    }
+    s = next + 1;
+  }
+  g_string_append (str, s);
+  g_string_append_c (str, '"');
+  return g_string_free (str, FALSE);
+}
+
diff --git a/vivified/code/vivi_code_printer.h b/vivified/code/vivi_code_printer.h
index 5e886f0..46d24c7 100644
--- a/vivified/code/vivi_code_printer.h
+++ b/vivified/code/vivi_code_printer.h
@@ -78,5 +78,9 @@ void			vivi_code_printer_pop_indentation
 guint			vivi_code_printer_get_indentation
 							(ViviCodePrinter *	printer);
 
+
+char *			vivi_code_escape_string		(const char *		s);
+
+
 G_END_DECLS
 #endif
diff --git a/vivified/code/vivi_code_string.c b/vivified/code/vivi_code_string.c
index a561f7d..41336bc 100644
--- a/vivified/code/vivi_code_string.c
+++ b/vivified/code/vivi_code_string.c
@@ -39,57 +39,13 @@ vivi_code_string_dispose (GObject *object)
   G_OBJECT_CLASS (vivi_code_string_parent_class)->dispose (object);
 }
 
-static char *
-escape_string (const char *s)
-{
-  GString *str;
-  char *next;
-
-  str = g_string_new ("\"");
-  while ((next = strpbrk (s, "\"\\\b\f\n\r\t\v"))) {
-    g_string_append_len (str, s, next - s);
-    switch (*next) {
-      case '"':
-	g_string_append (str, "\\\"");
-	break;
-      case '\\':
-	g_string_append (str, "\\\\");
-	break;
-      case '\b':
-	g_string_append (str, "\\b");
-	break;
-      case '\f':
-	g_string_append (str, "\\f");
-	break;
-      case '\n':
-	g_string_append (str, "\\n");
-	break;
-      case '\r':
-	g_string_append (str, "\\r");
-	break;
-      case '\t':
-	g_string_append (str, "\\t");
-	break;
-      case '\v':
-	g_string_append (str, "\\v");
-	break;
-      default:
-	g_assert_not_reached ();
-    }
-    s = next + 1;
-  }
-  g_string_append (str, s);
-  g_string_append_c (str, '"');
-  return g_string_free (str, FALSE);
-}
-
 static void
 vivi_code_string_print (ViviCodeToken *token, ViviCodePrinter *printer)
 {
   ViviCodeString *string = VIVI_CODE_STRING (token);
   char *s;
 
-  s = escape_string (string->value);
+  s = vivi_code_escape_string (string->value);
   vivi_code_printer_print (printer, s);
   g_free (s);
 }
commit 66e754fcd120096736742c821d13d96ed1e03412
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 17 23:31:30 2008 +0200

    add first step of an asm decompiler - it even decompiles stuff!

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index 95dc95b..1bd0f63 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -71,6 +71,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_compiler_empty_statement.c \
 	vivi_compiler_get_temporary.c \
 	vivi_compiler_goto_name.c \
+	vivi_decompiler_asm.c \
 	vivi_decompiler_block.c \
 	vivi_decompiler_duplicate.c \
 	vivi_decompiler_state.c \
diff --git a/vivified/code/decompiler.c b/vivified/code/decompiler.c
index f7fa70e..9fbf88f 100644
--- a/vivified/code/decompiler.c
+++ b/vivified/code/decompiler.c
@@ -30,6 +30,7 @@
 
 #include "vivi_code_function.h"
 #include "vivi_code_text_printer.h"
+#include "vivi_decompiler.h"
 
 static SwfdecDecoder *
 swfdec_decoder_new_from_file (const char *filename, GError **error)
@@ -57,23 +58,26 @@ swfdec_decoder_new_from_file (const char *filename, GError **error)
   return dec;
 }
 
-
 static void
-decode_script (gpointer scriptp, gpointer unused)
+decode_script (gpointer scriptp, gpointer use_asm)
 {
   SwfdecScript *script = scriptp;
-  ViviCodeValue *fun;
+  ViviCodeToken *token;
   ViviCodePrinter *printer;
 
   g_print ("/* %s */\n", script->name);
-  fun = vivi_code_function_new_from_script (scriptp);
+  if (use_asm) {
+    token = VIVI_CODE_TOKEN (vivi_decompile_script_asm (script));
+  } else {
+    token = VIVI_CODE_TOKEN (vivi_code_function_new_from_script (scriptp));
+  }
   printer = vivi_code_text_printer_new ();
 
-  vivi_code_printer_print_token (printer, VIVI_CODE_TOKEN (fun));
+  vivi_code_printer_print_token (printer, token);
   g_print ("\n\n");
 
   g_object_unref (printer);
-  g_object_unref (fun);
+  g_object_unref (token);
 }
 
 static void
@@ -98,7 +102,25 @@ main (int argc, char *argv[])
 {
   SwfdecSwfDecoder *dec;
   GList *scripts;
-  GError *error;
+  GError *error = NULL;
+  gboolean use_asm = FALSE;
+
+  GOptionEntry options[] = {
+    { "asm", 'a', 0, G_OPTION_ARG_NONE, &use_asm, "output assembler instead of decompiled script", NULL },
+    { NULL }
+  };
+  GOptionContext *ctx;
+
+  ctx = g_option_context_new ("");
+  g_option_context_add_main_entries (ctx, options, "options");
+  g_option_context_parse (ctx, &argc, &argv, &error);
+  g_option_context_free (ctx);
+
+  if (error) {
+    g_printerr ("Error parsing command line arguments: %s\n", error->message);
+    g_error_free (error);
+    return 1;
+  }
 
   if (argc < 2) {
     g_print ("%s FILENAME\n", argv[0]);
@@ -126,7 +148,7 @@ main (int argc, char *argv[])
   g_hash_table_foreach (dec->scripts, enqueue, &scripts);
   scripts = g_list_sort (scripts, script_compare);
   
-  g_list_foreach (scripts, decode_script, NULL);
+  g_list_foreach (scripts, decode_script, GINT_TO_POINTER (use_asm));
 
   g_list_free (scripts);
   g_object_unref (dec);
diff --git a/vivified/code/vivi_decompiler.h b/vivified/code/vivi_decompiler.h
index 943a040..1ac1212 100644
--- a/vivified/code/vivi_decompiler.h
+++ b/vivified/code/vivi_decompiler.h
@@ -28,6 +28,8 @@ G_BEGIN_DECLS
 
 ViviCodeStatement *	vivi_decompile_script		(SwfdecScript *		script);
 
+ViviCodeStatement *	vivi_decompile_script_asm	(SwfdecScript *		script);
+
 
 G_END_DECLS
 #endif
diff --git a/vivified/code/vivi_decompiler_asm.c b/vivified/code/vivi_decompiler_asm.c
new file mode 100644
index 0000000..e24b0ae
--- /dev/null
+++ b/vivified/code/vivi_decompiler_asm.c
@@ -0,0 +1,103 @@
+/* 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 <swfdec/swfdec_as_interpret.h>
+#include <swfdec/swfdec_bits.h>
+#include <swfdec/swfdec_script_internal.h>
+
+#include "vivi_decompiler.h"
+#include "vivi_code_assembler.h"
+#include "vivi_code_comment.h"
+#include "vivi_code_asm_code_default.h"
+
+#define vivi_decompiler_warning(assembler,...) G_STMT_START { \
+  char *__s = g_strdup_printf (__VA_ARGS__); \
+  ViviCodeStatement *comment = vivi_code_comment_new (__s); \
+  vivi_code_assembler_add_code(assembler, VIVI_CODE_ASM (comment)); \
+  g_object_unref (comment); \
+  g_free (__s); \
+}G_STMT_END
+
+static ViviCodeAsm * (* simple_commands[0x80]) (void) = {
+#define DEFAULT_ASM(a,b,c) [c] = vivi_code_asm_ ## b ## _new,
+#include "vivi_code_defaults.h"
+};
+
+
+ViviCodeStatement *
+vivi_decompile_script_asm (SwfdecScript *script)
+{
+  ViviCodeAssembler *assembler = VIVI_CODE_ASSEMBLER (vivi_code_assembler_new ());
+  GHashTable *bytecodes;
+  const guint8 *pc, *start, *end, *exit;
+  const guint8 *data;
+  guint code, len;
+  SwfdecBits bits;
+
+  start = script->buffer->data;
+  end = start + script->buffer->length;
+  exit = script->exit;
+  pc = script->main;
+
+  bytecodes = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+  while (pc != exit) {
+    if (pc < start || pc >= end) {
+      vivi_decompiler_warning (assembler, "program counter out of range");
+      goto error;
+    }
+    code = pc[0];
+    if (code & 0x80) {
+      if (pc + 2 >= end) {
+	vivi_decompiler_warning (assembler, "bytecode 0x%02X length value out of range", code);
+	goto error;
+      }
+      data = pc + 3;
+      len = pc[1] | pc[2] << 8;
+      if (data + len > end) {
+	vivi_decompiler_warning (assembler, "bytecode 0x%02X length %u out of range", code, len);
+	goto error;
+      }
+      swfdec_bits_init_data (&bits, data, len);
+      switch (code) {
+	default:
+	  vivi_decompiler_warning (assembler, "unknown bytecode 0x%02X", code);
+	  pc = data + len;
+      }
+    } else {
+      if (simple_commands[code]) {
+	ViviCodeAsm *asmcode = simple_commands[code] ();
+	vivi_code_assembler_add_code (assembler, asmcode);
+	g_object_unref (asmcode);
+      } else {
+	vivi_decompiler_warning (assembler, "unknown bytecode 0x%02X", code);
+      }
+      pc++;
+    }
+  }
+
+error:
+  g_hash_table_destroy (bytecodes);
+  return VIVI_CODE_STATEMENT (assembler);
+}
+
commit 49cca863f7f8a8470fe65a2a2a4c925086b1934d
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 17 23:30:59 2008 +0200

    inherit from the right object

diff --git a/vivified/code/vivi_code_asm_code.c b/vivified/code/vivi_code_asm_code.c
index 7f060b3..dc9fdf2 100644
--- a/vivified/code/vivi_code_asm_code.c
+++ b/vivified/code/vivi_code_asm_code.c
@@ -33,7 +33,7 @@ vivi_code_asm_code_asm_init (ViviCodeAsmInterface *iface)
 {
 }
 
-G_DEFINE_TYPE_WITH_CODE (ViviCodeAsmCode, vivi_code_asm_code, VIVI_TYPE_CODE_ASM_CODE,
+G_DEFINE_TYPE_WITH_CODE (ViviCodeAsmCode, vivi_code_asm_code, VIVI_TYPE_CODE_TOKEN,
     G_IMPLEMENT_INTERFACE (VIVI_TYPE_CODE_ASM, vivi_code_asm_code_asm_init))
 
 static void
commit e1b1d24dd4412739e23a883b2569754939ed9bda
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 17 23:30:41 2008 +0200

    use FLASE for newlines here, too

diff --git a/vivified/code/vivi_code_asm_code_default.c b/vivified/code/vivi_code_asm_code_default.c
index 3daf353..aa202ef 100644
--- a/vivified/code/vivi_code_asm_code_default.c
+++ b/vivified/code/vivi_code_asm_code_default.c
@@ -32,7 +32,7 @@ static void \
 vivi_code_asm_ ## underscore_name ## _print (ViviCodeToken *token, ViviCodePrinter *printer) \
 { \
   vivi_code_printer_print (printer, G_STRINGIFY (underscore_name)); \
-  vivi_code_printer_new_line (printer, TRUE); \
+  vivi_code_printer_new_line (printer, FALSE); \
 } \
 \
 static void \
commit 29707ff1593de80c59ccdc0c53e0cb5e17464312
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 17 23:24:40 2008 +0200

    use FALSE for the new-line argument
    
    Looks like we're taking the wrong argument there, if I can't remember it...

diff --git a/vivified/code/vivi_code_assembler.c b/vivified/code/vivi_code_assembler.c
index d1fecd5..49d52cb 100644
--- a/vivified/code/vivi_code_assembler.c
+++ b/vivified/code/vivi_code_assembler.c
@@ -59,14 +59,14 @@ vivi_code_assembler_print (ViviCodeToken *token, ViviCodePrinter *printer)
   guint i;
 
   vivi_code_printer_print (printer, "asm {");
-  vivi_code_printer_new_line (printer, TRUE);
+  vivi_code_printer_new_line (printer, FALSE);
   vivi_code_printer_push_indentation (printer);
   for (i = 0; i < assembler->codes->len; i++) {
     vivi_code_printer_print_token (printer, g_ptr_array_index (assembler->codes, i));
   }
   vivi_code_printer_pop_indentation (printer);
   vivi_code_printer_print (printer, "}");
-  vivi_code_printer_new_line (printer, TRUE);
+  vivi_code_printer_new_line (printer, FALSE);
 }
 
 static void
@@ -129,7 +129,7 @@ void
 vivi_code_assembler_insert_code (ViviCodeAssembler *assembler, guint i, ViviCodeAsm *code)
 {
   g_return_if_fail (VIVI_IS_CODE_ASSEMBLER (assembler));
-  g_return_if_fail (VIVI_IS_CODE_ASM (assembler));
+  g_return_if_fail (VIVI_IS_CODE_ASM (code));
 
   g_object_ref (code);
   if (i >= assembler->codes->len) {
commit cf0eb433befb858b474d72cbff93b5771362f638
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 17 22:56:30 2008 +0200

    make vivi_code_comment_new() return a statement

diff --git a/vivified/code/vivi_code_comment.c b/vivified/code/vivi_code_comment.c
index 65fe694..631862d 100644
--- a/vivified/code/vivi_code_comment.c
+++ b/vivified/code/vivi_code_comment.c
@@ -78,7 +78,7 @@ vivi_code_comment_init (ViviCodeComment *token)
 {
 }
 
-ViviCodeToken *
+ViviCodeStatement *
 vivi_code_comment_new (const char *comment)
 {
   ViviCodeComment *ret;
@@ -88,6 +88,6 @@ vivi_code_comment_new (const char *comment)
   ret = g_object_new (VIVI_TYPE_CODE_COMMENT, NULL);
   ret->comment = g_strdup (comment);
 
-  return VIVI_CODE_TOKEN (ret);
+  return VIVI_CODE_STATEMENT (ret);
 }
 
diff --git a/vivified/code/vivi_code_comment.h b/vivified/code/vivi_code_comment.h
index 13a4394..e368005 100644
--- a/vivified/code/vivi_code_comment.h
+++ b/vivified/code/vivi_code_comment.h
@@ -49,7 +49,7 @@ struct _ViviCodeCommentClass
 
 GType			vivi_code_comment_get_type   	(void);
 
-ViviCodeToken *		vivi_code_comment_new		(const char *		comment);
+ViviCodeStatement *	vivi_code_comment_new		(const char *		comment);
 
 
 G_END_DECLS
diff --git a/vivified/code/vivi_decompiler_block.c b/vivified/code/vivi_decompiler_block.c
index 1fc22b2..895cf58 100644
--- a/vivified/code/vivi_decompiler_block.c
+++ b/vivified/code/vivi_decompiler_block.c
@@ -199,7 +199,7 @@ void
 vivi_decompiler_block_add_error (ViviDecompilerBlock *block,
     ViviDecompilerState *state, const char *format, ...)
 {
-  ViviCodeToken *token;
+  ViviCodeStatement *stmt;
   va_list varargs;
   char *s;
 
@@ -207,10 +207,10 @@ vivi_decompiler_block_add_error (ViviDecompilerBlock *block,
   s = g_strdup_vprintf (format, varargs);
   va_end (varargs);
 
-  token = vivi_code_comment_new (s);
+  stmt = vivi_code_comment_new (s);
   g_printerr ("ERROR: %s\n", s);
   g_free (s);
-  vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), VIVI_CODE_STATEMENT (token));
+  vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), stmt);
   vivi_decompiler_block_finish (block, state);
 }
 
@@ -218,7 +218,7 @@ void
 vivi_decompiler_block_add_warning (ViviDecompilerBlock *block,
     const char *format, ...)
 {
-  ViviCodeToken *token;
+  ViviCodeStatement *stmt;
   va_list varargs;
   char *s;
 
@@ -226,10 +226,10 @@ vivi_decompiler_block_add_warning (ViviDecompilerBlock *block,
   s = g_strdup_vprintf (format, varargs);
   va_end (varargs);
 
-  token = vivi_code_comment_new (s);
+  stmt = vivi_code_comment_new (s);
   g_printerr ("WARNING: %s\n", s);
   g_free (s);
-  vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), VIVI_CODE_STATEMENT (token));
+  vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), stmt);
 }
 
 const guint8 *
commit c194e7719765a70de385f6ebdbb0eff858fc2fdd
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 17 21:45:50 2008 +0200

    make emission cause errors and add a push asm statement

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index 5819543..95dc95b 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -20,6 +20,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_asm.c \
 	vivi_code_asm_code.c \
 	vivi_code_asm_code_default.c \
+	vivi_code_asm_push.c \
 	vivi_code_assembler.c \
 	vivi_code_assignment.c \
 	vivi_code_binary.c \
@@ -40,6 +41,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_constant.c \
 	vivi_code_continue.c \
 	vivi_code_emitter.c \
+	vivi_code_error.c \
 	vivi_code_function.c \
 	vivi_code_function_call.c \
 	vivi_code_get.c \
@@ -82,6 +84,7 @@ noinst_HEADERS = \
 	vivi_code_asm.h \
 	vivi_code_asm_code.h \
 	vivi_code_asm_code_default.h \
+	vivi_code_asm_push.h \
 	vivi_code_assembler.h \
 	vivi_code_assignment.h \
 	vivi_code_binary.h \
@@ -103,6 +106,7 @@ noinst_HEADERS = \
 	vivi_code_continue.h \
 	vivi_code_defaults.h \
 	vivi_code_emitter.h \
+	vivi_code_error.h \
 	vivi_code_function.h \
 	vivi_code_function_call.h \
 	vivi_code_get.h \
diff --git a/vivified/code/vivi_code_asm.h b/vivified/code/vivi_code_asm.h
index cc7465d..d50fffa 100644
--- a/vivified/code/vivi_code_asm.h
+++ b/vivified/code/vivi_code_asm.h
@@ -39,8 +39,9 @@ typedef struct _ViviCodeAsmInterface ViviCodeAsmInterface;
 struct _ViviCodeAsmInterface {
   GTypeInterface	interface;
 
-  void			(* emit)			(ViviCodeAsm *		code,
-							 ViviCodeEmitter *	emitter);
+  gboolean		(* emit)			(ViviCodeAsm *		code,
+							 ViviCodeEmitter *	emitter,
+							 GError **		error);
 };
 
 GType			vivi_code_asm_get_type		(void) G_GNUC_CONST;
diff --git a/vivified/code/vivi_code_asm_push.c b/vivified/code/vivi_code_asm_push.c
new file mode 100644
index 0000000..6d20c38
--- /dev/null
+++ b/vivified/code/vivi_code_asm_push.c
@@ -0,0 +1,211 @@
+/* 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 <swfdec/swfdec_as_interpret.h>
+
+#include "vivi_code_asm_push.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_push_emit (ViviCodeAsm *code, ViviCodeEmitter *emitter, GError **error)
+{
+  ViviCodeAsmPush *push = VIVI_CODE_ASM_PUSH (code);
+  SwfdecBots *emit = vivi_code_emitter_get_bots (emitter);
+  gsize len;
+
+  len = swfdec_bots_get_bytes (push->contents);
+  if (len > G_MAXUINT16) {
+    g_set_error (error, VIVI_CODE_ERROR, VIVI_CODE_ERROR_SIZE,
+	"Push action too big");
+    return FALSE;
+  }
+  swfdec_bots_put_u8 (emit, SWFDEC_AS_ACTION_PUSH);
+  swfdec_bots_put_u16 (emit, len);
+  swfdec_bots_put_bots (emit, push->contents);
+  return TRUE;
+}
+
+static void
+vivi_code_asm_push_asm_init (ViviCodeAsmInterface *iface)
+{
+  iface->emit = vivi_code_asm_push_emit;
+}
+
+G_DEFINE_TYPE_WITH_CODE (ViviCodeAsmPush, vivi_code_asm_push, VIVI_TYPE_CODE_ASM_PUSH,
+    G_IMPLEMENT_INTERFACE (VIVI_TYPE_CODE_ASM, vivi_code_asm_push_asm_init))
+
+static void
+vivi_code_asm_push_dispose (GObject *object)
+{
+  ViviCodeAsmPush *push = VIVI_CODE_ASM_PUSH (object);
+
+  swfdec_bots_free (push->contents);
+  g_ptr_array_free (push->offsets, TRUE);
+
+  G_OBJECT_CLASS (vivi_code_asm_push_parent_class)->dispose (object);
+}
+
+static void
+vivi_code_asm_push_class_init (ViviCodeAsmPushClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = vivi_code_asm_push_dispose;
+}
+
+static void
+vivi_code_asm_push_init (ViviCodeAsmPush *push)
+{
+  push->contents = swfdec_bots_open ();
+  push->offsets = g_ptr_array_new ();
+}
+
+ViviCodeAsm *
+vivi_code_asm_push_new (void)
+{
+  return g_object_new (VIVI_TYPE_CODE_ASM_PUSH, NULL);
+}
+
+guint
+vivi_code_asm_push_get_n_values (ViviCodeAsmPush *push)
+{
+  g_return_val_if_fail (VIVI_IS_CODE_ASM_PUSH (push), 0);
+  
+  return push->offsets->len;
+}
+
+ViviCodeConstantType
+vivi_code_asm_push_get_value_type (ViviCodeAsmPush *push, guint i)
+{
+  g_return_val_if_fail (VIVI_IS_CODE_ASM_PUSH (push), 0);
+  g_return_val_if_fail (i < push->offsets->len, 0);
+
+  return push->contents->ptr[GPOINTER_TO_SIZE (g_ptr_array_index (push->offsets, i))];
+}
+
+void
+vivi_code_asm_push_add_string (ViviCodeAsmPush *push, const char *string)
+{
+  g_return_if_fail (VIVI_IS_CODE_ASM_PUSH (push));
+  g_return_if_fail (string != NULL);
+
+  g_ptr_array_add (push->offsets, GSIZE_TO_POINTER (swfdec_bots_get_bytes (push->contents)));
+  swfdec_bots_put_u8 (push->contents, VIVI_CODE_CONSTANT_STRING);
+  swfdec_bots_put_string (push->contents, string);
+}
+
+void
+vivi_code_asm_push_add_float (ViviCodeAsmPush *push, float f)
+{
+  g_return_if_fail (VIVI_IS_CODE_ASM_PUSH (push));
+
+  g_ptr_array_add (push->offsets, GSIZE_TO_POINTER (swfdec_bots_get_bytes (push->contents)));
+  swfdec_bots_put_u8 (push->contents, VIVI_CODE_CONSTANT_FLOAT);
+  swfdec_bots_put_float (push->contents, f);
+}
+
+void
+vivi_code_asm_push_add_null (ViviCodeAsmPush *push)
+{
+  g_return_if_fail (VIVI_IS_CODE_ASM_PUSH (push));
+
+  g_ptr_array_add (push->offsets, GSIZE_TO_POINTER (swfdec_bots_get_bytes (push->contents)));
+  swfdec_bots_put_u8 (push->contents, VIVI_CODE_CONSTANT_NULL);
+}
+
+void
+vivi_code_asm_push_add_undefined (ViviCodeAsmPush *push)
+{
+  g_return_if_fail (VIVI_IS_CODE_ASM_PUSH (push));
+
+  g_ptr_array_add (push->offsets, GSIZE_TO_POINTER (swfdec_bots_get_bytes (push->contents)));
+  swfdec_bots_put_u8 (push->contents, VIVI_CODE_CONSTANT_UNDEFINED);
+}
+
+void
+vivi_code_asm_push_add_register (ViviCodeAsmPush *push, guint id)
+{
+  g_return_if_fail (VIVI_IS_CODE_ASM_PUSH (push));
+  g_return_if_fail (id < 256);
+
+  g_ptr_array_add (push->offsets, GSIZE_TO_POINTER (swfdec_bots_get_bytes (push->contents)));
+  swfdec_bots_put_u8 (push->contents, VIVI_CODE_CONSTANT_REGISTER);
+  swfdec_bots_put_u8 (push->contents, id);
+}
+
+void
+vivi_code_asm_push_add_boolean (ViviCodeAsmPush *push, gboolean b)
+{
+  g_return_if_fail (VIVI_IS_CODE_ASM_PUSH (push));
+
+  g_ptr_array_add (push->offsets, GSIZE_TO_POINTER (swfdec_bots_get_bytes (push->contents)));
+  swfdec_bots_put_u8 (push->contents, VIVI_CODE_CONSTANT_BOOLEAN);
+  swfdec_bots_put_u8 (push->contents, b ? 1 : 0);
+}
+
+void
+vivi_code_asm_push_add_double (ViviCodeAsmPush *push, double d)
+{
+  g_return_if_fail (VIVI_IS_CODE_ASM_PUSH (push));
+
+  g_ptr_array_add (push->offsets, GSIZE_TO_POINTER (swfdec_bots_get_bytes (push->contents)));
+  swfdec_bots_put_u8 (push->contents, VIVI_CODE_CONSTANT_DOUBLE);
+  swfdec_bots_put_double (push->contents, d);
+}
+
+void
+vivi_code_asm_push_add_integer (ViviCodeAsmPush *push, int i)
+{
+  g_return_if_fail (VIVI_IS_CODE_ASM_PUSH (push));
+  g_return_if_fail (i >= G_MININT32 && i <= G_MAXINT32);
+
+  g_ptr_array_add (push->offsets, GSIZE_TO_POINTER (swfdec_bots_get_bytes (push->contents)));
+  swfdec_bots_put_u8 (push->contents, VIVI_CODE_CONSTANT_INTEGER);
+  swfdec_bots_put_u32 (push->contents, i);
+}
+
+void
+vivi_code_asm_push_add_pool (ViviCodeAsmPush *push, guint id)
+{
+  g_return_if_fail (VIVI_IS_CODE_ASM_PUSH (push));
+  g_return_if_fail (id < 256);
+
+  g_ptr_array_add (push->offsets, GSIZE_TO_POINTER (swfdec_bots_get_bytes (push->contents)));
+  swfdec_bots_put_u8 (push->contents, VIVI_CODE_CONSTANT_CONSTANT_POOL);
+  swfdec_bots_put_u8 (push->contents, id);
+}
+
+void
+vivi_code_asm_push_add_pool_big (ViviCodeAsmPush *push, guint id)
+{
+  g_return_if_fail (VIVI_IS_CODE_ASM_PUSH (push));
+  g_return_if_fail (id <= G_MAXUINT16);
+
+  g_ptr_array_add (push->offsets, GSIZE_TO_POINTER (swfdec_bots_get_bytes (push->contents)));
+  swfdec_bots_put_u8 (push->contents, VIVI_CODE_CONSTANT_CONSTANT_POOL_BIG);
+  swfdec_bots_put_u16 (push->contents, id);
+}
+
diff --git a/vivified/code/vivi_code_asm_push.h b/vivified/code/vivi_code_asm_push.h
new file mode 100644
index 0000000..194a9f3
--- /dev/null
+++ b/vivified/code/vivi_code_asm_push.h
@@ -0,0 +1,102 @@
+/* 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_PUSH_H_
+#define _VIVI_CODE_ASM_PUSH_H_
+
+#include <swfdec/swfdec_bots.h>
+#include <vivified/code/vivi_code_asm.h>
+#include <vivified/code/vivi_code_asm_code.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+  VIVI_CODE_CONSTANT_STRING = 0,
+  VIVI_CODE_CONSTANT_FLOAT = 1,
+  VIVI_CODE_CONSTANT_NULL = 2,
+  VIVI_CODE_CONSTANT_UNDEFINED = 3,
+  VIVI_CODE_CONSTANT_REGISTER = 4,
+  VIVI_CODE_CONSTANT_BOOLEAN = 5,
+  VIVI_CODE_CONSTANT_DOUBLE = 6,
+  VIVI_CODE_CONSTANT_INTEGER = 7,
+  VIVI_CODE_CONSTANT_CONSTANT_POOL = 8,
+  VIVI_CODE_CONSTANT_CONSTANT_POOL_BIG = 9
+} ViviCodeConstantType;
+
+typedef struct _ViviCodeAsmPush ViviCodeAsmPush;
+typedef struct _ViviCodeAsmPushClass ViviCodeAsmPushClass;
+
+#define VIVI_TYPE_CODE_ASM_PUSH                    (vivi_code_asm_push_get_type())
+#define VIVI_IS_CODE_ASM_PUSH(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_ASM_PUSH))
+#define VIVI_IS_CODE_ASM_PUSH_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_ASM_PUSH))
+#define VIVI_CODE_ASM_PUSH(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_ASM_PUSH, ViviCodeAsmPush))
+#define VIVI_CODE_ASM_PUSH_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_ASM_PUSH, ViviCodeAsmPushClass))
+#define VIVI_CODE_ASM_PUSH_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_ASM_PUSH, ViviCodeAsmPushClass))
+
+struct _ViviCodeAsmPush
+{
+  ViviCodeAsmCode	code;
+
+  SwfdecBots *		contents;
+  GPtrArray *		offsets;
+};
+
+struct _ViviCodeAsmPushClass
+{
+  ViviCodeAsmCodeClass	code_class;
+};
+
+GType			vivi_code_asm_push_get_type	  	(void);
+
+ViviCodeAsm *		vivi_code_asm_push_new			(void);
+
+guint			vivi_code_asm_push_get_n_values		(ViviCodeAsmPush *	push);
+ViviCodeConstantType	vivi_code_asm_push_get_value_type     	(ViviCodeAsmPush *	push,
+								 guint			i);
+const char *		vivi_code_asm_push_get_string		(ViviCodeAsmPush *	push,
+								 guint			i);
+double			vivi_code_asm_push_get_number		(ViviCodeAsmPush *	push,
+								 guint			i);
+int			vivi_code_asm_push_get_integer		(ViviCodeAsmPush *	push,
+								 guint			i);
+int			vivi_code_asm_push_get_boolean		(ViviCodeAsmPush *	push,
+								 guint			i);
+
+void			vivi_code_asm_push_add_string		(ViviCodeAsmPush *	push,
+								 const char *		string);
+void			vivi_code_asm_push_add_float		(ViviCodeAsmPush *	push,
+								 float			f);
+void			vivi_code_asm_push_add_null		(ViviCodeAsmPush *	push);
+void			vivi_code_asm_push_add_undefined	(ViviCodeAsmPush *	push);
+void			vivi_code_asm_push_add_register		(ViviCodeAsmPush *	push,
+								 guint			id);
+void			vivi_code_asm_push_add_boolean		(ViviCodeAsmPush *	push,
+								 gboolean		b);
+void			vivi_code_asm_push_add_double		(ViviCodeAsmPush *	push,
+								 double			d);
+void			vivi_code_asm_push_add_integer		(ViviCodeAsmPush *	push,
+								 int			i);
+void			vivi_code_asm_push_add_pool		(ViviCodeAsmPush *	push,
+								 guint			id);
+void			vivi_code_asm_push_add_pool_big		(ViviCodeAsmPush *	push,
+								 guint			id);
+
+
+G_END_DECLS
+#endif
diff --git a/vivified/code/vivi_code_emitter.c b/vivified/code/vivi_code_emitter.c
index e73cd57..21750a5 100644
--- a/vivified/code/vivi_code_emitter.c
+++ b/vivified/code/vivi_code_emitter.c
@@ -60,16 +60,16 @@ vivi_code_emitter_init (ViviCodeEmitter *emit)
       g_object_unref, g_free);
 }
 
-void
-vivi_code_emitter_emit_asm (ViviCodeEmitter *emitter, ViviCodeAsm *code)
+gboolean
+vivi_code_emitter_emit_asm (ViviCodeEmitter *emitter, ViviCodeAsm *code, GError **error)
 {
   ViviCodeAsmInterface *iface;
 
-  g_return_if_fail (VIVI_IS_CODE_EMITTER (emitter));
-  g_return_if_fail (VIVI_IS_CODE_ASM (code));
+  g_return_val_if_fail (VIVI_IS_CODE_EMITTER (emitter), FALSE);
+  g_return_val_if_fail (VIVI_IS_CODE_ASM (code), FALSE);
 
   iface = VIVI_CODE_ASM_GET_INTERFACE (code);
-  iface->emit (code, emitter);
+  return iface->emit (code, emitter, error);
 }
 
 void
diff --git a/vivified/code/vivi_code_emitter.h b/vivified/code/vivi_code_emitter.h
index 03c2fe4..baf0765 100644
--- a/vivified/code/vivi_code_emitter.h
+++ b/vivified/code/vivi_code_emitter.h
@@ -56,8 +56,9 @@ GType			vivi_code_emitter_get_type   	(void);
 
 ViviCodeEmitter *	vivi_code_emitter_new		(void);
 
-void			vivi_code_emitter_emit_asm	(ViviCodeEmitter *	emitter,
-							 ViviCodeAsm *		code);
+gboolean		vivi_code_emitter_emit_asm	(ViviCodeEmitter *	emitter,
+							 ViviCodeAsm *		code,
+							 GError **		error);
 
 SwfdecBots *		vivi_code_emitter_get_bots	(ViviCodeEmitter *	emitter);
 void			vivi_code_emitter_add_label	(ViviCodeEmitter *	emitter,
diff --git a/vivified/code/vivi_code_error.c b/vivified/code/vivi_code_error.c
new file mode 100644
index 0000000..3f5ad39
--- /dev/null
+++ b/vivified/code/vivi_code_error.c
@@ -0,0 +1,30 @@
+/* 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 "vivi_code_error.h"
+
+GQuark
+vivi_code_error_quark (void)
+{
+  return g_quark_from_static_string ("g-io-channel-error-quark");
+}
diff --git a/vivified/code/vivi_code_error.h b/vivified/code/vivi_code_error.h
new file mode 100644
index 0000000..854bad8
--- /dev/null
+++ b/vivified/code/vivi_code_error.h
@@ -0,0 +1,36 @@
+/* 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_ERROR_H_
+#define _VIVI_CODE_ERROR_H_
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define VIVI_CODE_ERROR (vivi_code_error_quark())
+
+typedef enum {
+  VIVI_CODE_ERROR_SIZE
+} ViviCodeError;
+
+GQuark		vivi_code_error_quark	(void);
+
+G_END_DECLS
+#endif
commit 887c156148c5cb382a87afb4e4edf3ba5fd908e4
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 17 21:43:12 2008 +0200

    add swfdec_bots_put_float() (untested)

diff --git a/swfdec/swfdec_bots.c b/swfdec/swfdec_bots.c
index 11352e2..0bdf16e 100644
--- a/swfdec/swfdec_bots.c
+++ b/swfdec/swfdec_bots.c
@@ -260,7 +260,21 @@ swfdec_bots_put_string (SwfdecBots *bots, const char *s)
   bots->ptr += len;
 }
 
- /* If little endian x86 byte order is 0 1 2 3 4 5 6 7 and PPC32 byte order is
+void
+swfdec_bots_put_float (SwfdecBots *bots, float f)
+{
+  union {
+    guint32 i;
+    float f;
+  } conv;
+
+  g_return_if_fail (bots != NULL);
+
+  conv.f = f;
+  swfdec_bots_put_u32 (bots, conv.i);
+}
+
+/* If little endian x86 byte order is 0 1 2 3 4 5 6 7 and PPC32 byte order is
  * 7 6 5 4 3 2 1 0, then Flash uses 4 5 6 7 0 1 2 3. */
 void
 swfdec_bots_put_double (SwfdecBots *bots, double value)
diff --git a/swfdec/swfdec_bots.h b/swfdec/swfdec_bots.h
index 0472a74..809477a 100644
--- a/swfdec/swfdec_bots.h
+++ b/swfdec/swfdec_bots.h
@@ -78,6 +78,8 @@ void		swfdec_bots_put_string		(SwfdecBots *		bots,
 						 const char *		s);
 void		swfdec_bots_put_double		(SwfdecBots *		bots,
 						 double			value);
+void		swfdec_bots_put_float		(SwfdecBots *		bots,
+						 float			f);
 
 void		swfdec_bots_put_rgb		(SwfdecBots *		bots,
 						 SwfdecColor		color);
commit bf1c92dd50aa97868a23d522660811a2998923b6
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 17 20:14:46 2008 +0200

    add swfdec_bots_free()
    
    Sometimes I don't want a buffer

diff --git a/swfdec/swfdec_bots.c b/swfdec/swfdec_bots.c
index cc5eb2c..11352e2 100644
--- a/swfdec/swfdec_bots.c
+++ b/swfdec/swfdec_bots.c
@@ -64,6 +64,15 @@ swfdec_bots_close (SwfdecBots *bots)
   return buffer;
 }
 
+void
+swfdec_bots_free (SwfdecBots *bots)
+{
+  g_return_if_fail (bots != NULL);
+
+  g_free (bots->data);
+  g_free (bots);
+}
+
 gsize
 swfdec_bots_get_bits (SwfdecBots *bots)
 {
diff --git a/swfdec/swfdec_bots.h b/swfdec/swfdec_bots.h
index 4af6f19..0472a74 100644
--- a/swfdec/swfdec_bots.h
+++ b/swfdec/swfdec_bots.h
@@ -39,8 +39,9 @@ struct _SwfdecBots {
 #define SWFDEC_OUT_INITIAL (32)
 #define SWFDEC_OUT_STEP (32)
 
-SwfdecBots *	swfdec_bots_open			(void);
+SwfdecBots *	swfdec_bots_open		(void);
 SwfdecBuffer *	swfdec_bots_close		(SwfdecBots *		bots);
+void		swfdec_bots_free		(SwfdecBots *		bots);
 
 gsize		swfdec_bots_get_bits		(SwfdecBots *		bots);
 gsize		swfdec_bots_get_bytes		(SwfdecBots *		bots);


More information about the Swfdec-commits mailing list