Benjamin Otte
2007-Mar-29 04:33 UTC
[Swfdec] Branch 'as' - 9 commits - configure.ac doc/swfdec-sections.txt libswfdec/Makefile.am libswfdec/swfdec_as_context.c libswfdec/swfdec_as_context.h libswfdec/swfdec_as_frame.c libswfdec/swfdec_as_frame.h libswfdec/swfdec_as_stack.c libswfdec/swfdec_as_stack.h libswfdec/swfdec_as_types.h libswfdec/swfdec_buffer.c libswfdec/swfdec_buffer.h libswfdec/swfdec_codec_adpcm.c libswfdec/swfdec_codec_ffmpeg.c libswfdec/swfdec_codec_mad.c libswfdec/swfdec_loader.c libswfdec/swfdec_script.c libswfdec/swfdec_script.h libswfdec/swfdec_sound.c libswfdec/swfdec_swf_decoder.c test/sound test/swfdec-extract.c test/swfedit_file.c
configure.ac | 7 +- doc/swfdec-sections.txt | 10 +++- libswfdec/Makefile.am | 2 libswfdec/swfdec_as_context.c | 82 ++++++++++++++++++++++----------- libswfdec/swfdec_as_context.h | 2 libswfdec/swfdec_as_frame.c | 10 ++++ libswfdec/swfdec_as_frame.h | 3 - libswfdec/swfdec_as_stack.c | 98 +++++++++++++++++++++++++++++++++++++++ libswfdec/swfdec_as_stack.h | 53 +++++++++++++++++++++ libswfdec/swfdec_as_types.h | 99 ++++++++++++++++++++++++++++++++++++++++ libswfdec/swfdec_buffer.c | 95 ++++++++++++++++++++++++++++++++++---- libswfdec/swfdec_buffer.h | 16 +++++- libswfdec/swfdec_codec_adpcm.c | 2 libswfdec/swfdec_codec_ffmpeg.c | 6 +- libswfdec/swfdec_codec_mad.c | 2 libswfdec/swfdec_loader.c | 2 libswfdec/swfdec_script.c | 6 +- libswfdec/swfdec_script.h | 2 libswfdec/swfdec_sound.c | 2 libswfdec/swfdec_swf_decoder.c | 2 test/sound/sound.c | 2 test/swfdec-extract.c | 4 - test/swfedit_file.c | 2 23 files changed, 450 insertions(+), 59 deletions(-) New commits: diff-tree a3edf76ea058a63d1ef650cf5f57eeb37b893f3a (from 16ba0d96c6f4b6a8624390ea073f4e19a66cd8d9) Author: Benjamin Otte <otte@gnome.org> Date: Thu Mar 29 13:34:07 2007 +0200 implement swfdec_context_as_return diff --git a/libswfdec/swfdec_as_context.c b/libswfdec/swfdec_as_context.c index 0de1748..cbbc378 100644 --- a/libswfdec/swfdec_as_context.c +++ b/libswfdec/swfdec_as_context.c @@ -325,10 +325,14 @@ start: startpc = script->buffer->data; endpc = startpc + script->buffer->length; - while (pc != endpc) { + while (TRUE) { + if (pc == endpc) { + swfdec_as_context_return (context, NULL); + goto start; + } if (pc < startpc || pc >= endpc) { SWFDEC_ERROR ("pc %p not in valid range [%p, %p) anymore", pc, startpc, endpc); - goto internal_error; + goto error; } /* decode next action */ @@ -339,13 +343,13 @@ start: if (action & 0x80) { if (pc + 2 >= endpc) { SWFDEC_ERROR ("action %u length value out of range", action); - goto internal_error; + goto error; } data = pc + 3; len = pc[1] | pc[2] << 8; if (data + len > endpc) { SWFDEC_ERROR ("action %u length %u out of range", action, len); - goto internal_error; + goto error; } nextpc = pc + 3 + len; } else { @@ -357,7 +361,7 @@ start: if (spec->exec[version] == NULL) { SWFDEC_ERROR ("cannot interpret action %u %s for version %u", action, spec->name ? spec->name : "Unknown", script->version); - goto internal_error; + goto error; } if (spec->remove > 0) { swfdec_as_stack_ensure_size (stack, spec->remove); @@ -368,7 +372,7 @@ start: swfdec_as_stack_ensure_left (stack, spec->add); } if (context->state != SWFDEC_AS_CONTEXT_RUNNING) - break; + goto error; #ifndef G_DISABLE_ASSERT check = (spec->add >= 0 && spec->remove >= 0) ? stack->cur + spec->add - spec->remove : NULL; #endif @@ -393,7 +397,23 @@ start: } } -internal_error: +error: return; } +void +swfdec_as_context_return (SwfdecAsContext *context, SwfdecAsValue *retval) +{ + g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context)); + g_return_if_fail (context->frame != NULL); + g_return_if_fail (retval == NULL || SWFDEC_IS_AS_VALUE (retval)); + + context->frame = context->frame->next; + swfdec_as_stack_ensure_left (context->frame->stack, 1); + if (retval) { + swfdec_as_stack_push (context->frame->stack, retval); + } else { + SwfdecAsValue value = { SWFDEC_TYPE_AS_UNDEFINED, }; + swfdec_as_stack_push (context->frame->stack, &value); + } +} diff --git a/libswfdec/swfdec_as_context.h b/libswfdec/swfdec_as_context.h index 67e7ec2..420df04 100644 --- a/libswfdec/swfdec_as_context.h +++ b/libswfdec/swfdec_as_context.h @@ -82,6 +82,8 @@ void swfdec_as_value_mark (SwfdecAsVal void swfdec_as_string_mark (const char * string); void swfdec_as_context_gc (SwfdecAsContext * context); +void swfdec_as_context_return (SwfdecAsContext * context, + SwfdecAsValue * retval); G_END_DECLS #endif diff-tree 16ba0d96c6f4b6a8624390ea073f4e19a66cd8d9 (from b65aacea6f0606a3402f16fb2af36199e587ded0) Author: Benjamin Otte <otte@gnome.org> Date: Thu Mar 29 13:33:32 2007 +0200 make swfdec_as_stack_push work diff --git a/libswfdec/swfdec_as_stack.h b/libswfdec/swfdec_as_stack.h index 4792b33..c201e8a 100644 --- a/libswfdec/swfdec_as_stack.h +++ b/libswfdec/swfdec_as_stack.h @@ -40,7 +40,7 @@ void swfdec_as_stack_free (SwfdecAsSta #define swfdec_as_stack_peek(stack,n) (&(stack)->cur[-(gssize)(n)]) #define swfdec_as_stack_pop(stack) (--(stack)->cur) -#define swfdec_as_stack_push(stack,val) (*(stack)->cur++) +#define swfdec_as_stack_push(stack,val) (*(stack)->cur++ = *(val)) void swfdec_as_stack_mark (SwfdecAsStack * stack); void swfdec_as_stack_ensure_size (SwfdecAsStack * stack, diff-tree b65aacea6f0606a3402f16fb2af36199e587ded0 (from 147645d82919dbf900f8f7aafec62282550215ce) Author: Benjamin Otte <otte@gnome.org> Date: Thu Mar 29 13:33:06 2007 +0200 add a huge enum for all actions diff --git a/libswfdec/swfdec_as_types.h b/libswfdec/swfdec_as_types.h index c5df8a6..9a293a4 100644 --- a/libswfdec/swfdec_as_types.h +++ b/libswfdec/swfdec_as_types.h @@ -93,6 +93,104 @@ extern const char *swfdec_as_strings[]; #define SWFDEC_AS_STR_PROTO (swfdec_as_strings[1] + 1) #define SWFDEC_AS_STR_THIS (swfdec_as_strings[2] + 1) +/* all existing actions */ +typedef enum { + SWFDEC_AS_ACTION_NEXT_FRAME = 0x04, + SWFDEC_AS_ACTION_PREVIOUS_FRAME = 0x05, + SWFDEC_AS_ACTION_PLAY = 0x06, + SWFDEC_AS_ACTION_STOP = 0x07, + SWFDEC_AS_ACTION_TOGGLE_QUALITY = 0x08, + SWFDEC_AS_ACTION_STOP_SOUNDS = 0x09, + SWFDEC_AS_ACTION_ADD = 0x0A, + SWFDEC_AS_ACTION_SUBTRACT = 0x0B, + SWFDEC_AS_ACTION_MULTIPLY = 0x0C, + SWFDEC_AS_ACTION_DIVIDE = 0x0D, + SWFDEC_AS_ACTION_EQUALS = 0x0E, + SWFDEC_AS_ACTION_LESS = 0x0F, + SWFDEC_AS_ACTION_AND = 0x10, + SWFDEC_AS_ACTION_OR = 0x11, + SWFDEC_AS_ACTION_NOT = 0x12, + SWFDEC_AS_ACTION_STRING_EQUALS = 0x13, + SWFDEC_AS_ACTION_STRING_LENGTH = 0x14, + SWFDEC_AS_ACTION_STRING_EXTRACT = 0x15, + SWFDEC_AS_ACTION_POP = 0x17, + SWFDEC_AS_ACTION_TO_INTEGER = 0x18, + SWFDEC_AS_ACTION_GET_VARIABLE = 0x1C, + SWFDEC_AS_ACTION_SET_VARIABLE = 0x1D, + SWFDEC_AS_ACTION_SET_TARGET2 = 0x20, + SWFDEC_AS_ACTION_STRING_ADD = 0x21, + SWFDEC_AS_ACTION_GET_PROPERTY = 0x22, + SWFDEC_AS_ACTION_SET_PROPERTY = 0x23, + SWFDEC_AS_ACTION_CLONE_SPRITE = 0x24, + SWFDEC_AS_ACTION_REMOVE_SPRITE = 0x25, + SWFDEC_AS_ACTION_TRACE = 0x26, + SWFDEC_AS_ACTION_START_DRAG = 0x27, + SWFDEC_AS_ACTION_END_DRAG = 0x28, + SWFDEC_AS_ACTION_STRING_LESS = 0x29, + SWFDEC_AS_ACTION_THROW = 0x2A, + SWFDEC_AS_ACTION_CAST = 0x2B, + SWFDEC_AS_ACTION_IMPLEMENTS = 0x2C, + SWFDEC_AS_ACTION_RANDOM = 0x30, + SWFDEC_AS_ACTION_MB_STRING_LENGTH = 0x31, + SWFDEC_AS_ACTION_CHAR_TO_ASCII = 0x32, + SWFDEC_AS_ACTION_ASCII_TO_CHAR = 0x33, + SWFDEC_AS_ACTION_DELETE = 0x3A, + SWFDEC_AS_ACTION_DELETE2 = 0x3B, + SWFDEC_AS_ACTION_DEFINE_LOCAL = 0x3C, + SWFDEC_AS_ACTION_CALL_FUNCTION = 0x3D, + SWFDEC_AS_ACTION_RETURN = 0x3E, + SWFDEC_AS_ACTION_MODULO = 0x3F, + SWFDEC_AS_ACTION_NEW_OBJECT = 0x40, + SWFDEC_AS_ACTION_DEFINE_LOCAL2 = 0x41, + SWFDEC_AS_ACTION_INIT_ARRAY = 0x42, + SWFDEC_AS_ACTION_INIT_OBJECT = 0x43, + SWFDEC_AS_ACTION_TYPE_OF = 0x44, + SWFDEC_AS_ACTION_TARGET_PATH = 0x45, + SWFDEC_AS_ACTION_ENUMERATE = 0x46, + SWFDEC_AS_ACTION_ADD2 = 0x47, + SWFDEC_AS_ACTION_LESS2 = 0x48, + SWFDEC_AS_ACTION_EQUALS2 = 0x49, + SWFDEC_AS_ACTION_TO_NUMBER = 0x4A, + SWFDEC_AS_ACTION_TO_STRING = 0x4B, + SWFDEC_AS_ACTION_PUSH_DUPLICATE = 0x4C, + SWFDEC_AS_ACTION_SWAP = 0x4D, + SWFDEC_AS_ACTION_GET_MEMBER = 0x4E, + SWFDEC_AS_ACTION_SET_MEMBER = 0x4F, + SWFDEC_AS_ACTION_INCREMENT = 0x50, + SWFDEC_AS_ACTION_DECREMENT = 0x51, + SWFDEC_AS_ACTION_CALL_METHOD = 0x52, + SWFDEC_AS_ACTION_NEW_METHOD = 0x53, + SWFDEC_AS_ACTION_INSTANCE_OF = 0x54, + SWFDEC_AS_ACTION_ENUMERATE2 = 0x55, + SWFDEC_AS_ACTION_BIT_AND = 0x60, + SWFDEC_AS_ACTION_BIT_OR = 0x61, + SWFDEC_AS_ACTION_BIT_XOR = 0x62, + SWFDEC_AS_ACTION_BIT_LSHIFT = 0x63, + SWFDEC_AS_ACTION_BIT_RSHIFT = 0x64, + SWFDEC_AS_ACTION_BIT_URSHIFT = 0x65, + SWFDEC_AS_ACTION_STRICT_EQUALS = 0x66, + SWFDEC_AS_ACTION_GREATER = 0x67, + SWFDEC_AS_ACTION_STRING_FREATER = 0x68, + SWFDEC_AS_ACTION_EXTENDS = 0x69, + SWFDEC_AS_ACTION_GOTO_FRAME = 0x81, + SWFDEC_AS_ACTION_GET_URL = 0x83, + SWFDEC_AS_ACTION_STORE_REGISTER = 0x87, + SWFDEC_AS_ACTION_CONSTANT_POOL = 0x88, + SWFDEC_AS_ACTION_WAIT_FOR_FRAME = 0x8A, + SWFDEC_AS_ACTION_SET_TARGET = 0x8B, + SWFDEC_AS_ACTION_GOTO_LABEL = 0x8C, + SWFDEC_AS_ACTION_WAIT_FOR_FRAME2 = 0x8D, + SWFDEC_AS_ACTION_DEFINE_FUNCTION2 = 0x8E, + SWFDEC_AS_ACTION_TRY = 0x8F, + SWFDEC_AS_ACTION_WITH = 0x94, + SWFDEC_AS_ACTION_PUSH = 0x96, + SWFDEC_AS_ACTION_JUMP = 0x99, + SWFDEC_AS_ACTION_GET_URL2 = 0x9A, + SWFDEC_AS_ACTION_DEFINE_FUNCTION = 0x9B, + SWFDEC_AS_ACTION_IF = 0x9D, + SWFDEC_AS_ACTION_CALL = 0x9E, + SWFDEC_AS_ACTION_GOTO_FRAME2 = 0x9F +} SwfdecAsAction; const char * swfdec_as_value_to_string (SwfdecAsContext * context, const SwfdecAsValue * value); diff-tree 147645d82919dbf900f8f7aafec62282550215ce (from 5cdfda32f8c6271deebd2977a0468d476961c22b) Author: Benjamin Otte <otte@gnome.org> Date: Thu Mar 29 09:18:34 2007 +0200 implement the stack diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am index 8bf4e50..dbcf847 100644 --- a/libswfdec/Makefile.am +++ b/libswfdec/Makefile.am @@ -19,6 +19,7 @@ libswfdec_@SWFDEC_MAJORMINOR@_la_SOURCES swfdec_as_context.c \ swfdec_as_frame.c \ swfdec_as_object.c \ + swfdec_as_stack.c \ swfdec_as_types.c \ swfdec_amf.c \ swfdec_audio.c \ @@ -113,6 +114,7 @@ noinst_HEADERS = \ swfdec_as_context.h \ swfdec_as_frame.h \ swfdec_as_object.h \ + swfdec_as_stack.h \ swfdec_as_types.h \ swfdec_amf.h \ swfdec_audio_internal.h \ diff --git a/libswfdec/swfdec_as_context.c b/libswfdec/swfdec_as_context.c index e9bdc80..0de1748 100644 --- a/libswfdec/swfdec_as_context.c +++ b/libswfdec/swfdec_as_context.c @@ -25,6 +25,7 @@ #include "swfdec_as_context.h" #include "swfdec_as_frame.h" #include "swfdec_as_object.h" +#include "swfdec_as_stack.h" #include "swfdec_as_types.h" #include "swfdec_debug.h" #include "swfdec_script.h" @@ -300,20 +301,26 @@ void swfdec_as_context_run (SwfdecAsContext *context) { SwfdecAsFrame *frame; + SwfdecAsStack *stack; SwfdecScript *script; const SwfdecActionSpec *spec; guint8 *startpc, *pc, *endpc, *nextpc; +#ifndef G_DISABLE_ASSERT + SwfdecAsValue *check; +#endif guint action, len; guint8 *data; int version; g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context)); +start: /* setup data */ frame = context->frame; if (frame == NULL) return; script = frame->script; + stack = frame->stack; version = EXTRACT_VERSION (script->version); startpc = script->buffer->data; endpc = startpc + script->buffer->length; @@ -352,35 +359,38 @@ swfdec_as_context_run (SwfdecAsContext * spec->name ? spec->name : "Unknown", script->version); goto internal_error; } -#if 0 if (spec->remove > 0) { - //!swfdec_script_ensure_stack (cx, spec->remove)) { - } - if (spec->add > 0 && - TRUE) { //fp->sp + spec->add - MAX (spec->remove, 0) > fp->spend) { - SWFDEC_ERROR ("FIXME: implement stack expansion, we got an overflow"); - goto internal_error; + swfdec_as_stack_ensure_size (stack, spec->remove); + if (spec->add > spec->remove) + swfdec_as_stack_ensure_left (stack, spec->add - spec->remove); + } else { + if (spec->add > 0) + swfdec_as_stack_ensure_left (stack, spec->add); } + if (context->state != SWFDEC_AS_CONTEXT_RUNNING) + break; #ifndef G_DISABLE_ASSERT - checksp = (spec->add >= 0 && spec->remove >= 0) ? fp->sp + spec->add - spec->remove : NULL; -#endif + check = (spec->add >= 0 && spec->remove >= 0) ? stack->cur + spec->add - spec->remove : NULL; #endif spec->exec[version] (NULL, action, data, len); -#if 0 + if (frame == context->frame) { #ifndef G_DISABLE_ASSERT - if (checksp != NULL && checksp != fp->sp) { - /* check stack was handled like expected */ - g_error ("action %s was supposed to change the stack by %d (+%d -%d), but it changed by %td", - spec->name, spec->add - spec->remove, spec->add, spec->remove, - fp->sp - checksp + spec->add - spec->remove); - } + if (check != NULL && check != stack->cur) { + g_error ("action %s was supposed to change the stack by %d (+%d -%d), but it changed by %td", + spec->name, spec->add - spec->remove, spec->add, spec->remove, + stack->cur - check + spec->add - spec->remove); + } #endif - if (fp->pc == pc) { - fp->pc = pc = nextpc; + /* adapt the pc if the action did not, otherwise, leave it alone */ + if (frame->pc == pc) { + frame->pc = pc = nextpc; + } else { + pc = frame->pc; + } } else { - pc = fp->pc; + /* someone called/returned from a function, reread variables */ + goto start; } -#endif } internal_error: diff --git a/libswfdec/swfdec_as_frame.c b/libswfdec/swfdec_as_frame.c index 8ce86db..632d439 100644 --- a/libswfdec/swfdec_as_frame.c +++ b/libswfdec/swfdec_as_frame.c @@ -23,6 +23,7 @@ #include "swfdec_as_frame.h" #include "swfdec_as_context.h" +#include "swfdec_as_stack.h" #include "swfdec_debug.h" G_DEFINE_TYPE (SwfdecAsFrame, swfdec_as_frame, SWFDEC_TYPE_AS_OBJECT) @@ -34,6 +35,7 @@ swfdec_as_frame_dispose (GObject *object g_slice_free1 (sizeof (SwfdecAsValue) * frame->n_registers, frame->registers); swfdec_script_unref (frame->script); + swfdec_as_stack_free (frame->stack); G_OBJECT_CLASS (swfdec_as_frame_parent_class)->dispose (object); } @@ -50,6 +52,7 @@ swfdec_as_frame_mark (SwfdecAsObject *ob for (i = 0; i < frame->n_registers; i++) { swfdec_as_value_mark (&frame->registers[i]); } + swfdec_as_stack_mark (frame->stack); SWFDEC_AS_OBJECT_CLASS (swfdec_as_frame_parent_class)->mark (object); } @@ -74,12 +77,16 @@ swfdec_as_frame_new (SwfdecAsContext *co { SwfdecAsValue val; SwfdecAsFrame *frame; + SwfdecAsStack *stack; gsize size; g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL); g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (thisp), NULL); g_return_val_if_fail (script != NULL, NULL); + stack = swfdec_as_stack_new (context, 100); /* FIXME: invent better numbers here */ + if (!stack) + return NULL; size = sizeof (SwfdecAsObject) + sizeof (SwfdecAsValue) * script->n_registers; if (!swfdec_as_context_use_mem (context, size)) return NULL; @@ -88,6 +95,9 @@ swfdec_as_frame_new (SwfdecAsContext *co g_object_unref (frame); frame->next = context->frame; context->frame = frame; + frame->script = swfdec_script_ref (script); + frame->pc = script->buffer->data; + frame->stack = stack; frame->scope = thisp; frame->var_object = thisp; frame->registers = g_slice_alloc0 (sizeof (SwfdecAsValue) * script->n_registers); diff --git a/libswfdec/swfdec_as_frame.h b/libswfdec/swfdec_as_frame.h index f55cc8f..10825de 100644 --- a/libswfdec/swfdec_as_frame.h +++ b/libswfdec/swfdec_as_frame.h @@ -45,7 +45,8 @@ struct _SwfdecAsFrame { SwfdecAsValue * registers; /* the registers */ guint n_registers; /* number of allocated registers */ SwfdecConstantPool * constant_pool; /* constant pool currently in use */ - //SwfdecAsStack * stack; /* variables on the stack */ + SwfdecAsStack * stack; /* variables on the stack */ + guint8 * pc; /* program counter on stack */ }; struct _SwfdecAsFrameClass { diff --git a/libswfdec/swfdec_as_stack.c b/libswfdec/swfdec_as_stack.c new file mode 100644 index 0000000..460afc6 --- /dev/null +++ b/libswfdec/swfdec_as_stack.c @@ -0,0 +1,98 @@ +/* SwfdecAs + * Copyright (C) 2007 Benjamin Otte <otte@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_as_stack.h" +#include "swfdec_as_context.h" + +SwfdecAsStack * +swfdec_as_stack_new (SwfdecAsContext *context, guint n_elements) +{ + SwfdecAsStack *stack; + + g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL); + g_return_val_if_fail (n_elements > 0, NULL); + + if (!swfdec_as_context_use_mem (context, sizeof (SwfdecAsStack) + + n_elements * sizeof (SwfdecAsValue))) + return NULL; + + stack = g_slice_new (SwfdecAsStack); + stack->context = context; + stack->base = g_slice_alloc (sizeof (SwfdecAsValue) * n_elements); + stack->end = stack->base + n_elements; + stack->cur = stack->base; + stack->next = NULL; + return stack; +} + +void +swfdec_as_stack_free (SwfdecAsStack *stack) +{ + g_return_if_fail (stack != NULL); + + swfdec_as_context_unuse_mem (stack->context, sizeof (SwfdecAsStack) + + (stack->end - stack->base) * sizeof (SwfdecAsValue)); + g_slice_free1 ((stack->end - stack->base) * sizeof (SwfdecAsValue), stack->base); + g_slice_free (SwfdecAsStack, stack); +} + +void +swfdec_as_stack_mark (SwfdecAsStack *stack) +{ + SwfdecAsValue *value; + + for (value = stack->base; value < stack->cur; value++) { + swfdec_as_value_mark (value); + } +} + +void +swfdec_as_stack_ensure_size (SwfdecAsStack *stack, guint n_elements) +{ + guint current; + + g_return_if_fail (stack != NULL); + g_return_if_fail (n_elements > (guint) (stack->end - stack->base)); + + current = (guint) (stack->cur - stack->base); + if (current) { + n_elements -= current; + memmove (stack->base + n_elements, stack->base, current * sizeof (SwfdecAsValue)); + } + stack->cur += n_elements; + if (n_elements) + memset (stack->cur - n_elements, 0, n_elements * sizeof (SwfdecAsValue)); +} + +void +swfdec_as_stack_ensure_left (SwfdecAsStack *stack, guint n_elements) +{ + g_return_if_fail (stack != NULL); + + if ((guint) (stack->end - stack->cur) < n_elements) { + /* FIXME FIXME FIXME */ + swfdec_as_context_abort (stack->context, "Out of stack space"); + } +} + diff --git a/libswfdec/swfdec_as_stack.h b/libswfdec/swfdec_as_stack.h new file mode 100644 index 0000000..4792b33 --- /dev/null +++ b/libswfdec/swfdec_as_stack.h @@ -0,0 +1,53 @@ +/* SwfdecAs + * Copyright (C) 2007 Benjamin Otte <otte@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 _SWFDEC_AS_STACK_H_ +#define _SWFDEC_AS_STACK_H_ + +#include <libswfdec/swfdec_as_types.h> + +G_BEGIN_DECLS + +struct _SwfdecAsStack { + SwfdecAsContext * context; /* context we operate on */ + + SwfdecAsValue * base; /* stack base */ + SwfdecAsValue * end; /* end of stack */ + SwfdecAsValue * cur; /* pointer to current top of stack */ + + SwfdecAsStack * next; /* pointer to next stack area */ +}; + +SwfdecAsStack * swfdec_as_stack_new (SwfdecAsContext * context, + guint n_elements); +void swfdec_as_stack_free (SwfdecAsStack * stack); + +#define swfdec_as_stack_peek(stack,n) (&(stack)->cur[-(gssize)(n)]) +#define swfdec_as_stack_pop(stack) (--(stack)->cur) +#define swfdec_as_stack_push(stack,val) (*(stack)->cur++) + +void swfdec_as_stack_mark (SwfdecAsStack * stack); +void swfdec_as_stack_ensure_size (SwfdecAsStack * stack, + guint n_elements); +void swfdec_as_stack_ensure_left (SwfdecAsStack * stack, + guint n_elements); + + +G_END_DECLS +#endif diff --git a/libswfdec/swfdec_as_types.h b/libswfdec/swfdec_as_types.h index 6fe9fbc..c5df8a6 100644 --- a/libswfdec/swfdec_as_types.h +++ b/libswfdec/swfdec_as_types.h @@ -37,6 +37,7 @@ typedef guint8 SwfdecAsType; typedef struct _SwfdecAsContext SwfdecAsContext; typedef struct _SwfdecAsFrame SwfdecAsFrame; typedef struct _SwfdecAsObject SwfdecAsObject; +typedef struct _SwfdecAsStack SwfdecAsStack; typedef struct _SwfdecAsValue SwfdecAsValue; struct _SwfdecAsValue { diff-tree 5cdfda32f8c6271deebd2977a0468d476961c22b (from dda05883a44d6813e2ae858d95f66686c7b8c22f) Author: Benjamin Otte <otte@gnome.org> Date: Thu Mar 29 09:17:47 2007 +0200 Make swfdec_script_ref return the ref'ed script This matches all the other refcounting functions diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index 6b7477e..a6e8312 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -2759,12 +2759,14 @@ swfdec_script_new (SwfdecBits *bits, con return script; } -void +SwfdecScript * swfdec_script_ref (SwfdecScript *script) { - g_return_if_fail (script != NULL); + g_return_val_if_fail (script != NULL, NULL); + g_return_val_if_fail (script->refcount > 0, NULL); script->refcount++; + return script; } void diff --git a/libswfdec/swfdec_script.h b/libswfdec/swfdec_script.h index b8fdcbb..27ef714 100644 --- a/libswfdec/swfdec_script.h +++ b/libswfdec/swfdec_script.h @@ -79,7 +79,7 @@ SwfdecScript * swfdec_script_new_for_pla SwfdecBits * bits, const char * name, unsigned int version); -void swfdec_script_ref (SwfdecScript * script); +SwfdecScript * swfdec_script_ref (SwfdecScript * script); void swfdec_script_unref (SwfdecScript * script); JSBool swfdec_script_interpret (SwfdecScript * script, diff-tree dda05883a44d6813e2ae858d95f66686c7b8c22f (from parents) Merge: c5ee4df92c31c8215b55ad11c582ea3a3ddad8c6 d5b0299d9f6cc23d8b3980ba8e34b1f76ae1902d Author: Benjamin Otte <otte@gnome.org> Date: Thu Mar 29 00:12:13 2007 +0200 Merge branch 'as' of ssh://company@git.freedesktop.org/git/swfdec into as diff-tree c5ee4df92c31c8215b55ad11c582ea3a3ddad8c6 (from parents) Merge: d906de1000e1ad4859df4b84c6b67129e70b3ac2 7f7d106034cd5fac344b12e3c93562a24ecd825f Author: Benjamin Otte <otte@gnome.org> Date: Thu Mar 29 00:12:03 2007 +0200 Merge branch 'master' of ssh://company@git.freedesktop.org/git/swfdec into as diff-tree 7f7d106034cd5fac344b12e3c93562a24ecd825f (from 579955e4dcc87dd9c91428ee1967e01bc9cfa69b) Author: Benjamin Otte <otte@gnome.org> Date: Wed Mar 28 22:38:10 2007 +0200 make SwfdecBuffer and SwfdecBufferQueue boxed types - add and document the types - change SwfdecBufferQueue to be refcounted (most changes here are s/_buffer_queue_free/_buffer_queue_unref/ - break API by removing swfdec_buffer_queue_unref diff --git a/configure.ac b/configure.ac index 5309072..30801ce 100644 --- a/configure.ac +++ b/configure.ac @@ -33,7 +33,7 @@ else fi AC_DEFINE_UNQUOTED(SWFDEC_LEVEL_DEFAULT, $DEFAULT_DEBUG_LEVEL, [Default debug level used]) -SWFDEC_LIBVERSION="2:0:0" +SWFDEC_LIBVERSION="3:0:0" AC_SUBST(SWFDEC_LIBVERSION) AM_PROG_LIBTOOL diff --git a/doc/swfdec-sections.txt b/doc/swfdec-sections.txt index a6e2d96..3d270af 100644 --- a/doc/swfdec-sections.txt +++ b/doc/swfdec-sections.txt @@ -57,7 +57,7 @@ swfdec_player_render swfdec_player_advance swfdec_player_handle_mouse swfdec_player_render_audio -swfdec_player_get_audio_enabled +swfdec_player_get_audio <SUBSECTION Standard> SwfdecPlayerClass SWFDEC_PLAYER @@ -73,7 +73,9 @@ SWFDEC_PLAYER_GET_CLASS <FILE>SwfdecBuffer</FILE> <TITLE>SwfdecBuffer</TITLE> SwfdecBuffer +SWFDEC_TYPE_BUFFER SwfdecBufferQueue +SWFDEC_TYPE_BUFFER_QUEUE swfdec_buffer_new swfdec_buffer_new_and_alloc swfdec_buffer_new_and_alloc0 @@ -84,13 +86,17 @@ swfdec_buffer_ref swfdec_buffer_unref swfdec_buffer_queue_new swfdec_buffer_queue_clear -swfdec_buffer_queue_free +swfdec_buffer_queue_ref +swfdec_buffer_queue_unref swfdec_buffer_queue_get_depth swfdec_buffer_queue_get_offset swfdec_buffer_queue_push swfdec_buffer_queue_pull swfdec_buffer_queue_pull_buffer swfdec_buffer_queue_peek +<SUBSECTION Standard> +swfdec_buffer_get_type +swfdec_buffer_queue_get_type </SECTION> <SECTION> diff --git a/libswfdec/swfdec_buffer.c b/libswfdec/swfdec_buffer.c index 49d47e7..3b8e929 100644 --- a/libswfdec/swfdec_buffer.c +++ b/libswfdec/swfdec_buffer.c @@ -54,6 +54,26 @@ /*** SwfdecBuffer ***/ /** + * SWFDEC_TYPE_BUFFER: + * + * #SwfdecBuffer is a boxed type for the glib type system. This macro + * returns its type. + **/ +GType +swfdec_buffer_get_type (void) +{ + static GType type_swfdec_buffer = 0; + + if (!type_swfdec_buffer) + type_swfdec_buffer = g_boxed_type_register_static + ("SwfdecBuffer", + (GBoxedCopyFunc) swfdec_buffer_ref, + (GBoxedFreeFunc) swfdec_buffer_unref); + + return type_swfdec_buffer; +} + +/** * swfdec_buffer_new: * * Creates a new #SwfdecBuffer to be filled by the user. Use like this: @@ -267,12 +287,36 @@ swfdec_buffer_unref (SwfdecBuffer * buff } } -/*** SwfdecBuffer ***/ +/*** SwfdecBufferQueue ***/ + +/** + * SWFDEC_TYPE_BUFFER_QUEUE: + * + * #SwfdecBufferQueue is a boxed type for the glib type system. This macro + * returns its type. + **/ +GType +swfdec_buffer_queue_get_type (void) +{ + static GType type_swfdec_buffer_queue = 0; + + if (!type_swfdec_buffer_queue) + type_swfdec_buffer_queue = g_boxed_type_register_static + ("SwfdecBufferQueue", + (GBoxedCopyFunc) swfdec_buffer_queue_ref, + (GBoxedFreeFunc) swfdec_buffer_queue_unref); + + return type_swfdec_buffer_queue; +} SwfdecBufferQueue * swfdec_buffer_queue_new (void) { - return g_new0 (SwfdecBufferQueue, 1); + SwfdecBufferQueue *buffer_queue; + + buffer_queue = g_new0 (SwfdecBufferQueue, 1); + buffer_queue->ref_count = 1; + return buffer_queue; } int @@ -296,13 +340,6 @@ swfdec_buffer_queue_clear (SwfdecBufferQ } void -swfdec_buffer_queue_free (SwfdecBufferQueue * queue) -{ - swfdec_buffer_queue_clear (queue); - g_free (queue); -} - -void swfdec_buffer_queue_push (SwfdecBufferQueue * queue, SwfdecBuffer * buffer) { g_return_if_fail (queue != NULL); @@ -443,3 +480,43 @@ swfdec_buffer_queue_peek (SwfdecBufferQu return newbuffer; } + +/** + * swfdec_buffer_queue_ref: + * @queue: a #SwfdecBufferQueue + * + * increases the reference count of @queue by one. + * + * Returns: The passed in @queue. + **/ +SwfdecBufferQueue * +swfdec_buffer_queue_ref (SwfdecBufferQueue * queue) +{ + g_return_val_if_fail (queue != NULL, NULL); + g_return_val_if_fail (queue->ref_count > 0, NULL); + + queue->ref_count++; + return queue; +} + +/** + * swfdec_buffer_queue_unref: + * @queue: a #SwfdecBufferQueue + * + * Decreases the reference count of @queue by one. If no reference + * to this buffer exists anymore, the buffer and the memory + * it manages are freed. + **/ +void +swfdec_buffer_queue_unref (SwfdecBufferQueue * queue) +{ + g_return_if_fail (queue != NULL); + g_return_if_fail (queue->ref_count > 0); + + queue->ref_count--; + if (queue->ref_count == 0) { + swfdec_buffer_queue_clear (queue); + g_free (queue); + } +} + diff --git a/libswfdec/swfdec_buffer.h b/libswfdec/swfdec_buffer.h index 81f6f66..38a7f2f 100644 --- a/libswfdec/swfdec_buffer.h +++ b/libswfdec/swfdec_buffer.h @@ -23,6 +23,7 @@ #define __SWFDEC_BUFFER_H__ #include <glib.h> +#include <glib-object.h> typedef struct _SwfdecBuffer SwfdecBuffer; typedef struct _SwfdecBufferQueue SwfdecBufferQueue; @@ -40,13 +41,21 @@ struct _SwfdecBuffer void *priv; }; +#define SWFDEC_TYPE_BUFFER swfdec_buffer_get_type() +GType swfdec_buffer_get_type (void); + struct _SwfdecBufferQueue { GList *buffers; unsigned int depth; unsigned int offset; + + int ref_count; }; +#define SWFDEC_TYPE_BUFFER_QUEUE swfdec_buffer_queue_get_type() +GType swfdec_buffer_queue_get_type (void); + SwfdecBuffer *swfdec_buffer_new (void); SwfdecBuffer *swfdec_buffer_new_and_alloc (unsigned int size); SwfdecBuffer *swfdec_buffer_new_and_alloc0 (unsigned int size); @@ -54,12 +63,11 @@ SwfdecBuffer *swfdec_buffer_new_for_data SwfdecBuffer *swfdec_buffer_new_subbuffer (SwfdecBuffer * buffer, unsigned int offset, unsigned int length); SwfdecBuffer *swfdec_buffer_new_from_file (const char *filename, GError **error); -SwfdecBuffer * swfdec_buffer_ref (SwfdecBuffer * buffer); +SwfdecBuffer *swfdec_buffer_ref (SwfdecBuffer * buffer); void swfdec_buffer_unref (SwfdecBuffer * buffer); SwfdecBufferQueue *swfdec_buffer_queue_new (void); void swfdec_buffer_queue_clear (SwfdecBufferQueue *queue); -void swfdec_buffer_queue_free (SwfdecBufferQueue * queue); int swfdec_buffer_queue_get_depth (SwfdecBufferQueue * queue); int swfdec_buffer_queue_get_offset (SwfdecBufferQueue * queue); void swfdec_buffer_queue_push (SwfdecBufferQueue * queue, @@ -67,5 +75,7 @@ void swfdec_buffer_queue_push (SwfdecBuf SwfdecBuffer *swfdec_buffer_queue_pull (SwfdecBufferQueue * queue, unsigned int length); SwfdecBuffer *swfdec_buffer_queue_pull_buffer (SwfdecBufferQueue * queue); SwfdecBuffer *swfdec_buffer_queue_peek (SwfdecBufferQueue * queue, unsigned int length); - +SwfdecBufferQueue *swfdec_buffer_queue_ref (SwfdecBufferQueue * queue); +void swfdec_buffer_queue_unref (SwfdecBufferQueue * queue); #endif + diff --git a/libswfdec/swfdec_codec_adpcm.c b/libswfdec/swfdec_codec_adpcm.c index f0fcc0d..93775c2 100644 --- a/libswfdec/swfdec_codec_adpcm.c +++ b/libswfdec/swfdec_codec_adpcm.c @@ -157,7 +157,7 @@ swfdec_codec_adpcm_decode (gpointer data } else { buffer = NULL; } - swfdec_buffer_queue_free (queue); + swfdec_buffer_queue_unref (queue); return buffer; } diff --git a/libswfdec/swfdec_codec_ffmpeg.c b/libswfdec/swfdec_codec_ffmpeg.c index cc5852a..127e1bd 100644 --- a/libswfdec/swfdec_codec_ffmpeg.c +++ b/libswfdec/swfdec_codec_ffmpeg.c @@ -151,7 +151,7 @@ swfdec_codec_ffmpeg_decode (gpointer ctx if (len < 0) { SWFDEC_ERROR ("Error %d while decoding", len); - swfdec_buffer_queue_free (queue); + swfdec_buffer_queue_unref (queue); swfdec_buffer_unref (outbuf); return NULL; } @@ -160,7 +160,7 @@ swfdec_codec_ffmpeg_decode (gpointer ctx outbuf->length = out_size; convert = swfdec_codec_ffmpeg_convert (ctx, outbuf); if (convert == NULL) { - swfdec_buffer_queue_free (queue); + swfdec_buffer_queue_unref (queue); swfdec_buffer_unref (outbuf); return NULL; } @@ -176,7 +176,7 @@ swfdec_codec_ffmpeg_decode (gpointer ctx outbuf = swfdec_buffer_queue_pull (queue, amount); else outbuf = NULL; - swfdec_buffer_queue_free (queue); + swfdec_buffer_queue_unref (queue); return outbuf; } diff --git a/libswfdec/swfdec_codec_mad.c b/libswfdec/swfdec_codec_mad.c index 18ca2fb..fa59e9c 100644 --- a/libswfdec/swfdec_codec_mad.c +++ b/libswfdec/swfdec_codec_mad.c @@ -189,7 +189,7 @@ swfdec_codec_mad_decode (gpointer datap, out = swfdec_buffer_queue_pull (queue, size); else out = NULL; - swfdec_buffer_queue_free (queue); + swfdec_buffer_queue_unref (queue); return out; } diff --git a/libswfdec/swfdec_loader.c b/libswfdec/swfdec_loader.c index 81d536c..fc5b1b6 100644 --- a/libswfdec/swfdec_loader.c +++ b/libswfdec/swfdec_loader.c @@ -139,7 +139,7 @@ swfdec_loader_dispose (GObject *object) { SwfdecLoader *loader = SWFDEC_LOADER (object); - swfdec_buffer_queue_free (loader->queue); + swfdec_buffer_queue_unref (loader->queue); g_free (loader->url); g_free (loader->error); diff --git a/libswfdec/swfdec_sound.c b/libswfdec/swfdec_sound.c index 85e3bb8..bc4ea93 100644 --- a/libswfdec/swfdec_sound.c +++ b/libswfdec/swfdec_sound.c @@ -223,7 +223,7 @@ swfdec_sound_get_decoded (SwfdecSound *s swfdec_buffer_queue_push (queue, tmp); swfdec_buffer_queue_push (queue, tmp2); tmp = swfdec_buffer_queue_pull (queue, swfdec_buffer_queue_get_depth (queue)); - swfdec_buffer_queue_free (queue); + swfdec_buffer_queue_unref (queue); } } SWFDEC_LOG ("after decoding, got %u samples, should get %u and skip %u", diff --git a/libswfdec/swfdec_swf_decoder.c b/libswfdec/swfdec_swf_decoder.c index f205eed..3954b36 100644 --- a/libswfdec/swfdec_swf_decoder.c +++ b/libswfdec/swfdec_swf_decoder.c @@ -60,7 +60,7 @@ swfdec_decoder_dispose (GObject *object) swfdec_buffer_unref (s->uncompressed_buffer); s->uncompressed_buffer = NULL; } - swfdec_buffer_queue_free (s->input_queue); + swfdec_buffer_queue_unref (s->input_queue); if (s->jpegtables) { swfdec_buffer_unref (s->jpegtables); diff --git a/test/sound/sound.c b/test/sound/sound.c index f42149f..6cbb5cc 100644 --- a/test/sound/sound.c +++ b/test/sound/sound.c @@ -119,7 +119,7 @@ finish_stream (TestStream *stream) gboolean ret = TRUE; buffer = swfdec_buffer_queue_pull (stream->queue, swfdec_buffer_queue_get_depth (stream->queue)); - swfdec_buffer_queue_free (stream->queue); + swfdec_buffer_queue_unref (stream->queue); file = swfdec_buffer_new_from_file (stream->name, &error); if (file) { ret = audio_diff (buffer, file, stream->name); diff --git a/test/swfdec-extract.c b/test/swfdec-extract.c index da0964b..36ae146 100644 --- a/test/swfdec-extract.c +++ b/test/swfdec-extract.c @@ -122,12 +122,12 @@ export_sprite_sound (SwfdecSprite *sprit } depth = swfdec_buffer_queue_get_depth (queue); if (depth == 0) { - swfdec_buffer_queue_free (queue); + swfdec_buffer_queue_unref (queue); g_printerr ("Sprite contains no sound\n"); return FALSE; } buffer = swfdec_buffer_queue_pull (queue, depth); - swfdec_buffer_queue_free (queue); + swfdec_buffer_queue_unref (queue); wav = encode_wav (buffer); swfdec_buffer_unref (buffer); if (!g_file_set_contents (filename, (char *) wav->data, diff --git a/test/swfedit_file.c b/test/swfedit_file.c index 26699de..e257010 100644 --- a/test/swfedit_file.c +++ b/test/swfedit_file.c @@ -260,7 +260,7 @@ swfedit_file_write (SwfeditFile *file) swfdec_out_put_buffer (out, buffer); swfdec_buffer_unref (buffer); } - swfdec_buffer_queue_free (queue); + swfdec_buffer_queue_unref (queue); return swfdec_out_close (out); } diff-tree 579955e4dcc87dd9c91428ee1967e01bc9cfa69b (from 493905baa1c07054276adb078f086e7ca4acc26b) Author: Benjamin Otte <otte@gnome.org> Date: Wed Mar 28 21:51:35 2007 +0200 print better error message when required cairo isn't available diff --git a/configure.ac b/configure.ac index 65be1fc..5309072 100644 --- a/configure.ac +++ b/configure.ac @@ -154,11 +154,12 @@ if test "$HAVE_LIBOIL" = "no"; then AC_MSG_ERROR([cannot find liboil-0.3, which is required for build]) fi -PKG_CHECK_MODULES(CAIRO, cairo >= 1.2.0, HAVE_CAIRO=yes, HAVE_CAIRO=no) +CAIRO_REQUIRES=1.2 +PKG_CHECK_MODULES(CAIRO, cairo >= $CAIRO_REQUIRES, HAVE_CAIRO=yes, HAVE_CAIRO=no) AC_SUBST(CAIRO_LIBS) AC_SUBST(CAIRO_CFLAGS) if test "$HAVE_CAIRO" = "no"; then - AC_MSG_ERROR([cannot find cairo, which is required for build]) + AC_MSG_ERROR([cannot find cairo >= $CAIRO_REQUIRES, which is required for build]) fi AC_ARG_ENABLE(mad,
Reasonably Related Threads
- Branch 'as' - 9 commits - libswfdec-gtk/swfdec_playback_alsa.c libswfdec/js libswfdec/Makefile.am libswfdec/swfdec_as_context.c libswfdec/swfdec_as_context.h libswfdec/swfdec_as_frame.c libswfdec/swfdec_as_frame.h libswfdec/swfdec_as_function.c
- Branch 'as' - 9 commits - libswfdec/swfdec_as_context.c libswfdec/swfdec_as_frame.c libswfdec/swfdec_as_frame.h libswfdec/swfdec_as_function.c libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_stack.c libswfdec/swfdec_as_stack.h
- Branch 'as' - 24 commits - configure.ac doc/Makefile.am doc/swfdec-sections.txt libswfdec/Makefile.am libswfdec/swfdec_amf.c libswfdec/swfdec_as_array.c libswfdec/swfdec_as_context.c libswfdec/swfdec_as_context.h libswfdec/swfdec_as_frame.c
- 3 commits - doc/Makefile.am doc/swfdec-docs.sgml doc/swfdec-sections.txt libswfdec/Makefile.am libswfdec/swfdec_as_array.c libswfdec/swfdec_as_boolean.c libswfdec/swfdec_as_context.c libswfdec/swfdec_as_context.h libswfdec/swfdec_as_frame.c
- 15 commits - doc/Makefile.am doc/swfdec-docs.sgml doc/swfdec-sections.txt INSTALL libswfdec/swfdec_as_context.c libswfdec/swfdec_as_frame.c libswfdec/swfdec_as_frame.h libswfdec/swfdec_as_interpret.h libswfdec/swfdec_as_object.h