This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch: relative pathnames, take 2
- To: Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Subject: Patch: relative pathnames, take 2
- From: Tom Tromey <tromey at cygnus dot com>
- Date: 08 Nov 1999 22:34:10 -0700
- Reply-To: tromey at cygnus dot com
Here is the updated version of the relative pathnames patch. In this
version, I incorporated Mumit's fixes, and I made the new code
conditional on !defined(VMS), per rth's request.
Is this ok to commit?
Mon Nov 8 22:24:35 1999 Tom Tromey <tromey@cygnus.com>
* gcc.c (process_command): Only use make_relative_prefix if !VMS.
(split_directories): Conditionalize on !VMS.
(free_split_directories): Likewise.
(make_relative_prefix): Likewise.
* gcc.c (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 05:29:16
*************** 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 05:31: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,2209 ----
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;
+ if (DIR_SEPARATOR == '\\' && name[1] == ':'
+ && (name[2] == DIR_SEPARATOR || name[2] == '/'))
+ {
+ p += 3;
+ num_dirs++;
+ }
+
+ while ((ch = *p++) != '\0')
+ {
+ if (ch == '/' || ch == DIR_SEPARATOR)
+ {
+ num_dirs++;
+ while ((ch = *p) == '/' || ch == DIR_SEPARATOR)
+ p++;
+ }
+ }
+
+ dirs = (char **) xmalloc (sizeof (char *) * (num_dirs + 2));
+
+ /* Now copy the directory parts. */
+ num_dirs = 0;
+ p = name;
+ if (DIR_SEPARATOR == '\\' && name[1] == ':'
+ && (name[2] == DIR_SEPARATOR || name[2] == '/'))
+ {
+ dirs[num_dirs++] = save_string (p, 3);
+ p += 3;
+ }
+
+ q = p;
+ while ((ch = *p++) != '\0')
+ {
+ if (ch == '/' || ch == DIR_SEPARATOR)
+ {
+ while ((ch = *p) == '/' || ch == DIR_SEPARATOR)
+ 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 (endp[-1] != '/' && endp[-1] != DIR_SEPARATOR)
+ {
+ 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. */
*************** process_command (argc, argv)
*** 2638,2645 ****
break;
}
}
! /* Set up the default search paths. */
if (gcc_exec_prefix)
{
--- 2890,2909 ----
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)
{
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 05:33:00
*************** 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.