X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fas3%2Finitcode.c;h=9bb4ffca1f9ceb93756527fff49f85025e046cd1;hb=639ac6b9f7a89f10d02c5d9ef41bca3bad4eaf2b;hp=59d2efca7eacc79b24df52e784ed58311dfd7a20;hpb=b8aa0577aae67db4da5221459102202febc5c103;p=swftools.git diff --git a/lib/as3/initcode.c b/lib/as3/initcode.c index 59d2efc..9bb4ffc 100644 --- a/lib/as3/initcode.c +++ b/lib/as3/initcode.c @@ -3,21 +3,96 @@ #include "registry.h" #include "initcode.h" -void initcode_add_classlist(abc_script_t*init, parsedclass_list_t*classes) +int compare_lists(const void *_v1, const void *_v2) +{ + classinfo_t**v1 = *(classinfo_t***)_v1; + classinfo_t**v2 = *(classinfo_t***)_v2; + parsedclass_t*p1 = **(parsedclass_t***)_v1; + parsedclass_t*p2 = **(parsedclass_t***)_v2; + if((p1->cls->flags^p2->cls->flags)&FLAG_INTERFACE) { + return (int)(p2->cls->flags&FLAG_INTERFACE) - (int)(p1->cls->flags&FLAG_INTERFACE); + } + do { + v1++;v2++; + if(*v1<*v2) return -1; + else if(*v1>*v2) return 1; + } while(*v1 && *v2); + return 0; +} + +/* sort classes so that + (a) interfaces appear before classes + (b) base classes always appear before their subclasses + (c) neighboring elements have similar scope stacks + + Notice: we don't yet handle multiple inheritance (in interfaces) correctly. +*/ +parsedclass_t** initcode_sort_classlist(parsedclass_list_t*classes) +{ + /* count classes */ + int count = 0; + parsedclass_list_t*l; + for(l=classes;l;l=l->next) { + count++; + } + void***list = malloc(sizeof(void**)*count); + + /* build an array for each class */ + int i = 0; + for(l=classes;l;l=l->next) { + classinfo_t*cls = l->parsedclass->cls; + int len=0; + classinfo_t*c=cls; + while(c) { + len ++; + c = c->flags&FLAG_INTERFACE?c->interfaces[0]:c->superclass; + } + void**a = (void**)malloc(sizeof(void*)*(len+2)); + a[0] = l->parsedclass; + a[len+1] = 0; + int t=len; + c = cls; + while(c) { + len ++; + a[t--] = c; + c = c->flags&FLAG_INTERFACE?c->interfaces[0]:c->superclass; + } + list[i++] = a; + } + + /* sort and flatten */ + qsort(list, count, sizeof(void**), compare_lists); + + parsedclass_t**list2 = malloc(sizeof(parsedclass_t*)*(count+1)); + for(i=0;inext) { - abc_class_t*abc = classes->parsedclass->abc; - classinfo_t*cls = classes->parsedclass->cls; + int t; + for(t=0;classes[t];t++) { + abc_class_t*abc = classes[t]->abc; + classinfo_t*cls = classes[t]->cls; + + array_append(init->file->classes, "", abc); /* write the construction code for this class to the global init function */ MULTINAME(classname2,cls); - int slotindex = abc_initscript_addClassTrait(init, &classname2, abc); + trait_t*trait = abc_initscript_addClassTrait(init, &classname2, abc); c = abc_getglobalscope(c); classinfo_t*s = cls->superclass; @@ -62,11 +137,13 @@ void initcode_add_classlist(abc_script_t*init, parsedclass_list_t*classes) while(count--) { c = abc_popscope(c); } - c = abc_setslot(c, slotindex); + c = abc_setslot(c, trait->slot_id); multiname_destroy(extends2); } c = abc_returnvoid(c); + free(classes); + init->method->body->code = c; }