+
+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/");
+}
+