diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1998-03-03 21:37:38 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1998-03-03 21:37:38 +0000 |
commit | c826e751760901de543f4640467e3a08df7f49bf (patch) | |
tree | 6a2323a78664ba45b78df1709ff3cc077db63ccd /gnu/usr.bin/gcc/prefix.c | |
parent | a4511fe6a5dc69a771b5ffdf64ba574c959cf37d (diff) |
GCC 2.8.0 merge
Diffstat (limited to 'gnu/usr.bin/gcc/prefix.c')
-rw-r--r-- | gnu/usr.bin/gcc/prefix.c | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/gnu/usr.bin/gcc/prefix.c b/gnu/usr.bin/gcc/prefix.c new file mode 100644 index 00000000000..bf501c74391 --- /dev/null +++ b/gnu/usr.bin/gcc/prefix.c @@ -0,0 +1,318 @@ +/* Utility to update paths from internal to external forms. + Copyright (C) 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +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 distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +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. */ + +/* This file contains routines to update a path, both to canonicalize + the directory format and to handle any prefix translation. + + This file must be compiled with -DPREFIX= to specify the "prefix" + value used by configure. If a filename does not begin with this + prefix, it will not be affected other than by directory canonicalization. + + Each caller of 'update_path' may specify both a filename and + a translation prefix and consist of the name of the package that contains + the file ("@GCC", "@BINUTIL", "@GNU", etc). + + If the prefix is not specified, the filename will only undergo + directory canonicalization. + + If it is specified, the string given by PREFIX will be replaced + by the specified prefix (with a '@' in front unless the prefix begins + with a '$') and further translation will be done as follows + until none of the two conditions below are met: + + 1) If the filename begins with '@', the string between the '@' and + the end of the name or the first '/' or directory separator will + 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 + + HKEY_LOCAL_MACHINE\SOFTWARE\Free Software Foundation\ + + if found, that value will be used. + + -- If not found (or not a Win32 OS), the environment variable + key_ROOT (the value of "key" concatenated with the constant "_ROOT") + is tried. If that fails, then PREFIX (see above) is used. + + 2) If the filename begins with a '$', the rest of the string up + to the end or the first '/' or directory separator will be used + 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. + + NOTE: using resolve_keyed_path under Win32 requires linking with + advapi32.dll. */ + + +#include "config.h" +#include "gansidecl.h" +#ifdef __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +#ifdef _WIN32 +#include <windows.h> +#endif + +static char *get_key_value PROTO((char *)); +static char *translate_name PROTO((char *)); +static char *concat PVPROTO((char *, ...)); +static char *save_string PROTO((char *, int)); + +#ifdef _WIN32 +static char *lookup_key PROTO((char *)); +static HKEY reg_key = (HKEY) INVALID_HANDLE_VALUE; +#endif + +extern char *getenv (); + +/* Given KEY, as above, return its value. */ + +static char * +get_key_value (key) + char *key; +{ + char *prefix = 0; + +#ifdef _WIN32 + prefix = lookup_key (key); +#endif + + if (prefix == 0) + prefix = getenv (concat (key, "_ROOT", NULL_PTR)); + + if (prefix == 0) + prefix = PREFIX; + + return prefix; +} + +/* Concatenate a sequence of strings, returning the result. + + This function is based on the one in libiberty. */ + +static char * +concat VPROTO((char *first, ...)) +{ + register int length; + register char *newstr; + register char *end; + register char *arg; + va_list args; +#ifndef __STDC__ + char *first; +#endif + + /* First compute the size of the result and get sufficient memory. */ + + VA_START (args, first); +#ifndef __STDC__ + first = va_arg (args, char *); +#endif + + arg = first; + length = 0; + + while (arg != 0) + { + length += strlen (arg); + arg = va_arg (args, char *); + } + + newstr = (char *) malloc (length + 1); + va_end (args); + + /* Now copy the individual pieces to the result string. */ + + VA_START (args, first); +#ifndef __STDC__ + first = va_arg (args, char *); +#endif + + end = newstr; + arg = first; + while (arg != 0) + { + while (*arg) + *end++ = *arg++; + arg = va_arg (args, 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) + char *s; + int len; +{ + register char *result = (char *) malloc (len + 1); + + bcopy (s, result, len); + result[len] = 0; + return result; +} + +#ifdef _WIN32 + +/* Look up "key" in the registry, as above. */ + +static char * +lookup_key (key) + char *key; +{ + char *dst; + DWORD size; + DWORD type; + LONG res; + + if (reg_key == (HKEY) INVALID_HANDLE_VALUE) + { + res = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE", 0, + KEY_READ, ®_key); + + if (res == ERROR_SUCCESS) + res = RegOpenKeyExA (reg_key, "Free Software Foundation", 0, + KEY_READ, ®_key); + + if (res != ERROR_SUCCESS) + { + reg_key = (HKEY) INVALID_HANDLE_VALUE; + return 0; + } + } + + size = 32; + dst = (char *) malloc (size); + + res = RegQueryValueExA (reg_key, key, 0, &type, dst, &size); + if (res == ERROR_MORE_DATA && type == REG_SZ) + { + dst = (char *) realloc (dst, size); + res = RegQueryValueExA (reg_key, key, 0, &type, dst, &size); + } + + if (type != REG_SZ || res != ERROR_SUCCESS) + { + free (dst); + dst = 0; + } + + return dst; +} +#endif + +/* If NAME starts with a '@' or '$', apply the translation rules above + and return a new name. Otherwise, return the given name. */ + +static char * +translate_name (name) + char *name; +{ + char code = name[0]; + char *key, *prefix; + int keylen; + + if (code != '@' && code != '$') + return name; + + for (keylen = 0; + (name[keylen + 1] != 0 && name[keylen + 1] != '/' +#ifdef DIR_SEPARATOR + && name[keylen + 1] != DIR_SEPARATOR +#endif + ); + keylen++) + ; + + key = alloca (keylen + 1); + strncpy (key, &name[1], keylen); + key[keylen] = 0; + + name = &name[keylen + 1]; + + if (code == '@') + { + prefix = get_key_value (key); + if (prefix == 0) + prefix = PREFIX; + } + else + { + prefix = getenv (key); + if (prefix == 0) + prefix = concat ("$", key, NULL_PTR); + } + + /* Remove any trailing directory separator from what we got. */ + if (prefix[strlen (prefix) - 1] == '/' +#ifdef DIR_SEPARATOR + || prefix[strlen (prefix) - 1] == DIR_SEPARATOR +#endif + ) + { + prefix = save_string (prefix, strlen (prefix)); + prefix[strlen (prefix) - 1] = 0; + } + + return concat (prefix, name, NULL_PTR); +} + +/* Update PATH using KEY if PATH starts with PREFIX. */ + +char * +update_path (path, key) + char *path; + char *key; +{ + if (! strncmp (path, PREFIX, strlen (PREFIX)) && key != 0) + { + if (key[0] != '$') + key = concat ("@", key, NULL_PTR); + + path = concat (key, &path[strlen (PREFIX)], NULL_PTR); + + while (path[0] == '@' || path[0] == '$') + path = translate_name (path); + } + +#ifdef DIR_SEPARATOR + if (DIR_SEPARATOR != '/') + { + int i; + int len = strlen (path); + + path = save_string (path, len); + for (i = 0; i < len; i++) + if (path[i] == '/') + path[i] = DIR_SEPARATOR; + } +#endif + + return path; +} |