Patch: relative pathnames, take 3

Tom Tromey tromey@cygnus.com
Tue Nov 9 10:50:00 GMT 1999


Here's the 3rd revision of the relative pathnames patch.  This one
fixes the djgpp problems pointed out by Mark Elbrecht.  It also cleans
up gcc.c and config/i386/xm-djgpp.h to use HAVE_DOS_BASED_FILE_SYSTEM
instead of HAVE_DOS_BASED_FILESYSTEM.

Is this ok to commit?

Incidentally, I think the directory defines like IS_DIR_SEPARATOR
should go in a header file, so we can more easily use them in gcj.
Which header would be the right one?


Tue Nov  9 10:30:08 1999  Tom Tromey  <tromey@cygnus.com>

	* config/i386/xm-djgpp.h (HAVE_DOS_BASED_FILE_SYSTEM): Renamed
	from HAVE_DOS_BASED_FILESYSTEM.
	* gcc.c (find_a_file): Use HAVE_DOS_BASED_FILE_SYSTEM, not
	HAVE_DOS_BASED_FILESYSTEM.
	(main): Likewise.
	(split_directories): Only special-case DOS file names if
	HAVE_DOS_BASED_FILE_SYSTEM is defined.  Use IS_DIR_SEPARATOR
	instead of explicit tests.  Conditionalize on !VMS.
	(make_relative_prefix): Use IS_DIR_SEPARATOR instead of explicit
	tests.  Conditionalize on !VMS.
	(process_command): Only use make_relative_prefix if !VMS.
	(free_split_directories): Conditionalize on !VMS.
	(DIR_UP): Conditionalize on !VMS.

Wed Jun  9 16:57:11 1999  Mumit Khan  <khan@xraylith.wisc.edu>

	* gcc.c (STANDARD_BINDIR_PREFIX): Provide default.

Fri Feb  5 14:22:01 1999  Mumit Khan  <khan@xraylith.wisc.edu>

	* gcc.c (make_relative_prefix): Handle the HAVE_EXECUTABLE_SUFFIX
	case.

Mon Nov  8 14:16:57 1999  Michael Meissner  <meissner@cygnus.com>

	* invoke.texi (Environment Variables): Document relative path
	lookup.
	* gcc.c (DIR_UP): If not defined, define as "..".
	(standard_bindir_prefix): New static, holds target location to
	install binaries.
	(split_directories): New function to split a filename into
	component directories.
	(free_split_directories): New function, release memory allocated
	by split_directories.
	(make_relative_prefix): New function, make a relative pathname if
	the compiler is not in the expected location.
	(process_command): If GCC_EXEC_PREFIX was not specified, see if we
	can figure out an appropriate prefix from argv[0].
	* Makefile.in (DRIVER_DEFINES): Use unlibsubdir in definition of
	STANDARD_STARTFILE_PREFIX and TOOLDIR_BASE_PREFIX.  Define
	STANDARD_BINDIR_PREFIX.

Tom

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/egcs/gcc/Makefile.in,v
retrieving revision 1.333
diff -c -3 -p -r1.333 Makefile.in
*** Makefile.in	1999/11/02 15:48:26	1.333
--- Makefile.in	1999/11/09 18:40:49
*************** c-common.o : c-common.c $(CONFIG_H) syst
*** 1395,1405 ****
  # Language-independent files.
  
  DRIVER_DEFINES = \
!   -DSTANDARD_STARTFILE_PREFIX=\"$(libdir)/\" \
    -DSTANDARD_EXEC_PREFIX=\"$(libdir)/gcc-lib/\" \
    -DDEFAULT_TARGET_VERSION=\"$(version)\" \
    -DDEFAULT_TARGET_MACHINE=\"$(target_alias)\" \
!   -DTOOLDIR_BASE_PREFIX=\"$(exec_prefix)/\"
  gcc.o: gcc.c $(CONFIG_H) system.h intl.h multilib.h \
      Makefile $(lang_specs_files) prefix.h gcc.h
  	$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
--- 1395,1406 ----
  # Language-independent files.
  
  DRIVER_DEFINES = \
!   -DSTANDARD_STARTFILE_PREFIX=\"$(unlibsubdir)/\" \
    -DSTANDARD_EXEC_PREFIX=\"$(libdir)/gcc-lib/\" \
    -DDEFAULT_TARGET_VERSION=\"$(version)\" \
    -DDEFAULT_TARGET_MACHINE=\"$(target_alias)\" \
!   -DSTANDARD_BINDIR_PREFIX=\"$(bindir)/\" \
!   -DTOOLDIR_BASE_PREFIX=\"$(unlibsubdir)/../\"
  gcc.o: gcc.c $(CONFIG_H) system.h intl.h multilib.h \
      Makefile $(lang_specs_files) prefix.h gcc.h
  	$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
Index: gcc.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/gcc.c,v
retrieving revision 1.118
diff -c -3 -p -r1.118 gcc.c
*** gcc.c	1999/11/01 01:11:20	1.118
--- gcc.c	1999/11/09 18:41:25
*************** extern int getrusage PROTO ((int, struct
*** 74,79 ****
--- 74,87 ----
  #define DIR_SEPARATOR '/'
  #endif
  
+ #ifndef VMS
+ /* FIXME: the location independence code for VMS is hairier than this,
+    and hasn't been written.  */
+ #ifndef DIR_UP
+ #define DIR_UP ".."
+ #endif /* DIR_UP */
+ #endif /* VMS */
+ 
  /* Define IS_DIR_SEPARATOR.  */
  #ifndef DIR_SEPARATOR_2
  # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
*************** extern char *version_string;
*** 199,204 ****
--- 207,217 ----
  struct path_prefix;
  
  static void init_spec		PROTO((void));
+ #ifndef VMS
+ static char **split_directories	PROTO((const char *, int *));
+ static void free_split_directories PROTO((char **));
+ static char *make_relative_prefix PROTO((const char *, const char *, const char *));
+ #endif /* VMS */
  static void read_specs		PROTO((const char *, int));
  static void set_spec		PROTO((const char *, const char *));
  static struct compiler *lookup_compiler PROTO((const char *, size_t, const char *));
*************** static const char *standard_startfile_pr
*** 1399,1404 ****
--- 1412,1422 ----
  static const char *tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
  static const char *tooldir_prefix;
  
+ #ifndef STANDARD_BINDIR_PREFIX
+ #define STANDARD_BINDIR_PREFIX "/usr/local/bin"
+ #endif
+ static char *standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
+ 
  /* Subdirectory to use for locating libraries.  Set by
     set_multilib_dir based on the compilation options.  */
  
*************** putenv_from_prefixes (paths, env_var)
*** 1952,1957 ****
--- 1970,2211 ----
    putenv (build_search_list (paths, env_var, 1));
  }
  
+ #ifndef VMS
+ 
+ /* FIXME: the location independence code for VMS is hairier than this,
+    and hasn't been written.  */
+ 
+ /* Split a filename into component directories.  */
+ 
+ static char **
+ split_directories (name, ptr_num_dirs)
+      const char *name;
+      int *ptr_num_dirs;
+ {
+   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 **) xmalloc (sizeof (char *) * (num_dirs + 2));
+ 
+   /* 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);
+       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);
+ 	  q = p;
+ 	}
+     }
+ 
+   if (p - 1 - q > 0)
+     dirs[num_dirs++] = save_string (q, p - 1 - q);
+ 
+   dirs[num_dirs] = NULL_PTR;
+   if (ptr_num_dirs)
+     *ptr_num_dirs = num_dirs;
+ 
+   return dirs;
+ }
+ 
+ /* Release storage held by split directories.  */
+ 
+ static void
+ free_split_directories (dirs)
+      char **dirs;
+ {
+   int i = 0;
+ 
+   while (dirs[i] != NULL_PTR)
+     free (dirs[i++]);
+ 
+   free ((char *)dirs);
+ }
+ 
+ /* Given three strings PROGNAME, BIN_PREFIX, PREFIX, return a string that gets
+    to PREFIX starting with the directory portion of PROGNAME and a relative
+    pathname of the difference between BIN_PREFIX and PREFIX.
+ 
+    For example, if BIN_PREFIX is /alpha/beta/gamma/gcc/delta, PREFIX is
+    /alpha/beta/gamma/omega/, and PROGNAME is /red/green/blue/gcc, then this
+    function will return /reg/green/blue/../omega.
+ 
+    If no relative prefix can be found, return NULL.  */
+ 
+ static char *
+ make_relative_prefix (progname, bin_prefix, 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, std_loc_p;
+   int i, n, common;
+ 
+   prog_dirs = split_directories (progname, &prog_num);
+   bin_dirs = split_directories (bin_prefix, &bin_num);
+ 
+   /* 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)
+     {
+       char *temp;
+ 
+       GET_ENV_PATH_LIST (temp, "PATH");
+       if (temp)
+ 	{
+ 	  char *startp, *endp;
+ 	  char *nstore = (char *) alloca (strlen (temp) + 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_EXECUTABLE_SUFFIX
+                       || ! access (strcat (nstore, EXECUTABLE_SUFFIX), X_OK)
+ #endif
+ 		      )
+ 		    {
+ 		      free_split_directories (prog_dirs);
+ 		      progname = nstore;
+ 		      prog_dirs = split_directories (progname, &prog_num);
+ 		      break;
+ 		    }
+ 
+ 		  if (*endp == 0)
+ 		    break;
+ 		  endp = startp = endp + 1;
+ 		}
+ 	      else
+ 		endp++;
+ 	    }
+ 	}
+     }
+ 
+   /* Remove the program name from comparison of directory names.  */
+   prog_num--;
+ 
+   /* Determine if the compiler is installed in the standard location, and if
+      so, we don't need to specify relative directories.  Also, if argv[0]
+      doesn't contain any directory specifiers, there is not much we can do.  */
+   std_loc_p = 0;
+   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)
+ 	{
+ 	  std_loc_p = 1;
+ 	  free_split_directories (prog_dirs);
+ 	  free_split_directories (bin_dirs);
+ 	  prog_dirs = bin_dirs = (char **)0;
+ 	  return NULL_PTR;
+ 	}
+     }
+ 
+   prefix_dirs = split_directories (prefix, &prefix_num);
+ 
+   /* 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_PTR;
+     }
+ 
+   /* Build up the pathnames in argv[0].  */
+   for (i = 0; i < prog_num; i++)
+     obstack_grow (&obstack, prog_dirs[i], strlen (prog_dirs[i]));
+ 
+   /* Now build up the ..'s.  */
+   for (i = common; i < n; i++)
+     {
+       obstack_grow (&obstack, DIR_UP, sizeof (DIR_UP)-1);
+       obstack_1grow (&obstack, DIR_SEPARATOR);
+     }
+ 
+   /* Put in directories to move over to prefix.  */
+   for (i = common; i < prefix_num; i++)
+     obstack_grow (&obstack, prefix_dirs[i], strlen (prefix_dirs[i]));
+ 
+   free_split_directories (prog_dirs);
+   free_split_directories (bin_dirs);
+   free_split_directories (prefix_dirs);
+ 
+   obstack_1grow (&obstack, '\0');
+   return obstack_finish (&obstack);
+ }
+ #endif /* VMS */
+ 
  /* Check whether NAME can be accessed in MODE.  This is like access,
     except that it never considers directories to be executable.  */
  
*************** find_a_file (pprefix, name, mode)
*** 2005,2011 ****
    /* Determine the filename to execute (special case for absolute paths).  */
  
    if (IS_DIR_SEPARATOR (*name)
! #ifdef HAVE_DOS_BASED_FILESYSTEM
        /* Check for disk name on MS-DOS-based systems.  */
        || (name[0] && name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
  #endif
--- 2259,2265 ----
    /* Determine the filename to execute (special case for absolute paths).  */
  
    if (IS_DIR_SEPARATOR (*name)
! #ifdef HAVE_DOS_BASED_FILE_SYSTEM
        /* Check for disk name on MS-DOS-based systems.  */
        || (name[0] && name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
  #endif
*************** process_command (argc, argv)
*** 2638,2645 ****
  	  break;
  	}
      }
  
!   /* Set up the default search paths.  */
  
    if (gcc_exec_prefix)
      {
--- 2892,2911 ----
  	  break;
  	}
      }
+ 
+   /* Set up the default search paths.  If there is no GCC_EXEC_PREFIX,
+      see if we can create it from the pathname specified in argv[0].  */
  
! #ifndef VMS
!   /* FIXME: make_relative_prefix doesn't yet work for VMS.  */
!   if (!gcc_exec_prefix)
!     {
!       gcc_exec_prefix = make_relative_prefix (argv[0], standard_bindir_prefix,
! 					      standard_exec_prefix);
!       if (gcc_exec_prefix)
! 	putenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL_PTR));
!     }
! #endif
  
    if (gcc_exec_prefix)
      {
*************** main (argc, argv)
*** 4906,4912 ****
  	 standard_startfile_prefix on that as well.  */
        if (IS_DIR_SEPARATOR (*standard_startfile_prefix)
  	    || *standard_startfile_prefix == '$'
! #ifdef HAVE_DOS_BASED_FILESYSTEM
    	    /* Check for disk name on MS-DOS-based systems.  */
            || (standard_startfile_prefix[1] == ':'
  	      && (IS_DIR_SEPARATOR (standard_startfile_prefix[2])))
--- 5172,5178 ----
  	 standard_startfile_prefix on that as well.  */
        if (IS_DIR_SEPARATOR (*standard_startfile_prefix)
  	    || *standard_startfile_prefix == '$'
! #ifdef HAVE_DOS_BASED_FILE_SYSTEM
    	    /* Check for disk name on MS-DOS-based systems.  */
            || (standard_startfile_prefix[1] == ':'
  	      && (IS_DIR_SEPARATOR (standard_startfile_prefix[2])))
Index: invoke.texi
===================================================================
RCS file: /cvs/gcc/egcs/gcc/invoke.texi,v
retrieving revision 1.148
diff -c -3 -p -r1.148 invoke.texi
*** invoke.texi	1999/11/01 01:11:20	1.148
--- invoke.texi	1999/11/09 18:42:58
*************** names of the subprograms executed by the
*** 7084,7089 ****
--- 7084,7092 ----
  when this prefix is combined with the name of a subprogram, but you can
  specify a prefix that ends with a slash if you wish.
  
+ If @code{GCC_EXEC_PREFIX} is not set, GNU CC will attempt to figure out
+ an appropriate prefix to use based on the pathname it was invoked with.
+ 
  If GCC cannot find the subprogram using the specified prefix, it
  tries looking in the usual places for the subprogram.
  
Index: config/i386/xm-djgpp.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/xm-djgpp.h,v
retrieving revision 1.4
diff -c -3 -p -r1.4 xm-djgpp.h
*** xm-djgpp.h	1999/06/21 05:23:16	1.4
--- xm-djgpp.h	1999/11/09 18:42:58
*************** Boston, MA 02111-1307, USA.  */
*** 32,38 ****
  #define DIR_SEPARATOR_2 '\\'
  
  /* Allow test for DOS drive names.  */
! #define HAVE_DOS_BASED_FILESYSTEM
  
  #define LIBSTDCXX "-lstdcxx"
  
--- 32,38 ----
  #define DIR_SEPARATOR_2 '\\'
  
  /* Allow test for DOS drive names.  */
! #define HAVE_DOS_BASED_FILE_SYSTEM
  
  #define LIBSTDCXX "-lstdcxx"
  


More information about the Gcc-patches mailing list