OSDN Git Service

2005-10-12 Paul Thomas <pault@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / libiberty / make-relative-prefix.c
index ef9177e..66ddcaa 100644 (file)
@@ -16,23 +16,32 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 /*
 
 @deftypefn Extension {const char*} make_relative_prefix (const char *@var{progname}, const char *@var{bin_prefix}, const char *@var{prefix})
 
-Given three strings @var{progname}, @var{bin_prefix}, @var{prefix}, return a string
-that gets to @var{prefix} starting with the directory portion of @var{progname} and
-a relative pathname of the difference between @var{bin_prefix} and @var{prefix}.
+Given three paths @var{progname}, @var{bin_prefix}, @var{prefix},
+return the path that is in the same position relative to
+@var{progname}'s directory as @var{prefix} is relative to
+@var{bin_prefix}.  That is, a string starting with the directory
+portion of @var{progname}, followed by a relative pathname of the
+difference between @var{bin_prefix} and @var{prefix}.
 
-For example, if @var{bin_prefix} is @code{/alpha/beta/gamma/gcc/delta}, @var{prefix}
-is @code{/alpha/beta/gamma/omega/}, and @var{progname} is @code{/red/green/blue/gcc},
-then this function will return @code{/red/green/blue/../../omega/}.
+If @var{progname} does not contain any directory separators,
+@code{make_relative_prefix} will search @env{PATH} to find a program
+named @var{progname}.  Also, if @var{progname} is a symbolic link,
+the symbolic link will be resolved.
 
-The return value is normally allocated via @code{malloc}.  If no relative prefix
-can be found, return @code{NULL}.
+For example, if @var{bin_prefix} is @code{/alpha/beta/gamma/gcc/delta},
+@var{prefix} is @code{/alpha/beta/gamma/omega/}, and @var{progname} is
+@code{/red/green/blue/gcc}, then this function will return
+@code{/red/green/blue/../../omega/}.
+
+The return value is normally allocated via @code{malloc}.  If no
+relative prefix can be found, return @code{NULL}.
 
 @end deftypefn
 
@@ -67,6 +76,7 @@ can be found, return @code{NULL}.
 #if defined (_WIN32) || defined (__MSDOS__) \
     || defined (__DJGPP__) || defined (__OS2__)
 #  define HAVE_DOS_BASED_FILE_SYSTEM
+#  define HAVE_HOST_EXECUTABLE_SUFFIX
 #  define HOST_EXECUTABLE_SUFFIX ".exe"
 #  ifndef DIR_SEPARATOR_2 
 #    define DIR_SEPARATOR_2 '\\'
@@ -85,16 +95,14 @@ can be found, return @code{NULL}.
 
 #define DIR_UP ".."
 
-static char *save_string PARAMS ((const char *, int));
-static char **split_directories        PARAMS ((const char *, int *));
-static void free_split_directories PARAMS ((char **));
+static char *save_string (const char *, int);
+static char **split_directories        (const char *, int *);
+static void free_split_directories (char **);
 
 static char *
-save_string (s, len)
-     const char *s;
-     int len;
+save_string (const char *s, int len)
 {
-  char *result = malloc (len + 1);
+  char *result = (char *) malloc (len + 1);
 
   memcpy (result, s, len);
   result[len] = 0;
@@ -104,9 +112,7 @@ save_string (s, len)
 /* Split a filename into component directories.  */
 
 static char **
-split_directories (name, ptr_num_dirs)
-     const char *name;
-     int *ptr_num_dirs;
+split_directories (const char *name, int *ptr_num_dirs)
 {
   int num_dirs = 0;
   char **dirs;
@@ -191,8 +197,7 @@ split_directories (name, ptr_num_dirs)
 /* Release storage held by split directories.  */
 
 static void
-free_split_directories (dirs)
-     char **dirs;
+free_split_directories (char **dirs)
 {
   int i = 0;
 
@@ -213,28 +218,21 @@ free_split_directories (dirs)
    If no relative prefix can be found, return NULL.  */
 
 char *
-make_relative_prefix (progname, bin_prefix, prefix)
-     const char *progname;
-     const char *bin_prefix;
-     const char *prefix;
+make_relative_prefix (const char *progname,
+                      const char *bin_prefix, const char *prefix)
 {
   char **prog_dirs, **bin_dirs, **prefix_dirs;
   int prog_num, bin_num, prefix_num;
   int i, n, common;
   int needed_len;
-  char *ret, *ptr;
+  char *ret, *ptr, *full_progname = NULL;
 
   if (progname == NULL || bin_prefix == NULL || prefix == NULL)
     return NULL;
 
-  prog_dirs = split_directories (progname, &prog_num);
-  bin_dirs = split_directories (bin_prefix, &bin_num);
-  if (bin_dirs == NULL || prog_dirs == NULL)
-    return NULL;
-
   /* If there is no full pathname, try to find the program by checking in each
      of the directories specified in the PATH environment variable.  */
-  if (prog_num == 1)
+  if (lbasename (progname) == progname)
     {
       char *temp;
 
@@ -277,14 +275,7 @@ make_relative_prefix (progname, bin_prefix, prefix)
 #endif
                      )
                    {
-                     free_split_directories (prog_dirs);
                      progname = nstore;
-                     prog_dirs = split_directories (progname, &prog_num);
-                     if (prog_dirs == NULL)
-                       {
-                         free_split_directories (bin_dirs);
-                         return NULL;
-                       }
                      break;
                    }
 
@@ -298,6 +289,16 @@ make_relative_prefix (progname, bin_prefix, prefix)
        }
     }
 
+  full_progname = lrealpath (progname);
+  if (full_progname == NULL)
+    return NULL;
+
+  prog_dirs = split_directories (full_progname, &prog_num);
+  bin_dirs = split_directories (bin_prefix, &bin_num);
+  free (full_progname);
+  if (bin_dirs == NULL || prog_dirs == NULL)
+    return NULL;
+
   /* Remove the program name from comparison of directory names.  */
   prog_num--;