more bugfixes
[swftools.git] / lib / as3 / mklib.c
1 /* mklib.c
2
3    File to generate builtin.c
4
5    Copyright (c) 2008,2009 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 "../q.h"
28 #include "pool.h"
29 #include "files.h"
30 #include "tokenizer.h"
31 #include "parser.tab.h"
32 #include "parser.h"
33 #include "import.h"
34
35 void fixstring(char*s)
36 {
37     char first=1;
38     for(;*s;s++) {
39         if(!((*s>='a' && *s<='z') || (*s>='A' && *s<='Z') || 
40                     (*s>='0' && *s<='9' && !first))) {
41             *s = '_';
42         }
43         first = 0;
44     }
45 }
46
47 static char* mkpid(const char*package)
48 {
49     char*id = malloc(strlen(package)+20);
50     strcpy(id, "package_");
51     if(!*package) 
52         strcat(id, "global");
53     else
54         strcat(id, package);
55     fixstring(id);
56     return id;
57 }
58 static char* mkcid(const char*package, const char*name)
59 {
60     char*id = malloc(strlen(package)+strlen(name)+10);
61     strcpy(id, package);
62     strcat(id, "_");
63     strcat(id, name);
64     fixstring(id);
65     return id;
66 }
67 static char* mkptr2(const char*package, const char*name)
68 {
69     if(!package[0] && !strcmp(name, "void")) {
70         return "&voidclass";
71     }
72     char*id = malloc(strlen(package)+strlen(name)+10);
73     strcpy(id, "&");
74     strcat(id, package);
75     strcat(id, "_");
76     strcat(id, name);
77     fixstring(id+1);
78     return id;
79 }
80 static char* mkid2(const char*cls, const char*member)
81 {
82     char*id = malloc(strlen(cls)+strlen(member)+10);
83     strcpy(id, cls);
84     strcat(id, "_");
85     strcat(id, member);
86     fixstring(id);
87     return id;
88 }
89 #define mkid(s) ((s)?mkcid((s)->package, (s)->name):"0")
90 #define mkptr(s) ((s)?mkptr2((s)->package, (s)->name):"0")
91
92 static array_t*tosort=0;
93 static int compare_classes(const void*v1, const void*v2)
94 {
95     int x1 = *(int*)v1;
96     int x2 = *(int*)v2;
97     abc_class_t*c1 = array_getvalue(tosort, x1);
98     abc_class_t*c2 = array_getvalue(tosort, x2);
99     int i = strcmp(c1->classname->ns->name, c2->classname->ns->name);
100     if(i)
101         return i;
102     return strcmp(c1->classname->name, c2->classname->name);
103 }
104
105 static int compare_traits(const void*v1, const void*v2)
106 {
107     trait_t* x1 = *(trait_t**)v1;
108     trait_t* x2 = *(trait_t**)v2;
109     int i = strcmp(x1->name->ns->name, x2->name->ns->name);
110     if(i)
111         return i;
112     return strcmp(x1->name->name, x2->name->name);
113 }
114
115 dict_t* builtin_getclasses()
116 {
117     return dict_new2(&slotinfo_type);
118 }
119
120 extern dict_t*registry_classes;
121
122 char*mktype(slotinfo_t*s) 
123 {
124     if(s->kind == INFOTYPE_CLASS) {
125         return "classinfo_t";
126     } else if(s->kind == INFOTYPE_METHOD) {
127         return "methodinfo_t";
128     } else if(s->kind == INFOTYPE_VAR) {
129         return "varinfo_t";
130     }
131     return "**ERROR**";
132 }
133
134 void write_slotinfo(FILE*fi, slotinfo_t*s, char*id, char*prefix);
135
136 void write_slotinfo_decl(FILE*fi, slotinfo_t*s, char*prefix)
137 {
138     fprintf(fi, "%s", prefix);
139     char*id = mkid(s);
140     fprintf(fi, "static %s %s;\n", mktype(s), id);
141
142     if(s->kind == INFOTYPE_CLASS) {
143         classinfo_t*c = (classinfo_t*)s;
144         dict_t*d = &c->members;
145         DICT_ITERATE_DATA(d, slotinfo_t*, s1) {
146             fprintf(fi, "static %s %s;\n", mktype(s1), mkid2(id, s1->name));
147         }
148         DICT_ITERATE_DATA(d, slotinfo_t*, s2) {
149             fprintf(fi, "static %s %s;\n", mktype(s2), mkid2(id, s2->name));
150         }
151     }
152 }
153 void write_initinfo(FILE*fi, slotinfo_t*s, char*prefix)
154 {
155     if(s->kind == INFOTYPE_CLASS) {
156         classinfo_t*c = (classinfo_t*)s;
157         char*id = mkid(c);
158         dict_t*d1 = &c->members;
159         dict_t*d2 = &c->static_members;
160         fprintf(fi, "%s", prefix);
161         fprintf(fi, "dict_init2(&%s.members, &memberinfo_type, %d);\n", id, d1->hashsize);
162         fprintf(fi, "%s", prefix);
163         fprintf(fi, "dict_init2(&%s.static_members, &memberinfo_type, %d);\n", id, d2->hashsize);
164         int t;
165         DICT_ITERATE_DATA(d1,slotinfo_t*,s1) {
166            fprintf(fi, "%s", prefix);
167            char*id2 = mkid2(id, s1->name);
168            fprintf(fi, "dict_put(&%s.members, &%s, &%s);\n", id, id2, id2);
169         }
170         DICT_ITERATE_DATA(d2,slotinfo_t*,s2) {
171            fprintf(fi, "%s", prefix);
172            char*id2 = mkid2(id, s2->name);
173            fprintf(fi, "dict_put(&%s.static_members, &%s, &%s);\n", id, id2, id2);
174         }
175     }
176 }
177
178 void write_constant(FILE*fi, constant_t*value, char*id, char*prefix)
179 {
180     if(NS_TYPE(value->type)) {
181         fprintf(fi, "%s", prefix);
182         fprintf(fi, "static namespace_t %s_constant_ns = {0x%02x, \"%s\"};\n", id, value->ns->access, value->ns->name);
183     } else if(value->type == CONSTANT_STRING) {
184         fprintf(fi, "%s", prefix);
185         fprintf(fi, "static string_t %s_constant_s = {\"%s\", %d};\n", id, value->s->str, value->s->len);
186     }
187     fprintf(fi, "%s", prefix);
188     fprintf(fi, "static constant_t %s_constant = ", id);
189     fprintf(fi, "{type: %d", value->type);
190     if(NS_TYPE(value->type)) {
191         fprintf(fi, ", &%s_constant_ns", id);
192     } else if(value->type == CONSTANT_INT) {
193         fprintf(fi, ",i: %d,", value->type);
194     } else if(value->type == CONSTANT_UINT) {
195         fprintf(fi, ",u: %u", value->u);
196     } else if(value->type == CONSTANT_FLOAT) {
197         if(!isnan(value->f) && !isinf(value->f))
198             fprintf(fi, ", %f", value->f);
199     } else if(value->type == CONSTANT_STRING) {
200         fprintf(fi, ", &%s_constant_s", id);
201     }
202     fprintf(fi, "};\n");
203 }
204
205 void write_slotinfo(FILE*fi, slotinfo_t*s, char*id, char*prefix)
206 {
207     if(s->kind == INFOTYPE_VAR) {
208         varinfo_t*v = (varinfo_t*)s;
209         if(v->value) {
210             write_constant(fi, v->value, id, prefix);
211         }
212     }
213     fprintf(fi, "%s", prefix);
214     fprintf(fi, "static %s %s = {", mktype(s), id);
215     fprintf(fi, "0x%02x, 0x%02x, 0x%02x, 0x%02x, ", s->kind, s->subtype, s->flags, s->access);
216     if(s->package)
217         fprintf(fi, "\"%s\", ", s->package);
218     else
219         fprintf(fi, "0, ");
220     
221     if(s->name)
222         fprintf(fi, "\"%s\", ", s->name);
223     else
224         fprintf(fi, "0, ");
225
226     fprintf(fi, "%d, ", s->slot);
227
228     if(s->kind == INFOTYPE_CLASS) {
229         classinfo_t*c = (classinfo_t*)s;
230         fprintf(fi, "%s, ", mkptr(c->superclass));
231         fprintf(fi, "interfaces: {");
232         int t;
233         for(t=0;c->interfaces[t];t++) {
234             fprintf(fi, "%s", mkptr(c->interfaces[t]));
235             fprintf(fi, ", ");
236         }
237         fprintf(fi, "0}};\n");
238     }
239     if(s->kind == INFOTYPE_METHOD) {
240         methodinfo_t*m = (methodinfo_t*)s;
241         fprintf(fi, "%s, ", mkptr(m->return_type));
242         fprintf(fi, "%s, ", mkptr(m->parent));
243         fprintf(fi, "0"); // params TODO
244         fprintf(fi, "};\n");
245     }
246     if(s->kind == INFOTYPE_VAR) {
247         varinfo_t*m = (varinfo_t*)s;
248         fprintf(fi, "%s, ", mkptr(m->type));
249         fprintf(fi, "%s, ", mkptr(m->parent));
250         if(!m->value) fprintf(fi, "0");
251         else          fprintf(fi, "&%s_constant", id);
252         fprintf(fi, "};\n");
253     }
254     
255     if(s->kind == INFOTYPE_CLASS) {
256         classinfo_t*c = (classinfo_t*)s;
257         dict_t*d = &c->members;
258         DICT_ITERATE_DATA(d, slotinfo_t*, s1) {
259             write_slotinfo(fi, s1, mkid2(id,s1->name), prefix);
260         }
261         d = &c->static_members;
262         DICT_ITERATE_DATA(d, slotinfo_t*, s2) {
263             write_slotinfo(fi, s2, mkid2(id,s2->name), prefix);
264         }
265     }
266 }
267
268 int main()
269 {
270     registry_classes = builtin_getclasses();
271
272     as3_import_abc("builtin.abc");
273     as3_import_abc("playerglobal.abc");
274
275     FILE*fi = fopen("builtin.c", "wb");
276
277     int t;
278     int pass;
279
280
281     for(pass=1;pass<=3;pass++) {
282         if(pass==1) {
283             fprintf(fi, "#include \"builtin.h\"\n");
284             fprintf(fi, "\n");
285         }
286         if(pass==3) {
287             fprintf(fi, "dict_t* builtin_getclasses()\n");
288             fprintf(fi, "{\n");
289             fprintf(fi, "    dict_t*d = dict_new2(&slotinfo_type);\n");
290         }
291         for(t=0;t<registry_classes->hashsize;t++) {
292             dictentry_t*l = registry_classes->slots[t];
293             while(l) {
294                 slotinfo_t*s = (slotinfo_t*)l->key;
295                 //printf("%08x %s %s\n", s, s->package, s->name);
296                 char*id = mkid(s);
297                 if(pass==1) {
298                     write_slotinfo_decl(fi, s, "");
299                 }
300                 if(pass==2) {
301                     write_slotinfo(fi, s, mkid(s), "");
302                 }
303                 if(pass==3) {
304                     fprintf(fi, "    dict_put(d, &%s, &%s);\n", id, id);
305                     write_initinfo(fi, s, "    ");
306                 }
307                 l = l->next;
308             }
309         }
310     }
311     fprintf(fi, "    _NaN_constant.f =  __builtin_nan(\"\");\n");
312     fprintf(fi, "    _Infinity_constant.f = __builtin_inf();\n");
313     fprintf(fi, "    return d;\n");
314     fprintf(fi, "}\n");
315     return 0;
316 }