]> gcc.gnu.org Git - gcc.git/blame - gcc/prefix.c
mh-djgpp: Conditionally set 'target_alias' to djgpp.
[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
JL
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or
7modify it under the terms of the GNU Library General Public
8License as published by the Free Software Foundation; either
9version 2 of the License, or (at your option) any later version.
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
KG
76static const char *get_key_value PARAMS ((char *));
77static const char *translate_name PARAMS ((const char *));
78static char *save_string PARAMS ((const char *, int));
4a5121b5 79
f4ab28e3 80#if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY)
13536812 81static char *lookup_key PARAMS ((char *));
4a5121b5
JL
82static HKEY reg_key = (HKEY) INVALID_HANDLE_VALUE;
83#endif
84
4a5121b5
JL
85/* Given KEY, as above, return its value. */
86
460ee112 87static const char *
4a5121b5
JL
88get_key_value (key)
89 char *key;
90{
460ee112 91 const char *prefix = 0;
6ed4bb9a 92 char *temp = 0;
4a5121b5 93
f4ab28e3 94#if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY)
4a5121b5
JL
95 prefix = lookup_key (key);
96#endif
97
98 if (prefix == 0)
6ed4bb9a 99 prefix = getenv (temp = concat (key, "_ROOT", NULL_PTR));
4a5121b5
JL
100
101 if (prefix == 0)
6ed4bb9a
MM
102 prefix = std_prefix;
103
104 if (temp)
105 free (temp);
4a5121b5
JL
106
107 return prefix;
108}
109
110/* Concatenate a sequence of strings, returning the result.
111
112 This function is based on the one in libiberty. */
113
2778b98d 114char *
13536812 115concat VPARAMS ((const char *first, ...))
4a5121b5
JL
116{
117 register int length;
118 register char *newstr;
119 register char *end;
2778b98d 120 register const char *arg;
4a5121b5 121 va_list args;
5148a72b 122#ifndef ANSI_PROTOTYPES
2778b98d 123 const char *first;
4a5121b5
JL
124#endif
125
126 /* First compute the size of the result and get sufficient memory. */
127
128 VA_START (args, first);
5148a72b 129#ifndef ANSI_PROTOTYPES
2778b98d 130 first = va_arg (args, const char *);
4a5121b5
JL
131#endif
132
133 arg = first;
134 length = 0;
135
136 while (arg != 0)
137 {
138 length += strlen (arg);
2778b98d 139 arg = va_arg (args, const char *);
4a5121b5
JL
140 }
141
3ea6b476 142 newstr = (char *) xmalloc (length + 1);
4a5121b5
JL
143 va_end (args);
144
145 /* Now copy the individual pieces to the result string. */
146
147 VA_START (args, first);
5148a72b 148#ifndef ANSI_PROTOTYPES
4a5121b5
JL
149 first = va_arg (args, char *);
150#endif
151
152 end = newstr;
153 arg = first;
154 while (arg != 0)
155 {
156 while (*arg)
157 *end++ = *arg++;
2778b98d 158 arg = va_arg (args, const char *);
4a5121b5
JL
159 }
160 *end = '\000';
161 va_end (args);
162
163 return (newstr);
164}
165
166/* Return a copy of a string that has been placed in the heap. */
167
168static char *
169save_string (s, len)
460ee112
KG
170 const char *s;
171 int len;
4a5121b5 172{
460ee112 173 register char *result = xmalloc (len + 1);
4a5121b5
JL
174
175 bcopy (s, result, len);
176 result[len] = 0;
177 return result;
178}
179
f4ab28e3 180#if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY)
4a5121b5
JL
181
182/* Look up "key" in the registry, as above. */
183
184static char *
185lookup_key (key)
186 char *key;
187{
188 char *dst;
189 DWORD size;
190 DWORD type;
191 LONG res;
192
193 if (reg_key == (HKEY) INVALID_HANDLE_VALUE)
194 {
195 res = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE", 0,
196 KEY_READ, &reg_key);
197
198 if (res == ERROR_SUCCESS)
199 res = RegOpenKeyExA (reg_key, "Free Software Foundation", 0,
200 KEY_READ, &reg_key);
201
f4ab28e3
MK
202 if (res == ERROR_SUCCESS)
203 res = RegOpenKeyExA (reg_key, WIN32_REGISTRY_KEY, 0,
204 KEY_READ, &reg_key);
205
4a5121b5
JL
206 if (res != ERROR_SUCCESS)
207 {
208 reg_key = (HKEY) INVALID_HANDLE_VALUE;
209 return 0;
210 }
211 }
212
213 size = 32;
3ea6b476 214 dst = (char *) xmalloc (size);
4a5121b5
JL
215
216 res = RegQueryValueExA (reg_key, key, 0, &type, dst, &size);
217 if (res == ERROR_MORE_DATA && type == REG_SZ)
218 {
3ea6b476 219 dst = (char *) xrealloc (dst, size);
4a5121b5
JL
220 res = RegQueryValueExA (reg_key, key, 0, &type, dst, &size);
221 }
222
223 if (type != REG_SZ || res != ERROR_SUCCESS)
224 {
225 free (dst);
226 dst = 0;
227 }
228
229 return dst;
230}
231#endif
232
233/* If NAME starts with a '@' or '$', apply the translation rules above
234 and return a new name. Otherwise, return the given name. */
235
460ee112 236static const char *
4a5121b5 237translate_name (name)
460ee112 238 const char *name;
4a5121b5
JL
239{
240 char code = name[0];
460ee112
KG
241 char *key;
242 const char *prefix = 0;
4a5121b5
JL
243 int keylen;
244
245 if (code != '@' && code != '$')
246 return name;
247
248 for (keylen = 0;
509781a4 249 (name[keylen + 1] != 0 && !IS_DIR_SEPARATOR (name[keylen + 1]));
4a5121b5
JL
250 keylen++)
251 ;
252
804a4e13 253 key = (char *) alloca (keylen + 1);
4a5121b5
JL
254 strncpy (key, &name[1], keylen);
255 key[keylen] = 0;
256
257 name = &name[keylen + 1];
258
259 if (code == '@')
260 {
261 prefix = get_key_value (key);
262 if (prefix == 0)
6ed4bb9a 263 prefix = std_prefix;
4a5121b5
JL
264 }
265 else
e5e809f4
JL
266 prefix = getenv (key);
267
268 if (prefix == 0)
269 prefix = PREFIX;
4a5121b5 270
7146dfdd
HB
271 /* Remove any trailing directory separator from what we got. First check
272 for an empty prefix. */
273 if (prefix[0] && IS_DIR_SEPARATOR (prefix[strlen (prefix) - 1]))
4a5121b5 274 {
ad85216e 275 char * temp = xstrdup (prefix);
460ee112
KG
276 temp[strlen (temp) - 1] = 0;
277 prefix = temp;
4a5121b5
JL
278 }
279
280 return concat (prefix, name, NULL_PTR);
281}
282
283/* Update PATH using KEY if PATH starts with PREFIX. */
284
460ee112 285const char *
4a5121b5 286update_path (path, key)
460ee112
KG
287 const char *path;
288 const char *key;
4a5121b5 289{
6ed4bb9a 290 if (! strncmp (path, std_prefix, strlen (std_prefix)) && key != 0)
4a5121b5
JL
291 {
292 if (key[0] != '$')
293 key = concat ("@", key, NULL_PTR);
294
6ed4bb9a 295 path = concat (key, &path[strlen (std_prefix)], NULL_PTR);
4a5121b5
JL
296
297 while (path[0] == '@' || path[0] == '$')
298 path = translate_name (path);
299 }
509781a4
ME
300
301#ifdef DIR_SEPARATOR_2
302 /* Convert DIR_SEPARATOR_2 to DIR_SEPARATOR. */
303 if (DIR_SEPARATOR != DIR_SEPARATOR_2)
304 {
ad85216e 305 char *new_path = xstrdup (path);
509781a4 306 path = new_path;
ad85216e
KG
307 do {
308 if (*new_path == DIR_SEPARATOR_2)
309 *new_path = DIR_SEPARATOR;
310 } while (*new_path++);
509781a4
ME
311 }
312#endif
4a5121b5 313
509781a4 314#if defined (DIR_SEPARATOR) && !defined (DIR_SEPARATOR_2)
4a5121b5
JL
315 if (DIR_SEPARATOR != '/')
316 {
ad85216e 317 char *new_path = xstrdup (path);
509781a4 318 path = new_path;
ad85216e
KG
319 do {
320 if (*new_path == '/')
321 *new_path = DIR_SEPARATOR;
fbb740da 322 } while (*new_path++);
4a5121b5
JL
323 }
324#endif
325
326 return path;
327}
6ed4bb9a
MM
328
329/* Reset the standard prefix */
330void
331set_std_prefix (prefix, len)
460ee112
KG
332 const char *prefix;
333 int len;
6ed4bb9a
MM
334{
335 std_prefix = save_string (prefix, len);
336}
This page took 0.718974 seconds and 5 git commands to generate.