X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fas3%2Fabc.c;h=7e11e1c94f07fbfb830916f89c572f47676767bc;hp=e7690c3e109bb516bf51c495a79ae6728bcf01ab;hb=2391d7ae5d8a145a250a8b80ab8c93ba74eba030;hpb=18a08d4b5573ce1aa0fccbdd5293baafb54d0591 diff --git a/lib/as3/abc.c b/lib/as3/abc.c index e7690c3..7e11e1c 100644 --- a/lib/as3/abc.c +++ b/lib/as3/abc.c @@ -26,6 +26,7 @@ #include "../rfxswf.h" #include "../q.h" #include "abc.h" +#include "assets.h" char stringbuffer[2048]; @@ -40,43 +41,30 @@ int abc_RegisterPrivateNameSpace(abc_file_t*file, const char*name); /* TODO: switch to a datastructure with just values */ #define NO_KEY "" -static char* params_tostring(multiname_list_t*list) +static void params_dump(FILE*fo, multiname_list_t*l, constant_list_t*o) { - multiname_list_t*l; - int n = list_length(list); - char**names = (char**)malloc(sizeof(char*)*n); - - l = list; - n = 0; - int size = 0; - while(l) { - names[n] = multiname_tostring(l->multiname); - size += strlen(names[n]) + 2; - n++;l=l->next; - } + int n = list_length(l); + int no = list_length(o); + int i = 0; - char* params = malloc(size+15); - params[0]='('; - params[1]=0; - l = list; - int s=0; - n = 0; + fprintf(fo, "("); while(l) { - if(s) - strcat(params, ", "); - strcat(params, names[n]); - free(names[n]); - l = l->next; - n++; - s=1; + char*s = multiname_tostring(l->multiname); + fprintf(fo, "%s", s); + free(s); + if(i>=n-no) { + s = constant_tostring(o->constant); + fprintf(fo, " = "); + fprintf(fo, "%s", s); + free(s); + o = o->next; + } + + if(l->next) + fprintf(fo, ", "); + l = l->next;i++; } - free(names); - /*char num[20]; - sprintf(num, "[%d params]", n); - strcat(params, num);*/ - strcat(params, ")"); - int t; - return params; + fprintf(fo, ")"); } //#define DEBUG @@ -87,7 +75,7 @@ static void parse_metadata(TAG*tag, abc_file_t*file, pool_t*pool) int t; int num_metadata = swf_GetU30(tag); - DEBUG printf("%d metadata\n"); + DEBUG printf("%d metadata\n", num_metadata); for(t=0;tclasses, NO_KEY, c); + if(file) + array_append(file->classes, NO_KEY, c); c->file = file; c->classname = multiname_clone(classname); @@ -169,55 +158,67 @@ void abc_class_add_interface(abc_class_t*c, multiname_t*interface) { list_append(c->interfaces, multiname_clone(interface)); } - -abc_method_body_t* add_method(abc_file_t*file, abc_class_t*cls, multiname_t*returntype, int num_params, va_list va) +char*abc_class_fullname(abc_class_t*cls) { - /* construct code (method body) object */ - NEW(abc_method_body_t,c); - array_append(file->method_bodies, NO_KEY, c); - c->index = array_length(file->method_bodies); - c->file = file; - c->traits = list_new(); - c->code = 0; + const char*package = cls->classname->ns->name; + const char*name = cls->classname->name; + int l1 = strlen(package); + int l2 = strlen(name); + char*fullname = malloc(l1+l2+2); + if(l1) { + memcpy(fullname, package, l1); + fullname[l1++]='.'; + } + memcpy(fullname+l1, name, l2+1); + return fullname; +} +void abc_method_init(abc_method_t*m, abc_file_t*file, multiname_t*returntype, char body) +{ /* construct method object */ - NEW(abc_method_t,m); m->index = array_length(file->methods); array_append(file->methods, NO_KEY, m); - m->return_type = returntype; - int t; - for(t=0;tparameters, multiname_fromstring(param)); + if(body) { + /* construct code (method body) object */ + NEW(abc_method_body_t,c); + array_append(file->method_bodies, NO_KEY, c); + c->index = array_length(file->method_bodies); + c->file = file; + c->traits = list_new(); + c->code = 0; + + /* crosslink the two objects */ + m->body = c; + c->method = m; } - - /* crosslink the two objects */ - m->body = c; - c->method = m; - - return c; +} +abc_method_t* abc_method_new(abc_file_t*file, multiname_t*returntype, char body) +{ + NEW(abc_method_t,m); + abc_method_init(m, file, returntype, body); + return m; } -abc_method_body_t* abc_class_constructor(abc_class_t*cls, multiname_t*returntype, int num_params, ...) +abc_method_t* abc_class_getconstructor(abc_class_t*cls, multiname_t*returntype) { - va_list va; - va_start(va, num_params); - abc_method_body_t* c = add_method(cls->file, cls, returntype, num_params, va); - va_end(va); - cls->constructor = c->method; - return c; + if(cls->constructor) { + return cls->constructor; + } + abc_method_t* m = abc_method_new(cls->file, returntype, 1); + cls->constructor = m; + return m; } -abc_method_body_t* abc_class_staticconstructor(abc_class_t*cls, multiname_t*returntype, int num_params, ...) +abc_method_t* abc_class_getstaticconstructor(abc_class_t*cls, multiname_t*returntype) { - va_list va; - va_start(va, num_params); - abc_method_body_t* c = add_method(cls->file, cls, returntype, num_params, va); - va_end(va); - cls->static_constructor = c->method; - return c; + if(cls->static_constructor) { + return cls->static_constructor; + } + abc_method_t* m = abc_method_new(cls->file, returntype, 1); + cls->static_constructor = m; + return m; } trait_t*trait_new(int type, multiname_t*name, int data1, int data2, constant_t*v) @@ -232,7 +233,8 @@ trait_t*trait_new(int type, multiname_t*name, int data1, int data2, constant_t*v trait->value = v; return trait; } -trait_t*trait_new_member(multiname_t*type, multiname_t*name,constant_t*v) + +trait_t*trait_new_member(trait_list_t**traits, multiname_t*type, multiname_t*name,constant_t*v) { int kind = TRAIT_SLOT; trait_t*trait = malloc(sizeof(trait_t)); @@ -241,9 +243,13 @@ trait_t*trait_new_member(multiname_t*type, multiname_t*name,constant_t*v) trait->attributes = kind&0xf0; trait->name = name; trait->type_name = type; + + trait->slot_id = list_length(*traits)+1; + trait_list_t*l = *traits; + list_append_(traits, trait); return trait; } -trait_t*trait_new_method(multiname_t*name, abc_method_t*m) +trait_t*trait_new_method(trait_list_t**traits, multiname_t*name, abc_method_t*m) { int type = TRAIT_METHOD; trait_t*trait = malloc(sizeof(trait_t)); @@ -252,42 +258,53 @@ trait_t*trait_new_method(multiname_t*name, abc_method_t*m) trait->attributes = type&0xf0; trait->name = name; trait->method = m; + + /* start assigning traits at position #1. + Weird things happen when assigning slot 0- slot 0 and 1 seem + to be identical */ + trait->slot_id = list_length(*traits)+1; + list_append_(traits, trait); return trait; } -abc_method_body_t* abc_class_method(abc_class_t*cls, multiname_t*returntype, char*name, int num_params, ...) +abc_method_t* abc_class_method(abc_class_t*cls, multiname_t*returntype, multiname_t*name) { abc_file_t*file = cls->file; - va_list va; - va_start(va, num_params); - abc_method_body_t* c = add_method(cls->file, cls, returntype, num_params, va); - va_end(va); - trait_t*t = trait_new_method(multiname_fromstring(name), c->method); - c->method->trait = t; - /* start assigning traits at position #1. - Weird things happen when assigning slot 0- slot 0 and 1 seem - to be identical */ - t->slot_id = list_length(cls->traits)+1; - list_append(cls->traits, t); - return c; + abc_method_t* m = abc_method_new(cls->file, returntype, !(cls->flags&CLASS_INTERFACE)); + m->trait = trait_new_method(&cls->traits, multiname_clone(name), m); + return m; +} +abc_method_t* abc_class_staticmethod(abc_class_t*cls, multiname_t*returntype, multiname_t*name) +{ + abc_file_t*file = cls->file; + abc_method_t* m = abc_method_new(cls->file, returntype, !(cls->flags&CLASS_INTERFACE)); + m->trait = trait_new_method(&cls->static_traits, multiname_clone(name), m); + return m; } -trait_t* abc_class_slot(abc_class_t*cls, char*name, multiname_t*type) +trait_t* abc_class_slot(abc_class_t*cls, multiname_t*name, multiname_t*type) { abc_file_t*file = cls->file; - multiname_t*m_name = multiname_fromstring(name); + multiname_t*m_name = multiname_clone(name); multiname_t*m_type = multiname_clone(type); - trait_t*t = trait_new_member(m_type, m_name, 0); - t->slot_id = list_length(cls->traits)+1; - list_append(cls->traits, t); + trait_t*t = trait_new_member(&cls->traits, m_type, m_name, 0); + return t; +} +trait_t* abc_class_staticslot(abc_class_t*cls, multiname_t*name, multiname_t*type) +{ + abc_file_t*file = cls->file; + multiname_t*m_name = multiname_clone(name); + multiname_t*m_type = multiname_clone(type); + trait_t*t = trait_new_member(&cls->static_traits, m_type, m_name, 0); return t; } -trait_t* abc_class_find_slotid(abc_class_t*cls, int slotid) + +trait_t* traits_find_slotid(trait_list_t*traits, int slotid) { trait_list_t*l; trait_t*t=0; - for(l=cls->traits;l;l=l->next) { + for(l=traits;l;l=l->next) { if(l->trait->slot_id==slotid) { t=l->trait; break; @@ -307,7 +324,7 @@ void abc_method_body_addClassTrait(abc_method_body_t*code, char*multiname, int s /* notice: traits of a method (body) belonging to an init script and traits of the init script are *not* the same thing */ -int abc_initscript_addClassTrait(abc_script_t*script, multiname_t*multiname, abc_class_t*cls) +trait_t* abc_initscript_addClassTrait(abc_script_t*script, multiname_t*multiname, abc_class_t*cls) { abc_file_t*file = script->file; multiname_t*m = multiname_clone(multiname); @@ -315,35 +332,43 @@ int abc_initscript_addClassTrait(abc_script_t*script, multiname_t*multiname, abc trait_t*trait = trait_new(TRAIT_CLASS, m, slotid, 0, 0); trait->cls = cls; list_append(script->traits, trait); - return slotid; + return trait; } -abc_script_t* abc_initscript(abc_file_t*file, multiname_t*returntype, int num_params, ...) +abc_script_t* abc_initscript(abc_file_t*file) { - va_list va; - va_start(va, num_params); - abc_method_body_t* c = add_method(file, 0, returntype, num_params, va); + abc_method_t*m = abc_method_new(file, 0, 1); abc_script_t* s = malloc(sizeof(abc_script_t)); - s->method = c->method; + s->method = m; s->traits = list_new(); s->file = file; array_append(file->scripts, NO_KEY, s); - va_end(va); return s; } -static void traits_dump(FILE*fo, const char*prefix, trait_list_t*traits, abc_file_t*file); +static void traits_dump(FILE*fo, const char*prefix, trait_list_t*traits, abc_file_t*file, dict_t*methods_seen); -static void dump_method(FILE*fo, const char*prefix, const char*type, const char*name, abc_method_t*m, abc_file_t*file) +static void dump_method(FILE*fo, const char*prefix, + const char*attr, + const char*type, + const char*name, + abc_method_t*m, abc_file_t*file, dict_t*methods_seen) { + if(methods_seen) + dict_put(methods_seen, m, 0); + char*return_type = 0; if(m->return_type) return_type = multiname_tostring(m->return_type); else - return_type = strdup("void"); - char*paramstr = params_tostring(m->parameters); - fprintf(fo, "%s%s %s %s=%s %s (%d params)\n", prefix, type, return_type, name, m->name, paramstr, list_length(m->parameters)); - free(paramstr);paramstr=0; + return_type = strdup("*"); + + fprintf(fo, "%s", prefix); + fprintf(fo, "%s %s ", attr, type); + fprintf(fo, "%s %s=%s", return_type, name, m->name); + params_dump(fo, m->parameters, m->optional_parameters); + fprintf(fo, "(%d params, %d optional)\n", list_length(m->parameters), list_length(m->optional_parameters)); + free(return_type);return_type=0; abc_method_body_t*c = m->body; @@ -375,9 +400,9 @@ static void dump_method(FILE*fo, const char*prefix, const char*type, const char* char prefix2[80]; sprintf(prefix2, "%s ", prefix); if(c->traits) - traits_dump(fo, prefix, c->traits, file); + traits_dump(fo, prefix, c->traits, file, methods_seen); fprintf(fo, "%s{\n", prefix); - code_dump(c->code, c->exceptions, file, prefix2, fo); + code_dump2(c->code, c->exceptions, file, prefix2, fo); fprintf(fo, "%s}\n\n", prefix); } @@ -441,12 +466,8 @@ static trait_list_t* traits_parse(TAG*tag, pool_t*pool, abc_file_t*file) } else if(kind == TRAIT_CLASS) { // class trait->slot_id = swf_GetU30(tag); trait->cls = (abc_class_t*)array_getvalue(file->classes, swf_GetU30(tag)); - DEBUG printf(" class %s %d %d\n", name, trait->slot_id, trait->cls); + DEBUG printf(" class %s %d %08x\n", name, trait->slot_id, (int)trait->cls); } else if(kind == TRAIT_SLOT || kind == TRAIT_CONST) { // slot, const - /* a slot is a variable in a class that is shared amonst all instances - of the same type, but which has a unique location in each object - (in other words, slots are non-static, traits are static) - */ trait->slot_id = swf_GetU30(tag); trait->type_name = multiname_clone(pool_lookup_multiname(pool, swf_GetU30(tag))); int vindex = swf_GetU30(tag); @@ -540,7 +561,7 @@ static void traits_write(pool_t*pool, TAG*tag, trait_list_t*traits) } -static void traits_dump(FILE*fo, const char*prefix, trait_list_t*traits, abc_file_t*file) +static void traits_dump(FILE*fo, const char*prefix, trait_list_t*traits, abc_file_t*file, dict_t*methods_seen) { int t; while(traits) { @@ -548,18 +569,31 @@ static void traits_dump(FILE*fo, const char*prefix, trait_list_t*traits, abc_fil char*name = multiname_tostring(trait->name); U8 kind = trait->kind; U8 attributes = trait->attributes; + + char a = attributes & (TRAIT_ATTR_OVERRIDE|TRAIT_ATTR_FINAL); + char* type = ""; + if(a==TRAIT_ATTR_FINAL) + type = "final "; + else if(a==TRAIT_ATTR_OVERRIDE) + type = "override "; + else if(a==(TRAIT_ATTR_OVERRIDE|TRAIT_ATTR_FINAL)) + type = "final override "; + + if(attributes&TRAIT_ATTR_METADATA) + fprintf(fo, ""); + if(kind == TRAIT_METHOD) { abc_method_t*m = trait->method; - dump_method(fo, prefix, "method", name, m, file); + dump_method(fo, prefix, type, "method", name, m, file, methods_seen); } else if(kind == TRAIT_GETTER) { abc_method_t*m = trait->method; - dump_method(fo, prefix, "getter", name, m, file); + dump_method(fo, prefix, type, "getter", name, m, file, methods_seen); } else if(kind == TRAIT_SETTER) { abc_method_t*m = trait->method; - dump_method(fo, prefix, "setter", name, m, file); + dump_method(fo, prefix, type, "setter", name, m, file, methods_seen); } else if(kind == TRAIT_FUNCTION) { // function abc_method_t*m = trait->method; - dump_method(fo, prefix, "function", name, m, file); + dump_method(fo, prefix, type, "function", name, m, file, methods_seen); } else if(kind == TRAIT_CLASS) { // class abc_class_t*cls = trait->cls; if(!cls) { @@ -571,9 +605,9 @@ static void traits_dump(FILE*fo, const char*prefix, trait_list_t*traits, abc_fil int slot_id = trait->slot_id; char*type_name = multiname_tostring(trait->type_name); char*value = constant_tostring(trait->value); - fprintf(fo, "%sslot %d: %s%s %s %s %s\n", prefix, trait->slot_id, - kind==TRAIT_CONST?"const ":"", type_name, name, - value?"=":"", value); + fprintf(fo, "%sslot %d: %s %s:%s %s %s\n", prefix, trait->slot_id, + kind==TRAIT_CONST?"const":"var", name, type_name, + trait->value?"=":"", trait->value?value:""); if(value) free(value); free(type_name); } else { @@ -587,7 +621,7 @@ static void traits_dump(FILE*fo, const char*prefix, trait_list_t*traits, abc_fil void* swf_DumpABC(FILE*fo, void*code, char*prefix) { abc_file_t* file = (abc_file_t*)code; - + if(file->name) { fprintf(fo, "%s#\n", prefix); fprintf(fo, "%s#name: %s\n", prefix, file->name); @@ -601,11 +635,12 @@ void* swf_DumpABC(FILE*fo, void*code, char*prefix) int s; array_t*items = (array_t*)array_getvalue(file->metadata, t); for(s=0;snum;s++) { - fprintf(fo, "%s# %s=%s\n", prefix, array_getkey(items, s), array_getvalue(items,s)); + fprintf(fo, "%s# %s=%s\n", prefix, (char*)array_getkey(items, s), (char*)array_getvalue(items,s)); } fprintf(fo, "%s#\n", prefix); } + dict_t*methods_seen = dict_new2(&ptr_type); for(t=0;tclasses->num;t++) { abc_class_t*cls = (abc_class_t*)array_getvalue(file->classes, t); char prefix2[80]; @@ -628,6 +663,8 @@ void* swf_DumpABC(FILE*fo, void*code, char*prefix) char*supername = multiname_tostring(cls->superclass); fprintf(fo, " extends %s", supername); free(supername); + } + if(cls->interfaces) { multiname_list_t*ilist = cls->interfaces; if(ilist) fprintf(fo, " implements"); @@ -643,25 +680,50 @@ void* swf_DumpABC(FILE*fo, void*code, char*prefix) fprintf(fo, "extra flags=%02x\n", cls->flags&0xf0); fprintf(fo, "%s{\n", prefix); - if(cls->static_constructor) - dump_method(fo, prefix2,"staticconstructor", "", cls->static_constructor, file); - traits_dump(fo, prefix2, cls->static_traits, file); + dict_put(methods_seen, cls->static_constructor, 0); + dict_put(methods_seen, cls->constructor, 0); + + if(cls->static_constructor) { + dump_method(fo, prefix2, "", "staticconstructor", "", cls->static_constructor, file, methods_seen); + } + traits_dump(fo, prefix2, cls->static_traits, file, methods_seen); char*n = multiname_tostring(cls->classname); if(cls->constructor) - dump_method(fo, prefix2, "constructor", n, cls->constructor, file); + dump_method(fo, prefix2, "", "constructor", n, cls->constructor, file, methods_seen); free(n); - traits_dump(fo, prefix2,cls->traits, file); - fprintf(fo, "%s}\n", prefix); + traits_dump(fo, prefix2,cls->traits, file, methods_seen); + + if(cls->asset) { + swf_DumpAsset(fo, cls->asset, prefix2); + } + fprintf(fo, "%s}\n", prefix); } fprintf(fo, "%s\n", prefix); for(t=0;tscripts->num;t++) { abc_script_t*s = (abc_script_t*)array_getvalue(file->scripts, t); - dump_method(fo, prefix,"initmethod", "init", s->method, file); - traits_dump(fo, prefix, s->traits, file); + dump_method(fo, prefix, "", "initmethod", "init", s->method, file, methods_seen); + traits_dump(fo, prefix, s->traits, file, methods_seen); + } + + char extra=0; + for(t=0;tmethods->num;t++) { + abc_method_t*m = (abc_method_t*)array_getvalue(file->methods, t); + if(!dict_contains(methods_seen, m)) { + if(!extra) { + extra=1; + fprintf(fo, "\n"); + fprintf(fo, "%s//internal (non-class non-script) methods:\n", prefix); + } + char name[18]; + sprintf(name, "%08x ", m->index); + dump_method(fo, prefix, "", "internalmethod", name, m, file, methods_seen); + } } + dict_destroy(methods_seen); + return file; } @@ -700,7 +762,7 @@ void* swf_ReadABC(TAG*tag) for(s=0;sparameters, param); } @@ -713,10 +775,11 @@ void* swf_ReadABC(TAG*tag) m->flags = swf_GetU8(tag); - DEBUG printf("method %d) %s %s flags=%02x\n", t, m->name, params_tostring(m->parameters), m->flags); + DEBUG printf("method %d) %s ", t, m->name); + DEBUG params_dump(stdout, m->parameters, m->optional_parameters); + DEBUG printf("flags=%02x\n", m->flags); if(m->flags&0x08) { - /* TODO optional parameters */ m->optional_parameters = list_new(); int num = swf_GetU30(tag); int s; @@ -725,13 +788,14 @@ void* swf_ReadABC(TAG*tag) U8 vkind = swf_GetU8(tag); // specifies index type for "val" constant_t*c = constant_fromindex(pool, vindex, vkind); list_append(m->optional_parameters, c); + } } if(m->flags&0x80) { /* debug information- not used by avm2 */ multiname_list_t*l = m->parameters; while(l) { - char*name = pool_lookup_string(pool, swf_GetU30(tag)); + const char*name = pool_lookup_string(pool, swf_GetU30(tag)); l = l->next; } } @@ -837,7 +901,7 @@ void* swf_ReadABC(TAG*tag) array_append(file->method_bodies, NO_KEY, c); } if(tag->len - tag->pos) { - fprintf(stderr, "%d unparsed bytes remaining in ABC block\n", tag->len - tag->pos); + fprintf(stderr, "ERROR: %d unparsed bytes remaining in ABC block\n", tag->len - tag->pos); return 0; } @@ -887,10 +951,13 @@ void* swf_ReadABC(TAG*tag) return file; } -void swf_WriteABC(TAG*abctag, void*code) +static pool_t*writeABC(TAG*abctag, void*code, pool_t*pool) { abc_file_t*file = (abc_file_t*)code; - pool_t*pool = pool_new(); + if(!pool) + pool = pool_new(); + if(!file) + file = abc_file_new(); TAG*tmp = swf_InsertTag(0,0); TAG*tag = tmp; @@ -905,7 +972,11 @@ void swf_WriteABC(TAG*abctag, void*code) NEW(abc_method_body_t,body);array_append(file->method_bodies, NO_KEY, body); // don't bother to set m->index body->method = m; m->body = body; - __ returnvoid(body); + if(c->superclass && c->superclass->name && strcmp(c->superclass->name,"Object")) { + body->code = abc_getlocal_0(body->code); + body->code = abc_constructsuper(body->code, 0); + } + body->code = abc_returnvoid(body->code); c->constructor = m; } else { NEW(abc_method_t,m);array_append(file->methods, NO_KEY, m); @@ -916,7 +987,7 @@ void swf_WriteABC(TAG*abctag, void*code) NEW(abc_method_t,m);array_append(file->methods, NO_KEY, m); NEW(abc_method_body_t,body);array_append(file->method_bodies, NO_KEY, body); body->method = m; m->body = body; - __ returnvoid(body); + body->code = abc_returnvoid(0); c->static_constructor = m; } } @@ -1013,8 +1084,13 @@ void swf_WriteABC(TAG*abctag, void*code) swf_SetU30(tag, list_length(m->optional_parameters)); constant_list_t*l = m->optional_parameters; while(l) { - swf_SetU30(tag, constant_get_index(pool, l->constant)); - swf_SetU8(tag, l->constant->type); + int i = constant_get_index(pool, l->constant); + swf_SetU30(tag, i); + if(!i) { + swf_SetU8(tag, CONSTANT_NULL); + } else { + swf_SetU8(tag, l->constant->type); + } l = l->next; } } @@ -1075,6 +1151,9 @@ void swf_WriteABC(TAG*abctag, void*code) swf_SetU30(tag, file->scripts->num); for(t=0;tscripts->num;t++) { abc_script_t*s = (abc_script_t*)array_getvalue(file->scripts, t); + if(!s->method->body || !s->method->body->code) { + fprintf(stderr, "Internal Error: initscript has no body\n"); + } swf_SetU30(tag, s->method->index); //!=t! traits_write(pool, tag, s->traits); } @@ -1091,10 +1170,14 @@ void swf_WriteABC(TAG*abctag, void*code) //swf_SetU30(tag, c->old.max_scope_depth); swf_SetU30(tag, c->stats->max_stack); - if(list_length(c->method->parameters)+1 <= c->stats->local_count) + int param_num = list_length(c->method->parameters)+1; + if(c->method->flags&METHOD_NEED_REST) + param_num++; + if(param_num <= c->stats->local_count) swf_SetU30(tag, c->stats->local_count); else - swf_SetU30(tag, list_length(c->method->parameters)+1); + swf_SetU30(tag, param_num); + swf_SetU30(tag, c->init_scope_depth); swf_SetU30(tag, c->stats->max_scope_depth+ c->init_scope_depth); @@ -1140,11 +1223,22 @@ void swf_WriteABC(TAG*abctag, void*code) swf_SetBlock(tag, tmp->data, tmp->len); swf_DeleteTag(0, tmp); + return pool; +} + +void swf_WriteABC(TAG*abctag, void*code) +{ + pool_t*pool = writeABC(abctag, code, 0); + pool_optimize(pool); + swf_ResetTag(abctag, abctag->id); + writeABC(abctag, code, pool); pool_destroy(pool); } void abc_file_free(abc_file_t*file) { + if(!file) + return; int t; if(file->metadata) { for(t=0;tmetadata->num;t++) { @@ -1251,228 +1345,3 @@ void swf_FreeABC(void*code) abc_file_free(file); } -void swf_AddButtonLinks(SWF*swf, char stop_each_frame, char events) -{ - int num_frames = 0; - int has_buttons = 0; - TAG*tag=swf->firstTag; - while(tag) { - if(tag->id == ST_SHOWFRAME) - num_frames++; - if(tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2) - has_buttons = 1; - tag = tag->next; - } - - abc_file_t*file = abc_file_new(); - abc_method_body_t*c = 0; - - abc_class_t*cls = abc_class_new2(file, "rfx::MainTimeline", "flash.display::MovieClip"); - abc_class_protectedNS(cls, "rfx:MainTimeline"); - - TAG*abctag = swf_InsertTagBefore(swf, swf->firstTag, ST_DOABC); - - tag = swf_InsertTag(abctag, ST_SYMBOLCLASS); - swf_SetU16(tag, 1); - swf_SetU16(tag, 0); - swf_SetString(tag, "rfx.MainTimeline"); - - c = abc_class_staticconstructor(cls, 0, 0); - c->old.max_stack = 1; - c->old.local_count = 1; - c->old.init_scope_depth = 9; - c->old.max_scope_depth = 10; - - __ getlocal_0(c); - __ pushscope(c); - __ returnvoid(c); - - c = abc_class_constructor(cls, 0, 0); - c->old.max_stack = 3; - c->old.local_count = 1; - c->old.init_scope_depth = 10; - c->old.max_scope_depth = 11; - - debugfile(c, "constructor.as"); - - __ getlocal_0(c); - __ pushscope(c); - - __ getlocal_0(c); - __ constructsuper(c,0); - - __ getlex(c, "[package]flash.system::Security"); - __ pushstring(c, "*"); - __ callpropvoid(c, "[package]::allowDomain", 1); - - if(stop_each_frame || has_buttons) { - int frame = 0; - tag = swf->firstTag; - abc_method_body_t*f = 0; //frame script - while(tag && tag->id!=ST_END) { - char framename[80]; - char needs_framescript=0; - char buttonname[80]; - char functionname[80]; - sprintf(framename, "[packageinternal]rfx::frame%d", frame); - - if(!f && (tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2 || stop_each_frame)) { - /* make the contructor add a frame script */ - __ findpropstrict(c,"[package]::addFrameScript"); - __ pushbyte(c,frame); - __ getlex(c,framename); - __ callpropvoid(c,"[package]::addFrameScript",2); - - f = abc_class_method(cls, 0, framename, 0); - f->old.max_stack = 3; - f->old.local_count = 1; - f->old.init_scope_depth = 10; - f->old.max_scope_depth = 11; - __ debugfile(f, "framescript.as"); - __ debugline(f, 1); - __ getlocal_0(f); - __ pushscope(f); - if(stop_each_frame) { - __ findpropstrict(f, "[package]::stop"); - __ callpropvoid(f, "[package]::stop", 0); - } - } - - if(tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2) { - U16 id = swf_GetDefineID(tag); - sprintf(buttonname, "::button%d", swf_GetDefineID(tag)); - __ getlex(f,buttonname); - __ getlex(f,"flash.events::MouseEvent"); - __ getproperty(f, "::CLICK"); - sprintf(functionname, "::clickbutton%d", swf_GetDefineID(tag)); - __ getlex(f,functionname); - __ callpropvoid(f, "::addEventListener" ,2); - - needs_framescript = 1; - - abc_method_body_t*h = - abc_class_method(cls, 0, functionname, 1, "flash.events::MouseEvent"); - h->old.max_stack = 6; - h->old.local_count = 2; - h->old.init_scope_depth = 10; - h->old.max_scope_depth = 11; - __ getlocal_0(h); - __ pushscope(h); - - ActionTAG*oldaction = swf_ButtonGetAction(tag); - if(oldaction && oldaction->op == ACTION__GOTOFRAME) { - int framenr = GET16(oldaction->data); - if(framenr>254) { - fprintf(stderr, "Warning: Couldn't translate jump to frame %d to flash 9 actionscript\n", framenr); - } - if(!events) { - __ findpropstrict(h,"[package]::gotoAndStop"); - __ pushbyte(h,framenr+1); - __ callpropvoid(h,"[package]::gotoAndStop", 1); - } else { - char framename[80]; - sprintf(framename, "frame%d", framenr); - __ getlocal_0(h); //this - __ findpropstrict(h, "[package]flash.events::TextEvent"); - __ pushstring(h, "link"); - __ pushtrue(h); - __ pushtrue(h); - __ pushstring(h, framename); - __ constructprop(h,"[package]flash.events::TextEvent", 4); - __ callpropvoid(h,"[package]::dispatchEvent", 1); - } - } else if(oldaction && oldaction->op == ACTION__GETURL) { - if(!events) { - __ findpropstrict(h,"flash.net::navigateToURL"); - __ findpropstrict(h,"flash.net::URLRequest"); - // TODO: target _blank - __ pushstring(h,oldaction->data); //url - __ constructprop(h,"flash.net::URLRequest", 1); - __ callpropvoid(h,"flash.net::navigateToURL", 1); - } else { - __ getlocal_0(h); //this - __ findpropstrict(h, "[package]flash.events::TextEvent"); - __ pushstring(h, "link"); - __ pushtrue(h); - __ pushtrue(h); - __ pushstring(h,oldaction->data); //url - __ constructprop(h,"[package]flash.events::TextEvent", 4); - __ callpropvoid(h,"[package]::dispatchEvent", 1); - } - } else if(oldaction) { - fprintf(stderr, "Warning: Couldn't translate button code of button %d to flash 9 abc action\n", id); - } - __ returnvoid(h); - swf_ActionFree(oldaction); - } - if(tag->id == ST_SHOWFRAME) { - if(f) { - __ returnvoid(f); - f = 0; - } - frame++; - } - tag = tag->next; - } - if(f) { - __ returnvoid(f); - } - } - __ returnvoid(c); - - tag = swf->firstTag; - while(tag) { - if(tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2) { - char buttonname[80]; - sprintf(buttonname, "::button%d", swf_GetDefineID(tag)); - multiname_t*s = multiname_fromstring(buttonname); - abc_class_slot(cls, buttonname, s); - } - tag = tag->next; - } - - - abc_script_t*s = abc_initscript(file, 0, 0); - c = s->method->body; - c->old.max_stack = 2; - c->old.local_count = 1; - c->old.init_scope_depth = 1; - c->old.max_scope_depth = 9; - - __ getlocal_0(c); - __ pushscope(c); - __ getscopeobject(c, 0); - __ getlex(c,"::Object"); - __ pushscope(c); - __ getlex(c,"flash.events::EventDispatcher"); - __ pushscope(c); - __ getlex(c,"flash.display::DisplayObject"); - __ pushscope(c); - __ getlex(c,"flash.display::InteractiveObject"); - __ pushscope(c); - __ getlex(c,"flash.display::DisplayObjectContainer"); - __ pushscope(c); - __ getlex(c,"flash.display::Sprite"); - __ pushscope(c); - __ getlex(c,"flash.display::MovieClip"); - __ pushscope(c); - __ getlex(c,"flash.display::MovieClip"); - __ newclass(c,cls); - __ popscope(c); - __ popscope(c); - __ popscope(c); - __ popscope(c); - __ popscope(c); - __ popscope(c); - __ popscope(c); - __ initproperty(c,"rfx::MainTimeline"); - __ returnvoid(c); - - //abc_method_body_addClassTrait(c, "rfx:MainTimeline", 1, cls); - multiname_t*classname = multiname_fromstring("rfx::MainTimeline"); - abc_initscript_addClassTrait(s, classname, cls); - multiname_destroy(classname); - - swf_WriteABC(abctag, file); -} -