new functions schedule_class, schedule_package
[swftools.git] / lib / as3 / compiler.c
index 049d158..28769e8 100644 (file)
 #include "parser.h"
 #include "parser.tab.h"
 #include "compiler.h"
-#include <errno.h>
+#include "../os.h"
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
 
 /* flex/bison definitions */
-extern void as3_set_in (FILE *  in_str );
 extern int a3_parse();
 extern int as3_lex();
 extern int as3_lex_destroy();
@@ -46,12 +48,38 @@ void as3_add_include_dir(char*dir)
 static char registry_initialized = 0;
 static char parser_initialized = 0;
 
-void a3_lex()
+//#define STORE_TOKENS
+
+#ifdef STORE_TOKENS
+static mem_t tokens;
+#endif
+
+int a3_lex()
 {
-    as3_lex();
+    as3_tokencount++;
+#ifdef STORE_TOKENS
+    if(as3_pass==1) {
+        int token = as3_lex();
+        /* FIXME: current_file needs to be stored, too */
+        mem_put(&tokens, &token, sizeof(token));
+        mem_put(&tokens, &a3_lval, sizeof(a3_lval));
+        mem_put(&tokens, &current_line, sizeof(current_line));
+        mem_put(&tokens, &current_column, sizeof(current_column));
+        return token;
+    } else {
+        int token;
+        mem_get(&tokens, &token, sizeof(token));
+        mem_get(&tokens, &a3_lval, sizeof(a3_lval));
+        mem_get(&tokens, &current_line, sizeof(current_line));
+        mem_get(&tokens, &current_column, sizeof(current_column));
+        return token;
+    }
+#else
+    return as3_lex();
+#endif
 }
 
-void as3_parse_file(char*filename) 
+static void as3_parse_file_or_array(int pass, const char*name, const char*filename, void*mem, int length)
 {
     if(!registry_initialized) {
         registry_initialized = 1;
@@ -60,36 +88,172 @@ void as3_parse_file(char*filename)
     if(!parser_initialized) {
         parser_initialized = 1;
         initialize_parser();
+#if defined(STORE_TOKENS)
+        mem_init(&tokens);
+#endif
     }
+    as3_pass=pass;
 
-    as3_pass = 0;
-    
-    char*fullfilename = enter_file(filename, 0);
-    FILE*fi = fopen(fullfilename, "rb");
-    if(!fi) {
-       syntaxerror("Couldn't find file %s: %s", fullfilename, strerror(errno));
+    FILE*fi = 0;
+    if(filename) {
+        fi = enter_file2(name, filename, 0);
+        as3_file_input(fi);
+    } else {
+        enter_file(name, name, 0);
+        as3_buffer_input(mem, length);
     }
-    /* pass 1 */
-    as3_pass = 1;
-    as3_set_in(fi);
-    initialize_file(filename);
-    a3_parse();
-    as3_lex_destroy();
-    finish_file();
 
-    /* pass 2 */
-    // TODO: this should re-use tokens!
-    enter_file(filename, 0);
-    as3_pass = 2;
-    fseek(fi, 0, SEEK_SET);
-    as3_set_in(fi);
-    initialize_file(filename);
+    as3_tokencount=0;
+    initialize_file(name);
     a3_parse();
     as3_lex_destroy();
     finish_file();
+}
+
+typedef struct _scheduled_file {
+    char*filename;
+    struct _scheduled_file*next;
+} scheduled_file_t;
+
+static scheduled_file_t*scheduled=0;
+dict_t*scheduled_dict=0;
+
+void as3_parse_scheduled()
+{
+    while(scheduled) {
+        scheduled_file_t*old = scheduled;
+        as3_parse_file(scheduled->filename);
+        scheduled = scheduled->next;
+        free(old->filename);
+        free(old);
+    }
+    if(scheduled_dict) {
+        dict_destroy(scheduled_dict);
+        scheduled_dict=0;
+    }
+}
+void as3_schedule_file(const char*filename) 
+{
+    if(!scheduled_dict) 
+        scheduled_dict = dict_new();
+
+    if(dict_lookup(scheduled_dict, filename)) {
+        return; //already processed
+    } else {
+        dict_put(scheduled_dict, filename, 0);
+    }
+
+    NEW(scheduled_file_t, f);
+    f->filename = strdup(filename);
+    f->next = scheduled; // dfs
+    scheduled = f;
+    printf("schedule %s\n", filename);
+}
+
+void as3_parse_bytearray(const char*name, void*mem, int length)
+{
+    as3_parse_file_or_array(1, name, 0, mem, length);
+    as3_parse_scheduled();
+    
+    as3_parse_file_or_array(2, name, 0, mem, length);
+    as3_parse_scheduled();
+}
 
-    fclose(fi);
+void as3_parse_file(const char*filename) 
+{
+    char*fullfilename = find_file(filename);
+    if(!fullfilename)
+        return; // not found
+    
+    as3_parse_file_or_array(1, filename, fullfilename, 0,0);
+    as3_parse_scheduled();
+
+    as3_parse_file_or_array(2, filename, fullfilename, 0,0);
+    as3_parse_scheduled();
+
+    free(fullfilename);
+}
 
+void as3_schedule_package(const char*package)
+{
+    char*dirname = strdup(package);
+    int s=0;
+    while(dirname[s]) {
+        if(package[s]=='.') dirname[s]='/';
+        s++;
+    };
+    char ok=0;
+#ifdef HAVE_DIRENT_H
+    include_dir_t*i = current_include_dirs;
+    while(i) {
+        char*fulldirname = concatPaths(i->path, dirname);
+        DIR*dir = opendir(dirname);
+        if(dir) {
+            ok = 1;
+            struct dirent*ent;
+            while(1) {
+                ent = readdir(dir);
+                if (!ent) 
+                    break;
+                char*name = ent->d_name;
+                char type = 0;
+                if(!name) continue;
+                int l=strlen(name);
+                if(l<4)
+                    continue;
+                if(strncasecmp(&name[l-3], ".as", 3)) 
+                    continue;
+                char*fullfilename = concatPaths(dirname, name);
+                as3_schedule_file(fullfilename);
+                free(fullfilename);
+            }
+        }
+        free(fulldirname);
+        i = i->next;
+    }
+#endif
+    if(!ok)
+        as3_warning("Could not find package %s", package);
+}
+
+void as3_schedule_class(const char*package, const char*cls)
+{
+    if(!cls) {
+        as3_schedule_package(package);
+        return;
+    }
+    int l1 = package?strlen(package):0;
+    int l2 = cls?strlen(cls):0;
+    char*filename = malloc(l1+l2+5);
+    int s=0,t=0;
+    while(package[s]) {
+        if(package[s]=='.')
+            filename[t++]='/';
+        else
+            filename[t++] = package[s];
+        s++;
+    }
+    if(t)
+        filename[t++] = '/';
+
+    strcpy(filename+t, cls);
+    strcpy(filename+t+l2, ".as");
+    char*f=0;
+    if(!(f=find_file(filename))) {
+        int i;
+        /* try lower case filename (not packagename!), too */
+        for(i=t;i<t+l2;i++) {
+            if(filename[i]>='A' && filename[i]<='Z')
+                filename[i] += 'a'-'A';
+        }
+        if(!(f=find_file(filename))) {
+            strcpy(filename+t, cls);
+            strcpy(filename+t+l2, ".as");
+            as3_warning("Could not open file %s", filename);
+            return;
+        }
+    }
+    as3_schedule_file(f);
 }
 
 static void*as3code = 0;
@@ -111,6 +275,9 @@ void as3_destroy()
     if(parser_initialized) {
         parser_initialized = 0;
         swf_FreeABC(finish_parser());
+#ifdef STORE_TOKENS
+        mem_clear(&tokens);
+#endif
     }
     if(as3_globalclass) {
         free(as3_globalclass);as3_globalclass=0;