\f
#include "config.h"
-#include "gansidecl.h"
-#include "system.h"
-
-#include <signal.h>
-#include <sys/stat.h>
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
+#include "system.h"
+#include <signal.h>
+#include <sys/stat.h>
+#include "gansidecl.h"
#include "obstack.h"
const char *, char **, char **, int));
extern int pwait PROTO ((int, int *, int));
extern char *update_path PROTO((char *, char *));
+extern void set_std_prefix PROTO((char *, int));
/* Flag arguments to pexecute. */
#define PEXECUTE_FIRST 1
#define PEXECUTE_LAST 2
#define exit __posix_exit
#endif
-/* Define O_RDONLY if the system hasn't defined it for us. */
-#ifndef O_RDONLY
-#define O_RDONLY 0
-#endif
-
#ifdef USG
#define vfork fork
#endif /* USG */
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
+#ifndef GET_ENVIRONMENT
+#define GET_ENVIRONMENT(ENV_VALUE,ENV_NAME) ENV_VALUE = getenv (ENV_NAME)
+#endif
+
extern char *choose_temp_base PROTO((void));
#ifndef HAVE_STRERROR
static void pfatal_with_name PROTO((char *));
static void perror_with_name PROTO((char *));
static void pfatal_pexecute PROTO((char *, char *));
-#ifdef HAVE_VPRINTF
static void fatal PVPROTO((char *, ...));
static void error PVPROTO((char *, ...));
-#else
-/* We must not provide any prototype here, even if ANSI C. */
-static void fatal PROTO(());
-static void error PROTO(());
-#endif
void fancy_abort ();
char *xmalloc ();
char *xrealloc ();
#ifdef LANG_SPECIFIC_DRIVER
-extern void lang_specific_driver PROTO ((void (*) (), int *, char ***));
+extern void lang_specific_driver PROTO ((void (*) PVPROTO((char *, ...)), int *, char ***, int *));
#endif
\f
/* Specs are strings containing lines, each of which (if not blank)
#endif
#endif
+#ifndef LINKER_NAME
+#define LINKER_NAME "collect2"
+#endif
+
static char *cpp_spec = CPP_SPEC;
static char *cpp_predefines = CPP_PREDEFINES;
static char *cc1_spec = CC1_SPEC;
static char *endfile_spec = ENDFILE_SPEC;
static char *startfile_spec = STARTFILE_SPEC;
static char *switches_need_spaces = SWITCHES_NEED_SPACES;
+static char *linker_name_spec = LINKER_NAME;
/* Some compilers have limits on line lengths, and the multilib_select
and/or multilib_matches strings can be very long, so we build them at
/* Don't generate -L options. */
static char *link_command_spec = "\
%{!fsyntax-only: \
- %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
+ %{!c:%{!M:%{!MM:%{!E:%{!S:%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
%{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
%{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
%{static:} %{L*} %o\
/* Use -L. */
static char *link_command_spec = "\
%{!fsyntax-only: \
- %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
+ %{!c:%{!M:%{!MM:%{!E:%{!S:%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
%{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
%{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
%{static:} %{L*} %D %o\
INIT_STATIC_SPEC ("multilib_defaults", &multilib_defaults),
INIT_STATIC_SPEC ("multilib_extra", &multilib_extra),
INIT_STATIC_SPEC ("multilib_matches", &multilib_matches),
+ INIT_STATIC_SPEC ("linker", &linker_name_spec),
};
#ifdef EXTRA_SPECS /* additional specs needed */
commands[0].prog = argbuf[0]; /* first command. */
commands[0].argv = &argbuf[0];
string = find_a_file (&exec_prefixes, commands[0].prog, X_OK);
+
if (string)
commands[0].argv[0] = string;
static int n_infiles;
+/* This counts the number of libraries added by LANG_SPECIFIC_DRIVER, so that
+ we can tell if there were any user supplied any files or libraries. */
+
+static int added_libraries;
+
/* And a vector of corresponding output files is made up later. */
static char **outfiles;
int have_o = 0;
int lang_n_infiles = 0;
- gcc_exec_prefix = getenv ("GCC_EXEC_PREFIX");
+ GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
n_switches = 0;
n_infiles = 0;
+ added_libraries = 0;
/* Figure compiler version from version string. */
if (gcc_exec_prefix)
{
+ int len = strlen (gcc_exec_prefix);
+ if (len > sizeof ("/lib/gcc-lib/")-1
+ && (gcc_exec_prefix[len-1] == '/'
+ || gcc_exec_prefix[len-1] == DIR_SEPARATOR))
+ {
+ temp = gcc_exec_prefix + len - sizeof ("/lib/gcc-lib/") + 1;
+ if ((*temp == '/' || *temp == DIR_SEPARATOR)
+ && strncmp (temp+1, "lib", 3) == 0
+ && (temp[4] == '/' || temp[4] == DIR_SEPARATOR)
+ && strncmp (temp+5, "gcc-lib", 7) == 0)
+ len -= sizeof ("/lib/gcc-lib/") - 1;
+ }
+
+ set_std_prefix (gcc_exec_prefix, len);
add_prefix (&exec_prefixes, gcc_exec_prefix, "GCC", 0, 0, NULL_PTR);
add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC", 0, 0, NULL_PTR);
}
/* COMPILER_PATH and LIBRARY_PATH have values
that are lists of directory names with colons. */
- temp = getenv ("COMPILER_PATH");
+ GET_ENVIRONMENT (temp, "COMPILER_PATH");
if (temp)
{
char *startp, *endp;
}
}
- temp = getenv ("LIBRARY_PATH");
+ GET_ENVIRONMENT (temp, "LIBRARY_PATH");
if (temp && *cross_compile == '0')
{
char *startp, *endp;
}
/* Use LPATH like LIBRARY_PATH (for the CMU build program). */
- temp = getenv ("LPATH");
+ GET_ENVIRONMENT (temp, "LPATH");
if (temp && *cross_compile == '0')
{
char *startp, *endp;
#ifdef LANG_SPECIFIC_DRIVER
/* Do language-specific adjustment/addition of flags. */
- lang_specific_driver (fatal, &argc, &argv);
+ lang_specific_driver (fatal, &argc, &argv, &added_libraries);
#endif
/* Scan argv twice. Here, the first time, just count how many switches
}
else if (! strcmp (argv[i], "-dumpversion"))
{
- printf ("%s\n", version_string);
+ printf ("%s\n", spec_version);
exit (0);
}
else if (! strcmp (argv[i], "-dumpmachine"))
spec_version = p + 1;
compiler_version = spec_version;
warn_std_ptr = &warn_std;
+
+ /* Validate the version number. Use the same checks
+ done when inserting it into a spec.
+
+ The format of the version string is
+ ([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)? */
+ {
+ char *v = compiler_version;
+
+ /* Ignore leading non-digits. i.e. "foo-" in "foo-2.7.2". */
+ while (! ISDIGIT (*v))
+ v++;
+
+ if (v > compiler_version && v[-1] != '-')
+ fatal ("invalid version number format");
+
+ /* Set V after the first period. */
+ while (ISDIGIT (*v))
+ v++;
+
+ if (*v != '.')
+ fatal ("invalid version number format");
+
+ v++;
+ while (ISDIGIT (*v))
+ v++;
+
+ if (*v != 0 && *v != ' ' && *v != '.' && *v != '-')
+ fatal ("invalid version number format");
+ }
break;
case 'c':
}
if (have_c && have_o && lang_n_infiles > 1)
- fatal ("cannot specify -o with -c and multiple compilations");
+ fatal ("cannot specify -o with -c or -S and multiple compilations");
/* Set up the search paths before we go looking for config files. */
for (j = 4; argv[i][j]; j++)
if (argv[i][j] == ',')
{
- infiles[n_infiles].language = 0;
+ infiles[n_infiles].language = "*";
infiles[n_infiles++].name
= save_string (argv[i] + prev, j - prev);
prev = j + 1;
}
/* Record the part after the last comma. */
- infiles[n_infiles].language = 0;
+ infiles[n_infiles].language = "*";
infiles[n_infiles++].name = argv[i] + prev;
}
else if (strcmp (argv[i], "-Xlinker") == 0)
{
- infiles[n_infiles].language = 0;
+ infiles[n_infiles].language = "*";
infiles[n_infiles++].name = argv[++i];
}
else if (strncmp (argv[i], "-l", 2) == 0)
{
- infiles[n_infiles].language = 0;
+ infiles[n_infiles].language = "*";
infiles[n_infiles++].name = argv[i];
}
else if (strcmp (argv[i], "-specs") == 0)
char *x = (char *) alloca (strlen (name) * 2 + 1);
char *buf = x;
char *y = name;
+ int flag = 0;
/* Copy all of NAME into BUF, but put __ after
every -D and at the end of each arg, */
while (1)
{
- int flag;
-
if (! strncmp (y, "-D", 2))
{
*x++ = '-';
first_time = FALSE;
obstack_grow (&collect_obstack, "'-", 2);
q = switches[i].part1;
- while ((p = (char *) index (q,'\'')))
+ while ((p = index (q,'\'')))
{
obstack_grow (&collect_obstack, q, p-q);
obstack_grow (&collect_obstack, "'\\''", 4);
{
obstack_grow (&collect_obstack, " '", 2);
q = *args;
- while ((p = (char *) index (q,'\'')))
+ while ((p = index (q,'\'')))
{
obstack_grow (&collect_obstack, q, p-q);
obstack_grow (&collect_obstack, "'\\''", 4);
as a unit. If GCC_EXEC_PREFIX is defined, base
standard_startfile_prefix on that as well. */
if (*standard_startfile_prefix == '/'
- || *standard_startfile_prefix == DIR_SEPARATOR)
+ || *standard_startfile_prefix == DIR_SEPARATOR
+ || *standard_startfile_prefix == '$'
+#ifdef __MSDOS__
+ /* Check for disk name on MS-DOS-based systems. */
+ || (standard_startfile_prefix[1] == ':'
+ && (standard_startfile_prefix[2] == DIR_SEPARATOR
+ || standard_startfile_prefix[2] == '/'))
+#endif
+ )
add_prefix (&startfile_prefixes, standard_startfile_prefix, "BINUTILS",
0, 0, NULL_PTR);
else
exit (0);
}
- if (n_infiles == 0)
+ if (n_infiles == added_libraries)
fatal ("No input files");
/* Make a place to record the compiler output file names
{
int tmp = execution_count;
+ /* We'll use ld if we can't find collect2. */
+ if (! strcmp (linker_name_spec, "collect2"))
+ {
+ char *s = find_a_file (&exec_prefixes, "collect2", X_OK);
+ if (s == NULL)
+ linker_name_spec = "ld";
+ }
/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
for collect. */
putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH=");
/* Find the proper compilation spec for the file name NAME,
whose length is LENGTH. LANGUAGE is the specified language,
- or 0 if none specified. */
+ or 0 if this file is to be passed to the linker. */
static struct compiler *
lookup_compiler (name, length, language)
{
struct compiler *cp;
- /* Look for the language, if one is spec'd. */
+ /* If this was specified by the user to be a linker input, indicate that. */
+ if (language != 0 && language[0] == '*')
+ return 0;
+
+ /* Otherwise, look for the language, if one is spec'd. */
if (language != 0)
{
for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
- {
- if (language != 0)
- {
- if (cp->suffix[0] == '@'
- && !strcmp (cp->suffix + 1, language))
- return cp;
- }
- }
+ if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language))
+ return cp;
+
error ("language %s not recognized", language);
+ return 0;
}
/* Look for a suffix. */
{
if (/* The suffix `-' matches only the file name `-'. */
(!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
- ||
- (strlen (cp->suffix) < length
- /* See if the suffix matches the end of NAME. */
+ || (strlen (cp->suffix) < length
+ /* See if the suffix matches the end of NAME. */
#ifdef OS2
- && (!strcmp (cp->suffix,
- name + length - strlen (cp->suffix))
- || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
- && !strcasecmp (cp->suffix,
- name + length - strlen (cp->suffix)))))
+ && ((!strcmp (cp->suffix,
+ name + length - strlen (cp->suffix))
+ || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
+ && !strcasecmp (cp->suffix,
+ name + length - strlen (cp->suffix)))
#else
- && !strcmp (cp->suffix,
- name + length - strlen (cp->suffix))))
+ && !strcmp (cp->suffix,
+ name + length - strlen (cp->suffix))
#endif
+ ))
{
if (cp->spec[0][0] == '@')
{
struct compiler *new;
+
/* An alias entry maps a suffix to a language.
Search for the language; pass 0 for NAME and LENGTH
to avoid infinite recursion if language not found.
(char *) new->spec, sizeof new->spec);
return new;
}
+
/* A non-alias entry: return it. */
return cp;
}
char *errmsg_fmt;
char *errmsg_arg;
{
+ int save_errno = errno;
+
if (errmsg_arg)
{
/* Space for trailing '\0' is in %s. */
errmsg_fmt = msg;
}
- fatal ("%s: %s", errmsg_fmt, my_strerror (errno));
+ fatal ("%s: %s", errmsg_fmt, my_strerror (save_errno));
}
/* More 'friendly' abort that prints the line and file.
fatal ("Internal gcc abort.");
}
\f
-#ifdef HAVE_VPRINTF
-
/* Output an error message and exit */
static void
fprintf (stderr, "\n");
}
-
-#else /* not HAVE_VPRINTF */
-
-static void
-fatal (msg, arg1, arg2)
- char *msg, *arg1, *arg2;
-{
- error (msg, arg1, arg2);
- delete_temp_files ();
- exit (1);
-}
-
-static void
-error (msg, arg1, arg2)
- char *msg, *arg1, *arg2;
-{
- fprintf (stderr, "%s: ", programname);
- fprintf (stderr, msg, arg1, arg2);
- fprintf (stderr, "\n");
-}
-
-#endif /* not HAVE_VPRINTF */
-
\f
static void
validate_all_switches ()