]> gcc.gnu.org Git - gcc.git/blame - gcc/prefix.c
Makefile.in, [...]: replace "GNU CC" with "GCC".
[gcc.git] / gcc / prefix.c
CommitLineData
4a5121b5 1/* Utility to update paths from internal to external forms.
9311a396 2 Copyright (C) 1997, 1998, 1999, 2000 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
8the Free Software Foundation; either version 2 of the License, or (at
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
17License along with GCC; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21/* This file contains routines to update a path, both to canonicalize
22 the directory format and to handle any prefix translation.
23
24 This file must be compiled with -DPREFIX= to specify the "prefix"
25 value used by configure. If a filename does not begin with this
26 prefix, it will not be affected other than by directory canonicalization.
27
28 Each caller of 'update_path' may specify both a filename and
29 a translation prefix and consist of the name of the package that contains
30 the file ("@GCC", "@BINUTIL", "@GNU", etc).
31
32 If the prefix is not specified, the filename will only undergo
33 directory canonicalization.
34
35 If it is specified, the string given by PREFIX will be replaced
36 by the specified prefix (with a '@' in front unless the prefix begins
37 with a '$') and further translation will be done as follows
38 until none of the two conditions below are met:
39
40 1) If the filename begins with '@', the string between the '@' and
41 the end of the name or the first '/' or directory separator will
42 be considered a "key" and looked up as follows:
43
44 -- If this is a Win32 OS, then the Registry will be examined for
45 an entry of "key" in
46
f4ab28e3 47 HKEY_LOCAL_MACHINE\SOFTWARE\Free Software Foundation\<KEY>
4a5121b5 48
f4ab28e3
MK
49 if found, that value will be used. <KEY> defaults to GCC version
50 string, but can be overridden at configuration time.
4a5121b5
JL
51
52 -- If not found (or not a Win32 OS), the environment variable
53 key_ROOT (the value of "key" concatenated with the constant "_ROOT")
54 is tried. If that fails, then PREFIX (see above) is used.
55
56 2) If the filename begins with a '$', the rest of the string up
57 to the end or the first '/' or directory separator will be used
58 as an environment variable, whose value will be returned.
59
60 Once all this is done, any '/' will be converted to DIR_SEPARATOR,
61 if they are different.
62
63 NOTE: using resolve_keyed_path under Win32 requires linking with
64 advapi32.dll. */
65
66
67#include "config.h"
670ee920 68#include "system.h"
f4ab28e3 69#if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY)
4a5121b5
JL
70#include <windows.h>
71#endif
460ee112 72#include "prefix.h"
4a5121b5 73
460ee112 74static const char *std_prefix = PREFIX;
6ed4bb9a 75
13536812 76static const char *get_key_value PARAMS ((char *));
51c04256 77static char *translate_name PARAMS ((char *));
13536812 78static char *save_string PARAMS ((const char *, int));
51c04256 79static void tr PARAMS ((char *, int, int));
4a5121b5 80
f4ab28e3 81#if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY)
13536812 82static char *lookup_key PARAMS ((char *));
4a5121b5
JL
83static HKEY reg_key = (HKEY) INVALID_HANDLE_VALUE;
84#endif
85
4a5121b5
JL
86/* Given KEY, as above, return its value. */
87
460ee112 88static const char *
4a5121b5
JL
89get_key_value (key)
90 char *key;
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
105 if (temp)
106 free (temp);
4a5121b5
JL
107
108 return prefix;
109}
110
111/* Concatenate a sequence of strings, returning the result.
112
113 This function is based on the one in libiberty. */
114
2778b98d 115char *
13536812 116concat VPARAMS ((const char *first, ...))
4a5121b5
JL
117{
118 register int length;
119 register char *newstr;
120 register char *end;
2778b98d 121 register const char *arg;
4a5121b5 122 va_list args;
5148a72b 123#ifndef ANSI_PROTOTYPES
2778b98d 124 const char *first;
4a5121b5
JL
125#endif
126
127 /* First compute the size of the result and get sufficient memory. */
128
129 VA_START (args, first);
5148a72b 130#ifndef ANSI_PROTOTYPES
2778b98d 131 first = va_arg (args, const char *);
4a5121b5
JL
132#endif
133
134 arg = first;
135 length = 0;
136
137 while (arg != 0)
138 {
139 length += strlen (arg);
2778b98d 140 arg = va_arg (args, const char *);
4a5121b5
JL
141 }
142
3ea6b476 143 newstr = (char *) xmalloc (length + 1);
4a5121b5
JL
144 va_end (args);
145
146 /* Now copy the individual pieces to the result string. */
147
148 VA_START (args, first);
5148a72b 149#ifndef ANSI_PROTOTYPES
4a5121b5
JL
150 first = va_arg (args, char *);
151#endif
152
153 end = newstr;
154 arg = first;
155 while (arg != 0)
156 {
157 while (*arg)
158 *end++ = *arg++;
2778b98d 159 arg = va_arg (args, const char *);
4a5121b5
JL
160 }
161 *end = '\000';
162 va_end (args);
163
164 return (newstr);
165}
166
167/* Return a copy of a string that has been placed in the heap. */
168
169static char *
170save_string (s, len)
460ee112
KG
171 const char *s;
172 int len;
4a5121b5 173{
460ee112 174 register char *result = xmalloc (len + 1);
4a5121b5 175
4e135bdd 176 memcpy (result, s, len);
4a5121b5
JL
177 result[len] = 0;
178 return result;
179}
180
f4ab28e3 181#if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY)
4a5121b5
JL
182
183/* Look up "key" in the registry, as above. */
184
185static char *
186lookup_key (key)
187 char *key;
188{
189 char *dst;
190 DWORD size;
191 DWORD type;
192 LONG res;
193
194 if (reg_key == (HKEY) INVALID_HANDLE_VALUE)
195 {
196 res = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE", 0,
197 KEY_READ, &reg_key);
198
199 if (res == ERROR_SUCCESS)
200 res = RegOpenKeyExA (reg_key, "Free Software Foundation", 0,
201 KEY_READ, &reg_key);
202
f4ab28e3
MK
203 if (res == ERROR_SUCCESS)
204 res = RegOpenKeyExA (reg_key, WIN32_REGISTRY_KEY, 0,
205 KEY_READ, &reg_key);
206
4a5121b5
JL
207 if (res != ERROR_SUCCESS)
208 {
209 reg_key = (HKEY) INVALID_HANDLE_VALUE;
210 return 0;
211 }
212 }
213
214 size = 32;
3ea6b476 215 dst = (char *) xmalloc (size);
4a5121b5
JL
216
217 res = RegQueryValueExA (reg_key, key, 0, &type, dst, &size);
218 if (res == ERROR_MORE_DATA && type == REG_SZ)
219 {
3ea6b476 220 dst = (char *) xrealloc (dst, size);
4a5121b5
JL
221 res = RegQueryValueExA (reg_key, key, 0, &type, dst, &size);
222 }
223
224 if (type != REG_SZ || res != ERROR_SUCCESS)
225 {
226 free (dst);
227 dst = 0;
228 }
229
230 return dst;
231}
232#endif
233
51c04256
NB
234/* If NAME, a malloc-ed string, starts with a '@' or '$', apply the
235 translation rules above and return a newly malloc-ed name.
236 Otherwise, return the given name. */
4a5121b5 237
51c04256 238static char *
4a5121b5 239translate_name (name)
51c04256 240 char *name;
4a5121b5 241{
51c04256
NB
242 char code;
243 char *key, *old_name;
244 const char *prefix;
4a5121b5
JL
245 int keylen;
246
51c04256
NB
247 for (;;)
248 {
249 code = name[0];
250 if (code != '@' && code != '$')
251 break;
252
253 for (keylen = 0;
254 (name[keylen + 1] != 0 && !IS_DIR_SEPARATOR (name[keylen + 1]));
255 keylen++)
256 ;
257
258 key = (char *) alloca (keylen + 1);
259 strncpy (key, &name[1], keylen);
260 key[keylen] = 0;
261
262 if (code == '@')
263 {
264 prefix = get_key_value (key);
265 if (prefix == 0)
266 prefix = std_prefix;
267 }
268 else
269 prefix = getenv (key);
4a5121b5 270
51c04256
NB
271 if (prefix == 0)
272 prefix = PREFIX;
4a5121b5 273
51c04256
NB
274 /* We used to strip trailing DIR_SEPARATORs here, but that can
275 sometimes yield a result with no separator when one was coded
276 and intended by the user, causing two path components to run
277 together. */
4a5121b5 278
51c04256
NB
279 old_name = name;
280 name = concat (prefix, &name[keylen + 1], NULL);
281 free (old_name);
4a5121b5 282 }
e5e809f4 283
51c04256
NB
284 return name;
285}
4a5121b5 286
51c04256
NB
287/* In a NUL-terminated STRING, replace character C1 with C2 in-place. */
288static void
289tr (string, c1, c2)
290 char *string;
291 int c1, c2;
292{
293 do
294 {
295 if (*string == c1)
296 *string = c2;
297 }
298 while (*string++);
4a5121b5
JL
299}
300
51c04256
NB
301/* Update PATH using KEY if PATH starts with PREFIX. The returned
302 string is always malloc-ed, and the caller is responsible for
303 freeing it. */
4a5121b5 304
51c04256 305char *
4a5121b5 306update_path (path, key)
460ee112
KG
307 const char *path;
308 const char *key;
4a5121b5 309{
51c04256
NB
310 char *result;
311
6ed4bb9a 312 if (! strncmp (path, std_prefix, strlen (std_prefix)) && key != 0)
4a5121b5 313 {
51c04256 314 bool free_key = false;
4a5121b5 315
51c04256
NB
316 if (key[0] != '$')
317 {
318 key = concat ("@", key, NULL);
319 free_key = true;
320 }
321
322 result = concat (key, &path[strlen (std_prefix)], NULL);
323 if (free_key)
324 free ((char *) key);
325 result = translate_name (result);
4a5121b5 326 }
51c04256
NB
327 else
328 result = xstrdup (path);
509781a4 329
93284395 330#ifdef UPDATE_PATH_HOST_CANONICALIZE
51c04256
NB
331 /* Perform host dependent canonicalization when needed. */
332 UPDATE_PATH_HOST_CANONICALIZE (path);
93284395
ME
333#endif
334
509781a4 335#ifdef DIR_SEPARATOR_2
dc297297 336 /* Convert DIR_SEPARATOR_2 to DIR_SEPARATOR. */
51c04256
NB
337 if (DIR_SEPARATOR_2 != DIR_SEPARATOR)
338 tr (result, DIR_SEPARATOR_2, DIR_SEPARATOR);
509781a4 339#endif
51c04256 340
509781a4 341#if defined (DIR_SEPARATOR) && !defined (DIR_SEPARATOR_2)
4a5121b5 342 if (DIR_SEPARATOR != '/')
51c04256 343 tr (result, '/', DIR_SEPARATOR);
4a5121b5
JL
344#endif
345
51c04256 346 return result;
4a5121b5 347}
6ed4bb9a
MM
348
349/* Reset the standard prefix */
350void
351set_std_prefix (prefix, len)
460ee112
KG
352 const char *prefix;
353 int len;
6ed4bb9a
MM
354{
355 std_prefix = save_string (prefix, len);
356}
This page took 1.902081 seconds and 5 git commands to generate.