98d54cddd312bc5cf2895460e405ea823a676e31
[swftools.git] / 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 "pool.h"
28 #include "files.h"
29 #include "tokenizer.h"
30 #include "parser.tab.h"
31 #include "parser.h"
32
33 void fixstring(char*s)
34 {
35     char first=1;
36     for(;*s;s++) {
37         if(!((*s>='a' && *s<='z') || (*s>='A' && *s<='Z') || 
38                     (*s>='0' && *s<='9' && !first))) {
39             *s = '_';
40         }
41         first = 0;
42     }
43 }
44
45 char* mkid(const char*package, const char*name)
46 {
47     char*id = malloc(strlen(package)+strlen(name)+10);
48     strcpy(id, package);
49     strcat(id, "_");
50     strcat(id, name);
51     fixstring(id);
52     return id;
53 }
54
55 char*mkid2(multiname_t*m)
56 {
57     if(m->type == QNAME)
58         return mkid(m->ns->name, m->name);
59     else if(m->type == MULTINAME) {
60         namespace_list_t*l = m->namespace_set->namespaces;
61         while(l) {
62             if(l->namespace->name &&
63                l->namespace->name[0])
64                 break;
65             l = l->next;
66         }
67         return mkid(l->namespace->name, m->name);
68     }
69     else {
70         fprintf(stderr, "can't convert multiname type %d\n", m->type);
71     }
72 }
73
74 static array_t*tosort=0;
75 static int compare_classes(const void*v1, const void*v2)
76 {
77     int x1 = *(int*)v1;
78     int x2 = *(int*)v2;
79     abc_class_t*c1 = array_getvalue(tosort, x1);
80     abc_class_t*c2 = array_getvalue(tosort, x2);
81     int i = strcmp(c1->classname->ns->name, c2->classname->ns->name);
82     if(i)
83         return i;
84     return strcmp(c1->classname->name, c2->classname->name);
85 }
86
87 char* kind2string(int kind)
88 {
89 }
90
91 void load_libraries(char*filename, int pass, FILE*fi)
92 {
93     SWF swf;
94     memset(&swf, 0, sizeof(SWF));
95     TAG*tag = swf_InsertTag(0, ST_RAWABC);
96     memfile_t*file = memfile_open(filename);
97     tag->data = file->data;
98     tag->len = file->len;
99     abc_file_t*abc = swf_ReadABC(tag);
100     //swf_DumpABC(stdout, abc, "");
101
102     int*index = malloc(abc->classes->num*sizeof(int));
103     int t;
104     tosort=abc->classes;
105     for(t=0;t<abc->classes->num;t++) {index[t]=t;}
106     qsort(index, abc->classes->num, sizeof(int), compare_classes);
107     for(t=0;t<abc->classes->num;t++) {
108         abc_class_t*cls = array_getvalue(abc->classes, index[t]);
109         int access = cls->classname->ns->access;
110         if(access==ACCESS_PRIVATE ||
111            access==ACCESS_PACKAGEINTERNAL)
112             continue;
113         if(!strncmp(cls->classname->ns->name, "__AS3", 5))
114             continue;
115
116         const char*package = cls->classname->ns->name;
117         const char*name = cls->classname->name;
118         const char*superpackage = 0;
119         const char*supername = 0;
120         char*superid = 0;
121         if(cls->superclass) {
122             superpackage = cls->superclass->ns->name;
123             supername = cls->superclass->name;
124             superid = mkid(superpackage, supername);
125         }
126         char*id = mkid(package, name);
127         U8 flags = cls->flags;
128         
129         if(pass==0)  {
130             fprintf(fi, "static classinfo_t %s;\n", id);
131         } else if(pass==1) {
132             fprintf(fi, "static classinfo_t %s = {0x%02x, 0x%02x, \"%s\", \"%s\"", id, access, flags, package, name);
133             fprintf(fi, ", 0"); //slot
134             if(superid)
135                 fprintf(fi, ", &%s, interfaces:{", superid);
136             else
137                 fprintf(fi, ", 0, {");
138             if(cls->interfaces) {
139                 multiname_list_t*i=cls->interfaces;
140                 while(i) {
141                     char*iid = mkid2(i->multiname);
142                     fprintf(fi, "&%s, ", iid);
143                     i = i->next;
144                 }
145             }
146             fprintf(fi, "0}};\n");
147         } else if(pass==2) {
148             trait_list_t*l=cls->traits;
149             fprintf(fi, "    dict_put(d, &%s, &%s);\n", id, id);
150             fprintf(fi, "    dict_init(&%s.members, %d);\n", id, list_length(l)+1);
151         }
152
153       
154         trait_list_t*l=0;
155         char is_static = 0;
156         dict_t*d = dict_new();
157         l = cls->traits;
158         while(l) {
159             trait_t*trait = l->trait;
160             if(trait->name->ns->access==ACCESS_PRIVATE)
161                 goto cont;
162             const char*name = trait->name->name;
163             char id2[1024];
164             sprintf(id2, "%s_%s", id, name);
165             char*retvalue = 0;
166
167             if(dict_lookup(d, name)) {
168                 goto cont;
169             } else {
170                 dict_put(d, (char*)name, (char*)name);
171             }
172             char*type="0";
173             switch(trait->kind) {
174                 case TRAIT_METHOD: {
175                     multiname_t*ret = trait->method->return_type;
176                     if(!ret)
177                         retvalue = 0;
178                     else
179                         retvalue = mkid(ret->ns->name, ret->name);
180                     if(ret && !strcmp(ret->name, "void"))
181                         retvalue = 0;
182                 } //fallthrough
183                 case TRAIT_FUNCTION:
184                     type = "MEMBER_METHOD";
185                     break;
186                 case TRAIT_CONST:
187                 case TRAIT_GETTER:
188                 case TRAIT_SETTER:
189                 case TRAIT_SLOT:
190                     type = "MEMBER_SLOT";
191                     break;
192                 default:
193                     fprintf(stderr, "Unknown trait type %d\n", trait->kind);
194             }
195             int flags = is_static?FLAG_STATIC:0;
196
197             if(access == ACCESS_PACKAGE) flags|=FLAG_PUBLIC;
198             if(access == ACCESS_PRIVATE) flags|=FLAG_PRIVATE;
199             if(access == ACCESS_PROTECTED) flags|=FLAG_PROTECTED;
200             if(access == ACCESS_PACKAGEINTERNAL) flags|=FLAG_INTERNAL;
201
202             if(pass==0) {
203                 fprintf(fi, "static memberinfo_t %s;\n", id2);
204             } if(pass==1) {
205                 fprintf(fi, "static memberinfo_t %s = {%s, 0x%02x, \"%s\"", id2, type, flags, name);
206                 if(!retvalue)
207                     fprintf(fi, ", 0");
208                 else
209                     fprintf(fi, ", &%s", retvalue);
210                 fprintf(fi, "};\n");
211             } else if(pass==2) {
212                 fprintf(fi, "    dict_put(&%s.members, \"%s\", &%s);\n", id, name, id2);
213             }
214 cont:
215             l = l->next;
216             if(!l && !is_static) {
217                 l = cls->static_traits;
218                 is_static = 1;
219             }
220         }
221         
222         dict_destroy(d);
223
224         if(id) free(id);
225         if(superid) free(superid);
226     }
227     
228     for(t=0;t<abc->scripts->num;t++) {
229         abc_script_t*s = array_getvalue(abc->scripts, t);
230         trait_list_t*l=0;
231         for(l=s->traits;l;l=l->next) {
232             trait_t*trait = l->trait;
233             if(trait->kind == TRAIT_METHOD) {
234                 printf("%s\n", multiname_tostring(trait->name));
235             }
236         }
237     }
238
239
240     swf_FreeABC(abc);
241     memfile_close(file);tag->data=0;
242     swf_DeleteTag(0, tag);
243 }
244
245 int main()
246 {
247     FILE*fi = fopen("builtin.c", "wb");
248     fprintf(fi, "#include \"builtin.h\"\n");
249     load_libraries("builtin.abc", 0, fi);
250     load_libraries("playerglobal.abc", 0, fi);
251     
252     load_libraries("builtin.abc", 1, fi);
253     load_libraries("playerglobal.abc", 1, fi);
254    
255     fprintf(fi, "dict_t* builtin_getclasses()\n");
256     fprintf(fi, "{\n");
257     fprintf(fi, "    dict_t*d = dict_new2(&classinfo_type);\n");
258     load_libraries("builtin.abc", 2, fi);
259     load_libraries("playerglobal.abc", 2, fi);
260     fprintf(fi, "    return d;\n");
261     fprintf(fi, "}\n");
262     fclose(fi);
263 }