fixed off-by-one bug
[swftools.git] / lib / as3 / compiler.c
blobe6571dbfc74f885c838b848f499101737259511a
1 /* compiler.h
3 Compiler for parsing Flash2 AVM2 ABC Actionscript
5 Extension module for the rfxswf library.
6 Part of the swftools package.
8 Copyright (c) 2008/2009 Matthias Kramm <kramm@quiss.org>
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.
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.
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 */
24 #include "common.h"
25 #include "tokenizer.h"
26 #include "files.h"
27 #include "parser.h"
28 #include "parser.tab.h"
29 #include "compiler.h"
30 #include "registry.h"
31 #include "assets.h"
32 #include "../os.h"
33 #ifdef HAVE_SYS_STAT_H
34 #include <sys/stat.h>
35 #endif
36 #ifdef HAVE_DIRENT_H
37 #include <dirent.h>
38 #endif
40 /* flex/bison definitions */
41 extern int a3_parse();
42 extern int as3_lex();
43 extern int as3_lex_destroy();
45 static char config_recurse = 0;
47 void as3_setverbosity(int level)
49 as3_verbosity=level;
51 void as3_add_include_dir(char*dir)
53 add_include_dir(dir);
55 void as3_set_option(const char*key, const char*value)
57 if(!strcmp(key, "recurse")) {
58 config_recurse=atoi(value);
62 static char registry_initialized = 0;
63 static char parser_initialized = 0;
65 //#define STORE_TOKENS
67 //#define DEBUG
68 #define DEBUG if(0)
70 int a3_lex()
72 as3_tokencount++;
73 return as3_lex();
76 typedef struct _compile_list {
77 const char*name;
78 const char*filename;
79 struct _compile_list*next;
80 } compile_list_t;
81 static compile_list_t*compile_list=0;
83 static void as3_parse_file_or_array(const char*name, const char*filename, const void*mem, int length)
85 if(!registry_initialized) {
86 registry_initialized = 1;
87 registry_init();
89 if(!parser_initialized) {
90 parser_initialized = 1;
91 initialize_parser();
94 FILE*fi = 0;
95 if(filename) {
96 if(as3_pass==1 && !mem) {
97 // record the fact that we compiled this file
98 compile_list_t*c = rfx_calloc(sizeof(compile_list_t));
99 c->next = compile_list;
100 c->name = strdup(name);
101 c->filename = strdup(filename);
102 compile_list = c;
104 DEBUG printf("[pass %d] parse file %s %s\n", as3_pass, name, filename);
105 fi = enter_file2(name, filename, 0);
106 as3_file_input(fi);
107 } else {
108 DEBUG printf("[pass %d] parse bytearray %s (%d bytes)\n", as3_pass, name, length);
109 enter_file(name, name, 0);
110 as3_buffer_input((void*)mem, length);
113 as3_tokencount=0;
114 initialize_file(name, filename);
115 a3_parse();
116 as3_lex_destroy();
117 finish_file();
118 if(fi) fclose(fi);
121 typedef struct _scheduled_file {
122 char*name;
123 char*filename;
124 struct _scheduled_file*next;
125 } scheduled_file_t;
127 static scheduled_file_t*scheduled=0;
128 dict_t*scheduled_dict=0;
130 void as3_parse_scheduled()
132 DEBUG printf("[pass %d] parse scheduled\n", as3_pass);
134 while(scheduled) {
135 scheduled_file_t*s = scheduled;
136 scheduled = 0;
137 while(s) {
138 scheduled_file_t*old = s;
139 as3_parse_file_or_array(s->name, s->filename, 0,0);
140 s = s->next;
142 free(old->filename);
143 free(old->name);
144 old->filename = old->name = 0;
145 free(old);
148 if(scheduled_dict) {
149 dict_destroy(scheduled_dict);
150 scheduled_dict=0;
154 void as3_schedule_file(const char*name, const char*filename)
156 if(!scheduled_dict) {
157 scheduled_dict = dict_new();
160 filename = normalize_path(filename);
162 if(dict_contains(scheduled_dict, filename)) {
163 return; //already processed
164 } else {
165 dict_put(scheduled_dict, filename, 0);
167 DEBUG printf("[pass %d] schedule %s %s\n", as3_pass, name, filename);
169 NEW(scheduled_file_t, f);
170 f->name = strdup(name);
171 f->filename = strdup(filename);
172 f->next = scheduled; // dfs
173 scheduled = f;
176 void as3_parse_list()
178 while(compile_list) {
179 as3_parse_file_or_array(compile_list->name, compile_list->filename, 0,0);
180 compile_list = compile_list->next;
184 void as3_parse_bytearray(const char*name, const void*mem, int length)
186 as3_pass = 1;
187 as3_parse_file_or_array(name, 0, mem, length);
188 as3_parse_scheduled();
190 registry_resolve_all();
192 as3_pass = 2;
193 as3_parse_file_or_array(name, 0, mem, length);
194 as3_parse_list();
197 void as3_parse_file(const char*filename)
199 char*fullfilename = find_file(filename, 1);
200 if(!fullfilename)
201 return; // not found
203 compile_list = 0;
204 as3_pass = 1;
205 as3_schedule_file(filename, fullfilename);
206 as3_parse_scheduled();
208 registry_resolve_all();
210 as3_pass = 2;
211 as3_parse_list();
213 free(fullfilename);
216 void as3_parse_directory(const char*dir)
218 compile_list = 0;
220 as3_pass = 1;
221 as3_schedule_directory(dir);
222 if(!scheduled)
223 as3_warning("Directory %s doesn't contain any ActionScript files", dir);
224 as3_parse_scheduled();
226 registry_resolve_all();
228 as3_pass = 2;
229 as3_parse_list();
232 char as3_schedule_directory(const char*dirname)
234 DEBUG printf("[pass %d] schedule directory %s\n", as3_pass, dirname);
235 char ok=0;
236 #ifdef HAVE_DIRENT_H
237 include_dir_t*i = current_include_dirs;
238 while(i) {
239 char*fulldirname = concat_paths(i->path, dirname);
240 DEBUG printf("[pass %d] ... %s\n", as3_pass, fulldirname);
241 DIR*dir = opendir(fulldirname);
242 if(dir) {
243 ok = 1;
244 struct dirent*ent;
245 while(1) {
246 ent = readdir(dir);
247 if (!ent)
248 break;
249 char*name = ent->d_name;
250 char type = 0;
251 if(!name) continue;
252 int l=strlen(name);
253 if(l<4)
254 continue;
255 if(strncasecmp(&name[l-3], ".as", 3))
256 continue;
257 char*fullfilename = concatPaths(fulldirname, name);
258 as3_schedule_file(name, fullfilename);
259 free(fullfilename);
262 free(fulldirname);
263 i = i->next;
265 #endif
266 return ok;
269 void as3_schedule_package(const char*package)
271 DEBUG printf("[pass %d] schedule package %s\n", as3_pass, package);
272 char*dirname = strdup(package);
273 int s=0;
274 while(dirname[s]) {
275 if(dirname[s]=='.')
276 dirname[s] = path_seperator;
277 s++;
279 if(!as3_schedule_directory(dirname))
280 as3_softwarning("Could not find package %s in file system", package);
283 static void schedule_class(const char*package, const char*cls, char error)
285 if(error) {
286 DEBUG printf("[pass %d] schedule class %s.%s\n", as3_pass, package, cls);
288 if(!cls) {
289 as3_schedule_package(package);
290 return;
292 int l1 = package?strlen(package):0;
293 int l2 = cls?strlen(cls):0;
294 char*filename = malloc(l1+l2+5);
295 int s=0,t=0;
296 while(package[s]) {
297 if(package[s]=='.')
298 filename[t++]='/';
299 else
300 filename[t++] = package[s];
301 s++;
303 if(t)
304 filename[t++] = '/';
306 strcpy(filename+t, cls);
307 strcpy(filename+t+l2, ".as");
308 char*f=find_file(filename, error);
309 if(!f) {
310 int i;
311 filename = filename_to_lowercase(filename);
312 f=find_file(filename, error);
314 if(!f) {
315 if(error) {
316 strcpy(filename+t, cls);
317 strcpy(filename+t+l2, ".as");
318 as3_warning("Could not open file %s", filename);
320 return;
322 as3_schedule_file(filename, f);
325 void as3_schedule_class(const char*package, const char*cls)
327 schedule_class(package, cls, 1);
330 void as3_schedule_class_noerror(const char*package, const char*cls)
332 if(config_recurse) {
333 schedule_class(package, cls, 0);
338 static void*as3code = 0;
339 void* as3_getcode()
341 if(parser_initialized) {
342 parser_initialized = 0;
343 as3code = finish_parser();
345 return as3code;
347 void* as3_getassets(void*t)
349 return swf_AssetsToTags((TAG*)t, registry_getassets());
351 char* as3_getglobalclass()
353 return as3_globalclass;
356 void as3_destroy()
358 if(parser_initialized) {
359 parser_initialized = 0;
360 swf_FreeABC(finish_parser());
361 #ifdef STORE_TOKENS
362 mem_clear(&tokens);
363 #endif
365 if(as3_globalclass) {
366 free(as3_globalclass);as3_globalclass=0;