Back to index

cell-binutils  2.17cvs20070401
Defines | Functions
make-relative-prefix.c File Reference
#include <string.h>
#include "ansidecl.h"
#include "libiberty.h"

Go to the source code of this file.

Defines

#define R_OK   4
#define W_OK   2
#define X_OK   1
#define DIR_SEPARATOR   '/'
#define PATH_SEPARATOR   ':'
#define IS_DIR_SEPARATOR(ch)   ((ch) == DIR_SEPARATOR)
#define DIR_UP   ".."

Functions

static char * save_string (const char *, int)
static char ** split_directories (const char *, int *)
static void free_split_directories (char **)
static char * make_relative_prefix_1 (const char *progname, const char *bin_prefix, const char *prefix, const int resolve_links)
char * make_relative_prefix (char *progname, const char *bin_prefix, const char *prefix) const
char * make_relative_prefix_ignore_links (char *progname, const char *bin_prefix, const char *prefix) const

Define Documentation

#define DIR_SEPARATOR   '/'

Definition at line 73 of file make-relative-prefix.c.

#define DIR_UP   ".."

Definition at line 96 of file make-relative-prefix.c.

#define IS_DIR_SEPARATOR (   ch)    ((ch) == DIR_SEPARATOR)

Definition at line 90 of file make-relative-prefix.c.

#define PATH_SEPARATOR   ':'

Definition at line 86 of file make-relative-prefix.c.

#define R_OK   4

Definition at line 67 of file make-relative-prefix.c.

#define W_OK   2

Definition at line 68 of file make-relative-prefix.c.

#define X_OK   1

Definition at line 69 of file make-relative-prefix.c.


Function Documentation

static void free_split_directories ( char **  dirs) [static]

Definition at line 200 of file make-relative-prefix.c.

{
  int i = 0;

  while (dirs[i] != NULL)
    free (dirs[i++]);

  free ((char *) dirs);
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* make_relative_prefix ( char *  progname,
const char *  bin_prefix,
const char *  prefix 
) const

Definition at line 403 of file make-relative-prefix.c.

{
  return make_relative_prefix_1 (progname, bin_prefix, prefix, 1);
}

Here is the call graph for this function:

static char* make_relative_prefix_1 ( const char *  progname,
const char *  bin_prefix,
const char *  prefix,
const int  resolve_links 
) [static]

Definition at line 221 of file make-relative-prefix.c.

{
  char **prog_dirs, **bin_dirs, **prefix_dirs;
  int prog_num, bin_num, prefix_num;
  int i, n, common;
  int needed_len;
  char *ret, *ptr, *full_progname = NULL;

  if (progname == NULL || bin_prefix == NULL || prefix == 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 (lbasename (progname) == progname)
    {
      char *temp;

      temp = getenv ("PATH");
      if (temp)
       {
         char *startp, *endp, *nstore;
         size_t prefixlen = strlen (temp) + 1;
         if (prefixlen < 2)
           prefixlen = 2;

         nstore = (char *) alloca (prefixlen + strlen (progname) + 1);

         startp = endp = temp;
         while (1)
           {
             if (*endp == PATH_SEPARATOR || *endp == 0)
              {
                if (endp == startp)
                  {
                    nstore[0] = '.';
                    nstore[1] = DIR_SEPARATOR;
                    nstore[2] = '\0';
                  }
                else
                  {
                    strncpy (nstore, startp, endp - startp);
                    if (! IS_DIR_SEPARATOR (endp[-1]))
                     {
                       nstore[endp - startp] = DIR_SEPARATOR;
                       nstore[endp - startp + 1] = 0;
                     }
                    else
                     nstore[endp - startp] = 0;
                  }
                strcat (nstore, progname);
                if (! access (nstore, X_OK)
#ifdef HAVE_HOST_EXECUTABLE_SUFFIX
                      || ! access (strcat (nstore, HOST_EXECUTABLE_SUFFIX), X_OK)
#endif
                    )
                  {
                    progname = nstore;
                    break;
                  }

                if (*endp == 0)
                  break;
                endp = startp = endp + 1;
              }
             else
              endp++;
           }
       }
    }

  if ( resolve_links )
    {
      full_progname = lrealpath (progname);
      if (full_progname == NULL)
       return NULL;
    }
  else
    full_progname = strdup(progname);

  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--;

  /* If we are still installed in the standard location, we don't need to
     specify relative directories.  Also, if argv[0] still doesn't contain
     any directory specifiers after the search above, then there is not much
     we can do.  */
  if (prog_num == bin_num)
    {
      for (i = 0; i < bin_num; i++)
       {
         if (strcmp (prog_dirs[i], bin_dirs[i]) != 0)
           break;
       }

      if (prog_num <= 0 || i == bin_num)
       {
         free_split_directories (prog_dirs);
         free_split_directories (bin_dirs);
         prog_dirs = bin_dirs = (char **) 0;
         return NULL;
       }
    }

  prefix_dirs = split_directories (prefix, &prefix_num);
  if (prefix_dirs == NULL)
    {
      free_split_directories (prog_dirs);
      free_split_directories (bin_dirs);
      return NULL;
    }

  /* Find how many directories are in common between bin_prefix & prefix.  */
  n = (prefix_num < bin_num) ? prefix_num : bin_num;
  for (common = 0; common < n; common++)
    {
      if (strcmp (bin_dirs[common], prefix_dirs[common]) != 0)
       break;
    }

  /* If there are no common directories, there can be no relative prefix.  */
  if (common == 0)
    {
      free_split_directories (prog_dirs);
      free_split_directories (bin_dirs);
      free_split_directories (prefix_dirs);
      return NULL;
    }

  /* Two passes: first figure out the size of the result string, and
     then construct it.  */
  needed_len = 0;
  for (i = 0; i < prog_num; i++)
    needed_len += strlen (prog_dirs[i]);
  needed_len += sizeof (DIR_UP) * (bin_num - common);
  for (i = common; i < prefix_num; i++)
    needed_len += strlen (prefix_dirs[i]);
  needed_len += 1; /* Trailing NUL.  */

  ret = (char *) malloc (needed_len);
  if (ret == NULL)
    return NULL;

  /* Build up the pathnames in argv[0].  */
  *ret = '\0';
  for (i = 0; i < prog_num; i++)
    strcat (ret, prog_dirs[i]);

  /* Now build up the ..'s.  */
  ptr = ret + strlen(ret);
  for (i = common; i < bin_num; i++)
    {
      strcpy (ptr, DIR_UP);
      ptr += sizeof (DIR_UP) - 1;
      *(ptr++) = DIR_SEPARATOR;
    }
  *ptr = '\0';

  /* Put in directories to move over to prefix.  */
  for (i = common; i < prefix_num; i++)
    strcat (ret, prefix_dirs[i]);

  free_split_directories (prog_dirs);
  free_split_directories (bin_dirs);
  free_split_directories (prefix_dirs);

  return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* make_relative_prefix_ignore_links ( char *  progname,
const char *  bin_prefix,
const char *  prefix 
) const

Definition at line 417 of file make-relative-prefix.c.

{
  return make_relative_prefix_1 (progname, bin_prefix, prefix, 0);
}

Here is the call graph for this function:

static char * save_string ( const char *  s,
int  len 
) [static]

Definition at line 103 of file make-relative-prefix.c.

{
  char *result = (char *) malloc (len + 1);

  memcpy (result, s, len);
  result[len] = 0;
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char ** split_directories ( const char *  name,
int ptr_num_dirs 
) [static]

Definition at line 115 of file make-relative-prefix.c.

{
  int num_dirs = 0;
  char **dirs;
  const char *p, *q;
  int ch;

  /* Count the number of directories.  Special case MSDOS disk names as part
     of the initial directory.  */
  p = name;
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
  if (name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
    {
      p += 3;
      num_dirs++;
    }
#endif /* HAVE_DOS_BASED_FILE_SYSTEM */

  while ((ch = *p++) != '\0')
    {
      if (IS_DIR_SEPARATOR (ch))
       {
         num_dirs++;
         while (IS_DIR_SEPARATOR (*p))
           p++;
       }
    }

  dirs = (char **) malloc (sizeof (char *) * (num_dirs + 2));
  if (dirs == NULL)
    return NULL;

  /* Now copy the directory parts.  */
  num_dirs = 0;
  p = name;
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
  if (name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
    {
      dirs[num_dirs++] = save_string (p, 3);
      if (dirs[num_dirs - 1] == NULL)
       {
         free (dirs);
         return NULL;
       }
      p += 3;
    }
#endif /* HAVE_DOS_BASED_FILE_SYSTEM */

  q = p;
  while ((ch = *p++) != '\0')
    {
      if (IS_DIR_SEPARATOR (ch))
       {
         while (IS_DIR_SEPARATOR (*p))
           p++;

         dirs[num_dirs++] = save_string (q, p - q);
         if (dirs[num_dirs - 1] == NULL)
           {
             dirs[num_dirs] = NULL;
             free_split_directories (dirs);
             return NULL;
           }
         q = p;
       }
    }

  if (p - 1 - q > 0)
    dirs[num_dirs++] = save_string (q, p - 1 - q);
  dirs[num_dirs] = NULL;

  if (dirs[num_dirs - 1] == NULL)
    {
      free_split_directories (dirs);
      return NULL;
    }

  if (ptr_num_dirs)
    *ptr_num_dirs = num_dirs;
  return dirs;
}

Here is the call graph for this function:

Here is the caller graph for this function: