X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fas3%2Fabc.c;h=623dc7c6ff1034578cb3d2c1f6536fb316092d35;hb=b90a862675445a668b49221a4ac2ead441b9d153;hp=8466dedb11b8af12266c0f3d8c5e661f423e583b;hpb=982309eae0ef6ce7672f440a86fcf91f5abd88dc;p=swftools.git diff --git a/lib/as3/abc.c b/lib/as3/abc.c index 8466ded..623dc7c 100644 --- a/lib/as3/abc.c +++ b/lib/as3/abc.c @@ -97,8 +97,8 @@ static void parse_metadata(TAG*tag, abc_file_t*file, pool_t*pool) for(s=0;sclasses, NO_KEY, c); c->file = file; - c->classname = classname; - c->superclass = superclass; + c->classname = multiname_clone(classname); + c->superclass = multiname_clone(superclass); c->flags = 0; c->constructor = 0; c->static_constructor = 0; @@ -172,55 +167,52 @@ void abc_class_protectedNS(abc_class_t*c, char*namespace) } void abc_class_add_interface(abc_class_t*c, multiname_t*interface) { - list_append(c->interfaces, 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) +abc_method_t* abc_method_new(abc_file_t*file, multiname_t*returntype, char body) { - /* construct code (method body) object */ - NEW(abc_method_body_t,c); - array_append(file->method_bodies, NO_KEY, c); - c->file = file; - c->traits = list_new(); - c->code = 0; - /* 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; + 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) @@ -235,7 +227,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)); @@ -244,9 +237,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)); @@ -255,28 +252,59 @@ 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); - list_append(cls->traits, trait_new_method(multiname_fromstring(name), c->method)); - 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; } -void abc_AddSlot(abc_class_t*cls, char*name, int slot, char*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_clone(name); + multiname_t*m_type = multiname_clone(type); + 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_fromstring(name); - multiname_t*m_type = multiname_fromstring(type); - trait_t*t = trait_new_member(m_type, m_name, 0); - t->slot_id = list_length(cls->traits); - list_append(cls->traits, t); + 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_list_t*l; + trait_t*t=0; + for(l=cls->traits;l;l=l->next) { + if(l->trait->slot_id==slotid) { + t=l->trait; + break; + } + } + return t; } void abc_method_body_addClassTrait(abc_method_body_t*code, char*multiname, int slotid, abc_class_t*cls) @@ -301,31 +329,38 @@ int abc_initscript_addClassTrait(abc_script_t*script, multiname_t*multiname, abc return slotid; } -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)); + fprintf(fo, "%s%s%s %s %s=%s %s (%d params, %d optional)\n", prefix, attr, type, return_type, name, m->name, paramstr, + list_length(m->parameters), + list_length(m->optional_parameters) + ); free(paramstr);paramstr=0; free(return_type);return_type=0; @@ -347,15 +382,20 @@ static void dump_method(FILE*fo, const char*prefix, const char*type, const char* if(flags&METHOD_SET_DXNS) {fprintf(fo, " set_dxns");flags&=~METHOD_SET_DXNS;} if(flags&METHOD_HAS_PARAM_NAMES) {fprintf(fo, " has_param_names");flags&=~METHOD_HAS_PARAM_NAMES;} if(flags) fprintf(fo, " %02x", flags); - fprintf(fo, "]\n"); + fprintf(fo, "]"); + + if(m->trait) { + fprintf(fo, " slot:%d", m->trait->slot_id); + } + fprintf(fo, "\n"); 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); } @@ -410,19 +450,17 @@ static trait_list_t* traits_parse(TAG*tag, pool_t*pool, abc_file_t*file) if(kind == TRAIT_METHOD || kind == TRAIT_GETTER || kind == TRAIT_SETTER) { // method / getter / setter trait->disp_id = swf_GetU30(tag); trait->method = (abc_method_t*)array_getvalue(file->methods, swf_GetU30(tag)); + trait->method->trait = trait; DEBUG printf(" method/getter/setter\n"); } else if(kind == TRAIT_FUNCTION) { // function trait->slot_id = swf_GetU30(tag); trait->method = (abc_method_t*)array_getvalue(file->methods, swf_GetU30(tag)); + trait->method->trait = trait; } 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); } 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); @@ -516,7 +554,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) { @@ -524,18 +562,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) { @@ -547,9 +598,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, + value?"=":"", value?value:""); if(value) free(value); free(type_name); } else { @@ -582,6 +633,7 @@ void* swf_DumpABC(FILE*fo, void*code, char*prefix) 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]; @@ -619,24 +671,45 @@ 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_constructor_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); + traits_dump(fo, prefix2,cls->traits, file, methods_seen); 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); + dump_method(fo, prefix, "", "internalmethod", name, m, file, methods_seen); + } + } + dict_destroy(methods_seen); + return file; } @@ -688,10 +761,9 @@ void* swf_ReadABC(TAG*tag) m->flags = swf_GetU8(tag); - DEBUG printf("method %d) %s flags=%02x\n", t, params_tostring(m->parameters), m->flags); + DEBUG printf("method %d) %s %s flags=%02x\n", t, m->name, params_tostring(m->parameters), m->flags); if(m->flags&0x08) { - /* TODO optional parameters */ m->optional_parameters = list_new(); int num = swf_GetU30(tag); int s; @@ -706,10 +778,11 @@ void* swf_ReadABC(TAG*tag) /* 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; } } + m->index = array_length(file->methods); array_append(file->methods, NO_KEY, m); } @@ -723,13 +796,13 @@ void* swf_ReadABC(TAG*tag) abc_class_t*cls = malloc(sizeof(abc_class_t)); memset(cls, 0, sizeof(abc_class_t)); - DEBUG printf("class %d\n", t); swf_GetU30(tag); //classname swf_GetU30(tag); //supername array_append(file->classes, NO_KEY, cls); cls->flags = swf_GetU8(tag); + DEBUG printf("class %d %02x\n", t, cls->flags); if(cls->flags&8) swf_GetU30(tag); //protectedNS int s; @@ -742,12 +815,14 @@ void* swf_ReadABC(TAG*tag) DEBUG printf(" class %d interface: %s\n", t, m->name); } - swf_GetU30(tag); //iinit + int iinit = swf_GetU30(tag); //iinit + DEBUG printf("--iinit-->%d\n", iinit); traits_skip(tag); } for(t=0;tclasses, t); int cinit = swf_GetU30(tag); + DEBUG printf("--cinit(%d)-->%d\n", t, cinit); cls->static_constructor = (abc_method_t*)array_getvalue(file->methods, cinit); traits_skip(tag); } @@ -789,7 +864,7 @@ void* swf_ReadABC(TAG*tag) int s; c->exceptions = list_new(); for(s=0;sfrom = code_atposition(codelookup, swf_GetU30(tag)); e->to = code_atposition(codelookup, swf_GetU30(tag)); @@ -804,7 +879,7 @@ void* swf_ReadABC(TAG*tag) codelookup_free(codelookup); c->traits = traits_parse(tag, pool, file); - DEBUG printf("method_body %d) (method %d), %d bytes of code", t, methodnr, code_length); + DEBUG printf("method_body %d) (method %d), %d bytes of code\n", t, methodnr, code_length); array_append(file->method_bodies, NO_KEY, c); } @@ -831,7 +906,7 @@ void* swf_ReadABC(TAG*tag) int num_interfaces = swf_GetU30(tag); //interface count int s; for(s=0;sconstructor = (abc_method_t*)array_getvalue(file->methods, iinit); @@ -841,7 +916,7 @@ void* swf_ReadABC(TAG*tag) abc_class_t*cls = (abc_class_t*)array_getvalue(file->classes, t); /* SKIP */ swf_GetU30(tag); // cindex - cls->static_constructor_traits = traits_parse(tag, pool, file); + cls->static_traits = traits_parse(tag, pool, file); } int num_scripts2 = swf_GetU30(tag); for(t=0;tclasses->num;t++) { abc_class_t*c = (abc_class_t*)array_getvalue(file->classes, t); - if(!c->constructor || !c->static_constructor) { - need_null_method=1; - break; + if(!c->constructor) { + if(!(c->flags&CLASS_INTERFACE)) { + 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); + // don't bother to set m->index + body->method = m; m->body = body; + __ returnvoid(body); + c->constructor = m; + } else { + NEW(abc_method_t,m);array_append(file->methods, NO_KEY, m); + c->constructor = m; + } + } + if(!c->static_constructor) { + 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); + c->static_constructor = m; } } - abc_method_t*nullmethod = 0; - if(need_null_method) { - NEW(abc_method_t,m); - nullmethod = m; - /*TODO: might be more efficient to have this at the beginning */ - array_append(file->methods, NO_KEY, nullmethod); - - NEW(abc_method_body_t,body); - body->method = m; - m->body = body; - __ returnvoid(body); - array_append(file->method_bodies, NO_KEY, body); - } - for(t=0;tclasses->num;t++) { - abc_class_t*c = (abc_class_t*)array_getvalue(file->classes, t); - if(!c->constructor) - c->constructor = nullmethod; - if(!c->static_constructor) - c->static_constructor = nullmethod; - } swf_SetU30(tag, file->methods->num); /* enumerate classes, methods and method bodies */ @@ -927,6 +998,8 @@ void swf_WriteABC(TAG*abctag, void*code) Not sure yet what to do with methods which are used at different locations- e.g. the nullmethod is used all over the place. + EDIT: flashplayer doesn't allow this anyway- a method can only + be used once Also, I have the strong suspicion that flash player uses only the difference between max_scope_stack and init_scope_stack, anyway. @@ -934,11 +1007,11 @@ void swf_WriteABC(TAG*abctag, void*code) for(t=0;tclasses->num;t++) { abc_class_t*c = (abc_class_t*)array_getvalue(file->classes, t); trait_list_t*traits = c->traits; - if(c->constructor && + if(c->constructor && c->constructor->body && c->constructor->body->init_scope_depth < c->init_scope_depth) { c->constructor->body->init_scope_depth = c->init_scope_depth; } - if(c->static_constructor && + if(c->static_constructor && c->static_constructor->body && c->static_constructor->body->init_scope_depth < c->init_scope_depth) { c->static_constructor->body->init_scope_depth = c->init_scope_depth; } @@ -1033,21 +1106,17 @@ void swf_WriteABC(TAG*abctag, void*code) interface = interface->next; } - if(!c->constructor) { - swf_SetU30(tag, nullmethod->index); - } else { - swf_SetU30(tag, c->constructor->index); - } + assert(c->constructor); + swf_SetU30(tag, c->constructor->index); + traits_write(pool, tag, c->traits); } for(t=0;tclasses->num;t++) { abc_class_t*c = (abc_class_t*)array_getvalue(file->classes, t); - if(!c->static_constructor) { - swf_SetU30(tag, nullmethod->index); - } else { - swf_SetU30(tag, c->static_constructor->index); - } - traits_write(pool, tag, c->static_constructor_traits); + assert(c->static_constructor); + swf_SetU30(tag, c->static_constructor->index); + + traits_write(pool, tag, c->static_traits); } swf_SetU30(tag, file->scripts->num); @@ -1069,10 +1138,15 @@ 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); @@ -1080,14 +1154,14 @@ void swf_WriteABC(TAG*abctag, void*code) code_write(tag, c->code, pool, file); swf_SetU30(tag, list_length(c->exceptions)); - exception_list_t*l = c->exceptions; + abc_exception_list_t*l = c->exceptions; while(l) { // warning: assumes "pos" in each code_t is up-to-date - swf_SetU30(tag, l->exception->from->pos); - swf_SetU30(tag, l->exception->to->pos); - swf_SetU30(tag, l->exception->target->pos); - swf_SetU30(tag, pool_register_multiname(pool, l->exception->exc_type)); - swf_SetU30(tag, pool_register_multiname(pool, l->exception->var_name)); + swf_SetU30(tag, l->abc_exception->from->pos); + swf_SetU30(tag, l->abc_exception->to->pos); + swf_SetU30(tag, l->abc_exception->target->pos); + swf_SetU30(tag, pool_register_multiname(pool, l->abc_exception->exc_type)); + swf_SetU30(tag, pool_register_multiname(pool, l->abc_exception->var_name)); l = l->next; } @@ -1124,15 +1198,17 @@ void swf_WriteABC(TAG*abctag, void*code) void abc_file_free(abc_file_t*file) { int t; - for(t=0;tmetadata->num;t++) { - array_t*items = (array_t*)array_getvalue(file->metadata, t); - int s; - for(s=0;snum;s++) { - free(array_getvalue(items, s)); + if(file->metadata) { + for(t=0;tmetadata->num;t++) { + array_t*items = (array_t*)array_getvalue(file->metadata, t); + int s; + for(s=0;snum;s++) { + free(array_getvalue(items, s)); + } + array_free(items); } - array_free(items); + array_free(file->metadata);file->metadata=0; } - array_free(file->metadata); for(t=0;tmethods->num;t++) { abc_method_t*m = (abc_method_t*)array_getvalue(file->methods, t); @@ -1159,12 +1235,12 @@ void abc_file_free(abc_file_t*file) } free(m); } - array_free(file->methods); + array_free(file->methods);file->methods=0; for(t=0;tclasses->num;t++) { abc_class_t*cls = (abc_class_t*)array_getvalue(file->classes, t); traits_free(cls->traits);cls->traits=0; - traits_free(cls->static_constructor_traits);cls->static_constructor_traits=0; + traits_free(cls->static_traits);cls->static_traits=0; if(cls->classname) { multiname_destroy(cls->classname); @@ -1185,23 +1261,23 @@ void abc_file_free(abc_file_t*file) } free(cls); } - array_free(file->classes); + array_free(file->classes);file->classes=0; for(t=0;tscripts->num;t++) { abc_script_t*s = (abc_script_t*)array_getvalue(file->scripts, t); traits_free(s->traits);s->traits=0; free(s); } - array_free(file->scripts); + array_free(file->scripts);file->scripts=0; for(t=0;tmethod_bodies->num;t++) { abc_method_body_t*body = (abc_method_body_t*)array_getvalue(file->method_bodies, t); code_free(body->code);body->code=0; traits_free(body->traits);body->traits=0; - exception_list_t*ee = body->exceptions; + abc_exception_list_t*ee = body->exceptions; while(ee) { - exception_t*e=ee->exception;ee->exception=0; + abc_exception_t*e=ee->abc_exception;ee->abc_exception=0; e->from = e->to = e->target = 0; multiname_destroy(e->exc_type);e->exc_type=0; multiname_destroy(e->var_name);e->var_name=0; @@ -1212,7 +1288,7 @@ void abc_file_free(abc_file_t*file) free(body); } - array_free(file->method_bodies); + array_free(file->method_bodies);file->method_bodies=0; if(file->name) { free((void*)file->name);file->name=0; @@ -1253,7 +1329,7 @@ void swf_AddButtonLinks(SWF*swf, char stop_each_frame, char events) swf_SetU16(tag, 0); swf_SetString(tag, "rfx.MainTimeline"); - c = abc_class_staticconstructor(cls, 0, 0); + c = abc_class_getstaticconstructor(cls, 0)->body; c->old.max_stack = 1; c->old.local_count = 1; c->old.init_scope_depth = 9; @@ -1263,7 +1339,7 @@ void swf_AddButtonLinks(SWF*swf, char stop_each_frame, char events) __ pushscope(c); __ returnvoid(c); - c = abc_class_constructor(cls, 0, 0); + c = abc_class_getconstructor(cls, 0)->body; c->old.max_stack = 3; c->old.local_count = 1; c->old.init_scope_depth = 10; @@ -1299,7 +1375,7 @@ void swf_AddButtonLinks(SWF*swf, char stop_each_frame, char events) __ getlex(c,framename); __ callpropvoid(c,"[package]::addFrameScript",2); - f = abc_class_method(cls, 0, framename, 0); + f = abc_class_method(cls, 0, multiname_fromstring(framename))->body; f->old.max_stack = 3; f->old.local_count = 1; f->old.init_scope_depth = 10; @@ -1308,6 +1384,10 @@ void swf_AddButtonLinks(SWF*swf, char stop_each_frame, char events) __ 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) { @@ -1320,14 +1400,12 @@ void swf_AddButtonLinks(SWF*swf, char stop_each_frame, char events) __ getlex(f,functionname); __ callpropvoid(f, "::addEventListener" ,2); - if(stop_each_frame) { - __ findpropstrict(f, "[package]::stop"); - __ callpropvoid(f, "[package]::stop", 0); - } needs_framescript = 1; abc_method_body_t*h = - abc_class_method(cls, 0, functionname, 1, "flash.events::MouseEvent"); + abc_class_method(cls, 0, multiname_fromstring(functionname))->body; + list_append(h->method->parameters, multiname_fromstring("flash.events::MouseEvent")); + h->old.max_stack = 6; h->old.local_count = 2; h->old.init_scope_depth = 10; @@ -1401,13 +1479,16 @@ void swf_AddButtonLinks(SWF*swf, char stop_each_frame, char events) if(tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2) { char buttonname[80]; sprintf(buttonname, "::button%d", swf_GetDefineID(tag)); - abc_AddSlot(cls, buttonname, 0, "flash.display::SimpleButton"); + multiname_t*s = multiname_fromstring(buttonname); + //abc_class_slot(cls, multiname_fromstring(buttonname), s); + abc_class_slot(cls, multiname_fromstring(buttonname), + multiname_fromstring("flash.display::SimpleButton")); } tag = tag->next; } - abc_script_t*s = abc_initscript(file, 0, 0); + abc_script_t*s = abc_initscript(file); c = s->method->body; c->old.max_stack = 2; c->old.local_count = 1; @@ -1451,3 +1532,39 @@ void swf_AddButtonLinks(SWF*swf, char stop_each_frame, char events) swf_WriteABC(abctag, file); } +TAG*swf_AddAS3FontDefine(TAG*tag, U16 id, char*fontname) +{ + tag = swf_InsertTag(tag, ST_DOABC); + abc_file_t*file = abc_file_new(); + + //abc_class_t*cls = abc_class_new2(file, fontname, "flash.display::MovieClip"); + //abc_class_slot(cls, multiname_fromstring(fontname), multiname_fromstring("flash.text::Font")); + + abc_class_t*cls = abc_class_new2(file, fontname, "flash.text::Font"); + + abc_script_t*s = abc_initscript(file); + code_t*c = s->method->body->code; + c = abc_getlocal_0(c); + c = abc_pushscope(c); + c = abc_getscopeobject(c, 0); + c = abc_getlex(c,"flash.text::Font"); + c = abc_pushscope(c); + c = abc_getlex(c,"flash.text::Font"); + c = abc_newclass(c,cls); + c = abc_popscope(c); + c = abc_initproperty(c, fontname); + c = abc_returnvoid(c); + s->method->body->code = c; + + abc_initscript_addClassTrait(s, multiname_fromstring(fontname), cls); + swf_WriteABC(tag, file); + + tag = swf_InsertTag(tag, ST_SYMBOLCLASS); + swf_SetU16(tag, 1); + swf_SetU16(tag, id); + swf_SetString(tag, fontname); + + return tag; +} + +