bugfixes
[swftools.git] / lib / as3 / compiler.c
1 /* compiler.h
2
3    Compiler for parsing Flash2 AVM2 ABC Actionscript
4
5    Extension module for the rfxswf library.
6    Part of the swftools package.
7
8    Copyright (c) 2008/2009 Matthias Kramm <kramm@quiss.org>
9  
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
23
24 #include "tokenizer.h"
25 #include "files.h"
26 #include "parser.h"
27 #include "parser.tab.h"
28 #include "compiler.h"
29 #include "../os.h"
30 #ifdef HAVE_DIRENT_H
31 #include <dirent.h>
32 #endif
33
34 /* flex/bison definitions */
35 extern int a3_parse();
36 extern int as3_lex();
37 extern int as3_lex_destroy();
38
39 void as3_setverbosity(int level)
40 {
41     as3_verbosity=level;
42 }
43 void as3_add_include_dir(char*dir)
44 {
45     add_include_dir(dir);
46 }
47
48 static char registry_initialized = 0;
49 static char parser_initialized = 0;
50
51 //#define STORE_TOKENS
52
53 #ifdef STORE_TOKENS
54 static mem_t tokens;
55 #endif
56
57 int a3_lex()
58 {
59     as3_tokencount++;
60 #ifdef STORE_TOKENS
61     if(as3_pass==1) {
62         int token = as3_lex();
63         /* FIXME: current_file needs to be stored, too */
64         mem_put(&tokens, &token, sizeof(token));
65         mem_put(&tokens, &a3_lval, sizeof(a3_lval));
66         mem_put(&tokens, &current_line, sizeof(current_line));
67         mem_put(&tokens, &current_column, sizeof(current_column));
68         return token;
69     } else {
70         int token;
71         mem_get(&tokens, &token, sizeof(token));
72         mem_get(&tokens, &a3_lval, sizeof(a3_lval));
73         mem_get(&tokens, &current_line, sizeof(current_line));
74         mem_get(&tokens, &current_column, sizeof(current_column));
75         return token;
76     }
77 #else
78     return as3_lex();
79 #endif
80 }
81
82 static void as3_parse_file_or_array(int pass, const char*name, const char*filename, void*mem, int length)
83 {
84     if(!registry_initialized) {
85         registry_initialized = 1;
86         registry_init();
87     }
88     if(!parser_initialized) {
89         parser_initialized = 1;
90         initialize_parser();
91 #if defined(STORE_TOKENS)
92         mem_init(&tokens);
93 #endif
94     }
95     as3_pass=pass;
96
97     FILE*fi = 0;
98     if(filename) {
99         //printf("[pass %d] parse file %s %s\n", pass, name, filename);
100         fi = enter_file2(name, filename, 0);
101         as3_file_input(fi);
102     } else {
103         //printf("[pass %d] parse bytearray %s (%d bytes)\n", pass, name, length);
104         enter_file(name, name, 0);
105         as3_buffer_input(mem, length);
106     }
107
108     as3_tokencount=0;
109     initialize_file(name, filename);
110     a3_parse();
111     as3_lex_destroy();
112     finish_file();
113 }
114
115 typedef struct _scheduled_file {
116     char*name;
117     char*filename;
118     struct _scheduled_file*next;
119 } scheduled_file_t;
120
121 static scheduled_file_t*scheduled=0;
122 dict_t*scheduled_dict=0;
123
124 void as3_parse_scheduled(int pass)
125 {
126     scheduled_file_t*s = scheduled;
127     scheduled = 0;
128     while(s) {
129         scheduled_file_t*old = s;
130         as3_parse_file_or_array(pass, s->name, s->filename, 0,0);
131         s = s->next;
132
133         free(old->filename);
134         free(old->name);
135         old->filename = old->name = 0;
136         free(old);
137     }
138     if(scheduled_dict) {
139         dict_destroy(scheduled_dict);
140         scheduled_dict=0;
141     }
142 }
143 void as3_schedule_file(const char*name, const char*filename) 
144 {
145     if(!scheduled_dict) 
146         scheduled_dict = dict_new();
147     
148     //printf("schedule %s %s\n", name, filename);
149
150     if(dict_contains(scheduled_dict, filename)) {
151         return; //already processed
152     } else {
153         dict_put(scheduled_dict, filename, 0);
154     }
155
156     NEW(scheduled_file_t, f);
157     f->name = strdup(name);
158     f->filename = strdup(filename);
159     f->next = scheduled; // dfs
160     scheduled = f;
161 }
162
163 void as3_parse_bytearray(const char*name, void*mem, int length)
164 {
165     as3_parse_file_or_array(1, name, 0, mem, length);
166     as3_parse_scheduled(1);
167     
168     as3_parse_file_or_array(2, name, 0, mem, length);
169     as3_parse_scheduled(2);
170 }
171
172 void as3_parse_file(const char*filename) 
173 {
174     char*fullfilename = find_file(filename);
175     if(!fullfilename)
176         return; // not found
177     
178     as3_parse_file_or_array(1, filename, fullfilename, 0,0);
179     as3_parse_scheduled(1);
180
181     as3_parse_file_or_array(2, filename, fullfilename, 0,0);
182     as3_parse_scheduled(2);
183
184     free(fullfilename);
185 }
186
187 void as3_schedule_package(const char*package)
188 {
189     char*dirname = strdup(package);
190     int s=0;
191     while(dirname[s]) {
192         if(package[s]=='.') dirname[s]='/';
193         s++;
194     };
195     char ok=0;
196 #ifdef HAVE_DIRENT_H
197     include_dir_t*i = current_include_dirs;
198     while(i) {
199         char*fulldirname = concatPaths(i->path, dirname);
200         DIR*dir = opendir(dirname);
201         if(dir) {
202             ok = 1;
203             struct dirent*ent;
204             while(1) {
205                 ent = readdir(dir);
206                 if (!ent) 
207                     break;
208                 char*name = ent->d_name;
209                 char type = 0;
210                 if(!name) continue;
211                 int l=strlen(name);
212                 if(l<4)
213                     continue;
214                 if(strncasecmp(&name[l-3], ".as", 3)) 
215                     continue;
216                 char*fullfilename = concatPaths(dirname, name);
217                 as3_schedule_file(name, fullfilename);
218                 free(fullfilename);
219             }
220         }
221         free(fulldirname);
222         i = i->next;
223     }
224 #endif
225     if(!ok)
226         as3_softwarning("Could not find package %s in file system", package);
227 }
228
229 void as3_schedule_class(const char*package, const char*cls)
230 {
231     if(!cls) {
232         as3_schedule_package(package);
233         return;
234     }
235     int l1 = package?strlen(package):0;
236     int l2 = cls?strlen(cls):0;
237     char*filename = malloc(l1+l2+5);
238     int s=0,t=0;
239     while(package[s]) {
240         if(package[s]=='.')
241             filename[t++]='/';
242         else
243             filename[t++] = package[s];
244         s++;
245     }
246     if(t)
247         filename[t++] = '/';
248
249     strcpy(filename+t, cls);
250     strcpy(filename+t+l2, ".as");
251     char*f=0;
252     if(!(f=find_file(filename))) {
253         int i;
254         /* try lower case filename (not packagename!), too */
255         for(i=t;i<t+l2;i++) {
256             if(filename[i]>='A' && filename[i]<='Z')
257                 filename[i] += 'a'-'A';
258         }
259         if(!(f=find_file(filename))) {
260             strcpy(filename+t, cls);
261             strcpy(filename+t+l2, ".as");
262             as3_warning("Could not open file %s", filename);
263             return;
264         }
265     }
266     as3_schedule_file(filename, f);
267 }
268
269 static void*as3code = 0;
270 void* as3_getcode()
271 {
272     if(parser_initialized) {
273         parser_initialized = 0;
274         as3code = finish_parser();
275     }
276     return as3code;
277 }
278 char* as3_getglobalclass()
279 {
280     return as3_globalclass;
281 }
282
283 void as3_destroy() 
284 {
285     if(parser_initialized) {
286         parser_initialized = 0;
287         swf_FreeABC(finish_parser());
288 #ifdef STORE_TOKENS
289         mem_clear(&tokens);
290 #endif
291     }
292     if(as3_globalclass) {
293         free(as3_globalclass);as3_globalclass=0;
294     }
295 }
296