This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch: relative pathnames, take 3
- To: Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Subject: Patch: relative pathnames, take 3
- From: Tom Tromey <tromey at cygnus dot com>
- Date: 09 Nov 1999 11:48:45 -0700
- Reply-To: tromey at cygnus dot com
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"