new registry format
[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 "../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     char*id = malloc(strlen(package)+strlen(name)+10);
70     strcpy(id, "&");
71     strcat(id, package);
72     strcat(id, "_");
73     strcat(id, name);
74     fixstring(id+1);
75     return id;
76 }
77 static char* mkid2(const char*cls, const char*member)
78 {
79     char*id = malloc(strlen(cls)+strlen(member)+10);
80     strcpy(id, cls);
81     strcat(id, "_");
82     strcat(id, member);
83     fixstring(id);
84     return id;
85 }
86 #define mkid(s) ((s)?mkcid((s)->package, (s)->name):"0")
87 #define mkptr(s) ((s)?mkptr2((s)->package, (s)->name):"0")
88
89 static array_t*tosort=0;
90 static int compare_classes(const void*v1, const void*v2)
91 {
92     int x1 = *(int*)v1;
93     int x2 = *(int*)v2;
94     abc_class_t*c1 = array_getvalue(tosort, x1);
95     abc_class_t*c2 = array_getvalue(tosort, x2);
96     int i = strcmp(c1->classname->ns->name, c2->classname->ns->name);
97     if(i)
98         return i;
99     return strcmp(c1->classname->name, c2->classname->name);
100 }
101
102 static int compare_traits(const void*v1, const void*v2)
103 {
104     trait_t* x1 = *(trait_t**)v1;
105     trait_t* x2 = *(trait_t**)v2;
106     int i = strcmp(x1->name->ns->name, x2->name->ns->name);
107     if(i)
108         return i;
109     return strcmp(x1->name->name, x2->name->name);
110 }
111
112 dict_t* builtin_getclasses()
113 {
114     return dict_new2(&slotinfo_type);
115 }
116
117 extern dict_t*registry_classes;
118
119 char*mktype(slotinfo_t*s) 
120 {
121     if(s->kind == INFOTYPE_CLASS) {
122         return "classinfo_t";
123     } else if(s->kind == INFOTYPE_METHOD) {
124         return "methodinfo_t";
125     } else if(s->kind == INFOTYPE_SLOT) {
126         return "varinfo_t";
127     }
128 }
129
130 void write_slotinfo(FILE*fi, slotinfo_t*s, char*id, char*prefix);
131
132 void write_slotinfo_decl(FILE*fi, slotinfo_t*s, char*prefix)
133 {
134     fprintf(fi, "%s", prefix);
135     char*id = mkid(s);
136     fprintf(fi, "static %s %s;\n", mktype(s), id);
137
138     if(s->kind == INFOTYPE_CLASS) {
139         classinfo_t*c = (classinfo_t*)s;
140         dict_t*d = &c->members;
141         int t;
142         for(t=0;t<d->hashsize;t++) {
143             dictentry_t*l = d->slots[t];
144             while(l) {
145                 slotinfo_t*s2 = (slotinfo_t*)l->data;
146                 fprintf(fi, "static %s %s;\n", mktype(s2), mkid2(id, s2->name));
147                 l = l->next;
148             }
149         }
150     }
151 }
152 void write_initinfo(FILE*fi, slotinfo_t*s, char*prefix)
153 {
154     if(s->kind == INFOTYPE_CLASS) {
155         classinfo_t*c = (classinfo_t*)s;
156         fprintf(fi, "%s", prefix);
157         char*id = mkid(c);
158         dict_t*d = &c->members;
159         fprintf(fi, "dict_init(&%s.members, %d);\n", id, d->hashsize);
160         int t;
161         for(t=0;t<d->hashsize;t++) {
162             dictentry_t*l = d->slots[t];
163             while(l) {
164                 slotinfo_t*s2 = (slotinfo_t*)l->data;
165                 fprintf(fi, "%s", prefix);
166                 fprintf(fi, "dict_put(&%s.members, \"%s\", &%s);\n", id, s2->name, mkid2(id, s2->name));
167                 l = l->next;
168             }
169         }
170     }
171 }
172 void write_slotinfo(FILE*fi, slotinfo_t*s, char*id, char*prefix)
173 {
174     fprintf(fi, "%s", prefix);
175     fprintf(fi, "static %s %s = {", mktype(s), id);
176     fprintf(fi, "0x%02x, 0x%02x, 0x%02x, 0x%02x, ", s->kind, s->subtype, s->flags, s->access);
177     if(s->package)
178         fprintf(fi, "\"%s\", ", s->package);
179     else
180         fprintf(fi, "0, ");
181     
182     if(s->name)
183         fprintf(fi, "\"%s\", ", s->name);
184     else
185         fprintf(fi, "0, ");
186
187     fprintf(fi, "%d, ", s->slot);
188
189     if(s->kind == INFOTYPE_CLASS) {
190         classinfo_t*c = (classinfo_t*)s;
191         fprintf(fi, "%s, ", mkptr(c->superclass));
192         fprintf(fi, "interfaces: {");
193         int t;
194         for(t=0;c->interfaces[t];t++) {
195             fprintf(fi, "%c", mkptr(c->interfaces[t]));
196             if(c->interfaces[t+1]) 
197                 fprintf(fi, ", ");
198         }
199         fprintf(fi, "0}};\n");
200     }
201     if(s->kind == INFOTYPE_METHOD) {
202         methodinfo_t*m = (methodinfo_t*)s;
203         fprintf(fi, "%s, ", mkptr(m->return_type));
204         fprintf(fi, "%s, ", mkptr(m->parent));
205         fprintf(fi, "0"); // params TODO
206         fprintf(fi, "};\n");
207     }
208     if(s->kind == INFOTYPE_SLOT) {
209         varinfo_t*m = (varinfo_t*)s;
210         fprintf(fi, "%s, ", mkptr(m->type));
211         fprintf(fi, "%s, ", mkptr(m->parent));
212         fprintf(fi, "0"); // value TODO
213         fprintf(fi, "};\n");
214     }
215     
216     if(s->kind == INFOTYPE_CLASS) {
217         classinfo_t*c = (classinfo_t*)s;
218         dict_t*d = &c->members;
219         int t;
220         for(t=0;t<d->hashsize;t++) {
221             dictentry_t*l = d->slots[t];
222             while(l) {
223                 slotinfo_t*s2 = (slotinfo_t*)l->data;
224                 write_slotinfo(fi, s2, mkid2(id,s2->name), prefix);
225                 l = l->next;
226             }
227         }
228     }
229 }
230
231 int main()
232 {
233     registry_classes = builtin_getclasses();
234
235     as3_import_abc("/home/kramm/c/swftools/lib/as3/builtin.abc");
236     as3_import_abc("/home/kramm/c/swftools/lib/as3/playerglobal.abc");
237
238     FILE*fi = fopen("builtin.c", "wb");
239
240     int t;
241     int pass;
242
243
244     for(pass=1;pass<=3;pass++) {
245         if(pass==1) {
246             fprintf(fi, "#include \"builtin.h\"\n");
247             fprintf(fi, "\n");
248         }
249         if(pass==3) {
250             fprintf(fi, "dict_t* builtin_getclasses()\n");
251             fprintf(fi, "{\n");
252             fprintf(fi, "    dict_t*d = dict_new2(&slotinfo_type);\n");
253         }
254         for(t=0;t<registry_classes->hashsize;t++) {
255             dictentry_t*l = registry_classes->slots[t];
256             while(l) {
257                 slotinfo_t*s = (slotinfo_t*)l->key;
258                 //printf("%08x %s %s\n", s, s->package, s->name);
259                 char*id = mkid(s);
260                 if(pass==1) {
261                     write_slotinfo_decl(fi, s, "");
262                 }
263                 if(pass==2) {
264                     write_slotinfo(fi, s, mkid(s), "");
265                 }
266                 if(pass==3) {
267                     fprintf(fi, "    dict_put(d, &%s, &%s);\n", id, id);
268                     write_initinfo(fi, s, "    ");
269                 }
270                 l = l->next;
271             }
272         }
273     }
274     fprintf(fi, "    return d;\n");
275     fprintf(fi, "}\n");
276
277 }