source: trunk/third/gcc/prefix.c @ 11288

Revision 11288, 7.2 KB checked in by ghudson, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r11287, which included commits to RCS files with non-trunk default branches.
Line 
1/* Utility to update paths from internal to external forms.
2   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
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
47      HKEY_LOCAL_MACHINE\SOFTWARE\Free Software Foundation\
48
49      if found, that value will be used.
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,
60   if they are different.
61
62   NOTE:  using resolve_keyed_path under Win32 requires linking with
63   advapi32.dll.  */
64
65
66#include "config.h"
67#include "gansidecl.h"
68#ifdef __STDC__
69#include <stdarg.h>
70#else
71#include <varargs.h>
72#endif
73
74#ifdef _WIN32
75#include <windows.h>
76#endif
77
78static char *get_key_value      PROTO((char *));
79static char *translate_name     PROTO((char *));
80static char *concat             PVPROTO((char *, ...));
81static char *save_string        PROTO((char *, int));
82
83#ifdef _WIN32
84static char *lookup_key         PROTO((char *));
85static HKEY reg_key = (HKEY) INVALID_HANDLE_VALUE;
86#endif
87
88extern char *getenv ();
89
90/* Given KEY, as above, return its value.  */
91
92static char *
93get_key_value (key)
94     char *key;
95{
96  char *prefix = 0;
97
98#ifdef _WIN32
99  prefix = lookup_key (key);
100#endif
101
102  if (prefix == 0)
103    prefix = getenv (concat (key, "_ROOT", NULL_PTR));
104
105  return prefix;
106}
107
108/* Concatenate a sequence of strings, returning the result.
109
110   This function is based on the one in libiberty.  */
111
112static char *
113concat VPROTO((char *first, ...))
114{
115  register int length;
116  register char *newstr;
117  register char *end;
118  register char *arg;
119  va_list args;
120#ifndef __STDC__
121  char *first;
122#endif
123
124  /* First compute the size of the result and get sufficient memory.  */
125
126  VA_START (args, first);
127#ifndef __STDC__
128  first = va_arg (args, char *);
129#endif
130
131  arg = first;
132  length = 0;
133
134  while (arg != 0)
135    {
136      length += strlen (arg);
137      arg = va_arg (args, char *);
138    }
139
140  newstr = (char *) malloc (length + 1);
141  va_end (args);
142
143  /* Now copy the individual pieces to the result string.  */
144
145  VA_START (args, first);
146#ifndef __STDC__
147  first = va_arg (args, char *);
148#endif
149
150  end = newstr;
151  arg = first;
152  while (arg != 0)
153    {
154      while (*arg)
155        *end++ = *arg++;
156      arg = va_arg (args, char *);
157    }
158  *end = '\000';
159  va_end (args);
160
161  return (newstr);
162}
163
164/* Return a copy of a string that has been placed in the heap.  */
165
166static char *
167save_string (s, len)
168     char *s;
169     int len;
170{
171  register char *result = (char *) malloc (len + 1);
172
173  bcopy (s, result, len);
174  result[len] = 0;
175  return result;
176}
177
178#ifdef _WIN32
179
180/* Look up "key" in the registry, as above.  */
181
182static char *
183lookup_key (key)
184     char *key;
185{
186  char *dst;
187  DWORD size;
188  DWORD type;
189  LONG res;
190
191  if (reg_key == (HKEY) INVALID_HANDLE_VALUE)
192    {
193      res = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE", 0,
194                           KEY_READ, &reg_key);
195
196      if (res == ERROR_SUCCESS)
197        res = RegOpenKeyExA (reg_key, "Free Software Foundation", 0,
198                             KEY_READ, &reg_key);
199
200      if (res != ERROR_SUCCESS)
201        {
202          reg_key = (HKEY) INVALID_HANDLE_VALUE;
203          return 0;
204        }
205    }
206
207  size = 32;
208  dst = (char *) malloc (size);
209
210  res = RegQueryValueExA (reg_key, key, 0, &type, dst, &size);
211  if (res == ERROR_MORE_DATA && type == REG_SZ)
212    {
213      dst = (char *) realloc (dst, size);
214      res = RegQueryValueExA (reg_key, key, 0, &type, dst, &size);
215    }
216
217  if (type != REG_SZ || res != ERROR_SUCCESS)
218    {
219      free (dst);
220      dst = 0;
221    }
222
223  return dst;
224}
225#endif
226
227/* If NAME starts with a '@' or '$', apply the translation rules above
228   and return a new name.  Otherwise, return the given name.  */
229
230static char *
231translate_name (name)
232     char *name;
233{
234  char code = name[0];
235  char *key, *prefix = 0;
236  int keylen;
237
238  if (code != '@' && code != '$')
239    return name;
240
241  for (keylen = 0;
242       (name[keylen + 1] != 0 && name[keylen + 1] != '/'
243#ifdef DIR_SEPARATOR
244        && name[keylen + 1] != DIR_SEPARATOR
245#endif
246        );
247       keylen++)
248    ;
249
250  key = alloca (keylen + 1);
251  strncpy (key, &name[1], keylen);
252  key[keylen] = 0;
253
254  name = &name[keylen + 1];
255
256  if (code == '@')
257    prefix = get_key_value (key);
258  else
259    prefix = getenv (key);
260
261  if (prefix == 0)
262    prefix = PREFIX;
263
264  /* Remove any trailing directory separator from what we got.  */
265  if (prefix[strlen (prefix) - 1] == '/'
266#ifdef DIR_SEPARATOR
267      || prefix[strlen (prefix) - 1] == DIR_SEPARATOR
268#endif
269      )
270    {
271      prefix = save_string (prefix, strlen (prefix));
272      prefix[strlen (prefix) - 1] = 0;
273    }
274
275  return concat (prefix, name, NULL_PTR);
276}
277
278/* Update PATH using KEY if PATH starts with PREFIX.  */
279
280char *
281update_path (path, key)
282     char *path;
283     char *key;
284{
285  if (! strncmp (path, PREFIX, strlen (PREFIX)) && key != 0)
286    {
287      if (key[0] != '$')
288        key = concat ("@", key, NULL_PTR);
289
290      path = concat (key, &path[strlen (PREFIX)], NULL_PTR);
291
292      while (path[0] == '@' || path[0] == '$')
293        path = translate_name (path);
294    }
295     
296#ifdef DIR_SEPARATOR
297  if (DIR_SEPARATOR != '/')
298    {
299      int i;
300      int len = strlen (path);
301
302      path = save_string (path, len);
303      for (i = 0; i < len; i++)
304        if (path[i] == '/')
305          path[i] = DIR_SEPARATOR;
306    }
307#endif
308
309  return path;
310}
Note: See TracBrowser for help on using the repository browser.