Vladimir Simonov(sv@sw.ru) - normailize filenames. Useful if you crossbuild Linux app on Windows. - Make filenames a bit shorter (constractions like ../dir/../ are collapced into ../dir). It sometimes helps to avoid Windows ascii-filenames length restriction (near to 160 bytes as I remenber). --- gcc-4.4.2/include/filenames.h.orig 2010-01-28 14:58:49.000000000 +0300 +++ gcc-4.4.2/include/filenames.h 2010-01-28 16:26:23.000000000 +0300 @@ -52,6 +52,8 @@ extern int filename_cmp (const char *s1, const char *s2); #define FILENAME_CMP(s1, s2) filename_cmp(s1, s2) +extern void filename_normalize (char *f); +#define FILENAME_NORMALIZE(f) filename_normalize(f) #ifdef __cplusplus } --- gcc-4.4.2/libiberty/filename_cmp.c.orig 2010-01-28 14:59:04.000000000 +0300 +++ gcc-4.4.2/libiberty/filename_cmp.c 2010-01-28 16:23:36.000000000 +0300 @@ -76,3 +76,116 @@ #endif } +#ifdef HAVE_MEMMOVE +#define memmove_left memmove +#else +static void * +memmove_left (void *dest, const void *src, int n) +{ + char *d; + const char *s; + int i; + for (d = (char *)dest, s = (const char *)src, i = 0; i < n; i++) + *d++ = *s++; +} +#endif + +/* + +@deftypefn Extension void filename_normalize (char *@var{fn}) + +This function tries to normalize file names inplace. + +@end deftypefn + +*/ + +#ifndef HAVE_DOS_BASED_FILE_SYSTEM +void +filename_normalize (char *fn) +#else +static void +filename_normalize_unix (char *fn) +#endif +{ + char *p; + int rest; + + rest = strlen (fn) + 1; + for (p = fn; *p != '\0' ; p++, rest--) + { + char *next; + const char *next2; + const char *next3; + + next = p + 1; + if (*next == '\0') + break; + if (!IS_DIR_SEPARATOR( *p)) + continue; + next2 = p + 2; + next3 = p + 3; + *p = '/'; + /* don't handle some special cases, i.e. "//C/" on Microsoft Windows */ + if (IS_DIR_SEPARATOR (*next)) + { + memmove_left (next, next2, rest - 2); + p--; + continue; + } + if (*next != '.' || *next2 == '\0' || *next3 == '\0') + continue; + /* simplify "./" case */ + if (IS_DIR_SEPARATOR (*next2)) + { + memmove_left (next, next3, rest - 3); + rest--; + p--; + continue; + } + if (*next2 != '.' || ! IS_DIR_SEPARATOR (*next3)) + continue; + while (--p >= fn) + { + if (*p == '/') + break; + } + if (p < fn) + { + if (*fn == '/') + memmove_left (p + 2, next3 + 1, rest - 4); + else if (*fn != '.') + memmove_left (p + 1, next3 + 1, rest - 4); + else + { + p = next - 1; + continue; + } + } + else if (*(p + 1) != '.') + { + memmove_left (p + 1, next3 + 1, rest - 4); + p--; + } + else + { + p = next - 1; + continue; + } + rest -= 2; + } +} + + +#ifdef HAVE_DOS_BASED_FILE_SYSTEM +void +filename_normalize (char *fn) +{ + if (IS_DIR_SEPARATOR (fn[0]) || ! IS_ABSOLUTE_PATH (fn)) + /* Absolute path in Unix style or relative path */ + filename_normalize_unix (fn); + else if (fn[1] != '\0') + filename_normalize_unix (fn + 2); +} +#endif + --- gcc-4.4.2/libcpp/directives.c.orig 2010-01-28 15:09:00.000000000 +0300 +++ gcc-4.4.2/libcpp/directives.c 2010-01-28 16:28:04.000000000 +0300 @@ -716,6 +716,7 @@ return NULL; } + FILENAME_NORMALIZE (fname); if (pfile->directive == &dtable[T_PRAGMA]) { /* This pragma allows extra tokens after the file name. */ --- gcc-4.4.2/libcpp/files.c.orig 2010-02-12 11:47:27.886977300 +0300 +++ gcc-4.4.2/libcpp/files.c 2010-02-14 15:38:39.757260300 +0300 @@ -355,6 +355,7 @@ if (path) { + FILENAME_NORMALIZE (path); hashval_t hv = htab_hash_string (path); char *copy; void **pp;