add blend mode tests
[swfdec.git] / swfdec / swfdec_script.c
blobeefd66cec389956841db4b9090910551dc04dde3
1 /* Swfdec
2 * Copyright (C) 2007 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include "swfdec_script.h"
25 #include "swfdec_script_internal.h"
26 #include "swfdec_as_context.h"
27 #include "swfdec_as_interpret.h"
28 #include "swfdec_debug.h"
30 /**
31 * SwfdecScript:
33 * This is the object used for code to be executed by Swfdec. Scripts are
34 * independant from the #SwfdecAsContext they are executed in, so you can
35 * execute the same script in multiple contexts.
38 /* Define this to get SWFDEC_WARN'd about missing properties of objects.
39 * This can be useful to find out about unimplemented native properties,
40 * but usually just causes a lot of spam. */
41 //#define SWFDEC_WARN_MISSING_PROPERTIES
43 /*** SUPPORT FUNCTIONS ***/
45 static gboolean
46 swfdec_script_foreach_internal (SwfdecBits *bits, SwfdecScriptForeachFunc func, gpointer user_data)
48 guint action, len;
49 const guint8 *data;
50 gconstpointer bytecode;
52 bytecode = bits->ptr;
53 while (swfdec_bits_left (bits) && (action = swfdec_bits_get_u8 (bits))) {
54 if (action & 0x80) {
55 len = swfdec_bits_get_u16 (bits);
56 data = bits->ptr;
57 } else {
58 len = 0;
59 data = NULL;
61 if (swfdec_bits_skip_bytes (bits, len) != len) {
62 SWFDEC_ERROR ("script too short");
63 return FALSE;
65 if (!func (bytecode, action, data, len, user_data))
66 return FALSE;
67 bytecode = bits->ptr;
69 return TRUE;
72 static gboolean
73 validate_action (gconstpointer bytecode, guint action, const guint8 *data, guint len, gpointer scriptp)
75 // TODO: get rid of this function
76 return TRUE;
79 /*** PUBLIC API ***/
81 gboolean
82 swfdec_script_foreach (SwfdecScript *script, SwfdecScriptForeachFunc func, gpointer user_data)
84 SwfdecBits bits;
86 g_return_val_if_fail (script != NULL, FALSE);
87 g_return_val_if_fail (func != NULL, FALSE);
89 swfdec_bits_init (&bits, script->buffer);
90 bits.ptr = script->main;
91 return swfdec_script_foreach_internal (&bits, func, user_data);
94 /**
95 * swfdec_script_new:
96 * @buffer: the #SwfdecBuffer containing the script. This function will take
97 * ownership of the passed in buffer.
98 * @name: name of the script for debugging purposes
99 * @version: Actionscript version to use in this script
101 * Creates a new script for the actionscript provided in @buffer.
103 * Returns: a new #SwfdecScript for executing the script in @buffer.
105 SwfdecScript *
106 swfdec_script_new (SwfdecBuffer *buffer, const char *name, guint version)
108 SwfdecBits bits;
109 SwfdecScript *script;
111 g_return_val_if_fail (buffer != NULL, NULL);
113 swfdec_bits_init (&bits, buffer);
114 script = swfdec_script_new_from_bits (&bits, name, version);
115 swfdec_buffer_unref (buffer);
116 return script;
119 SwfdecScript *
120 swfdec_script_new_from_bits (SwfdecBits *bits, const char *name, guint version)
122 SwfdecScript *script;
123 SwfdecBuffer *buffer;
124 SwfdecBits org;
125 guint len;
127 g_return_val_if_fail (bits != NULL, NULL);
129 org = *bits;
130 len = swfdec_bits_left (bits) / 8;
131 script = g_new0 (SwfdecScript, 1);
132 script->refcount = 1;
133 script->name = g_strdup (name ? name : "Unnamed script");
134 script->version = version;
135 /* by default, a function has 4 registers */
136 script->n_registers = 5;
137 /* These flags are the default arguments used by scripts read from a file.
138 * DefineFunction and friends override this */
139 script->flags = SWFDEC_SCRIPT_SUPPRESS_ARGS;
141 if (!swfdec_script_foreach_internal (bits, validate_action, script)) {
142 swfdec_script_unref (script);
143 return NULL;
145 len -= swfdec_bits_left (bits) / 8;
146 if (len == 0) {
147 buffer = swfdec_buffer_new (0);
148 } else {
149 buffer = swfdec_bits_get_buffer (&org, len);
152 script->main = buffer->data;
153 script->exit = buffer->data + buffer->length;
154 script->buffer = swfdec_buffer_ref (swfdec_buffer_get_super (buffer));
155 swfdec_buffer_unref (buffer);
156 return script;
160 * swfdec_script_ref:
161 * @script: a script
163 * Increases the reference count of the given @script by one.
165 * Returns: The @script given as an argument
167 SwfdecScript *
168 swfdec_script_ref (SwfdecScript *script)
170 g_return_val_if_fail (script != NULL, NULL);
171 g_return_val_if_fail (script->refcount > 0, NULL);
173 script->refcount++;
174 return script;
178 * swfdec_script_unref:
179 * @script: a script
181 * Decreases the reference count of the given @script by one. If the count
182 * reaches zero, it will automatically be destroyed.
184 void
185 swfdec_script_unref (SwfdecScript *script)
187 guint i;
189 g_return_if_fail (script != NULL);
190 g_return_if_fail (script->refcount > 0);
192 script->refcount--;
193 if (script->refcount > 0)
194 return;
196 if (script->buffer)
197 swfdec_buffer_unref (script->buffer);
198 if (script->constant_pool)
199 swfdec_buffer_unref (script->constant_pool);
200 g_free (script->name);
201 for (i = 0; i < script->n_arguments; i++) {
202 g_free (script->arguments[i].name);
204 g_free (script->arguments);
205 g_free (script);
209 * swfdec_script_get_version:
210 * @script: the script
212 * Queries the Flash version this script was compiled with. Different versions
213 * result in slightly different behavior in the script interpreter.
215 * Returns: The Flash version this script conforms to
217 guint
218 swfdec_script_get_version (SwfdecScript *script)
220 g_return_val_if_fail (script != NULL, 0);
222 return script->version;
225 /*** UTILITY FUNCTIONS ***/
227 const char *
228 swfdec_action_get_name (guint action)
230 g_return_val_if_fail (action < 256, NULL);
232 return swfdec_as_actions[action].name;
235 guint
236 swfdec_action_get_from_name (const char *name)
238 guint i;
240 g_return_val_if_fail (name != NULL, 0);
242 for (i = 0; i < 256; i++) {
243 if (swfdec_as_actions[i].name && g_str_equal (name, swfdec_as_actions[i].name))
244 return i;
246 return 0;