X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fprefix.c;h=c72203c22219082a5ee993143f73ac42e66cf1aa;hp=5fa47e75a634c6e083c5b8e64939671062aa3fd4;hb=ee3f12db46181a28daf58d05b44266b675cade78;hpb=aa40f56162c529feae5e13986bf6c46cf9b39245 diff --git a/gcc/prefix.c b/gcc/prefix.c index 5fa47e75a63..c72203c2221 100644 --- a/gcc/prefix.c +++ b/gcc/prefix.c @@ -1,12 +1,13 @@ /* Utility to update paths from internal to external forms. - Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + 2007 Free Software Foundation, Inc. -This file is part of GNU CC. +This file is part of GCC. -GNU CC is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at +your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,9 +15,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public -License along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +License along with GCC; see the file COPYING3. If not see +. */ /* This file contains routines to update a path, both to canonicalize the directory format and to handle any prefix translation. @@ -42,7 +42,7 @@ Boston, MA 02111-1307, USA. */ be considered a "key" and looked up as follows: -- If this is a Win32 OS, then the Registry will be examined for - an entry of "key" in + an entry of "key" in HKEY_LOCAL_MACHINE\SOFTWARE\Free Software Foundation\ @@ -58,7 +58,7 @@ Boston, MA 02111-1307, USA. */ as an environment variable, whose value will be returned. Once all this is done, any '/' will be converted to DIR_SEPARATOR, - if they are different. + if they are different. NOTE: using resolve_keyed_path under Win32 requires linking with advapi32.dll. */ @@ -66,6 +66,8 @@ Boston, MA 02111-1307, USA. */ #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY) #include #endif @@ -73,20 +75,20 @@ Boston, MA 02111-1307, USA. */ static const char *std_prefix = PREFIX; -static const char *get_key_value PARAMS ((char *)); -static const char *translate_name PARAMS ((const char *)); -static char *save_string PARAMS ((const char *, int)); +static const char *get_key_value (char *); +static char *translate_name (char *); +static char *save_string (const char *, int); +static void tr (char *, int, int); #if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY) -static char *lookup_key PARAMS ((char *)); +static char *lookup_key (char *); static HKEY reg_key = (HKEY) INVALID_HANDLE_VALUE; #endif /* Given KEY, as above, return its value. */ static const char * -get_key_value (key) - char *key; +get_key_value (char *key) { const char *prefix = 0; char *temp = 0; @@ -107,70 +109,12 @@ get_key_value (key) return prefix; } -/* Concatenate a sequence of strings, returning the result. - - This function is based on the one in libiberty. */ - -char * -concat VPARAMS ((const char *first, ...)) -{ - register int length; - register char *newstr; - register char *end; - register const char *arg; - va_list args; -#ifndef ANSI_PROTOTYPES - const char *first; -#endif - - /* First compute the size of the result and get sufficient memory. */ - - VA_START (args, first); -#ifndef ANSI_PROTOTYPES - first = va_arg (args, const char *); -#endif - - arg = first; - length = 0; - - while (arg != 0) - { - length += strlen (arg); - arg = va_arg (args, const char *); - } - - newstr = (char *) xmalloc (length + 1); - va_end (args); - - /* Now copy the individual pieces to the result string. */ - - VA_START (args, first); -#ifndef ANSI_PROTOTYPES - first = va_arg (args, char *); -#endif - - end = newstr; - arg = first; - while (arg != 0) - { - while (*arg) - *end++ = *arg++; - arg = va_arg (args, const char *); - } - *end = '\000'; - va_end (args); - - return (newstr); -} - /* Return a copy of a string that has been placed in the heap. */ static char * -save_string (s, len) - const char *s; - int len; +save_string (const char *s, int len) { - register char *result = xmalloc (len + 1); + char *result = XNEWVEC (char, len + 1); memcpy (result, s, len); result[len] = 0; @@ -179,11 +123,14 @@ save_string (s, len) #if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY) +#ifndef WIN32_REGISTRY_KEY +# define WIN32_REGISTRY_KEY BASEVER +#endif + /* Look up "key" in the registry, as above. */ static char * -lookup_key (key) - char *key; +lookup_key (char *key) { char *dst; DWORD size; @@ -204,20 +151,20 @@ lookup_key (key) KEY_READ, ®_key); if (res != ERROR_SUCCESS) - { - reg_key = (HKEY) INVALID_HANDLE_VALUE; - return 0; - } + { + reg_key = (HKEY) INVALID_HANDLE_VALUE; + return 0; + } } size = 32; - dst = (char *) xmalloc (size); + dst = xmalloc (size); - res = RegQueryValueExA (reg_key, key, 0, &type, dst, &size); + res = RegQueryValueExA (reg_key, key, 0, &type, (LPBYTE) dst, &size); if (res == ERROR_MORE_DATA && type == REG_SZ) { - dst = (char *) xrealloc (dst, size); - res = RegQueryValueExA (reg_key, key, 0, &type, dst, &size); + dst = xrealloc (dst, size); + res = RegQueryValueExA (reg_key, key, 0, &type, (LPBYTE) dst, &size); } if (type != REG_SZ || res != ERROR_SUCCESS) @@ -230,108 +177,180 @@ lookup_key (key) } #endif -/* If NAME starts with a '@' or '$', apply the translation rules above - and return a new name. Otherwise, return the given name. */ +/* If NAME, a malloc-ed string, starts with a '@' or '$', apply the + translation rules above and return a newly malloc-ed name. + Otherwise, return the given name. */ -static const char * -translate_name (name) - const char *name; +static char * +translate_name (char *name) { - char code = name[0]; - char *key; - const char *prefix = 0; + char code; + char *key, *old_name; + const char *prefix; int keylen; - if (code != '@' && code != '$') - return name; - - for (keylen = 0; - (name[keylen + 1] != 0 && !IS_DIR_SEPARATOR (name[keylen + 1])); - keylen++) - ; + for (;;) + { + code = name[0]; + if (code != '@' && code != '$') + break; + + for (keylen = 0; + (name[keylen + 1] != 0 && !IS_DIR_SEPARATOR (name[keylen + 1])); + keylen++) + ; + + key = (char *) alloca (keylen + 1); + strncpy (key, &name[1], keylen); + key[keylen] = 0; + + if (code == '@') + { + prefix = get_key_value (key); + if (prefix == 0) + prefix = std_prefix; + } + else + prefix = getenv (key); - key = (char *) alloca (keylen + 1); - strncpy (key, &name[1], keylen); - key[keylen] = 0; + if (prefix == 0) + prefix = PREFIX; - name = &name[keylen + 1]; + /* We used to strip trailing DIR_SEPARATORs here, but that can + sometimes yield a result with no separator when one was coded + and intended by the user, causing two path components to run + together. */ - if (code == '@') - { - prefix = get_key_value (key); - if (prefix == 0) - prefix = std_prefix; + old_name = name; + name = concat (prefix, &name[keylen + 1], NULL); + free (old_name); } - else - prefix = getenv (key); - if (prefix == 0) - prefix = PREFIX; - - /* We used to strip trailing DIR_SEPARATORs here, but that can - sometimes yield a result with no separator when one was coded - and intended by the user, causing two path components to run - together. */ + return name; +} - return concat (prefix, name, NULL); +/* In a NUL-terminated STRING, replace character C1 with C2 in-place. */ +static void +tr (char *string, int c1, int c2) +{ + do + { + if (*string == c1) + *string = c2; + } + while (*string++); } -/* Update PATH using KEY if PATH starts with PREFIX. */ +/* Update PATH using KEY if PATH starts with PREFIX as a directory. + The returned string is always malloc-ed, and the caller is + responsible for freeing it. */ -const char * -update_path (path, key) - const char *path; - const char *key; +char * +update_path (const char *path, const char *key) { - if (! strncmp (path, std_prefix, strlen (std_prefix)) && key != 0) + char *result, *p; + const int len = strlen (std_prefix); + + if (! strncmp (path, std_prefix, len) + && (IS_DIR_SEPARATOR(path[len]) + || path[len] == '\0') + && key != 0) { + bool free_key = false; + if (key[0] != '$') - key = concat ("@", key, NULL); + { + key = concat ("@", key, NULL); + free_key = true; + } + + result = concat (key, &path[len], NULL); + if (free_key) + free (CONST_CAST (char *, key)); + result = translate_name (result); + } + else + result = xstrdup (path); - path = concat (key, &path[strlen (std_prefix)], NULL); +#ifndef ALWAYS_STRIP_DOTDOT +#define ALWAYS_STRIP_DOTDOT 0 +#endif - while (path[0] == '@' || path[0] == '$') - path = translate_name (path); + p = result; + while (1) + { + char *src, *dest; + + p = strchr (p, '.'); + if (p == NULL) + break; + /* Look for `/../' */ + if (p[1] == '.' + && IS_DIR_SEPARATOR (p[2]) + && (p != result && IS_DIR_SEPARATOR (p[-1]))) + { + *p = 0; + if (!ALWAYS_STRIP_DOTDOT && access (result, X_OK) == 0) + { + *p = '.'; + break; + } + else + { + /* We can't access the dir, so we won't be able to + access dir/.. either. Strip out `dir/../'. If `dir' + turns out to be `.', strip one more path component. */ + dest = p; + do + { + --dest; + while (dest != result && IS_DIR_SEPARATOR (*dest)) + --dest; + while (dest != result && !IS_DIR_SEPARATOR (dest[-1])) + --dest; + } + while (dest != result && *dest == '.'); + /* If we have something like `./..' or `/..', don't + strip anything more. */ + if (*dest == '.' || IS_DIR_SEPARATOR (*dest)) + { + *p = '.'; + break; + } + src = p + 3; + while (IS_DIR_SEPARATOR (*src)) + ++src; + p = dest; + while ((*dest++ = *src++) != 0) + ; + } + } + else + ++p; } #ifdef UPDATE_PATH_HOST_CANONICALIZE -/* Perform host dependant canonicalization when needed. */ -UPDATE_PATH_HOST_CANONICALIZE (path, key); + /* Perform host dependent canonicalization when needed. */ + UPDATE_PATH_HOST_CANONICALIZE (result); #endif #ifdef DIR_SEPARATOR_2 /* Convert DIR_SEPARATOR_2 to DIR_SEPARATOR. */ - if (DIR_SEPARATOR != DIR_SEPARATOR_2) - { - char *new_path = xstrdup (path); - path = new_path; - do { - if (*new_path == DIR_SEPARATOR_2) - *new_path = DIR_SEPARATOR; - } while (*new_path++); - } + if (DIR_SEPARATOR_2 != DIR_SEPARATOR) + tr (result, DIR_SEPARATOR_2, DIR_SEPARATOR); #endif - + #if defined (DIR_SEPARATOR) && !defined (DIR_SEPARATOR_2) if (DIR_SEPARATOR != '/') - { - char *new_path = xstrdup (path); - path = new_path; - do { - if (*new_path == '/') - *new_path = DIR_SEPARATOR; - } while (*new_path++); - } + tr (result, '/', DIR_SEPARATOR); #endif - return path; + return result; } -/* Reset the standard prefix */ +/* Reset the standard prefix. */ void -set_std_prefix (prefix, len) - const char *prefix; - int len; +set_std_prefix (const char *prefix, int len) { std_prefix = save_string (prefix, len); }