X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fas3%2Ffiles.c;h=f6284ddf55b3b8309ee3cfa39ce311d1e0ea910e;hb=c63b2bf21dc1df9a736f0b4c08f6cba828cdab92;hp=e30b112eb38f7333d22bfee636791e3080e121f5;hpb=1ae58b8b15dee25f1915c344f4fdea9f9c3d41ea;p=swftools.git diff --git a/lib/as3/files.c b/lib/as3/files.c index e30b112..f6284dd 100644 --- a/lib/as3/files.c +++ b/lib/as3/files.c @@ -23,7 +23,11 @@ #include #include #include +#include #include "files.h" +#include "common.h" +#include "tokenizer.h" +#include "../os.h" static int verbose = 0; static void dbg(const char*format, ...) @@ -34,7 +38,7 @@ static void dbg(const char*format, ...) if(!verbose) return; va_start(arglist, format); - vsprintf(buf, format, arglist); + vsnprintf(buf, sizeof(buf)-1, format, arglist); va_end(arglist); l = strlen(buf); while(l && buf[l-1]=='\n') { @@ -47,14 +51,11 @@ 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; +char* current_filename_short=0; +char* current_filename_long=0; include_dir_t* current_include_dirs=0; #define MAX_INCLUDE_DEPTH 16 @@ -63,6 +64,8 @@ void*include_stack[MAX_INCLUDE_DEPTH]; int line_stack[MAX_INCLUDE_DEPTH]; int column_stack[MAX_INCLUDE_DEPTH]; char* filename_stack[MAX_INCLUDE_DEPTH]; +char* shortfilename_stack[MAX_INCLUDE_DEPTH]; +char* longfilename_stack[MAX_INCLUDE_DEPTH]; include_dir_t* includedir_stack[MAX_INCLUDE_DEPTH]; int include_stack_ptr = 0; @@ -70,11 +73,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, '/'); @@ -89,35 +104,133 @@ char*get_path(char*file) return strdup("."); } } + +char is_absolute(const char*filename) +{ + if(!filename || !filename[0]) + return 0; + if(filename[0]=='/' || filename[0]=='\\') + return 1; + if(filename[1]==':' && filename[2]=='/') + return 1; + if(filename[1]==':' && filename[2]=='\\') + return 1; + return 0; +} + +char* filename_to_lowercase(const char*name) +{ + char*n = strdup(name); + //char*x1 = strrchr(name, '/'); + //char*x2 = strrchr(name, '\\'); + char*s = n; + //if(x1+1>s) s=x1+1; + //if(x2+1>s) s=x2+1; + while(*s) { + /* FIXME: what we probably should do here is use libc's tolower(). + I don't really know yet, though, how Windows (or MacOS X) handles + lowercasing of Unicode filenames */ + if(*s>='A' && *s<='Z') + *s += 'a'-'A'; + s++; + } + return n; +} + +char* normalize_path(const char*path) +{ + char*n = 0, *d = 0; + if(!is_absolute(path)) { + 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]!=path_seperator) { + *d=path_seperator;d++; + } + } else { + d = n = strdup(path); + } + const char*s=path; + char init = 1; + + while(*s) { + if(init && s[0] == '.' && (s[1]==path_seperator || s[1]=='\0')) { + if(!s[1]) break; + s+=2; + init=1; + continue; + } + if(init && s[0] == '.' && s[1] == '.' && (s[2] == path_seperator || s[2]=='\0')) { + // step one down + char*last = 0; + if(d<=n) + return 0; + *--d = 0; + if(!(last=strrchr(n, path_seperator))) { + return 0; + } + d = last+1; + if(!s[2]) break; + s+=3; + init=1; + continue; + } + + *d = *s; + if(*s==path_seperator) init=1; + else init=0; + d++;s++; + } + if(d!=n && d[-1]==path_seperator) + d--; + *d = 0; + +#ifdef LOWERCASE_UPPERCASE + n = filename_to_lowercase(n); +#endif + + 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); int l2 = strlen(add); int pos = 0; char*n = 0; - while(l1 && base[l1-1] == '/') + while(l1 && base[l1-1] == path_seperator) l1--; - while(pos < l2 && add[pos] == '/') + while(pos < l2 && add[pos] == path_seperator) pos++; n = (char*)malloc(l1 + (l2-pos) + 2); memcpy(n,base,l1); - n[l1]='/'; + n[l1]=path_seperator; memcpy(&n[l1+1],&add[pos],l2-pos+1); return n; } -char is_absolute(char*filename) -{ - if(!filename || !filename[0]) - return 0; - if(filename[0]=='/' || filename[0]=='\\') - return 1; - if(filename[1]==':' && filename[1]=='/') - return 1; - if(filename[1]==':' && filename[1]=='\\') - 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; @@ -127,63 +240,88 @@ 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; + longfilename_stack[include_stack_ptr] = current_filename_long; 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(name); + current_filename_short = strdup(name); + current_filename_long = strdup(filename); +} + +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 { + free(current_filename);current_filename = filename_stack[include_stack_ptr]; + free(current_filename_short);current_filename_short = shortfilename_stack[include_stack_ptr]; + free(current_filename_long);current_filename_long = longfilename_stack[include_stack_ptr]; current_column = column_stack[include_stack_ptr]; current_line = line_stack[include_stack_ptr]; - free(current_filename); - current_filename = filename_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]; } } +