OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libiberty/] [make-relative-prefix.c] - Blame information for rev 22

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* Relative (relocatable) prefix support.
2
   Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3
   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
4
 
5
This file is part of libiberty.
6
 
7
GCC is free software; you can redistribute it and/or modify it under
8
the terms of the GNU General Public License as published by the Free
9
Software Foundation; either version 2, or (at your option) any later
10
version.
11
 
12
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13
WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GCC; see the file COPYING.  If not, write to the Free
19
Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20
02110-1301, USA.  */
21
 
22
/*
23
 
24
@deftypefn Extension {const char*} make_relative_prefix (const char *@var{progname}, const char *@var{bin_prefix}, const char *@var{prefix})
25
 
26
Given three paths @var{progname}, @var{bin_prefix}, @var{prefix},
27
return the path that is in the same position relative to
28
@var{progname}'s directory as @var{prefix} is relative to
29
@var{bin_prefix}.  That is, a string starting with the directory
30
portion of @var{progname}, followed by a relative pathname of the
31
difference between @var{bin_prefix} and @var{prefix}.
32
 
33
If @var{progname} does not contain any directory separators,
34
@code{make_relative_prefix} will search @env{PATH} to find a program
35
named @var{progname}.  Also, if @var{progname} is a symbolic link,
36
the symbolic link will be resolved.
37
 
38
For example, if @var{bin_prefix} is @code{/alpha/beta/gamma/gcc/delta},
39
@var{prefix} is @code{/alpha/beta/gamma/omega/}, and @var{progname} is
40
@code{/red/green/blue/gcc}, then this function will return
41
@code{/red/green/blue/../../omega/}.
42
 
43
The return value is normally allocated via @code{malloc}.  If no
44
relative prefix can be found, return @code{NULL}.
45
 
46
@end deftypefn
47
 
48
*/
49
 
50
#ifdef HAVE_CONFIG_H
51
#include "config.h"
52
#endif
53
 
54
#ifdef HAVE_STDLIB_H
55
#include <stdlib.h>
56
#endif
57
#ifdef HAVE_UNISTD_H
58
#include <unistd.h>
59
#endif
60
 
61
#include <string.h>
62
 
63
#include "ansidecl.h"
64
#include "libiberty.h"
65
 
66
#ifndef R_OK
67
#define R_OK 4
68
#define W_OK 2
69
#define X_OK 1
70
#endif
71
 
72
#ifndef DIR_SEPARATOR
73
#  define DIR_SEPARATOR '/'
74
#endif
75
 
76
#if defined (_WIN32) || defined (__MSDOS__) \
77
    || defined (__DJGPP__) || defined (__OS2__)
78
#  define HAVE_DOS_BASED_FILE_SYSTEM
79
#  define HAVE_HOST_EXECUTABLE_SUFFIX
80
#  define HOST_EXECUTABLE_SUFFIX ".exe"
81
#  ifndef DIR_SEPARATOR_2 
82
#    define DIR_SEPARATOR_2 '\\'
83
#  endif
84
#  define PATH_SEPARATOR ';'
85
#else
86
#  define PATH_SEPARATOR ':'
87
#endif
88
 
89
#ifndef DIR_SEPARATOR_2
90
#  define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
91
#else
92
#  define IS_DIR_SEPARATOR(ch) \
93
        (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
94
#endif
95
 
96
#define DIR_UP ".."
97
 
98
static char *save_string (const char *, int);
99
static char **split_directories (const char *, int *);
100
static void free_split_directories (char **);
101
 
102
static char *
103
save_string (const char *s, int len)
104
{
105
  char *result = (char *) malloc (len + 1);
106
 
107
  memcpy (result, s, len);
108
  result[len] = 0;
109
  return result;
110
}
111
 
112
/* Split a filename into component directories.  */
113
 
114
static char **
115
split_directories (const char *name, int *ptr_num_dirs)
116
{
117
  int num_dirs = 0;
118
  char **dirs;
119
  const char *p, *q;
120
  int ch;
121
 
122
  /* Count the number of directories.  Special case MSDOS disk names as part
123
     of the initial directory.  */
124
  p = name;
125
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
126
  if (name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
127
    {
128
      p += 3;
129
      num_dirs++;
130
    }
131
#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
132
 
133
  while ((ch = *p++) != '\0')
134
    {
135
      if (IS_DIR_SEPARATOR (ch))
136
        {
137
          num_dirs++;
138
          while (IS_DIR_SEPARATOR (*p))
139
            p++;
140
        }
141
    }
142
 
143
  dirs = (char **) malloc (sizeof (char *) * (num_dirs + 2));
144
  if (dirs == NULL)
145
    return NULL;
146
 
147
  /* Now copy the directory parts.  */
148
  num_dirs = 0;
149
  p = name;
150
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
151
  if (name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
152
    {
153
      dirs[num_dirs++] = save_string (p, 3);
154
      if (dirs[num_dirs - 1] == NULL)
155
        {
156
          free (dirs);
157
          return NULL;
158
        }
159
      p += 3;
160
    }
161
#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
162
 
163
  q = p;
164
  while ((ch = *p++) != '\0')
165
    {
166
      if (IS_DIR_SEPARATOR (ch))
167
        {
168
          while (IS_DIR_SEPARATOR (*p))
169
            p++;
170
 
171
          dirs[num_dirs++] = save_string (q, p - q);
172
          if (dirs[num_dirs - 1] == NULL)
173
            {
174
              dirs[num_dirs] = NULL;
175
              free_split_directories (dirs);
176
              return NULL;
177
            }
178
          q = p;
179
        }
180
    }
181
 
182
  if (p - 1 - q > 0)
183
    dirs[num_dirs++] = save_string (q, p - 1 - q);
184
  dirs[num_dirs] = NULL;
185
 
186
  if (dirs[num_dirs - 1] == NULL)
187
    {
188
      free_split_directories (dirs);
189
      return NULL;
190
    }
191
 
192
  if (ptr_num_dirs)
193
    *ptr_num_dirs = num_dirs;
194
  return dirs;
195
}
196
 
197
/* Release storage held by split directories.  */
198
 
199
static void
200
free_split_directories (char **dirs)
201
{
202
  int i = 0;
203
 
204
  while (dirs[i] != NULL)
205
    free (dirs[i++]);
206
 
207
  free ((char *) dirs);
208
}
209
 
210
/* Given three strings PROGNAME, BIN_PREFIX, PREFIX, return a string that gets
211
   to PREFIX starting with the directory portion of PROGNAME and a relative
212
   pathname of the difference between BIN_PREFIX and PREFIX.
213
 
214
   For example, if BIN_PREFIX is /alpha/beta/gamma/gcc/delta, PREFIX is
215
   /alpha/beta/gamma/omega/, and PROGNAME is /red/green/blue/gcc, then this
216
   function will return /red/green/blue/../../omega/.
217
 
218
   If no relative prefix can be found, return NULL.  */
219
 
220
char *
221
make_relative_prefix (const char *progname,
222
                      const char *bin_prefix, const char *prefix)
223
{
224
  char **prog_dirs, **bin_dirs, **prefix_dirs;
225
  int prog_num, bin_num, prefix_num;
226
  int i, n, common;
227
  int needed_len;
228
  char *ret, *ptr, *full_progname = NULL;
229
 
230
  if (progname == NULL || bin_prefix == NULL || prefix == NULL)
231
    return NULL;
232
 
233
  /* If there is no full pathname, try to find the program by checking in each
234
     of the directories specified in the PATH environment variable.  */
235
  if (lbasename (progname) == progname)
236
    {
237
      char *temp;
238
 
239
      temp = getenv ("PATH");
240
      if (temp)
241
        {
242
          char *startp, *endp, *nstore;
243
          size_t prefixlen = strlen (temp) + 1;
244
          if (prefixlen < 2)
245
            prefixlen = 2;
246
 
247
          nstore = (char *) alloca (prefixlen + strlen (progname) + 1);
248
 
249
          startp = endp = temp;
250
          while (1)
251
            {
252
              if (*endp == PATH_SEPARATOR || *endp == 0)
253
                {
254
                  if (endp == startp)
255
                    {
256
                      nstore[0] = '.';
257
                      nstore[1] = DIR_SEPARATOR;
258
                      nstore[2] = '\0';
259
                    }
260
                  else
261
                    {
262
                      strncpy (nstore, startp, endp - startp);
263
                      if (! IS_DIR_SEPARATOR (endp[-1]))
264
                        {
265
                          nstore[endp - startp] = DIR_SEPARATOR;
266
                          nstore[endp - startp + 1] = 0;
267
                        }
268
                      else
269
                        nstore[endp - startp] = 0;
270
                    }
271
                  strcat (nstore, progname);
272
                  if (! access (nstore, X_OK)
273
#ifdef HAVE_HOST_EXECUTABLE_SUFFIX
274
                      || ! access (strcat (nstore, HOST_EXECUTABLE_SUFFIX), X_OK)
275
#endif
276
                      )
277
                    {
278
                      progname = nstore;
279
                      break;
280
                    }
281
 
282
                  if (*endp == 0)
283
                    break;
284
                  endp = startp = endp + 1;
285
                }
286
              else
287
                endp++;
288
            }
289
        }
290
    }
291
 
292
  full_progname = lrealpath (progname);
293
  if (full_progname == NULL)
294
    return NULL;
295
 
296
  prog_dirs = split_directories (full_progname, &prog_num);
297
  bin_dirs = split_directories (bin_prefix, &bin_num);
298
  free (full_progname);
299
  if (bin_dirs == NULL || prog_dirs == NULL)
300
    return NULL;
301
 
302
  /* Remove the program name from comparison of directory names.  */
303
  prog_num--;
304
 
305
  /* If we are still installed in the standard location, we don't need to
306
     specify relative directories.  Also, if argv[0] still doesn't contain
307
     any directory specifiers after the search above, then there is not much
308
     we can do.  */
309
  if (prog_num == bin_num)
310
    {
311
      for (i = 0; i < bin_num; i++)
312
        {
313
          if (strcmp (prog_dirs[i], bin_dirs[i]) != 0)
314
            break;
315
        }
316
 
317
      if (prog_num <= 0 || i == bin_num)
318
        {
319
          free_split_directories (prog_dirs);
320
          free_split_directories (bin_dirs);
321
          prog_dirs = bin_dirs = (char **) 0;
322
          return NULL;
323
        }
324
    }
325
 
326
  prefix_dirs = split_directories (prefix, &prefix_num);
327
  if (prefix_dirs == NULL)
328
    {
329
      free_split_directories (prog_dirs);
330
      free_split_directories (bin_dirs);
331
      return NULL;
332
    }
333
 
334
  /* Find how many directories are in common between bin_prefix & prefix.  */
335
  n = (prefix_num < bin_num) ? prefix_num : bin_num;
336
  for (common = 0; common < n; common++)
337
    {
338
      if (strcmp (bin_dirs[common], prefix_dirs[common]) != 0)
339
        break;
340
    }
341
 
342
  /* If there are no common directories, there can be no relative prefix.  */
343
  if (common == 0)
344
    {
345
      free_split_directories (prog_dirs);
346
      free_split_directories (bin_dirs);
347
      free_split_directories (prefix_dirs);
348
      return NULL;
349
    }
350
 
351
  /* Two passes: first figure out the size of the result string, and
352
     then construct it.  */
353
  needed_len = 0;
354
  for (i = 0; i < prog_num; i++)
355
    needed_len += strlen (prog_dirs[i]);
356
  needed_len += sizeof (DIR_UP) * (bin_num - common);
357
  for (i = common; i < prefix_num; i++)
358
    needed_len += strlen (prefix_dirs[i]);
359
  needed_len += 1; /* Trailing NUL.  */
360
 
361
  ret = (char *) malloc (needed_len);
362
  if (ret == NULL)
363
    return NULL;
364
 
365
  /* Build up the pathnames in argv[0].  */
366
  *ret = '\0';
367
  for (i = 0; i < prog_num; i++)
368
    strcat (ret, prog_dirs[i]);
369
 
370
  /* Now build up the ..'s.  */
371
  ptr = ret + strlen(ret);
372
  for (i = common; i < bin_num; i++)
373
    {
374
      strcpy (ptr, DIR_UP);
375
      ptr += sizeof (DIR_UP) - 1;
376
      *(ptr++) = DIR_SEPARATOR;
377
    }
378
  *ptr = '\0';
379
 
380
  /* Put in directories to move over to prefix.  */
381
  for (i = common; i < prefix_num; i++)
382
    strcat (ret, prefix_dirs[i]);
383
 
384
  free_split_directories (prog_dirs);
385
  free_split_directories (bin_dirs);
386
  free_split_directories (prefix_dirs);
387
 
388
  return ret;
389
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.