store global functions as classes, too
authorkramm <kramm>
Fri, 2 Jan 2009 19:47:35 +0000 (19:47 +0000)
committerkramm <kramm>
Fri, 2 Jan 2009 19:47:35 +0000 (19:47 +0000)
lib/as3/mklib.c

index 98d54cd..1a90eb8 100644 (file)
@@ -42,6 +42,17 @@ void fixstring(char*s)
     }
 }
 
+char* mkpid(const char*package)
+{
+    char*id = malloc(strlen(package)+20);
+    strcpy(id, "package_");
+    if(!*package) 
+        strcat(id, "global");
+    else
+        strcat(id, package);
+    fixstring(id);
+    return id;
+}
 char* mkid(const char*package, const char*name)
 {
     char*id = malloc(strlen(package)+strlen(name)+10);
@@ -84,10 +95,65 @@ static int compare_classes(const void*v1, const void*v2)
     return strcmp(c1->classname->name, c2->classname->name);
 }
 
+static int compare_traits(const void*v1, const void*v2)
+{
+    trait_t* x1 = *(trait_t**)v1;
+    trait_t* x2 = *(trait_t**)v2;
+    int i = strcmp(x1->name->ns->name, x2->name->ns->name);
+    if(i)
+        return i;
+    return strcmp(x1->name->name, x2->name->name);
+}
+
 char* kind2string(int kind)
 {
 }
 
+void write_member_info(FILE*fi, char*id2, const char*name, int flags, trait_t*trait)
+{
+    char*retvalue = 0;
+    char*type="0";
+    switch(trait->kind) {
+        case TRAIT_METHOD: {
+            multiname_t*ret = trait->method->return_type;
+
+            if(!ret)
+                retvalue = 0;
+            else
+                retvalue = mkid(ret->ns->name, ret->name);
+            if(ret && !strcmp(ret->name, "void"))
+                retvalue = 0;
+        } //fallthrough
+        case TRAIT_FUNCTION:
+            type = "MEMBER_METHOD";
+            break;
+        case TRAIT_CONST:
+        case TRAIT_GETTER:
+        case TRAIT_SETTER:
+        case TRAIT_SLOT:
+            type = "MEMBER_SLOT";
+            break;
+        default:
+            fprintf(stderr, "Unknown trait type %d\n", trait->kind);
+    }
+    fprintf(fi, "static memberinfo_t %s = {%s, 0x%02x, \"%s\"", id2, type, flags, name);
+    if(!retvalue)
+        fprintf(fi, ", 0");
+    else
+        fprintf(fi, ", &%s", retvalue);
+    fprintf(fi, "};\n");
+}
+
+int access2flags(int access)
+{
+    int flags=0;
+    if(access == ACCESS_PACKAGE) flags|=FLAG_PUBLIC;
+    if(access == ACCESS_PRIVATE) flags|=FLAG_PRIVATE;
+    if(access == ACCESS_PROTECTED) flags|=FLAG_PROTECTED;
+    if(access == ACCESS_PACKAGEINTERNAL) flags|=FLAG_INTERNAL;
+    return flags;
+}
+
 void load_libraries(char*filename, int pass, FILE*fi)
 {
     SWF swf;
@@ -99,143 +165,179 @@ void load_libraries(char*filename, int pass, FILE*fi)
     abc_file_t*abc = swf_ReadABC(tag);
     //swf_DumpABC(stdout, abc, "");
 
-    int*index = malloc(abc->classes->num*sizeof(int));
-    int t;
-    tosort=abc->classes;
-    for(t=0;t<abc->classes->num;t++) {index[t]=t;}
-    qsort(index, abc->classes->num, sizeof(int), compare_classes);
-    for(t=0;t<abc->classes->num;t++) {
-        abc_class_t*cls = array_getvalue(abc->classes, index[t]);
-        int access = cls->classname->ns->access;
-        if(access==ACCESS_PRIVATE ||
-           access==ACCESS_PACKAGEINTERNAL)
-            continue;
-        if(!strncmp(cls->classname->ns->name, "__AS3", 5))
-            continue;
+    if(pass<=2) {
+        int*index = malloc(abc->classes->num*sizeof(int));
+        int t;
+        tosort=abc->classes;
+        for(t=0;t<abc->classes->num;t++) {index[t]=t;}
+        qsort(index, abc->classes->num, sizeof(int), compare_classes);
 
-        const char*package = cls->classname->ns->name;
-        const char*name = cls->classname->name;
-        const char*superpackage = 0;
-        const char*supername = 0;
-        char*superid = 0;
-        if(cls->superclass) {
-            superpackage = cls->superclass->ns->name;
-            supername = cls->superclass->name;
-            superid = mkid(superpackage, supername);
-        }
-        char*id = mkid(package, name);
-        U8 flags = cls->flags;
-        
-        if(pass==0)  {
-            fprintf(fi, "static classinfo_t %s;\n", id);
-        } else if(pass==1) {
-            fprintf(fi, "static classinfo_t %s = {0x%02x, 0x%02x, \"%s\", \"%s\"", id, access, flags, package, name);
-            fprintf(fi, ", 0"); //slot
-            if(superid)
-                fprintf(fi, ", &%s, interfaces:{", superid);
-            else
-                fprintf(fi, ", 0, {");
-            if(cls->interfaces) {
-                multiname_list_t*i=cls->interfaces;
-                while(i) {
-                    char*iid = mkid2(i->multiname);
-                    fprintf(fi, "&%s, ", iid);
-                    i = i->next;
+        if(pass==-1) {
+            const char*last_package = "-*-";
+            for(t=0;t<abc->classes->num;t++) {
+                abc_class_t*cls = array_getvalue(abc->classes, index[t]);
+                const char*package = cls->classname->ns->name;
+                char*pid = mkpid(package);
+                if(strcmp(last_package, package)) {
+                    last_package = package;
+                    fprintf(fi, "static packageinfo_t %s = {\"%s\"};\n", pid, package);
                 }
             }
-            fprintf(fi, "0}};\n");
-        } else if(pass==2) {
-            trait_list_t*l=cls->traits;
-            fprintf(fi, "    dict_put(d, &%s, &%s);\n", id, id);
-            fprintf(fi, "    dict_init(&%s.members, %d);\n", id, list_length(l)+1);
         }
 
-      
-        trait_list_t*l=0;
-        char is_static = 0;
-        dict_t*d = dict_new();
-        l = cls->traits;
-        while(l) {
-            trait_t*trait = l->trait;
-            if(trait->name->ns->access==ACCESS_PRIVATE)
-                goto cont;
-            const char*name = trait->name->name;
-            char id2[1024];
-            sprintf(id2, "%s_%s", id, name);
-            char*retvalue = 0;
+        if(pass>=0)
+        for(t=0;t<abc->classes->num;t++) {
+            abc_class_t*cls = array_getvalue(abc->classes, index[t]);
+            int access = cls->classname->ns->access;
+            if(access==ACCESS_PRIVATE ||
+               access==ACCESS_PACKAGEINTERNAL)
+                continue;
+            if(!strncmp(cls->classname->ns->name, "__AS3", 5))
+                continue;
 
-            if(dict_lookup(d, name)) {
-                goto cont;
-            } else {
-                dict_put(d, (char*)name, (char*)name);
-            }
-            char*type="0";
-            switch(trait->kind) {
-                case TRAIT_METHOD: {
-                    multiname_t*ret = trait->method->return_type;
-                    if(!ret)
-                        retvalue = 0;
-                    else
-                        retvalue = mkid(ret->ns->name, ret->name);
-                    if(ret && !strcmp(ret->name, "void"))
-                        retvalue = 0;
-                } //fallthrough
-                case TRAIT_FUNCTION:
-                    type = "MEMBER_METHOD";
-                    break;
-                case TRAIT_CONST:
-                case TRAIT_GETTER:
-                case TRAIT_SETTER:
-                case TRAIT_SLOT:
-                    type = "MEMBER_SLOT";
-                    break;
-                default:
-                    fprintf(stderr, "Unknown trait type %d\n", trait->kind);
+            const char*package = cls->classname->ns->name;
+            const char*name = cls->classname->name;
+            const char*superpackage = 0;
+            const char*supername = 0;
+            char*superid = 0;
+            if(cls->superclass) {
+                superpackage = cls->superclass->ns->name;
+                supername = cls->superclass->name;
+                superid = mkid(superpackage, supername);
             }
-            int flags = is_static?FLAG_STATIC:0;
-
-            if(access == ACCESS_PACKAGE) flags|=FLAG_PUBLIC;
-            if(access == ACCESS_PRIVATE) flags|=FLAG_PRIVATE;
-            if(access == ACCESS_PROTECTED) flags|=FLAG_PROTECTED;
-            if(access == ACCESS_PACKAGEINTERNAL) flags|=FLAG_INTERNAL;
-
-            if(pass==0) {
-                fprintf(fi, "static memberinfo_t %s;\n", id2);
-            } if(pass==1) {
-                fprintf(fi, "static memberinfo_t %s = {%s, 0x%02x, \"%s\"", id2, type, flags, name);
-                if(!retvalue)
-                    fprintf(fi, ", 0");
+            char*id = mkid(package, name);
+            U8 flags = cls->flags;
+            
+            if(pass==0)  {
+                fprintf(fi, "static classinfo_t %s;\n", id);
+            } else if(pass==1) {
+                fprintf(fi, "static classinfo_t %s = {0x%02x, 0x%02x, \"%s\", \"%s\"", id, access, flags, package, name);
+                fprintf(fi, ", 0"); //slot
+                if(superid)
+                    fprintf(fi, ", &%s, interfaces:{", superid);
                 else
-                    fprintf(fi, ", &%s", retvalue);
-                fprintf(fi, "};\n");
+                    fprintf(fi, ", 0, {");
+                if(cls->interfaces) {
+                    multiname_list_t*i=cls->interfaces;
+                    while(i) {
+                        char*iid = mkid2(i->multiname);
+                        fprintf(fi, "&%s, ", iid);
+                        i = i->next;
+                    }
+                }
+                fprintf(fi, "0}};\n");
             } else if(pass==2) {
-                fprintf(fi, "    dict_put(&%s.members, \"%s\", &%s);\n", id, name, id2);
+                trait_list_t*l=cls->traits;
+                fprintf(fi, "    dict_put(d, &%s, &%s);\n", id, id);
+                fprintf(fi, "    dict_init(&%s.members, %d);\n", id, list_length(l)+1);
             }
-cont:
-            l = l->next;
-            if(!l && !is_static) {
-                l = cls->static_traits;
-                is_static = 1;
+
+          
+            trait_list_t*l=0;
+            char is_static = 0;
+            dict_t*d = dict_new();
+            l = cls->traits;
+            while(l) {
+                trait_t*trait = l->trait;
+                if(trait->name->ns->access==ACCESS_PRIVATE)
+                    goto cont;
+                const char*name = trait->name->name;
+                char id2[1024];
+                sprintf(id2, "%s_%s", id, name);
+                
+                if(dict_lookup(d, name)) {
+                    goto cont;
+                } else {
+                    dict_put(d, (char*)name, (char*)name);
+                }
+                int flags = is_static?FLAG_STATIC:0;
+                //flags |= access2flags(access);
+                flags |= access2flags(trait->name->ns->access);
+
+                if(pass==0) {
+                    fprintf(fi, "static memberinfo_t %s;\n", id2);
+                } if(pass==1) {
+                    write_member_info(fi, id2, name, flags, trait);
+                } else if(pass==2) {
+                    fprintf(fi, "    dict_put(&%s.members, \"%s\", &%s);\n", id, name, id2);
+                }
+    cont:
+                l = l->next;
+                if(!l && !is_static) {
+                    l = cls->static_traits;
+                    is_static = 1;
+                }
             }
-        }
-        
-        dict_destroy(d);
+            
+            dict_destroy(d);
 
-        if(id) free(id);
-        if(superid) free(superid);
-    }
-    
-    for(t=0;t<abc->scripts->num;t++) {
-        abc_script_t*s = array_getvalue(abc->scripts, t);
-        trait_list_t*l=0;
-       for(l=s->traits;l;l=l->next) {
-            trait_t*trait = l->trait;
-            if(trait->kind == TRAIT_METHOD) {
-               printf("%s\n", multiname_tostring(trait->name));
-           }
-       }
+            if(id) free(id);
+            if(superid) free(superid);
+        }
+        free(index);
     }
 
+    if(pass==0 || pass==1 || pass==3) {
+        int t;
+
+#define IS_PUBLIC_MEMBER(trait) ((trait)->kind != TRAIT_CLASS)
+  
+        /* count public functions */
+        int num_methods=0;
+        for(t=0;t<abc->scripts->num;t++) {
+            trait_list_t*l = ((abc_script_t*)array_getvalue(abc->scripts, t))->traits;
+            for(;l;l=l->next) {
+                num_methods += IS_PUBLIC_MEMBER(l->trait);
+            }
+        }
+        trait_t**traits = (trait_t**)malloc(num_methods*sizeof(trait_t*));
+        num_methods=0;
+        for(t=0;t<abc->scripts->num;t++) {
+            trait_list_t*l = ((abc_script_t*)array_getvalue(abc->scripts, t))->traits;
+            for(;l;l=l->next) {
+                if(IS_PUBLIC_MEMBER(l->trait)) {
+                    traits[num_methods++] = l->trait;
+                }
+            }
+        }
+        qsort(traits, num_methods, sizeof(trait_t*), compare_traits);
+        const char*last_package = "-xxx-";
+        for(t=0;t<num_methods;t++) {
+            trait_t*trait = traits[t];
+            if(IS_PUBLIC_MEMBER(trait)) {
+                const char*package = trait->name->ns->name;
+                const char*name = trait->name->name;
+                char*pid = mkpid(package);
+                char*id2 = mkid2(trait->name);
+                int flags = FLAG_STATIC|access2flags(trait->name->ns->access);
+                NEW(memberinfo_t,m);
+                char np = 0;
+                int clsflags = FLAG_STATIC | FLAG_METHOD;
+                if(pass==0) {
+                    fprintf(fi, "static memberinfo_t %s;\n", id2);
+                    fprintf(fi, "static classinfo_t %s_class;\n", id2);
+                } else if(pass==1) {
+                    write_member_info(fi, id2, name, flags, trait);
+                    fprintf(fi, "static classinfo_t %s_class = {0x%02x, 0x%02x, \"%s\", \"%s\", &%s, 0, members:{0}};\n", 
+                            id2,
+                            trait->name->ns->access, clsflags,
+                            package, name, 
+                            id2);
+                } else if(pass==3) {
+                    /*if(np) {
+                        fprintf(fi, "    dict_init(%s.classes, 1); //not used yet\n", pid);
+                        fprintf(fi, "    dict_init(%s.functions, 1);\n", pid);
+                    }
+                    fprintf(fi, "    dict_put(&%s.functions, \"%s\", &%s);\n", pid, name, id2);*/
+                    fprintf(fi, "    dict_put(d, &%s_class, &%s_class);\n", id2, id2);
+                }
+            } else if(trait->kind == TRAIT_CLASS) {
+                // ignore classes, these are treated above
+            } else {
+                printf("%02x %s\n", trait->kind, multiname_tostring(trait->name));
+            }
+        }
+    }
 
     swf_FreeABC(abc);
     memfile_close(file);tag->data=0;
@@ -246,6 +348,12 @@ int main()
 {
     FILE*fi = fopen("builtin.c", "wb");
     fprintf(fi, "#include \"builtin.h\"\n");
+
+    //load_libraries("builtin.abc", -1, fi);
+    //load_libraries("playerglobal.abc", -1, fi);
+    //fprintf(fi, "static packageinfo_t package_flash_debugger = {\"flash.debugger\"};\n");
+    //fprintf(fi, "static packageinfo_t package_flash_profiler = {\"flash.profiler\"};\n");
+
     load_libraries("builtin.abc", 0, fi);
     load_libraries("playerglobal.abc", 0, fi);
     
@@ -257,7 +365,19 @@ int main()
     fprintf(fi, "    dict_t*d = dict_new2(&classinfo_type);\n");
     load_libraries("builtin.abc", 2, fi);
     load_libraries("playerglobal.abc", 2, fi);
+    load_libraries("builtin.abc", 3, fi);
+    load_libraries("playerglobal.abc", 3, fi);
     fprintf(fi, "    return d;\n");
     fprintf(fi, "}\n");
+    fprintf(fi, "\n");
+    
+    //fprintf(fi, "dict_t* builtin_getglobalfunctions()\n");
+    //fprintf(fi, "{\n");
+    //fprintf(fi, "    dict_t*d = dict_new();\n");
+    //load_libraries("builtin.abc", 3, fi);
+    //load_libraries("playerglobal.abc", 3, fi);
+    //fprintf(fi, "    return d;\n");
+    //fprintf(fi, "}\n");
+
     fclose(fi);
 }