Subversion Repositories Kolibri OS

Rev

Rev 5191 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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