new functions schedule_class, schedule_package
[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         fi = enter_file2(name, filename, 0);
100         as3_file_input(fi);
101     } else {
102         enter_file(name, name, 0);
103         as3_buffer_input(mem, length);
104     }
105
106     as3_tokencount=0;
107     initialize_file(name);
108     a3_parse();
109     as3_lex_destroy();
110     finish_file();
111 }
112
113 typedef struct _scheduled_file {
114     char*filename;
115     struct _scheduled_file*next;
116 } scheduled_file_t;
117
118 static scheduled_file_t*scheduled=0;
119 dict_t*scheduled_dict=0;
120
121 void as3_parse_scheduled()
122 {
123     while(scheduled) {
124         scheduled_file_t*old = scheduled;
125         as3_parse_file(scheduled->filename);
126         scheduled = scheduled->next;
127         free(old->filename);
128         free(old);
129     }
130     if(scheduled_dict) {
131         dict_destroy(scheduled_dict);
132         scheduled_dict=0;
133     }
134 }
135 void as3_schedule_file(const char*filename) 
136 {
137     if(!scheduled_dict) 
138         scheduled_dict = dict_new();
139
140     if(dict_lookup(scheduled_dict, filename)) {
141         return; //already processed
142     } else {
143         dict_put(scheduled_dict, filename, 0);
144     }
145
146     NEW(scheduled_file_t, f);
147     f->filename = strdup(filename);
148     f->next = scheduled; // dfs
149     scheduled = f;
150     printf("schedule %s\n", filename);
151 }
152
153 void as3_parse_bytearray(const char*name, void*mem, int length)
154 {
155     as3_parse_file_or_array(1, name, 0, mem, length);
156     as3_parse_scheduled();
157     
158     as3_parse_file_or_array(2, name, 0, mem, length);
159     as3_parse_scheduled();
160 }
161
162 void as3_parse_file(const char*filename) 
163 {
164     char*fullfilename = find_file(filename);
165     if(!fullfilename)
166         return; // not found
167     
168     as3_parse_file_or_array(1, filename, fullfilename, 0,0);
169     as3_parse_scheduled();
170
171     as3_parse_file_or_array(2, filename, fullfilename, 0,0);
172     as3_parse_scheduled();
173
174     free(fullfilename);
175 }
176
177 void as3_schedule_package(const char*package)
178 {
179     char*dirname = strdup(package);
180     int s=0;
181     while(dirname[s]) {
182         if(package[s]=='.') dirname[s]='/';
183         s++;
184     };
185     char ok=0;
186 #ifdef HAVE_DIRENT_H
187     include_dir_t*i = current_include_dirs;
188     while(i) {
189         char*fulldirname = concatPaths(i->path, dirname);
190         DIR*dir = opendir(dirname);
191         if(dir) {
192             ok = 1;
193             struct dirent*ent;
194             while(1) {
195                 ent = readdir(dir);
196                 if (!ent) 
197                     break;
198                 char*name = ent->d_name;
199                 char type = 0;
200                 if(!name) continue;
201                 int l=strlen(name);
202                 if(l<4)
203                     continue;
204                 if(strncasecmp(&name[l-3], ".as", 3)) 
205                     continue;
206                 char*fullfilename = concatPaths(dirname, name);
207                 as3_schedule_file(fullfilename);
208                 free(fullfilename);
209             }
210         }
211         free(fulldirname);
212         i = i->next;
213     }
214 #endif
215     if(!ok)
216         as3_warning("Could not find package %s", package);
217 }
218
219 void as3_schedule_class(const char*package, const char*cls)
220 {
221     if(!cls) {
222         as3_schedule_package(package);
223         return;
224     }
225     int l1 = package?strlen(package):0;
226     int l2 = cls?strlen(cls):0;
227     char*filename = malloc(l1+l2+5);
228     int s=0,t=0;
229     while(package[s]) {
230         if(package[s]=='.')
231             filename[t++]='/';
232         else
233             filename[t++] = package[s];
234         s++;
235     }
236     if(t)
237         filename[t++] = '/';
238
239     strcpy(filename+t, cls);
240     strcpy(filename+t+l2, ".as");
241     char*f=0;
242     if(!(f=find_file(filename))) {
243         int i;
244         /* try lower case filename (not packagename!), too */
245         for(i=t;i<t+l2;i++) {
246             if(filename[i]>='A' && filename[i]<='Z')
247                 filename[i] += 'a'-'A';
248         }
249         if(!(f=find_file(filename))) {
250             strcpy(filename+t, cls);
251             strcpy(filename+t+l2, ".as");
252             as3_warning("Could not open file %s", filename);
253             return;
254         }
255     }
256     as3_schedule_file(f);
257 }
258
259 static void*as3code = 0;
260 void* as3_getcode()
261 {
262     if(parser_initialized) {
263         parser_initialized = 0;
264         as3code = finish_parser();
265     }
266     return as3code;
267 }
268 char* as3_getglobalclass()
269 {
270     return as3_globalclass;
271 }
272
273 void as3_destroy() 
274 {
275     if(parser_initialized) {
276         parser_initialized = 0;
277         swf_FreeABC(finish_parser());
278 #ifdef STORE_TOKENS
279         mem_clear(&tokens);
280 #endif
281     }
282     if(as3_globalclass) {
283         free(as3_globalclass);as3_globalclass=0;
284     }
285 }
286