added _noerror version of functions
[swftools.git] / lib / as3 / files.c
index 10e5de6..6e75fd7 100644 (file)
@@ -23,7 +23,9 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include <memory.h>
+#include <errno.h>
 #include "files.h"
+#include "tokenizer.h"
 
 static int verbose = 0;
 static void dbg(const char*format, ...)
@@ -47,11 +49,6 @@ static void dbg(const char*format, ...)
 }
 
 
-typedef struct _include_dir {
-    char*path;
-    struct _include_dir*next;
-} include_dir_t;
-
 int current_line=1;
 int current_column=0;
 char* current_filename=0;
@@ -72,11 +69,23 @@ void add_include_dir(char*dir)
 {
     include_dir_t*d = malloc(sizeof(include_dir_t));
     memset(d , 0, sizeof(include_dir_t));
-    d->path = dir;
+    d->path = strdup(dir);
     d->next = current_include_dirs;
     current_include_dirs = d;
 }
-char*get_path(char*file)
+
+void del_include_dirs(include_dir_t*d, include_dir_t*d2)
+{
+    while(d && d!=d2) {
+        include_dir_t*next = d->next;
+        free(d->path);d->path=0;
+        d->next = 0;
+        free(d);
+        d = next;
+    }
+}
+
+char*get_path(const char*file)
 {
     char*path = strdup(file);
     char*r1 = strrchr(path, '/');
@@ -91,6 +100,78 @@ char*get_path(char*file)
         return strdup(".");
     }
 }
+char* normalize_path(const char*path)
+{
+    char*n = 0, *d = 0;
+    if(path[0] != '/') {
+        char buf[512];
+        char*c = getcwd(buf,512);
+        int l = strlen(buf);
+        d = n = malloc(l+strlen(path)+10);
+        strcpy(n, buf);d += l;
+        if(!l || n[l-1]!='/') {
+            *d='/';d++;
+        }
+    } else {
+        d = n = strdup(path);
+    }
+    const char*s=path;
+    char init = 1;
+
+    while(*s) {
+        if(init && s[0] == '.' && (s[1]=='/' || s[1]=='\0')) {
+            if(!s[1]) break;
+            s+=2;
+            init=1;
+            continue;
+        }
+        if(init && s[0] == '.' && s[1] == '.' && (s[2] == '/' || s[2]=='\0')) {
+            // step one down
+            char*last = 0;
+            if(d<=n) 
+                return 0;
+            *--d = 0;
+            if(!(last=strrchr(n, '/'))) {
+                return 0;
+            }
+            d = last+1;
+            if(!s[2]) break;
+            s+=3;
+            init=1;
+            continue;
+        }
+
+        *d = *s;
+        if(*s=='/') init=1;
+        else init=0;
+        d++;s++;
+    }
+    if(d!=n && d[-1]=='/') 
+        d--;
+    *d = 0;
+    return n;
+}
+static void testnormalize()
+{
+#define TEST(x) {printf("%s -> %s\n", (x), normalize_path(x));}
+    TEST(".");
+    TEST("../as3");
+    TEST("../as3/");
+    TEST("../as3/parser.y");
+    TEST("../as3/ok/../ok/scope.as");
+    TEST("ok/scope.as");
+    TEST("ok/./scope.as");
+    TEST("./ok/scope.as");
+    TEST("./");
+    TEST("/tmp/");
+    TEST("/./tmp/");
+    TEST("../");
+    TEST("/");
+    TEST("/tmp");
+    TEST("/tmp/../usr/");
+}
+
+
 char* concat_paths(const char*base, const char*add)
 {
     int l1 = strlen(base);
@@ -107,7 +188,7 @@ char* concat_paths(const char*base, const char*add)
     memcpy(&n[l1+1],&add[pos],l2-pos+1);
     return n;
 }
-char is_absolute(char*filename) 
+char is_absolute(const char*filename) 
 {
     if(!filename || !filename[0])
         return 0;
@@ -119,7 +200,8 @@ char is_absolute(char*filename)
         return 1;
     return 0;
 }
-char*find_file(char*filename)
+
+char*find_file(const char*filename, char error)
 {
     include_dir_t*i = current_include_dirs;
     FILE*fi = 0;
@@ -129,63 +211,83 @@ char*find_file(char*filename)
             fclose(fi);
             return strdup(filename);
         }
+    } else {
+        if(!i && error) {
+            as3_warning("Include directory stack is empty, while looking for file %s", filename);
+        }
+        while(i) {
+            char*p = concat_paths(i->path, filename);
+            fi = fopen(p, "rb");
+            if(fi) {
+                fclose(fi);
+                return p;
+            } else {
+                free(p);
+            }
+            i = i->next;
+        }
+    }
+    if(!error) {
         return 0;
     }
+
+    as3_error("Couldn't find file %s", filename);
+    i = current_include_dirs;
     while(i) {
-        char*p = concat_paths(i->path, filename);
-        fi = fopen(p, "rb");
-        if(fi) {
-            fclose(fi);
-            return p;
-        }
+        fprintf(stderr, "include dir: %s\n", i->path);
         i = i->next;
     }
     return 0;
 }
 
-char*enter_file(char*filename, void*state)
+void enter_file(const char*name, const char*filename, void*state)
 {
     if(include_stack_ptr >= MAX_INCLUDE_DEPTH) {
-       syntaxerror("Includes nested too deeply");
-       exit(1);
-    }
-    char*fullfilename = find_file(filename);
-    if(!fullfilename) {
-       syntaxerror("Couldn't find file %s", filename);
-        include_dir_t*i = current_include_dirs;
-        while(i) {
-            fprintf(stderr, "include dir: %s\n", i->path);
-            i = i->next;
-        }
+       as3_error("Includes nested too deeply");
        exit(1);
     }
     include_stack[include_stack_ptr] = state;
     line_stack[include_stack_ptr] = current_line;
     column_stack[include_stack_ptr] = current_column;
-    shortfilename_stack[include_stack_ptr] = current_filename_short = strdup(filename);
+    shortfilename_stack[include_stack_ptr] = current_filename_short;
     filename_stack[include_stack_ptr] = current_filename;
     includedir_stack[include_stack_ptr] = current_include_dirs;
-    add_include_dir(get_path(fullfilename));
+    
+    /*char*dir = get_path(filename);
+    add_include_dir(dir);
+    free(dir);*/
+
     include_stack_ptr++;
     
-    dbg("entering file %s", fullfilename);
+    dbg("entering file %s", filename);
 
     current_line=1;
     current_column=0;
-    current_filename=fullfilename;
-    return fullfilename;
+    current_filename = strdup(filename);
+    current_filename_short = strdup(name);
+}
+
+FILE*enter_file2(const char*name, const char*filename, void*state)
+{
+    enter_file(name, filename, state);
+    FILE*fi = fopen(filename, "rb");
+    if(!fi) {
+       as3_error("Couldn't find file %s: %s", filename, strerror(errno));
+    }
+    return fi;
 }
 
 void* leave_file()
 {
     dbg("leaving file %s", current_filename);
-    if(--include_stack_ptr<0) {
+    if(--include_stack_ptr<=0) {
         return 0;
     } else {
-        current_column = column_stack[include_stack_ptr];
-        current_line = line_stack[include_stack_ptr];
         free(current_filename);current_filename = filename_stack[include_stack_ptr];
         free(current_filename_short);current_filename_short = shortfilename_stack[include_stack_ptr];
+        current_column = column_stack[include_stack_ptr];
+        current_line = line_stack[include_stack_ptr];
+        del_include_dirs(includedir_stack[include_stack_ptr], current_include_dirs);
         current_include_dirs = includedir_stack[include_stack_ptr];
         return include_stack[include_stack_ptr];
     }