X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fas3%2Fabc.c;h=c8e9636486b869ac5161896fc29a426c017ed0f2;hb=876cadced9adaae335e18d8d0bb5288eec53570a;hp=7d4bce54eacaf4e089448011ec3b0c753028c075;hpb=f746167a36406fbea8879d15df89195ca25c7150;p=swftools.git diff --git a/lib/as3/abc.c b/lib/as3/abc.c index 7d4bce5..c8e9636 100644 --- a/lib/as3/abc.c +++ b/lib/as3/abc.c @@ -40,43 +40,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); + free(s); + if(i>=n-no) { + s = constant_tostring(o->constant); + fprintf(fo, " = "); + fprintf(fo, 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 @@ -170,7 +157,7 @@ void abc_class_add_interface(abc_class_t*c, multiname_t*interface) list_append(c->interfaces, multiname_clone(interface)); } -static abc_method_t* add_method(abc_file_t*file, abc_class_t*cls, multiname_t*returntype, char body) +abc_method_t* abc_method_new(abc_file_t*file, multiname_t*returntype, char body) { /* construct method object */ NEW(abc_method_t,m); @@ -200,7 +187,7 @@ abc_method_t* abc_class_getconstructor(abc_class_t*cls, multiname_t*returntype) if(cls->constructor) { return cls->constructor; } - abc_method_t* m = add_method(cls->file, cls, returntype, 1); + abc_method_t* m = abc_method_new(cls->file, returntype, 1); cls->constructor = m; return m; } @@ -210,7 +197,7 @@ abc_method_t* abc_class_getstaticconstructor(abc_class_t*cls, multiname_t*return if(cls->static_constructor) { return cls->static_constructor; } - abc_method_t* m = add_method(cls->file, cls, returntype, 1); + abc_method_t* m = abc_method_new(cls->file, returntype, 1); cls->static_constructor = m; return m; } @@ -227,7 +214,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)); @@ -236,9 +224,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)); @@ -247,28 +239,27 @@ 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_t* abc_class_method(abc_class_t*cls, multiname_t*returntype, multiname_t*name) { abc_file_t*file = cls->file; - abc_method_t* m = add_method(cls->file, cls, returntype, !(cls->flags&CLASS_INTERFACE)); - m->trait = trait_new_method(multiname_clone(name), m); - /* start assigning traits at position #1. - Weird things happen when assigning slot 0- slot 0 and 1 seem - to be identical */ - m->trait->slot_id = list_length(cls->traits)+1; - list_append(cls->traits, m->trait); + 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 = add_method(cls->file, cls, returntype, !(cls->flags&CLASS_INTERFACE)); - m->trait = trait_new_method(multiname_clone(name), m); - m->trait->slot_id = list_length(cls->static_traits)+1; - list_append(cls->static_traits, m->trait); + 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; } @@ -277,9 +268,7 @@ 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(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) @@ -287,9 +276,7 @@ trait_t* abc_class_staticslot(abc_class_t*cls, multiname_t*name, multiname_t*typ 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(m_type, m_name, 0); - t->slot_id = list_length(cls->static_traits)+1; - list_append(cls->static_traits, t); + trait_t*t = trait_new_member(&cls->static_traits, m_type, m_name, 0); return t; } @@ -329,9 +316,9 @@ 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) +abc_script_t* abc_initscript(abc_file_t*file) { - abc_method_t*m = add_method(file, 0, returntype, 1); + abc_method_t*m = abc_method_new(file, 0, 1); abc_script_t* s = malloc(sizeof(abc_script_t)); s->method = m; s->traits = list_new(); @@ -340,21 +327,29 @@ abc_script_t* abc_initscript(abc_file_t*file, multiname_t*returntype) 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*attr, 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 %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; + + 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; @@ -386,9 +381,9 @@ static void dump_method(FILE*fo, const char*prefix, const char*attr, 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); } @@ -454,10 +449,6 @@ static trait_list_t* traits_parse(TAG*tag, pool_t*pool, abc_file_t*file) 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); @@ -551,7 +542,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) { @@ -574,16 +565,16 @@ static void traits_dump(FILE*fo, const char*prefix, trait_list_t*traits, abc_fil if(kind == TRAIT_METHOD) { abc_method_t*m = trait->method; - dump_method(fo, prefix, type, "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, type, "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, type, "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, type, "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) { @@ -595,9 +586,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 { @@ -611,7 +602,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); @@ -630,6 +621,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]; @@ -667,25 +659,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_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->index); + dump_method(fo, prefix, "", "internalmethod", name, m, file, methods_seen); + } + } + dict_destroy(methods_seen); + return file; } @@ -708,6 +720,8 @@ void* swf_ReadABC(TAG*tag) } pool_read(pool, tag); + pool_dump(pool, stdout, 2); + printf("pool is %d bytes\n", tag->pos); int num_methods = swf_GetU30(tag); DEBUG printf("%d methods\n", num_methods); @@ -724,7 +738,7 @@ void* swf_ReadABC(TAG*tag) for(s=0;sparameters, param); } @@ -737,7 +751,9 @@ 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 ", m->name); + DEBUG params_dump(stdout, m->parameters, m->optional_parameters); + DEBUG printf("flags=%02x\n", t, m->flags); if(m->flags&0x08) { m->optional_parameters = list_new(); @@ -748,6 +764,7 @@ 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) { @@ -910,10 +927,11 @@ 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(); TAG*tmp = swf_InsertTag(0,0); TAG*tag = tmp; @@ -1036,8 +1054,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; } } @@ -1114,7 +1137,6 @@ void swf_WriteABC(TAG*abctag, void*code) //swf_SetU30(tag, c->old.max_scope_depth); swf_SetU30(tag, c->stats->max_stack); - int param_num = list_length(c->method->parameters)+1; if(c->method->flags&METHOD_NEED_REST) param_num++; @@ -1168,6 +1190,14 @@ 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); + writeABC(abctag, code, pool); pool_destroy(pool); } @@ -1456,13 +1486,15 @@ void swf_AddButtonLinks(SWF*swf, char stop_each_frame, char events) char buttonname[80]; sprintf(buttonname, "::button%d", swf_GetDefineID(tag)); multiname_t*s = multiname_fromstring(buttonname); - abc_class_slot(cls, multiname_fromstring(buttonname), s); + //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); + abc_script_t*s = abc_initscript(file); c = s->method->body; c->old.max_stack = 2; c->old.local_count = 1; @@ -1506,3 +1538,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; +} + +