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.
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
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"
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 ***/
46 swfdec_script_foreach_internal (SwfdecBits
*bits
, SwfdecScriptForeachFunc func
, gpointer user_data
)
50 gconstpointer bytecode
;
53 while (swfdec_bits_left (bits
) && (action
= swfdec_bits_get_u8 (bits
))) {
55 len
= swfdec_bits_get_u16 (bits
);
61 if (swfdec_bits_skip_bytes (bits
, len
) != len
) {
62 SWFDEC_ERROR ("script too short");
65 if (!func (bytecode
, action
, data
, len
, user_data
))
73 validate_action (gconstpointer bytecode
, guint action
, const guint8
*data
, guint len
, gpointer scriptp
)
75 // TODO: get rid of this function
82 swfdec_script_foreach (SwfdecScript
*script
, SwfdecScriptForeachFunc func
, gpointer user_data
)
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
);
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.
106 swfdec_script_new (SwfdecBuffer
*buffer
, const char *name
, guint version
)
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
);
120 swfdec_script_new_from_bits (SwfdecBits
*bits
, const char *name
, guint version
)
122 SwfdecScript
*script
;
123 SwfdecBuffer
*buffer
;
127 g_return_val_if_fail (bits
!= NULL
, NULL
);
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
);
145 len
-= swfdec_bits_left (bits
) / 8;
147 buffer
= swfdec_buffer_new (0);
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
);
163 * Increases the reference count of the given @script by one.
165 * Returns: The @script given as an argument
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
);
178 * swfdec_script_unref:
181 * Decreases the reference count of the given @script by one. If the count
182 * reaches zero, it will automatically be destroyed.
185 swfdec_script_unref (SwfdecScript
*script
)
189 g_return_if_fail (script
!= NULL
);
190 g_return_if_fail (script
->refcount
> 0);
193 if (script
->refcount
> 0)
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
);
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
218 swfdec_script_get_version (SwfdecScript
*script
)
220 g_return_val_if_fail (script
!= NULL
, 0);
222 return script
->version
;
225 /*** UTILITY FUNCTIONS ***/
228 swfdec_action_get_name (guint action
)
230 g_return_val_if_fail (action
< 256, NULL
);
232 return swfdec_as_actions
[action
].name
;
236 swfdec_action_get_from_name (const char *name
)
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
))