added class flags
[swftools.git] / lib / as3 / mklib.c
1 /* code.c
2
3    File to generate builtin.c
4
5    Copyright (c) 2008 Matthias Kramm <kramm@quiss.org>
6  
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <memory.h>
25 #include "../rfxswf.h"
26 #include "../os.h"
27 #include "files.h"
28 #include "tokenizer.h"
29 #include "parser.tab.h"
30 #include "parser.h"
31
32 void fixstring(char*s)
33 {
34     char first=1;
35     for(;*s;s++) {
36         if(!((*s>='a' && *s<='z') || (*s>='A' && *s<='Z') || 
37                     (*s>='0' && *s<='9' && !first))) {
38             *s = '_';
39         }
40         first = 0;
41     }
42 }
43
44 char* mkid(const char*package, const char*name)
45 {
46     char*id = malloc(strlen(package)+strlen(name)+10);
47     strcpy(id, package);
48     strcat(id, "_");
49     strcat(id, name);
50     fixstring(id);
51     return id;
52 }
53
54 char*mkid2(multiname_t*m)
55 {
56     if(m->type == QNAME)
57         return mkid(m->ns->name, m->name);
58     else if(m->type == MULTINAME) {
59         namespace_list_t*l = m->namespace_set->namespaces;
60         while(l) {
61             if(l->namespace->name &&
62                l->namespace->name[0])
63                 break;
64             l = l->next;
65         }
66         return mkid(l->namespace->name, m->name);
67     }
68     else {
69         fprintf(stderr, "can't convert multiname type %d\n", m->type);
70     }
71 }
72
73 static array_t*tosort=0;
74 static int compare_classes(const void*v1, const void*v2)
75 {
76     int x1 = *(int*)v1;
77     int x2 = *(int*)v2;
78     abc_class_t*c1 = array_getvalue(tosort, x1);
79     abc_class_t*c2 = array_getvalue(tosort, x2);
80     int i = strcmp(c1->classname->ns->name, c2->classname->ns->name);
81     if(i)
82         return i;
83     return strcmp(c1->classname->name, c2->classname->name);
84 }
85
86 void load_libraries(char*filename, int pass, FILE*fi)
87 {
88     SWF swf;
89     memset(&swf, 0, sizeof(SWF));
90     TAG*tag = swf_InsertTag(0, ST_RAWABC);
91     memfile_t*file = memfile_open(filename);
92     tag->data = file->data;
93     tag->len = file->len;
94     abc_file_t*abc = swf_ReadABC(tag);
95     //swf_DumpABC(stdout, abc, "");
96
97     int*index = malloc(abc->classes->num*sizeof(int));
98     int t;
99     tosort=abc->classes;
100     for(t=0;t<abc->classes->num;t++) {index[t]=t;}
101     qsort(index, abc->classes->num, sizeof(int), compare_classes);
102
103     for(t=0;t<abc->classes->num;t++) {
104         abc_class_t*cls = array_getvalue(abc->classes, index[t]);
105         int access = cls->classname->ns->access;
106         if(access==ACCESS_PRIVATE ||
107            access==ACCESS_PACKAGEINTERNAL)
108             continue;
109         if(!strncmp(cls->classname->ns->name, "__AS3", 5))
110             continue;
111
112         const char*package = cls->classname->ns->name;
113         const char*name = cls->classname->name;
114         const char*superpackage = 0;
115         const char*supername = 0;
116         char*superid = 0;
117         if(cls->superclass) {
118             superpackage = cls->superclass->ns->name;
119             supername = cls->superclass->name;
120             superid = mkid(superpackage, supername);
121         }
122         char*id = mkid(package, name);
123         U8 flags = cls->flags;
124       
125         if(pass==0) 
126             fprintf(fi, "static class_signature_t %s;\n", id);
127         else if(pass==1) {
128             fprintf(fi, "static class_signature_t %s = {0x%02x, 0x%02x, \"%s\", \"%s\"", id, access, flags, package, name);
129             if(superid)
130                 fprintf(fi, ", &%s, interfaces:{", superid);
131             else
132                 fprintf(fi, ", 0, {");
133             if(cls->interfaces) {
134                 multiname_list_t*i=cls->interfaces;
135                 while(i) {
136                     char*iid = mkid2(i->multiname);
137                     fprintf(fi, "&%s, ", iid);
138                     i = i->next;
139                 }
140             }
141             fprintf(fi, "0}};\n");
142         } else if(pass==2) {
143             trait_list_t*l=cls->traits;
144             fprintf(fi, "    dict_put(d, &%s, &%s);\n", id, id);
145             fprintf(fi, "    dict_init(&%s.members, %d);\n", id, list_length(l)+1);
146             int j;
147             dict_t*d = dict_new();
148             for(;l;l=l->next) {
149                 trait_t*trait = l->trait;
150                 if(trait->name->ns->access==ACCESS_PRIVATE)
151                     continue;
152                 char*type="something";
153                 const char*name = trait->name->name;
154                 if(dict_lookup(d, name)) {
155                     continue;
156                 } else {
157                     dict_put(d, (char*)name, (char*)name);
158                 }
159                 switch(trait->kind) {
160                     case TRAIT_METHOD: type="method";break;
161                     case TRAIT_CONST: type="const";break;
162                     case TRAIT_FUNCTION: type="function";break;
163                     case TRAIT_GETTER: type="member";break;
164                     case TRAIT_SETTER: type="member";break;
165                     case TRAIT_SLOT: type="member";break;
166                     case TRAIT_CLASS: type="subclass";break;
167                 }
168                 fprintf(fi, "    dict_put(&%s.members, \"%s\", \"%s\");\n", 
169                         id, name, type);
170             }
171             l=cls->static_traits;
172             for(;l;l=l->next) {
173                 trait_t*trait = l->trait;
174                 if(trait->name->ns->access==ACCESS_PRIVATE)
175                     continue;
176                 char*type="static entity";
177                 const char*name = trait->name->name;
178                 if(dict_lookup(d, name)) {
179                     continue;
180                 } else {
181                     dict_put(d, (char*)name, (char*)name);
182                 }
183                 switch(trait->kind) {
184                     case TRAIT_METHOD: type="static method";break;
185                     case TRAIT_CONST: type="constant";break;
186                     case TRAIT_FUNCTION: type="static function";break;
187                     case TRAIT_GETTER: type="static variable";break;
188                     case TRAIT_SETTER: type="static variable";break;
189                     case TRAIT_SLOT: type="static variable";break;
190                     case TRAIT_CLASS: type="static subclass";break;
191                 }
192                 fprintf(fi, "    dict_put(&%s.members, \"%s\", \"%s\");\n", 
193                         id, name, type);
194             }
195             dict_destroy(d);
196         }
197
198         if(id) free(id);
199         if(superid) free(superid);
200     }
201
202     swf_FreeABC(abc);
203     memfile_close(file);tag->data=0;
204     swf_DeleteTag(0, tag);
205 }
206
207 int main()
208 {
209     FILE*fi = fopen("builtin.c", "wb");
210     fprintf(fi, "#include \"builtin.h\"\n");
211     load_libraries("builtin.abc", 0, fi);
212     load_libraries("playerglobal.abc", 0, fi);
213     
214     load_libraries("builtin.abc", 1, fi);
215     load_libraries("playerglobal.abc", 1, fi);
216    
217     fprintf(fi, "dict_t* builtin_getclasses()\n");
218     fprintf(fi, "{\n");
219     fprintf(fi, "    dict_t*d = dict_new2(&class_signature_type);\n");
220     load_libraries("builtin.abc", 2, fi);
221     load_libraries("playerglobal.abc", 2, fi);
222     fprintf(fi, "    return d;\n");
223     fprintf(fi, "}\n");
224     fclose(fi);
225 }