diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a953cd380908..de9440f04e92 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2003-03-02 Neil Booth + + * c-incpath.c (remove_component_p, simplify_path): Move back to + cppfiles.c. + (remove_duplicates): Use cpp_simplify_path. + * c-incpath.h (simplify_path): Remove. + * c-lex.c: Don't include c-incpath.h. + (init_c_lex): Remove simplify_path. + * cppfiles.c (remove_component_p, cpp_simplify_path): Restore. + (find_or_create_entry, validate_pch): Revert. + 2003-03-02 Ashif Harji * gcc.c (default_compilers): Add -no-integrated-cpp flag to invoke diff --git a/gcc/c-incpath.c b/gcc/c-incpath.c index 96bf69d7e28c..b1c8de5cb3b0 100644 --- a/gcc/c-incpath.c +++ b/gcc/c-incpath.c @@ -47,7 +47,6 @@ static void add_env_var_paths PARAMS ((const char *, int)); static void add_standard_paths PARAMS ((const char *, const char *, int)); static void free_path PARAMS ((struct cpp_path *, int)); static void merge_include_chains PARAMS ((cpp_reader *, int)); -static int remove_component_p PARAMS ((const char *)); static struct cpp_path * remove_duplicates PARAMS ((cpp_reader *, struct cpp_path *, struct cpp_path *, struct cpp_path *, int)); @@ -177,7 +176,7 @@ remove_duplicates (pfile, head, system, join, verbose) int reason = REASON_QUIET; cur = *pcur; - simplify_path (cur->name); + cpp_simplify_path (cur->name); if (stat (cur->name, &st)) { @@ -355,156 +354,3 @@ register_include_chains (pfile, sysroot, iprefix, cpp_set_include_chains (pfile, heads[QUOTE], heads[BRACKET], quote_ignores_source_dir); } - -/* Returns true if it is safe to remove the final component of path, - when it is followed by a ".." component. We use lstat to avoid - symlinks if we have it. If not, we can still catch errors with - stat (). */ -static int -remove_component_p (path) - const char *path; -{ - struct stat s; - int result; - -#ifdef HAVE_LSTAT - result = lstat (path, &s); -#else - result = stat (path, &s); -#endif - - /* There's no guarantee that errno will be unchanged, even on - success. Cygwin's lstat(), for example, will often set errno to - ENOSYS. In case of success, reset errno to zero. */ - if (result == 0) - errno = 0; - - return result == 0 && S_ISDIR (s.st_mode); -} - -/* Simplify a path name in place, deleting redundant components. This - reduces OS overhead and guarantees that equivalent paths compare - the same (modulo symlinks). - - Transforms made: - foo/bar/../quux foo/quux - foo/./bar foo/bar - foo//bar foo/bar - /../quux /quux - //quux //quux (POSIX allows leading // as a namespace escape) - - Guarantees no trailing slashes. All transforms reduce the length - of the string. Returns PATH. errno is 0 if no error occurred; - nonzero if an error occurred when using stat () or lstat (). */ -void -simplify_path (path) - char *path ATTRIBUTE_UNUSED; -{ -#ifndef VMS - char *from, *to; - char *base, *orig_base; - int absolute = 0; - - errno = 0; - /* Don't overflow the empty path by putting a '.' in it below. */ - if (*path == '\0') - return; - -#if defined (HAVE_DOS_BASED_FILE_SYSTEM) - /* Convert all backslashes to slashes. */ - for (from = path; *from; from++) - if (*from == '\\') *from = '/'; - - /* Skip over leading drive letter if present. */ - if (ISALPHA (path[0]) && path[1] == ':') - from = to = &path[2]; - else - from = to = path; -#else - from = to = path; -#endif - - /* Remove redundant leading /s. */ - if (*from == '/') - { - absolute = 1; - to++; - from++; - if (*from == '/') - { - if (*++from == '/') - /* 3 or more initial /s are equivalent to 1 /. */ - while (*++from == '/'); - else - /* On some hosts // differs from /; Posix allows this. */ - to++; - } - } - - base = orig_base = to; - for (;;) - { - int move_base = 0; - - while (*from == '/') - from++; - - if (*from == '\0') - break; - - if (*from == '.') - { - if (from[1] == '\0') - break; - if (from[1] == '/') - { - from += 2; - continue; - } - else if (from[1] == '.' && (from[2] == '/' || from[2] == '\0')) - { - /* Don't simplify if there was no previous component. */ - if (absolute && orig_base == to) - { - from += 2; - continue; - } - /* Don't simplify if the previous component was "../", - or if an error has already occurred with (l)stat. */ - if (base != to && errno == 0) - { - /* We don't back up if it's a symlink. */ - *to = '\0'; - if (remove_component_p (path)) - { - while (to > base && *to != '/') - to--; - from += 2; - continue; - } - } - move_base = 1; - } - } - - /* Add the component separator. */ - if (to > orig_base) - *to++ = '/'; - - /* Copy this component until the trailing null or '/'. */ - while (*from != '\0' && *from != '/') - *to++ = *from++; - - if (move_base) - base = to; - } - - /* Change the empty string to "." so that it is not treated as stdin. - Null terminate. */ - if (to == path) - *to++ = '.'; - *to = '\0'; -#else /* VMS */ - errno = 0; -#endif /* !VMS */ -} diff --git a/gcc/c-incpath.h b/gcc/c-incpath.h index 860ea3cdc95c..e5b02182a822 100644 --- a/gcc/c-incpath.h +++ b/gcc/c-incpath.h @@ -19,6 +19,5 @@ extern void split_quote_chain PARAMS ((void)); extern void add_path PARAMS ((char *, int, int)); extern void register_include_chains PARAMS ((cpp_reader *, const char *, const char *, int, int, int)); -extern void simplify_path PARAMS ((char *)); enum { QUOTE = 0, BRACKET, SYSTEM, AFTER }; diff --git a/gcc/c-lex.c b/gcc/c-lex.c index e0617bd142d0..d063cfe9eccc 100644 --- a/gcc/c-lex.c +++ b/gcc/c-lex.c @@ -41,7 +41,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "tm_p.h" #include "splay-tree.h" #include "debug.h" -#include "c-incpath.h" #ifdef MULTIBYTE_CHARS #include "mbchar.h" @@ -125,7 +124,6 @@ init_c_lex (filename) cb->ident = cb_ident; cb->file_change = cb_file_change; cb->def_pragma = cb_def_pragma; - cb->simplify_path = simplify_path; cb->valid_pch = c_common_valid_pch; cb->read_pch = c_common_read_pch; diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c index 502e8a2e161c..dda7ac2e24eb 100644 --- a/gcc/cppfiles.c +++ b/gcc/cppfiles.c @@ -153,6 +153,7 @@ static int report_missing_guard PARAMS ((splay_tree_node, void *)); static splay_tree_node find_or_create_entry PARAMS ((cpp_reader *, const char *)); static void handle_missing_header PARAMS ((cpp_reader *, const char *, int)); +static int remove_component_p PARAMS ((const char *)); /* Set up the splay tree we use to store information about all the file names seen in this compilation. We also have entries for each @@ -160,7 +161,7 @@ static void handle_missing_header PARAMS ((cpp_reader *, const char *, int)); don't try to open it again in future. The key of each node is the file name, after processing by - simplify_path. The path name may or may not be absolute. + cpp_simplify_path. The path name may or may not be absolute. The path string has been malloced, as is automatically freed by registering free () as the splay tree key deletion function. @@ -216,15 +217,8 @@ find_or_create_entry (pfile, fname) splay_tree_node node; struct include_file *file; char *name = xstrdup (fname); - int saved_errno = 0; - - if (pfile->cb.simplify_path) - { - errno = 0; - (pfile->cb.simplify_path) (name); - saved_errno = errno; - } + cpp_simplify_path (name); node = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) name); if (node) free (name); @@ -233,7 +227,7 @@ find_or_create_entry (pfile, fname) file = xcnew (struct include_file); file->name = name; file->header_name = name; - file->err_no = saved_errno; + file->err_no = errno; node = splay_tree_insert (pfile->all_include_files, (splay_tree_key) file->name, (splay_tree_value) file); @@ -343,7 +337,7 @@ validate_pch (pfile, filename, pchname) if (INCLUDE_PCH_P (file)) { char *f = xstrdup (filename); - (pfile->cb.simplify_path) (f); + cpp_simplify_path (f); file->header_name = f; return file; } @@ -1171,3 +1165,156 @@ cpp_set_include_chains (pfile, quote, bracket, quote_ignores_source_dir) pfile->bracket_include = bracket; } } + +/* Returns true if it is safe to remove the final component of path, + when it is followed by a ".." component. We use lstat to avoid + symlinks if we have it. If not, we can still catch errors with + stat (). */ +static int +remove_component_p (path) + const char *path; +{ + struct stat s; + int result; + +#ifdef HAVE_LSTAT + result = lstat (path, &s); +#else + result = stat (path, &s); +#endif + + /* There's no guarantee that errno will be unchanged, even on + success. Cygwin's lstat(), for example, will often set errno to + ENOSYS. In case of success, reset errno to zero. */ + if (result == 0) + errno = 0; + + return result == 0 && S_ISDIR (s.st_mode); +} + +/* Simplify a path name in place, deleting redundant components. This + reduces OS overhead and guarantees that equivalent paths compare + the same (modulo symlinks). + + Transforms made: + foo/bar/../quux foo/quux + foo/./bar foo/bar + foo//bar foo/bar + /../quux /quux + //quux //quux (POSIX allows leading // as a namespace escape) + + Guarantees no trailing slashes. All transforms reduce the length + of the string. Returns PATH. errno is 0 if no error occurred; + nonzero if an error occurred when using stat () or lstat (). */ +void +cpp_simplify_path (path) + char *path ATTRIBUTE_UNUSED; +{ +#ifndef VMS + char *from, *to; + char *base, *orig_base; + int absolute = 0; + + errno = 0; + /* Don't overflow the empty path by putting a '.' in it below. */ + if (*path == '\0') + return; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Convert all backslashes to slashes. */ + for (from = path; *from; from++) + if (*from == '\\') *from = '/'; + + /* Skip over leading drive letter if present. */ + if (ISALPHA (path[0]) && path[1] == ':') + from = to = &path[2]; + else + from = to = path; +#else + from = to = path; +#endif + + /* Remove redundant leading /s. */ + if (*from == '/') + { + absolute = 1; + to++; + from++; + if (*from == '/') + { + if (*++from == '/') + /* 3 or more initial /s are equivalent to 1 /. */ + while (*++from == '/'); + else + /* On some hosts // differs from /; Posix allows this. */ + to++; + } + } + + base = orig_base = to; + for (;;) + { + int move_base = 0; + + while (*from == '/') + from++; + + if (*from == '\0') + break; + + if (*from == '.') + { + if (from[1] == '\0') + break; + if (from[1] == '/') + { + from += 2; + continue; + } + else if (from[1] == '.' && (from[2] == '/' || from[2] == '\0')) + { + /* Don't simplify if there was no previous component. */ + if (absolute && orig_base == to) + { + from += 2; + continue; + } + /* Don't simplify if the previous component was "../", + or if an error has already occurred with (l)stat. */ + if (base != to && errno == 0) + { + /* We don't back up if it's a symlink. */ + *to = '\0'; + if (remove_component_p (path)) + { + while (to > base && *to != '/') + to--; + from += 2; + continue; + } + } + move_base = 1; + } + } + + /* Add the component separator. */ + if (to > orig_base) + *to++ = '/'; + + /* Copy this component until the trailing null or '/'. */ + while (*from != '\0' && *from != '/') + *to++ = *from++; + + if (move_base) + base = to; + } + + /* Change the empty string to "." so that it is not treated as stdin. + Null terminate. */ + if (to == path) + *to++ = '.'; + *to = '\0'; +#else /* VMS */ + errno = 0; +#endif /* !VMS */ +} diff --git a/gcc/cpplib.h b/gcc/cpplib.h index 384dd209ac2f..2ed5ed03d708 100644 --- a/gcc/cpplib.h +++ b/gcc/cpplib.h @@ -402,7 +402,6 @@ struct cpp_callbacks void (*undef) PARAMS ((cpp_reader *, unsigned int, cpp_hashnode *)); void (*ident) PARAMS ((cpp_reader *, unsigned int, const cpp_string *)); void (*def_pragma) PARAMS ((cpp_reader *, unsigned int)); - void (*simplify_path) PARAMS ((char *)); /* Called when the client has a chance to properly register built-ins with cpp_define() and cpp_assert(). */ void (*register_builtins) PARAMS ((cpp_reader *)); @@ -741,6 +740,7 @@ extern unsigned char *cpp_quote_string PARAMS ((unsigned char *, /* In cppfiles.c */ extern int cpp_included PARAMS ((cpp_reader *, const char *)); extern void cpp_make_system_header PARAMS ((cpp_reader *, int, int)); +extern void cpp_simplify_path PARAMS ((char *)); /* In cpppch.c */ struct save_macro_data;