new registry format
[swftools.git] / lib / as3 / mklib.c
index ff9cfbc..1d186b4 100644 (file)
 #include <memory.h>
 #include "../rfxswf.h"
 #include "../os.h"
+#include "../q.h"
 #include "pool.h"
 #include "files.h"
 #include "tokenizer.h"
 #include "parser.tab.h"
 #include "parser.h"
+#include "import.h"
 
 void fixstring(char*s)
 {
@@ -42,7 +44,18 @@ void fixstring(char*s)
     }
 }
 
-char* mkid(const char*package, const char*name)
+static 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;
+}
+static char* mkcid(const char*package, const char*name)
 {
     char*id = malloc(strlen(package)+strlen(name)+10);
     strcpy(id, package);
@@ -51,25 +64,27 @@ char* mkid(const char*package, const char*name)
     fixstring(id);
     return id;
 }
-
-char*mkid2(multiname_t*m)
+static char* mkptr2(const char*package, const char*name)
 {
-    if(m->type == QNAME)
-        return mkid(m->ns->name, m->name);
-    else if(m->type == MULTINAME) {
-        namespace_list_t*l = m->namespace_set->namespaces;
-        while(l) {
-            if(l->namespace->name &&
-               l->namespace->name[0])
-                break;
-            l = l->next;
-        }
-        return mkid(l->namespace->name, m->name);
-    }
-    else {
-        fprintf(stderr, "can't convert multiname type %d\n", m->type);
-    }
+    char*id = malloc(strlen(package)+strlen(name)+10);
+    strcpy(id, "&");
+    strcat(id, package);
+    strcat(id, "_");
+    strcat(id, name);
+    fixstring(id+1);
+    return id;
+}
+static char* mkid2(const char*cls, const char*member)
+{
+    char*id = malloc(strlen(cls)+strlen(member)+10);
+    strcpy(id, cls);
+    strcat(id, "_");
+    strcat(id, member);
+    fixstring(id);
+    return id;
 }
+#define mkid(s) ((s)?mkcid((s)->package, (s)->name):"0")
+#define mkptr(s) ((s)?mkptr2((s)->package, (s)->name):"0")
 
 static array_t*tosort=0;
 static int compare_classes(const void*v1, const void*v2)
@@ -84,172 +99,179 @@ static int compare_classes(const void*v1, const void*v2)
     return strcmp(c1->classname->name, c2->classname->name);
 }
 
-char* kind2string(int kind)
+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);
 }
 
-void load_libraries(char*filename, int pass, FILE*fi)
+dict_t* builtin_getclasses()
 {
-    SWF swf;
-    memset(&swf, 0, sizeof(SWF));
-    TAG*tag = swf_InsertTag(0, ST_RAWABC);
-    memfile_t*file = memfile_open(filename);
-    tag->data = file->data;
-    tag->len = file->len;
-    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;
-
-        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);
-            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;
-                }
-            }
-            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);
-        }
+    return dict_new2(&slotinfo_type);
+}
 
-      
-        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(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);
-            }
-            if(pass==0) {
-                fprintf(fi, "static memberinfo_t %s;\n", id2);
-            } if(pass==1) {
-                fprintf(fi, "static memberinfo_t %s = {%s, \"%s\"", id2, type, name);
-                if(!retvalue)
-                    fprintf(fi, ", 0");
-                else
-                    fprintf(fi, ", &%s", retvalue);
-                fprintf(fi, "};\n");
-            } else if(pass==2) {
-                fprintf(fi, "    dict_put(&%s.members, \"%s\", &%s);\n", id, name, id2);
+extern dict_t*registry_classes;
+
+char*mktype(slotinfo_t*s) 
+{
+    if(s->kind == INFOTYPE_CLASS) {
+        return "classinfo_t";
+    } else if(s->kind == INFOTYPE_METHOD) {
+        return "methodinfo_t";
+    } else if(s->kind == INFOTYPE_SLOT) {
+        return "varinfo_t";
+    }
+}
+
+void write_slotinfo(FILE*fi, slotinfo_t*s, char*id, char*prefix);
+
+void write_slotinfo_decl(FILE*fi, slotinfo_t*s, char*prefix)
+{
+    fprintf(fi, "%s", prefix);
+    char*id = mkid(s);
+    fprintf(fi, "static %s %s;\n", mktype(s), id);
+
+    if(s->kind == INFOTYPE_CLASS) {
+        classinfo_t*c = (classinfo_t*)s;
+        dict_t*d = &c->members;
+        int t;
+        for(t=0;t<d->hashsize;t++) {
+            dictentry_t*l = d->slots[t];
+            while(l) {
+                slotinfo_t*s2 = (slotinfo_t*)l->data;
+                fprintf(fi, "static %s %s;\n", mktype(s2), mkid2(id, s2->name));
+                l = l->next;
             }
-cont:
-            l = l->next;
-            if(!l && !is_static) {
-                l = cls->static_traits;
-                is_static = 1;
+        }
+    }
+}
+void write_initinfo(FILE*fi, slotinfo_t*s, char*prefix)
+{
+    if(s->kind == INFOTYPE_CLASS) {
+        classinfo_t*c = (classinfo_t*)s;
+        fprintf(fi, "%s", prefix);
+        char*id = mkid(c);
+        dict_t*d = &c->members;
+        fprintf(fi, "dict_init(&%s.members, %d);\n", id, d->hashsize);
+        int t;
+        for(t=0;t<d->hashsize;t++) {
+            dictentry_t*l = d->slots[t];
+            while(l) {
+                slotinfo_t*s2 = (slotinfo_t*)l->data;
+                fprintf(fi, "%s", prefix);
+                fprintf(fi, "dict_put(&%s.members, \"%s\", &%s);\n", id, s2->name, mkid2(id, s2->name));
+                l = l->next;
             }
         }
-        
-        dict_destroy(d);
-
-        if(id) free(id);
-        if(superid) free(superid);
     }
+}
+void write_slotinfo(FILE*fi, slotinfo_t*s, char*id, char*prefix)
+{
+    fprintf(fi, "%s", prefix);
+    fprintf(fi, "static %s %s = {", mktype(s), id);
+    fprintf(fi, "0x%02x, 0x%02x, 0x%02x, 0x%02x, ", s->kind, s->subtype, s->flags, s->access);
+    if(s->package)
+        fprintf(fi, "\"%s\", ", s->package);
+    else
+        fprintf(fi, "0, ");
     
-    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(s->name)
+        fprintf(fi, "\"%s\", ", s->name);
+    else
+        fprintf(fi, "0, ");
 
+    fprintf(fi, "%d, ", s->slot);
 
-    swf_FreeABC(abc);
-    memfile_close(file);tag->data=0;
-    swf_DeleteTag(0, tag);
+    if(s->kind == INFOTYPE_CLASS) {
+        classinfo_t*c = (classinfo_t*)s;
+        fprintf(fi, "%s, ", mkptr(c->superclass));
+        fprintf(fi, "interfaces: {");
+        int t;
+        for(t=0;c->interfaces[t];t++) {
+            fprintf(fi, "%c", mkptr(c->interfaces[t]));
+            if(c->interfaces[t+1]) 
+                fprintf(fi, ", ");
+        }
+        fprintf(fi, "0}};\n");
+    }
+    if(s->kind == INFOTYPE_METHOD) {
+        methodinfo_t*m = (methodinfo_t*)s;
+        fprintf(fi, "%s, ", mkptr(m->return_type));
+        fprintf(fi, "%s, ", mkptr(m->parent));
+        fprintf(fi, "0"); // params TODO
+        fprintf(fi, "};\n");
+    }
+    if(s->kind == INFOTYPE_SLOT) {
+        varinfo_t*m = (varinfo_t*)s;
+        fprintf(fi, "%s, ", mkptr(m->type));
+        fprintf(fi, "%s, ", mkptr(m->parent));
+        fprintf(fi, "0"); // value TODO
+        fprintf(fi, "};\n");
+    }
+    
+    if(s->kind == INFOTYPE_CLASS) {
+        classinfo_t*c = (classinfo_t*)s;
+        dict_t*d = &c->members;
+        int t;
+        for(t=0;t<d->hashsize;t++) {
+            dictentry_t*l = d->slots[t];
+            while(l) {
+                slotinfo_t*s2 = (slotinfo_t*)l->data;
+                write_slotinfo(fi, s2, mkid2(id,s2->name), prefix);
+                l = l->next;
+            }
+        }
+    }
 }
 
 int main()
 {
+    registry_classes = builtin_getclasses();
+
+    as3_import_abc("/home/kramm/c/swftools/lib/as3/builtin.abc");
+    as3_import_abc("/home/kramm/c/swftools/lib/as3/playerglobal.abc");
+
     FILE*fi = fopen("builtin.c", "wb");
-    fprintf(fi, "#include \"builtin.h\"\n");
-    load_libraries("builtin.abc", 0, fi);
-    load_libraries("playerglobal.abc", 0, fi);
-    
-    load_libraries("builtin.abc", 1, fi);
-    load_libraries("playerglobal.abc", 1, fi);
-   
-    fprintf(fi, "dict_t* builtin_getclasses()\n");
-    fprintf(fi, "{\n");
-    fprintf(fi, "    dict_t*d = dict_new2(&classinfo_type);\n");
-    load_libraries("builtin.abc", 2, fi);
-    load_libraries("playerglobal.abc", 2, fi);
+
+    int t;
+    int pass;
+
+
+    for(pass=1;pass<=3;pass++) {
+        if(pass==1) {
+            fprintf(fi, "#include \"builtin.h\"\n");
+            fprintf(fi, "\n");
+        }
+        if(pass==3) {
+            fprintf(fi, "dict_t* builtin_getclasses()\n");
+            fprintf(fi, "{\n");
+            fprintf(fi, "    dict_t*d = dict_new2(&slotinfo_type);\n");
+        }
+        for(t=0;t<registry_classes->hashsize;t++) {
+            dictentry_t*l = registry_classes->slots[t];
+            while(l) {
+                slotinfo_t*s = (slotinfo_t*)l->key;
+                //printf("%08x %s %s\n", s, s->package, s->name);
+                char*id = mkid(s);
+                if(pass==1) {
+                    write_slotinfo_decl(fi, s, "");
+                }
+                if(pass==2) {
+                    write_slotinfo(fi, s, mkid(s), "");
+                }
+                if(pass==3) {
+                    fprintf(fi, "    dict_put(d, &%s, &%s);\n", id, id);
+                    write_initinfo(fi, s, "    ");
+                }
+                l = l->next;
+            }
+        }
+    }
     fprintf(fi, "    return d;\n");
     fprintf(fi, "}\n");
-    fclose(fi);
+
 }