]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/prefix.c
rs6000: re-enable web and rnreg with -funroll-loops
[thirdparty/gcc.git] / gcc / prefix.c
CommitLineData
4a5121b5 1/* Utility to update paths from internal to external forms.
a5544970 2 Copyright (C) 1997-2019 Free Software Foundation, Inc.
4a5121b5 3
1322177d 4This file is part of GCC.
4a5121b5 5
1322177d
LB
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU Library General Public License as published by
9dcd6f09 8the Free Software Foundation; either version 3 of the License, or (at
1322177d 9your option) any later version.
4a5121b5
JL
10
11GCC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14Library General Public License for more details.
15
16You should have received a copy of the GNU Library General Public
9dcd6f09
NC
17License along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
4a5121b5
JL
19
20/* This file contains routines to update a path, both to canonicalize
21 the directory format and to handle any prefix translation.
22
23 This file must be compiled with -DPREFIX= to specify the "prefix"
24 value used by configure. If a filename does not begin with this
25 prefix, it will not be affected other than by directory canonicalization.
26
27 Each caller of 'update_path' may specify both a filename and
28 a translation prefix and consist of the name of the package that contains
29 the file ("@GCC", "@BINUTIL", "@GNU", etc).
30
31 If the prefix is not specified, the filename will only undergo
32 directory canonicalization.
33
34 If it is specified, the string given by PREFIX will be replaced
35 by the specified prefix (with a '@' in front unless the prefix begins
36 with a '$') and further translation will be done as follows
37 until none of the two conditions below are met:
38
39 1) If the filename begins with '@', the string between the '@' and
40 the end of the name or the first '/' or directory separator will
41 be considered a "key" and looked up as follows:
42
43 -- If this is a Win32 OS, then the Registry will be examined for
6a4d6760 44 an entry of "key" in
4a5121b5 45
f4ab28e3 46 HKEY_LOCAL_MACHINE\SOFTWARE\Free Software Foundation\<KEY>
4a5121b5 47
f4ab28e3
MK
48 if found, that value will be used. <KEY> defaults to GCC version
49 string, but can be overridden at configuration time.
4a5121b5
JL
50
51 -- If not found (or not a Win32 OS), the environment variable
52 key_ROOT (the value of "key" concatenated with the constant "_ROOT")
53 is tried. If that fails, then PREFIX (see above) is used.
54
55 2) If the filename begins with a '$', the rest of the string up
56 to the end or the first '/' or directory separator will be used
57 as an environment variable, whose value will be returned.
58
59 Once all this is done, any '/' will be converted to DIR_SEPARATOR,
6a4d6760 60 if they are different.
4a5121b5
JL
61
62 NOTE: using resolve_keyed_path under Win32 requires linking with
63 advapi32.dll. */
64
65
66#include "config.h"
670ee920 67#include "system.h"
4977bab6 68#include "coretypes.h"
f4ab28e3 69#if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY)
4a5121b5
JL
70#include <windows.h>
71#endif
460ee112 72#include "prefix.h"
c49a6962 73#include "common/common-target.h"
4a5121b5 74
460ee112 75static const char *std_prefix = PREFIX;
6ed4bb9a 76
0c20a65f
AJ
77static const char *get_key_value (char *);
78static char *translate_name (char *);
79static char *save_string (const char *, int);
80static void tr (char *, int, int);
4a5121b5 81
f4ab28e3 82#if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY)
0c20a65f 83static char *lookup_key (char *);
4a5121b5
JL
84static HKEY reg_key = (HKEY) INVALID_HANDLE_VALUE;
85#endif
86
4a5121b5
JL
87/* Given KEY, as above, return its value. */
88
460ee112 89static const char *
0c20a65f 90get_key_value (char *key)
4a5121b5 91{
460ee112 92 const char *prefix = 0;
6ed4bb9a 93 char *temp = 0;
4a5121b5 94
f4ab28e3 95#if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY)
4a5121b5
JL
96 prefix = lookup_key (key);
97#endif
98
99 if (prefix == 0)
d4f2852f 100 prefix = getenv (temp = concat (key, "_ROOT", NULL));
4a5121b5
JL
101
102 if (prefix == 0)
6ed4bb9a
MM
103 prefix = std_prefix;
104
04695783 105 free (temp);
4a5121b5
JL
106
107 return prefix;
108}
109
4a5121b5
JL
110/* Return a copy of a string that has been placed in the heap. */
111
112static char *
0c20a65f 113save_string (const char *s, int len)
4a5121b5 114{
cceb1885 115 char *result = XNEWVEC (char, len + 1);
4a5121b5 116
4e135bdd 117 memcpy (result, s, len);
4a5121b5
JL
118 result[len] = 0;
119 return result;
120}
121
f4ab28e3 122#if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY)
4a5121b5 123
a1286ef5
ZW
124#ifndef WIN32_REGISTRY_KEY
125# define WIN32_REGISTRY_KEY BASEVER
126#endif
127
4a5121b5
JL
128/* Look up "key" in the registry, as above. */
129
130static char *
0c20a65f 131lookup_key (char *key)
4a5121b5
JL
132{
133 char *dst;
134 DWORD size;
135 DWORD type;
136 LONG res;
137
138 if (reg_key == (HKEY) INVALID_HANDLE_VALUE)
139 {
140 res = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE", 0,
141 KEY_READ, &reg_key);
142
143 if (res == ERROR_SUCCESS)
144 res = RegOpenKeyExA (reg_key, "Free Software Foundation", 0,
145 KEY_READ, &reg_key);
146
f4ab28e3
MK
147 if (res == ERROR_SUCCESS)
148 res = RegOpenKeyExA (reg_key, WIN32_REGISTRY_KEY, 0,
149 KEY_READ, &reg_key);
150
4a5121b5 151 if (res != ERROR_SUCCESS)
6a4d6760
KH
152 {
153 reg_key = (HKEY) INVALID_HANDLE_VALUE;
154 return 0;
155 }
4a5121b5
JL
156 }
157
158 size = 32;
e97cae96 159 dst = XNEWVEC (char, size);
4a5121b5 160
aff982b1 161 res = RegQueryValueExA (reg_key, key, 0, &type, (LPBYTE) dst, &size);
4a5121b5
JL
162 if (res == ERROR_MORE_DATA && type == REG_SZ)
163 {
e97cae96 164 dst = XRESIZEVEC (char, dst, size);
aff982b1 165 res = RegQueryValueExA (reg_key, key, 0, &type, (LPBYTE) dst, &size);
4a5121b5
JL
166 }
167
168 if (type != REG_SZ || res != ERROR_SUCCESS)
169 {
170 free (dst);
171 dst = 0;
172 }
173
174 return dst;
175}
176#endif
177
51c04256
NB
178/* If NAME, a malloc-ed string, starts with a '@' or '$', apply the
179 translation rules above and return a newly malloc-ed name.
180 Otherwise, return the given name. */
4a5121b5 181
51c04256 182static char *
0c20a65f 183translate_name (char *name)
4a5121b5 184{
51c04256
NB
185 char code;
186 char *key, *old_name;
187 const char *prefix;
4a5121b5
JL
188 int keylen;
189
51c04256
NB
190 for (;;)
191 {
192 code = name[0];
193 if (code != '@' && code != '$')
194 break;
195
196 for (keylen = 0;
197 (name[keylen + 1] != 0 && !IS_DIR_SEPARATOR (name[keylen + 1]));
198 keylen++)
199 ;
200
cceb1885 201 key = (char *) alloca (keylen + 1);
42c544b0 202 memcpy (key, &name[1], keylen);
51c04256
NB
203 key[keylen] = 0;
204
205 if (code == '@')
206 {
207 prefix = get_key_value (key);
208 if (prefix == 0)
209 prefix = std_prefix;
210 }
211 else
212 prefix = getenv (key);
4a5121b5 213
51c04256
NB
214 if (prefix == 0)
215 prefix = PREFIX;
4a5121b5 216
51c04256
NB
217 /* We used to strip trailing DIR_SEPARATORs here, but that can
218 sometimes yield a result with no separator when one was coded
219 and intended by the user, causing two path components to run
220 together. */
4a5121b5 221
51c04256
NB
222 old_name = name;
223 name = concat (prefix, &name[keylen + 1], NULL);
224 free (old_name);
4a5121b5 225 }
e5e809f4 226
51c04256
NB
227 return name;
228}
4a5121b5 229
51c04256
NB
230/* In a NUL-terminated STRING, replace character C1 with C2 in-place. */
231static void
0c20a65f 232tr (char *string, int c1, int c2)
51c04256
NB
233{
234 do
235 {
236 if (*string == c1)
237 *string = c2;
238 }
239 while (*string++);
4a5121b5
JL
240}
241
428d4d76
TQ
242/* Update PATH using KEY if PATH starts with PREFIX as a directory.
243 The returned string is always malloc-ed, and the caller is
244 responsible for freeing it. */
4a5121b5 245
51c04256 246char *
0c20a65f 247update_path (const char *path, const char *key)
4a5121b5 248{
f6f23ad2 249 char *result, *p;
428d4d76 250 const int len = strlen (std_prefix);
51c04256 251
ba78087b 252 if (! filename_ncmp (path, std_prefix, len)
c3284718 253 && (IS_DIR_SEPARATOR (path[len])
428d4d76
TQ
254 || path[len] == '\0')
255 && key != 0)
4a5121b5 256 {
51c04256 257 bool free_key = false;
4a5121b5 258
51c04256
NB
259 if (key[0] != '$')
260 {
261 key = concat ("@", key, NULL);
262 free_key = true;
263 }
264
428d4d76 265 result = concat (key, &path[len], NULL);
51c04256 266 if (free_key)
b1d5455a 267 free (CONST_CAST (char *, key));
51c04256 268 result = translate_name (result);
4a5121b5 269 }
51c04256
NB
270 else
271 result = xstrdup (path);
509781a4 272
f6f23ad2
AM
273 p = result;
274 while (1)
275 {
276 char *src, *dest;
277
278 p = strchr (p, '.');
279 if (p == NULL)
280 break;
f6f23ad2 281 /* Look for `/../' */
d4348177
AM
282 if (p[1] == '.'
283 && IS_DIR_SEPARATOR (p[2])
284 && (p != result && IS_DIR_SEPARATOR (p[-1])))
f6f23ad2
AM
285 {
286 *p = 0;
c49a6962
JM
287 if (!targetm_common.always_strip_dotdot
288 && access (result, X_OK) == 0)
f6f23ad2
AM
289 {
290 *p = '.';
d4348177 291 break;
f6f23ad2
AM
292 }
293 else
294 {
295 /* We can't access the dir, so we won't be able to
d4348177
AM
296 access dir/.. either. Strip out `dir/../'. If `dir'
297 turns out to be `.', strip one more path component. */
298 dest = p;
299 do
300 {
301 --dest;
302 while (dest != result && IS_DIR_SEPARATOR (*dest))
303 --dest;
304 while (dest != result && !IS_DIR_SEPARATOR (dest[-1]))
305 --dest;
306 }
307 while (dest != result && *dest == '.');
308 /* If we have something like `./..' or `/..', don't
309 strip anything more. */
310 if (*dest == '.' || IS_DIR_SEPARATOR (*dest))
311 {
312 *p = '.';
313 break;
314 }
f6f23ad2
AM
315 src = p + 3;
316 while (IS_DIR_SEPARATOR (*src))
317 ++src;
318 p = dest;
319 while ((*dest++ = *src++) != 0)
320 ;
321 }
322 }
323 else
324 ++p;
325 }
326
93284395 327#ifdef UPDATE_PATH_HOST_CANONICALIZE
51c04256 328 /* Perform host dependent canonicalization when needed. */
f6f23ad2 329 UPDATE_PATH_HOST_CANONICALIZE (result);
93284395
ME
330#endif
331
509781a4 332#ifdef DIR_SEPARATOR_2
dc297297 333 /* Convert DIR_SEPARATOR_2 to DIR_SEPARATOR. */
51c04256
NB
334 if (DIR_SEPARATOR_2 != DIR_SEPARATOR)
335 tr (result, DIR_SEPARATOR_2, DIR_SEPARATOR);
509781a4 336#endif
51c04256 337
509781a4 338#if defined (DIR_SEPARATOR) && !defined (DIR_SEPARATOR_2)
4a5121b5 339 if (DIR_SEPARATOR != '/')
51c04256 340 tr (result, '/', DIR_SEPARATOR);
4a5121b5
JL
341#endif
342
51c04256 343 return result;
4a5121b5 344}
6ed4bb9a 345
f9da5064 346/* Reset the standard prefix. */
6ed4bb9a 347void
0c20a65f 348set_std_prefix (const char *prefix, int len)
6ed4bb9a
MM
349{
350 std_prefix = save_string (prefix, len);
351}