/* Compiler driver program that can handle many languages.
- Copyright (C) 1987, 89, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
Once it knows which kind of compilation to perform, the procedure for
compilation is specified by a string called a "spec". */
\f
-#include <sys/types.h>
-#include <ctype.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-#ifndef NO_SYS_FILE_H
-#include <sys/file.h> /* May get R_OK, etc. on some systems. */
-#endif
-
#include "config.h"
-#include "obstack.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 <stdio.h>
-#ifndef R_OK
-#define R_OK 4
-#define W_OK 2
-#define X_OK 1
-#endif
+#include "obstack.h"
+
/* ??? Need to find a GCC header to put these in. */
extern int pexecute PROTO ((const char *, char * const *, const char *,
const char *, char **, char **, int));
extern int pwait PROTO ((int, int *, int));
+extern char *update_path PROTO((char *, char *));
/* Flag arguments to pexecute. */
#define PEXECUTE_FIRST 1
#define PEXECUTE_LAST 2
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-extern void free ();
-extern char *getenv ();
-
extern char *choose_temp_base PROTO((void));
-#ifndef errno
-extern int errno;
-#endif
-
#ifndef HAVE_STRERROR
extern int sys_nerr;
-#if defined(bsd4_4)
-extern const char *const sys_errlist[];
-#else
extern char *sys_errlist[];
-#endif
#else
extern char *strerror();
#endif
+#ifndef HAVE_KILL
+#define kill(p,s) raise(s)
+#endif
+
/* If a stage of compilation returns an exit status >= 1,
compilation of that file ceases. */
When -b is used, the value comes from the `specs' file. */
#ifdef CROSS_COMPILE
-static int cross_compile = 1;
+static char *cross_compile = "1";
#else
-static int cross_compile = 0;
+static char *cross_compile = "0";
#endif
/* The number of errors that have occurred; the link phase will not be
/* Forward declaration for prototypes. */
struct path_prefix;
+static void init_spec PROTO((void));
+static void read_specs PROTO((char *, int));
static void set_spec PROTO((char *, char *));
static struct compiler *lookup_compiler PROTO((char *, int, char *));
static char *build_search_list PROTO((struct path_prefix *, char *, int));
static void putenv_from_prefixes PROTO((struct path_prefix *, char *));
static char *find_a_file PROTO((struct path_prefix *, char *, int));
-static void add_prefix PROTO((struct path_prefix *, char *, int, int, int *));
+static void add_prefix PROTO((struct path_prefix *, char *, char *,
+ int, int, int *));
static char *skip_whitespace PROTO((char *));
static void record_temp_file PROTO((char *, int, int));
static void delete_if_ordinary PROTO((char *));
static int is_directory PROTO((char *, char *, int));
static void validate_switches PROTO((char *));
static void validate_all_switches PROTO((void));
-static void give_switch PROTO((int, int));
+static void give_switch PROTO((int, int, int));
static int used_arg PROTO((char *, int));
static int default_arg PROTO((char *, int));
static void set_multilib_dir PROTO((void));
arguments. CC considers `-o foo' as being one switch whose
name starts with `o'. %{o*} would substitute this text,
including the space; thus, two arguments would be generated.
+ %{^S*} likewise, but don't put a blank between a switch and any args.
%{S*:X} substitutes X if one or more switches whose names start with -S are
specified to CC. Note that the tail part of the -S option
(i.e. the part matched by the `*') will be substituted for each
static char *multilib_defaults_raw[] = MULTILIB_DEFAULTS;
-#ifdef EXTRA_SPECS
-static struct { char *name, *spec; } extra_specs[] = { EXTRA_SPECS };
-#endif
-
struct user_specs {
struct user_specs *next;
char *filename;
/* This defines which switch letters take arguments. */
-#define DEFAULT_SWITCH_TAKES_ARG(CHAR) \
+#define DEFAULT_SWITCH_TAKES_ARG(CHAR) \
((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
|| (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
|| (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \
- || (CHAR) == 'L' || (CHAR) == 'A')
+ || (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'V' \
+ || (CHAR) == 'B' || (CHAR) == 'b')
#ifndef SWITCH_TAKES_ARG
#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
static struct compiler default_compilers[] =
{
/* Add lists of suffixes of known languages here. If those languages
- were no present when we built the driver, we will hit these copies
- and given a more meaningful error than "file not used since
+ were not present when we built the driver, we will hit these copies
+ and be given a more meaningful error than "file not used since
linking is not done". */
{".cc", "#C++"}, {".cxx", "#C++"}, {".cpp", "#C++"}, {".c++", "#C++"},
{".C", "#C++"}, {".ads", "#Ada"}, {".adb", "#Ada"}, {".ada", "#Ada"},
{".f", "#Fortran"}, {".for", "#Fortran"}, {".F", "#Fortran"},
{".fpp", "#Fortran"},
+ {".p", "#Pascal"}, {".pas", "#Pascal"},
/* Next come the entries for C. */
{".c", "@c"},
{"@c",
-undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
%{ansi:-trigraphs -D__STRICT_ANSI__}\
%{!undef:%{!ansi:%p} %P} %{trigraphs} \
- %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
+ %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{traditional} %{ftraditional:-traditional}\
%{traditional-cpp:-traditional}\
%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
%i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
-undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
%{ansi:-trigraphs -D__STRICT_ANSI__}\
%{!undef:%{!ansi:%p} %P} %{trigraphs}\
- %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
+ %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{traditional} %{ftraditional:-traditional}\
%{traditional-cpp:-traditional}\
%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
%i %W{o*}}\
-undef -D__OBJC__ -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
%{ansi:-trigraphs -D__STRICT_ANSI__}\
%{!undef:%{!ansi:%p} %P} %{trigraphs}\
- %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
+ %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{traditional} %{ftraditional:-traditional}\
%{traditional-cpp:-traditional}\
%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
%i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
-undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
%{ansi:-trigraphs -D__STRICT_ANSI__}\
%{!undef:%{!ansi:%p} %P} %{trigraphs}\
- %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
+ %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{traditional} %{ftraditional:-traditional}\
%{traditional-cpp:-traditional}\
%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
%i %W{o*}"},
%{C:%{!E:%eGNU C does not support -C without using -E}}\
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG} %{trigraphs}\
-undef -$ %{!undef:%p %P} -D__ASSEMBLER__ \
- %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
+ %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{traditional} %{ftraditional:-traditional}\
%{traditional-cpp:-traditional}\
%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
%i %{!M:%{!MM:%{!E:%{!pipe:%g.s}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
#endif
}
\f
-/* Read compilation specs from a file named FILENAME,
- replacing the default ones.
-
- A suffix which starts with `*' is a definition for
- one of the machine-specific sub-specs. The "suffix" should be
- *asm, *cc1, *cpp, *link, *startfile, *signed_char, etc.
- The corresponding spec is stored in asm_spec, etc.,
- rather than in the `compilers' vector.
-
- Anything invalid in the file is a fatal error. */
-
-static void
-read_specs (filename)
- char *filename;
-{
- int desc;
- int readlen;
- struct stat statbuf;
- char *buffer;
- register char *p;
-
- if (verbose_flag)
- fprintf (stderr, "Reading specs from %s\n", filename);
-
- /* Open and stat the file. */
- desc = open (filename, O_RDONLY, 0);
- if (desc < 0)
- pfatal_with_name (filename);
- if (stat (filename, &statbuf) < 0)
- pfatal_with_name (filename);
-
- /* Read contents of file into BUFFER. */
- buffer = xmalloc ((unsigned) statbuf.st_size + 1);
- readlen = read (desc, buffer, (unsigned) statbuf.st_size);
- if (readlen < 0)
- pfatal_with_name (filename);
- buffer[readlen] = 0;
- close (desc);
-
- /* Scan BUFFER for specs, putting them in the vector. */
- p = buffer;
- while (1)
- {
- char *suffix;
- char *spec;
- char *in, *out, *p1, *p2;
-
- /* Advance P in BUFFER to the next nonblank nocomment line. */
- p = skip_whitespace (p);
- if (*p == 0)
- break;
-
- /* Find the colon that should end the suffix. */
- p1 = p;
- while (*p1 && *p1 != ':' && *p1 != '\n') p1++;
- /* The colon shouldn't be missing. */
- if (*p1 != ':')
- fatal ("specs file malformed after %d characters", p1 - buffer);
- /* Skip back over trailing whitespace. */
- p2 = p1;
- while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t')) p2--;
- /* Copy the suffix to a string. */
- suffix = save_string (p, p2 - p);
- /* Find the next line. */
- p = skip_whitespace (p1 + 1);
- if (p[1] == 0)
- fatal ("specs file malformed after %d characters", p - buffer);
- p1 = p;
- /* Find next blank line. */
- while (*p1 && !(*p1 == '\n' && p1[1] == '\n')) p1++;
- /* Specs end at the blank line and do not include the newline. */
- spec = save_string (p, p1 - p);
- p = p1;
-
- /* Delete backslash-newline sequences from the spec. */
- in = spec;
- out = spec;
- while (*in != 0)
- {
- if (in[0] == '\\' && in[1] == '\n')
- in += 2;
- else if (in[0] == '#')
- {
- while (*in && *in != '\n') in++;
- }
- else
- *out++ = *in++;
- }
- *out = 0;
-
- if (suffix[0] == '*')
- {
- if (! strcmp (suffix, "*link_command"))
- link_command_spec = spec;
- else
- set_spec (suffix + 1, spec);
- }
- else
- {
- /* Add this pair to the vector. */
- compilers
- = ((struct compiler *)
- xrealloc (compilers, (n_compilers + 2) * sizeof (struct compiler)));
- compilers[n_compilers].suffix = suffix;
- bzero ((char *) compilers[n_compilers].spec,
- sizeof compilers[n_compilers].spec);
- compilers[n_compilers].spec[0] = spec;
- n_compilers++;
- bzero ((char *) &compilers[n_compilers],
- sizeof compilers[n_compilers]);
- }
-
- if (*suffix == 0)
- link_command_spec = spec;
- }
-
- if (link_command_spec == 0)
- fatal ("spec file has no spec for linking");
-}
-
static char *
skip_whitespace (p)
char *p;
struct spec_list
{
- char *name; /* Name of the spec. */
- char *spec; /* The spec itself. */
- struct spec_list *next; /* Next spec in linked list. */
+ /* The following 2 fields must be first */
+ /* to allow EXTRA_SPECS to be initialized */
+ char *name; /* name of the spec. */
+ char *ptr; /* available ptr if no static pointer */
+
+ /* The following fields are not initialized */
+ /* by EXTRA_SPECS */
+ char **ptr_spec; /* pointer to the spec itself. */
+ struct spec_list *next; /* Next spec in linked list. */
+ int name_len; /* length of the name */
+ int alloc_p; /* whether string was allocated */
};
-/* List of specs that have been defined so far. */
+#define INIT_STATIC_SPEC(NAME,PTR) \
+{ NAME, NULL_PTR, PTR, (struct spec_list *)0, sizeof (NAME)-1, 0 }
+
+/* List of statically defined specs */
+static struct spec_list static_specs[] = {
+ INIT_STATIC_SPEC ("asm", &asm_spec),
+ INIT_STATIC_SPEC ("asm_final", &asm_final_spec),
+ INIT_STATIC_SPEC ("cpp", &cpp_spec),
+ INIT_STATIC_SPEC ("cc1", &cc1_spec),
+ INIT_STATIC_SPEC ("cc1plus", &cc1plus_spec),
+ INIT_STATIC_SPEC ("endfile", &endfile_spec),
+ INIT_STATIC_SPEC ("link", &link_spec),
+ INIT_STATIC_SPEC ("lib", &lib_spec),
+ INIT_STATIC_SPEC ("libgcc", &libgcc_spec),
+ INIT_STATIC_SPEC ("startfile", &startfile_spec),
+ INIT_STATIC_SPEC ("switches_need_spaces", &switches_need_spaces),
+ INIT_STATIC_SPEC ("signed_char", &signed_char_spec),
+ INIT_STATIC_SPEC ("predefines", &cpp_predefines),
+ INIT_STATIC_SPEC ("cross_compile", &cross_compile),
+ INIT_STATIC_SPEC ("version", &compiler_version),
+ INIT_STATIC_SPEC ("multilib", &multilib_select),
+ INIT_STATIC_SPEC ("multilib_defaults", &multilib_defaults),
+ INIT_STATIC_SPEC ("multilib_extra", &multilib_extra),
+ INIT_STATIC_SPEC ("multilib_matches", &multilib_matches),
+};
+
+#ifdef EXTRA_SPECS /* additional specs needed */
+static struct spec_list extra_specs[] = { EXTRA_SPECS };
+#endif
+
+/* List of dynamically allocates specs that have been defined so far. */
+
+static struct spec_list *specs = (struct spec_list *)0;
+
+\f
+/* Initialize the specs lookup routines. */
+
+static void
+init_spec ()
+{
+ struct spec_list *next = (struct spec_list *)0;
+ struct spec_list *sl = (struct spec_list *)0;
+ int i;
+
+ if (specs)
+ return; /* already initialized */
+
+ if (verbose_flag)
+ fprintf (stderr, "Using builtin specs.\n");
+
+#ifdef EXTRA_SPECS
+ for (i = (sizeof (extra_specs) / sizeof (extra_specs[0])) - 1; i >= 0; i--)
+ {
+ sl = &extra_specs[i];
+ sl->next = next;
+ sl->name_len = strlen (sl->name);
+ sl->ptr_spec = &sl->ptr;
+ next = sl;
+ }
+#endif
+
+ for (i = (sizeof (static_specs) / sizeof (static_specs[0])) - 1; i >= 0; i--)
+ {
+ sl = &static_specs[i];
+ sl->next = next;
+ next = sl;
+ }
+
+ specs = sl;
+}
-static struct spec_list *specs = (struct spec_list *) 0;
\f
/* Change the value of spec NAME to SPEC. If SPEC is empty, then the spec is
removed; If the spec starts with a + then SPEC is added to the end of the
{
struct spec_list *sl;
char *old_spec;
+ int name_len = strlen (name);
+ int i;
+
+ /* If this is the first call, initialize the statically allocated specs */
+ if (!specs)
+ {
+ struct spec_list *next = (struct spec_list *)0;
+ for (i = (sizeof (static_specs) / sizeof (static_specs[0])) - 1;
+ i >= 0; i--)
+ {
+ sl = &static_specs[i];
+ sl->next = next;
+ next = sl;
+ }
+ specs = sl;
+ }
/* See if the spec already exists */
for (sl = specs; sl; sl = sl->next)
- if (strcmp (sl->name, name) == 0)
+ if (name_len == sl->name_len && !strcmp (sl->name, name))
break;
if (!sl)
/* Not found - make it */
sl = (struct spec_list *) xmalloc (sizeof (struct spec_list));
sl->name = save_string (name, strlen (name));
- sl->spec = save_string ("", 0);
+ sl->name_len = name_len;
+ sl->ptr_spec = &sl->ptr;
+ sl->alloc_p = 0;
+ *(sl->ptr_spec) = "";
sl->next = specs;
specs = sl;
}
- old_spec = sl->spec;
- if (name && spec[0] == '+' && isspace (spec[1]))
- sl->spec = concat (old_spec, spec + 1, NULL_PTR);
- else
- sl->spec = save_string (spec, strlen (spec));
-
- if (! strcmp (name, "asm"))
- asm_spec = sl->spec;
- else if (! strcmp (name, "asm_final"))
- asm_final_spec = sl->spec;
- else if (! strcmp (name, "cc1"))
- cc1_spec = sl->spec;
- else if (! strcmp (name, "cc1plus"))
- cc1plus_spec = sl->spec;
- else if (! strcmp (name, "cpp"))
- cpp_spec = sl->spec;
- else if (! strcmp (name, "endfile"))
- endfile_spec = sl->spec;
- else if (! strcmp (name, "lib"))
- lib_spec = sl->spec;
- else if (! strcmp (name, "libgcc"))
- libgcc_spec = sl->spec;
- else if (! strcmp (name, "link"))
- link_spec = sl->spec;
- else if (! strcmp (name, "predefines"))
- cpp_predefines = sl->spec;
- else if (! strcmp (name, "signed_char"))
- signed_char_spec = sl->spec;
- else if (! strcmp (name, "startfile"))
- startfile_spec = sl->spec;
- else if (! strcmp (name, "switches_need_spaces"))
- switches_need_spaces = sl->spec;
- else if (! strcmp (name, "cross_compile"))
- cross_compile = atoi (sl->spec);
- else if (! strcmp (name, "multilib"))
- multilib_select = sl->spec;
- else if (! strcmp (name, "multilib_matches"))
- multilib_matches = sl->spec;
- else if (! strcmp (name, "multilib_extra"))
- multilib_extra = sl->spec;
- else if (! strcmp (name, "multilib_defaults"))
- multilib_defaults = sl->spec;
- else if (! strcmp (name, "version"))
- compiler_version = sl->spec;
-#ifdef EXTRA_SPECS
- else
- {
- int i;
- for (i = 0; i < sizeof (extra_specs) / sizeof (extra_specs[0]); i++)
- {
- if (! strcmp (name, extra_specs[i].name))
- {
- extra_specs[i].spec = sl->spec;
- break;
- }
- }
- }
+ old_spec = *(sl->ptr_spec);
+ *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE (spec[1]))
+ ? concat (old_spec, spec + 1, NULL_PTR)
+ : save_string (spec, strlen (spec)));
+
+#ifdef DEBUG_SPECS
+ if (verbose_flag)
+ fprintf (stderr, "Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
#endif
/* Free the old spec */
- if (old_spec)
+ if (old_spec && sl->alloc_p)
free (old_spec);
+
+ sl->alloc_p = 1;
}
\f
/* Accumulate a command (program name and args), and run it. */
int delete_always, delete_failure;
{
if (argbuf_index + 1 == argbuf_length)
- {
- argbuf = (char **) xrealloc (argbuf, (argbuf_length *= 2) * sizeof (char *));
- }
+ argbuf
+ = (char **) xrealloc (argbuf, (argbuf_length *= 2) * sizeof (char *));
argbuf[argbuf_index++] = arg;
argbuf[argbuf_index] = 0;
record_temp_file (arg, delete_always, delete_failure);
}
\f
+/* Read compilation specs from a file named FILENAME,
+ replacing the default ones.
+
+ A suffix which starts with `*' is a definition for
+ one of the machine-specific sub-specs. The "suffix" should be
+ *asm, *cc1, *cpp, *link, *startfile, *signed_char, etc.
+ The corresponding spec is stored in asm_spec, etc.,
+ rather than in the `compilers' vector.
+
+ Anything invalid in the file is a fatal error. */
+
+static void
+read_specs (filename, main_p)
+ char *filename;
+ int main_p;
+{
+ int desc;
+ int readlen;
+ struct stat statbuf;
+ char *buffer;
+ register char *p;
+
+ if (verbose_flag)
+ fprintf (stderr, "Reading specs from %s\n", filename);
+
+ /* Open and stat the file. */
+ desc = open (filename, O_RDONLY, 0);
+ if (desc < 0)
+ pfatal_with_name (filename);
+ if (stat (filename, &statbuf) < 0)
+ pfatal_with_name (filename);
+
+ /* Read contents of file into BUFFER. */
+ buffer = xmalloc ((unsigned) statbuf.st_size + 1);
+ readlen = read (desc, buffer, (unsigned) statbuf.st_size);
+ if (readlen < 0)
+ pfatal_with_name (filename);
+ buffer[readlen] = 0;
+ close (desc);
+
+ /* Scan BUFFER for specs, putting them in the vector. */
+ p = buffer;
+ while (1)
+ {
+ char *suffix;
+ char *spec;
+ char *in, *out, *p1, *p2, *p3;
+
+ /* Advance P in BUFFER to the next nonblank nocomment line. */
+ p = skip_whitespace (p);
+ if (*p == 0)
+ break;
+
+ /* Is this a special command that starts with '%'? */
+ /* Don't allow this for the main specs file, since it would
+ encourage people to overwrite it. */
+ if (*p == '%' && !main_p)
+ {
+ p1 = p;
+ while (*p && *p != '\n')
+ p++;
+
+ p++; /* Skip '\n' */
+
+ if (!strncmp (p1, "%include", sizeof ("%include")-1)
+ && (p1[sizeof "%include" - 1] == ' '
+ || p1[sizeof "%include" - 1] == '\t'))
+ {
+ char *new_filename;
+
+ p1 += sizeof ("%include");
+ while (*p1 == ' ' || *p1 == '\t')
+ p1++;
+
+ if (*p1++ != '<' || p[-2] != '>')
+ fatal ("specs %%include syntax malformed after %d characters",
+ p1 - buffer + 1);
+
+ p[-2] = '\0';
+ new_filename = find_a_file (&startfile_prefixes, p1, R_OK);
+ read_specs (new_filename ? new_filename : p1, FALSE);
+ continue;
+ }
+ else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1)
+ && (p1[sizeof "%include_noerr" - 1] == ' '
+ || p1[sizeof "%include_noerr" - 1] == '\t'))
+ {
+ char *new_filename;
+
+ p1 += sizeof "%include_noerr";
+ while (*p1 == ' ' || *p1 == '\t') p1++;
+
+ if (*p1++ != '<' || p[-2] != '>')
+ fatal ("specs %%include syntax malformed after %d characters",
+ p1 - buffer + 1);
+
+ p[-2] = '\0';
+ new_filename = find_a_file (&startfile_prefixes, p1, R_OK);
+ if (new_filename)
+ read_specs (new_filename, FALSE);
+ else if (verbose_flag)
+ fprintf (stderr, "Could not find specs file %s\n", p1);
+ continue;
+ }
+ else if (!strncmp (p1, "%rename", sizeof "%rename" - 1)
+ && (p1[sizeof "%rename" - 1] == ' '
+ || p1[sizeof "%rename" - 1] == '\t'))
+ {
+ int name_len;
+ struct spec_list *sl;
+
+ /* Get original name */
+ p1 += sizeof "%rename";
+ while (*p1 == ' ' || *p1 == '\t')
+ p1++;
+
+ if (! ISALPHA (*p1))
+ fatal ("specs %%rename syntax malformed after %d characters",
+ p1 - buffer);
+
+ p2 = p1;
+ while (*p2 && !ISSPACE (*p2))
+ p2++;
+
+ if (*p2 != ' ' && *p2 != '\t')
+ fatal ("specs %%rename syntax malformed after %d characters",
+ p2 - buffer);
+
+ name_len = p2 - p1;
+ *p2++ = '\0';
+ while (*p2 == ' ' || *p2 == '\t')
+ p2++;
+
+ if (! ISALPHA (*p2))
+ fatal ("specs %%rename syntax malformed after %d characters",
+ p2 - buffer);
+
+ /* Get new spec name */
+ p3 = p2;
+ while (*p3 && !ISSPACE (*p3))
+ p3++;
+
+ if (p3 != p-1)
+ fatal ("specs %%rename syntax malformed after %d characters",
+ p3 - buffer);
+ *p3 = '\0';
+
+ for (sl = specs; sl; sl = sl->next)
+ if (name_len == sl->name_len && !strcmp (sl->name, p1))
+ break;
+
+ if (!sl)
+ fatal ("specs %s spec was not found to be renamed", p1);
+
+ if (strcmp (p1, p2) == 0)
+ continue;
+
+ if (verbose_flag)
+ {
+ fprintf (stderr, "rename spec %s to %s\n", p1, p2);
+#ifdef DEBUG_SPECS
+ fprintf (stderr, "spec is '%s'\n\n", *(sl->ptr_spec));
+#endif
+ }
+
+ set_spec (p2, *(sl->ptr_spec));
+ if (sl->alloc_p)
+ free (*(sl->ptr_spec));
+
+ *(sl->ptr_spec) = "";
+ sl->alloc_p = 0;
+ continue;
+ }
+ else
+ fatal ("specs unknown %% command after %d characters",
+ p1 - buffer);
+ }
+
+ /* Find the colon that should end the suffix. */
+ p1 = p;
+ while (*p1 && *p1 != ':' && *p1 != '\n')
+ p1++;
+
+ /* The colon shouldn't be missing. */
+ if (*p1 != ':')
+ fatal ("specs file malformed after %d characters", p1 - buffer);
+
+ /* Skip back over trailing whitespace. */
+ p2 = p1;
+ while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t'))
+ p2--;
+
+ /* Copy the suffix to a string. */
+ suffix = save_string (p, p2 - p);
+ /* Find the next line. */
+ p = skip_whitespace (p1 + 1);
+ if (p[1] == 0)
+ fatal ("specs file malformed after %d characters", p - buffer);
+
+ p1 = p;
+ /* Find next blank line. */
+ while (*p1 && !(*p1 == '\n' && p1[1] == '\n'))
+ p1++;
+
+ /* Specs end at the blank line and do not include the newline. */
+ spec = save_string (p, p1 - p);
+ p = p1;
+
+ /* Delete backslash-newline sequences from the spec. */
+ in = spec;
+ out = spec;
+ while (*in != 0)
+ {
+ if (in[0] == '\\' && in[1] == '\n')
+ in += 2;
+ else if (in[0] == '#')
+ while (*in && *in != '\n')
+ in++;
+
+ else
+ *out++ = *in++;
+ }
+ *out = 0;
+
+ if (suffix[0] == '*')
+ {
+ if (! strcmp (suffix, "*link_command"))
+ link_command_spec = spec;
+ else
+ set_spec (suffix + 1, spec);
+ }
+ else
+ {
+ /* Add this pair to the vector. */
+ compilers
+ = ((struct compiler *)
+ xrealloc (compilers,
+ (n_compilers + 2) * sizeof (struct compiler)));
+
+ compilers[n_compilers].suffix = suffix;
+ bzero ((char *) compilers[n_compilers].spec,
+ sizeof compilers[n_compilers].spec);
+ compilers[n_compilers].spec[0] = spec;
+ n_compilers++;
+ bzero ((char *) &compilers[n_compilers],
+ sizeof compilers[n_compilers]);
+ }
+
+ if (*suffix == 0)
+ link_command_spec = spec;
+ }
+
+ if (link_command_spec == 0)
+ fatal ("spec file has no spec for linking");
+}
+\f
/* Record the names of temporary files we tell compilers to write,
and delete them at the end of the run. */
for (temp = always_delete_queue; temp; temp = temp->next)
if (! strcmp (name, temp->name))
goto already1;
+
temp = (struct temp_file *) xmalloc (sizeof (struct temp_file));
temp->next = always_delete_queue;
temp->name = name;
always_delete_queue = temp;
+
already1:;
}
for (temp = failure_delete_queue; temp; temp = temp->next)
if (! strcmp (name, temp->name))
goto already2;
+
temp = (struct temp_file *) xmalloc (sizeof (struct temp_file));
temp->next = failure_delete_queue;
temp->name = name;
failure_delete_queue = temp;
+
already2:;
}
}
fflush (stdout);
i = getchar ();
if (i != '\n')
- while ((c = getchar ()) != '\n' && c != EOF) ;
+ while ((c = getchar ()) != '\n' && c != EOF)
+ ;
+
if (i == 'y' || i == 'Y')
#endif /* DEBUG */
if (stat (name, &st) >= 0 && S_ISREG (st.st_mode))
int len = strlen (pprefix->prefix);
if (machine_suffix
- && (!check_dir_p
+ && (! check_dir_p
|| is_directory (pprefix->prefix, machine_suffix, 0)))
{
if (!first_time)
if (just_machine_suffix
&& pprefix->require_machine_suffix == 2
- && (!check_dir_p
+ && (! check_dir_p
|| is_directory (pprefix->prefix, just_machine_suffix, 0)))
{
- if (!first_time)
+ if (! first_time)
obstack_1grow (&collect_obstack, PATH_SEPARATOR);
first_time = FALSE;
just_suffix_len);
}
- if (!pprefix->require_machine_suffix)
+ if (! pprefix->require_machine_suffix)
{
- if (!first_time)
+ if (! first_time)
obstack_1grow (&collect_obstack, PATH_SEPARATOR);
first_time = FALSE;
obstack_grow (&collect_obstack, pprefix->prefix, len);
}
}
+
obstack_1grow (&collect_obstack, '\0');
return obstack_finish (&collect_obstack);
}
/* Determine the filename to execute (special case for absolute paths). */
- if (*name == '/' || *name == DIR_SEPARATOR)
+ if (*name == '/' || *name == DIR_SEPARATOR
+ /* Check for disk name on MS-DOS-based systems. */
+ || (DIR_SEPARATOR == '\\' && name[1] == ':'
+ && (name[2] == DIR_SEPARATOR || name[2] == '/')))
{
if (access (name, mode))
{
/* Certain prefixes can't be used without the machine suffix
when the machine or version is explicitly specified. */
- if (!pl->require_machine_suffix)
+ if (! pl->require_machine_suffix)
{
/* Some systems have a suffix for executable files.
So try appending that first. */
through this prefix. WARN should point to an int
which will be set to 1 if this entry is used.
+ COMPONENT is the value to be passed to update_path.
+
REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without
the complete value of machine_suffix.
2 means try both machine_suffix and just_machine_suffix. */
static void
-add_prefix (pprefix, prefix, first, require_machine_suffix, warn)
+add_prefix (pprefix, prefix, component, first, require_machine_suffix, warn)
struct path_prefix *pprefix;
char *prefix;
+ char *component;
int first;
int require_machine_suffix;
int *warn;
struct prefix_list *pl, **prev;
int len;
- if (!first && pprefix->plist)
+ if (! first && pprefix->plist)
{
for (pl = pprefix->plist; pl->next; pl = pl->next)
;
/* Keep track of the longest prefix */
+ prefix = update_path (prefix, component);
len = strlen (prefix);
if (len > pprefix->max_len)
pprefix->max_len = len;
/* Prevent duplicate warnings. */
*pl->used_flag_ptr = 1;
}
- pl = pl->next;
- }
-}
-
-/* Get rid of all prefixes built up so far in *PLISTP. */
-
-static void
-free_path_prefix (pprefix)
- struct path_prefix *pprefix;
-{
- struct prefix_list *pl = pprefix->plist;
- struct prefix_list *temp;
- while (pl)
- {
- temp = pl;
pl = pl->next;
- free (temp->prefix);
- free ((char *) temp);
}
- pprefix->plist = (struct prefix_list *) 0;
}
+
\f
/* Execute the command specified by the arguments on the current line of spec.
When using pipes, this includes several piped-together commands
for (n_commands = 1, i = 0; i < argbuf_index; i++)
if (strcmp (argbuf[i], "|") == 0)
{ /* each command. */
-#if defined (__MSDOS__) || (defined (_WIN32) && ! defined (__CYGWIN32__)) || defined (OS2)
+#if defined (__MSDOS__) || (defined (_WIN32) && defined (__CYGWIN32_)) || defined (OS2) || defined (VMS)
fatal ("-pipe not supported");
#endif
argbuf[i] = 0; /* termination of command args. */
fflush (stderr);
i = getchar ();
if (i != '\n')
- while (getchar () != '\n') ;
+ while (getchar () != '\n')
+ ;
+
if (i != 'y' && i != 'Y')
return 0;
#endif /* DEBUG */
&& name[len - 2] == '.'
&& name[len - 1] == 'o')
{
- obstack_grow (&obstack, name[i], len - 2);
+ obstack_grow (&obstack, name, len - 2);
obstack_grow0 (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX));
name = obstack_finish (&obstack);
}
if (gcc_exec_prefix)
{
- add_prefix (&exec_prefixes, gcc_exec_prefix, 0, 0, NULL_PTR);
- add_prefix (&startfile_prefixes, gcc_exec_prefix, 0, 0, NULL_PTR);
+ 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
}
else
nstore[endp-startp] = 0;
- add_prefix (&exec_prefixes, nstore, 0, 0, NULL_PTR);
+ add_prefix (&exec_prefixes, nstore, 0, 0, 0, NULL_PTR);
+ add_prefix (&include_prefixes,
+ concat (nstore, "include", NULL_PTR),
+ 0, 0, 0, NULL_PTR);
if (*endp == 0)
break;
endp = startp = endp + 1;
}
temp = getenv ("LIBRARY_PATH");
- if (temp && ! cross_compile)
+ if (temp && *cross_compile == '0')
{
char *startp, *endp;
char *nstore = (char *) alloca (strlen (temp) + 3);
}
else
nstore[endp-startp] = 0;
- add_prefix (&startfile_prefixes, nstore, 0, 0, NULL_PTR);
+ add_prefix (&startfile_prefixes, nstore, NULL_PTR,
+ 0, 0, NULL_PTR);
if (*endp == 0)
break;
endp = startp = endp + 1;
/* Use LPATH like LIBRARY_PATH (for the CMU build program). */
temp = getenv ("LPATH");
- if (temp && ! cross_compile)
+ if (temp && *cross_compile == '0')
{
char *startp, *endp;
char *nstore = (char *) alloca (strlen (temp) + 3);
}
else
nstore[endp-startp] = 0;
- add_prefix (&startfile_prefixes, nstore, 0, 0, NULL_PTR);
+ add_prefix (&startfile_prefixes, nstore, NULL_PTR,
+ 0, 0, NULL_PTR);
if (*endp == 0)
break;
endp = startp = endp + 1;
#ifdef LANG_SPECIFIC_DRIVER
/* Do language-specific adjustment/addition of flags. */
- lang_specific_driver (&fatal, &argc, &argv);
+ lang_specific_driver (fatal, &argc, &argv);
#endif
/* Scan argv twice. Here, the first time, just count how many switches
{
if (! strcmp (argv[i], "-dumpspecs"))
{
- printf ("*asm:\n%s\n\n", asm_spec);
- printf ("*asm_final:\n%s\n\n", asm_final_spec);
- printf ("*cpp:\n%s\n\n", cpp_spec);
- printf ("*cc1:\n%s\n\n", cc1_spec);
- printf ("*cc1plus:\n%s\n\n", cc1plus_spec);
- printf ("*endfile:\n%s\n\n", endfile_spec);
- printf ("*link:\n%s\n\n", link_spec);
- printf ("*lib:\n%s\n\n", lib_spec);
- printf ("*libgcc:\n%s\n\n", libgcc_spec);
- printf ("*startfile:\n%s\n\n", startfile_spec);
- printf ("*switches_need_spaces:\n%s\n\n", switches_need_spaces);
- printf ("*signed_char:\n%s\n\n", signed_char_spec);
- printf ("*predefines:\n%s\n\n", cpp_predefines);
- printf ("*cross_compile:\n%d\n\n", cross_compile);
- printf ("*version:\n%s\n\n", compiler_version);
- printf ("*multilib:\n%s\n\n", multilib_select);
- printf ("*multilib_defaults:\n%s\n\n", multilib_defaults);
- printf ("*multilib_extra:\n%s\n\n", multilib_extra);
- printf ("*multilib_matches:\n%s\n\n", multilib_matches);
-
-#ifdef EXTRA_SPECS
- {
- int j;
- for (j = 0; j < sizeof (extra_specs) / sizeof (extra_specs[0]); j++)
- printf ("*%s:\n%s\n\n", extra_specs[j].name,
- (extra_specs[j].spec) ? extra_specs[j].spec : "");
- }
-#endif
+ struct spec_list *sl;
+ init_spec ();
+ for (sl = specs; sl; sl = sl->next)
+ printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec));
exit (0);
}
else if (! strcmp (argv[i], "-dumpversion"))
switch (c)
{
case 'b':
+ n_switches++;
if (p[1] == 0 && i + 1 == argc)
fatal ("argument to `-b' is missing");
if (p[1] == 0)
case 'B':
{
- int *temp = (int *) xmalloc (sizeof (int));
char *value;
if (p[1] == 0 && i + 1 == argc)
fatal ("argument to `-B' is missing");
value = argv[++i];
else
value = p + 1;
- add_prefix (&exec_prefixes, value, 1, 0, &warn_B);
- add_prefix (&startfile_prefixes, value, 1, 0, &warn_B);
- add_prefix (&include_prefixes, concat (value, "include", NULL_PTR),
- 1, 0, NULL_PTR);
+ add_prefix (&exec_prefixes, value, NULL_PTR, 1, 0, &warn_B);
+ add_prefix (&startfile_prefixes, value, NULL_PTR,
+ 1, 0, &warn_B);
+ add_prefix (&include_prefixes, concat (value, "include",
+ NULL_PTR),
+ NULL_PTR, 1, 0, NULL_PTR);
/* As a kludge, if the arg is "[foo/]stageN/", just add
"[foo/]include" to the include prefix. */
&& (value[len - 8] == '/'
|| value[len - 8] == DIR_SEPARATOR)))
&& strncmp (value + len - 7, "stage", 5) == 0
- && isdigit (value[len - 2])
+ && ISDIGIT (value[len - 2])
&& (value[len - 1] == '/'
|| value[len - 1] == DIR_SEPARATOR))
{
if (len == 7)
- add_prefix (&include_prefixes, "include",
+ add_prefix (&include_prefixes, "include", NULL_PTR,
1, 0, NULL_PTR);
else
{
char *string = xmalloc (len + 1);
strncpy (string, value, len-7);
- strcat (string, "include");
- add_prefix (&include_prefixes, string,
+ strcpy (string+len-7, "include");
+ add_prefix (&include_prefixes, string, NULL_PTR,
1, 0, NULL_PTR);
}
}
}
+ n_switches++;
}
break;
break;
case 'V':
+ n_switches++;
if (p[1] == 0 && i + 1 == argc)
fatal ("argument to `-V' is missing");
if (p[1] == 0)
/* Use 2 as fourth arg meaning try just the machine as a suffix,
as well as trying the machine and the version. */
#ifndef OS2
- add_prefix (&exec_prefixes, standard_exec_prefix, 0, 2, warn_std_ptr);
- add_prefix (&exec_prefixes, standard_exec_prefix_1, 0, 2, warn_std_ptr);
+ add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS",
+ 0, 2, warn_std_ptr);
+ add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS",
+ 0, 2, warn_std_ptr);
#endif
- add_prefix (&startfile_prefixes, standard_exec_prefix, 0, 1, warn_std_ptr);
- add_prefix (&startfile_prefixes, standard_exec_prefix_1, 0, 1, warn_std_ptr);
+ add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS",
+ 0, 1, warn_std_ptr);
+ add_prefix (&startfile_prefixes, standard_exec_prefix_1, "BINUTILS",
+ 0, 1, warn_std_ptr);
tooldir_prefix = concat (tooldir_base_prefix, spec_machine,
dir_separator_str, NULL_PTR);
add_prefix (&exec_prefixes,
concat (gcc_exec_tooldir_prefix, "bin",
dir_separator_str, NULL_PTR),
- 0, 0, NULL_PTR);
+ NULL_PTR, 0, 0, NULL_PTR);
add_prefix (&startfile_prefixes,
concat (gcc_exec_tooldir_prefix, "lib",
dir_separator_str, NULL_PTR),
- 0, 0, NULL_PTR);
+ NULL_PTR, 0, 0, NULL_PTR);
}
tooldir_prefix = concat (standard_exec_prefix, spec_machine,
add_prefix (&exec_prefixes,
concat (tooldir_prefix, "bin", dir_separator_str, NULL_PTR),
- 0, 0, NULL_PTR);
+ "BINUTILS", 0, 0, NULL_PTR);
add_prefix (&startfile_prefixes,
concat (tooldir_prefix, "lib", dir_separator_str, NULL_PTR),
- 0, 0, NULL_PTR);
+ "BINUTILS", 0, 0, NULL_PTR);
/* More prefixes are enabled in main, after we read the specs file
and determine whether this is cross-compilation or not. */
i++;
else if (strncmp (argv[i], "-specs=", 7) == 0)
;
+ /* -save-temps overrides -pipe, so that temp files are produced */
+ else if (save_temps_flag && strcmp (argv[i], "-pipe") == 0)
+ error ("Warning: -pipe ignored since -save-temps specified");
else if (argv[i][0] == '-' && argv[i][1] != 0)
{
register char *p = &argv[i][1];
register int c = *p;
- if (c == 'B' || c == 'b' || c == 'V')
- {
- /* Skip a separate arg, if any. */
- if (p[1] == 0)
- i++;
- continue;
- }
if (c == 'x')
{
if (p[1] == 0 && i + 1 == argc)
/* This is always valid, since gcc.c itself understands it. */
if (!strcmp (p, "save-temps"))
switches[n_switches].valid = 1;
+ else
+ {
+ char ch = switches[n_switches].part1[0];
+ if (ch == 'V' || ch == 'b' || ch == 'B')
+ switches[n_switches].valid = 1;
+ }
n_switches++;
}
else
char *string;
int value;
- while (c = *p++)
+ while ((c = *p++))
/* If substituting a switch, treat all chars like letters.
Otherwise, NL, SPC, TAB and % are special. */
switch (inswitch ? 'a' : c)
In 2.4, do something about that. */
struct temp_name *t;
char *suffix = p;
- while (*p == '.' || isalpha (*p)
+ while (*p == '.' || ISALPHA (*p)
|| (p[0] == '%' && p[1] == 'O'))
p++;
*x++ = *y++;
if (*y != '_'
- || (*(y+1) != '_' && ! isupper (*(y+1))))
+ || (*(y+1) != '_' && ! ISUPPER (*(y+1))))
{
/* Stick __ at front of macro name. */
*x++ = '_';
y += 2;
if (*y != '_'
- || (*(y+1) != '_' && ! isupper (*(y+1))))
+ || (*(y+1) != '_' && ! ISUPPER (*(y+1))))
{
/* Stick -D__ at front of macro name. */
*x++ = '-';
/* See if it's in the list */
for (len = p - name, sl = specs; sl; sl = sl->next)
- if (strncmp (sl->name, name, len) == 0 && !sl->name[len])
+ if (sl->name_len == len && !strncmp (sl->name, name, len))
{
- name = sl->spec;
+ name = *(sl->ptr_spec);
+#ifdef DEBUG_SPECS
+ fprintf (stderr, "Processing spec %c%s%c, which is '%s'\n",
+ c, sl->name, (c == '(') ? ')' : ']', name);
+#endif
break;
}
([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)? */
/* Ignore leading non-digits. i.e. "foo-" in "foo-2.7.2". */
- while (! isdigit (*v))
+ while (! ISDIGIT (*v))
v++;
if (v > compiler_version && v[-1] != '-')
abort ();
if (c1 == '2')
{
/* Set V after the first period. */
- while (isdigit (*v))
+ while (ISDIGIT (*v))
v++;
if (*v != '.')
abort ();
/* Set Q at the next period or at the end. */
q = v;
- while (isdigit (*q))
+ while (ISDIGIT (*q))
q++;
if (*q != 0 && *q != ' ' && *q != '.' && *q != '-')
abort ();
int pipe_p = 0;
int negate = 0;
int suffix = 0;
+ int include_blanks = 1;
+
+ if (*p == '^')
+ /* A '^' after the open-brace means to not give blanks before args. */
+ include_blanks = 0, ++p;
if (*p == '|')
/* A `|' after the open-brace means,
for (i = 0; i < n_switches; i++)
if (!strncmp (switches[i].part1, filter, p - filter)
&& check_live_switch (i, p - filter))
- give_switch (i, 0);
+ give_switch (i, 0, include_blanks);
}
else
{
{
do_spec_1 (string, 0, &switches[i].part1[hard_match_len]);
/* Pass any arguments this switch has. */
- give_switch (i, 1);
+ give_switch (i, 1, 1);
}
return q;
{
if (*p == '}')
{
- give_switch (i, 0);
+ give_switch (i, 0, include_blanks);
}
else
{
the vector of switches gcc received, which is `switches'.
This cannot fail since it never finishes a command line.
- If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument. */
+ If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument.
+
+ If INCLUDE_BLANKS is nonzero, then we include blanks before each argument
+ of the switch. */
static void
-give_switch (switchnum, omit_first_word)
+give_switch (switchnum, omit_first_word, include_blanks)
int switchnum;
int omit_first_word;
+ int include_blanks;
{
if (!omit_first_word)
{
do_spec_1 ("-", 0, NULL_PTR);
do_spec_1 (switches[switchnum].part1, 1, NULL_PTR);
}
- do_spec_1 (" ", 0, NULL_PTR);
+
if (switches[switchnum].args != 0)
{
char **p;
for (p = switches[switchnum].args; *p; p++)
{
+ if (include_blanks)
+ do_spec_1 (" ", 0, NULL_PTR);
do_spec_1 (*p, 1, NULL_PTR);
- do_spec_1 (" ", 0, NULL_PTR);
}
}
+
+ do_spec_1 (" ", 0, NULL_PTR);
switches[switchnum].valid = 1;
}
\f
process_command (argc, argv);
+ {
+ int i;
+ int first_time;
+
+ /* Build COLLECT_GCC_OPTIONS to have all of the options specified to
+ the compiler. */
+ obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
+ sizeof ("COLLECT_GCC_OPTIONS=")-1);
+
+ first_time = TRUE;
+ for (i = 0; i < n_switches; i++)
+ {
+ char **args;
+ char *p, *q;
+ if (!first_time)
+ obstack_grow (&collect_obstack, " ", 1);
+
+ first_time = FALSE;
+ obstack_grow (&collect_obstack, "'-", 2);
+ q = switches[i].part1;
+ while ((p = (char *) index (q,'\'')))
+ {
+ obstack_grow (&collect_obstack, q, p-q);
+ obstack_grow (&collect_obstack, "'\\''", 4);
+ q = ++p;
+ }
+ obstack_grow (&collect_obstack, q, strlen (q));
+ obstack_grow (&collect_obstack, "'", 1);
+
+ for (args = switches[i].args; args && *args; args++)
+ {
+ obstack_grow (&collect_obstack, " '", 2);
+ q = *args;
+ while ((p = (char *) index (q,'\'')))
+ {
+ obstack_grow (&collect_obstack, q, p-q);
+ obstack_grow (&collect_obstack, "'\\''", 4);
+ q = ++p;
+ }
+ obstack_grow (&collect_obstack, q, strlen (q));
+ obstack_grow (&collect_obstack, "'", 1);
+ }
+ }
+ obstack_grow (&collect_obstack, "\0", 1);
+ putenv (obstack_finish (&collect_obstack));
+ }
+
/* Initialize the vector of specs to just the default.
This means one element containing 0s, as a terminator. */
specs_file = find_a_file (&startfile_prefixes, "specs", R_OK);
/* Read the specs file unless it is a default one. */
if (specs_file != 0 && strcmp (specs_file, "specs"))
- read_specs (specs_file);
-
-#ifdef EXTRA_SPECS
+ read_specs (specs_file, TRUE);
else
- {
- int k;
- for (k = 0; k < sizeof (extra_specs) / sizeof (extra_specs[0]); k++)
- set_spec (extra_specs[k].name, extra_specs[k].spec);
- }
-#endif
-
+ init_spec ();
+
+ /* We need to check standard_exec_prefix/just_machine_suffix/specs
+ for any override of as, ld and libraries. */
+ specs_file = (char *) alloca (strlen (standard_exec_prefix)
+ + strlen (just_machine_suffix)
+ + sizeof ("specs"));
+
+ strcpy (specs_file, standard_exec_prefix);
+ strcat (specs_file, just_machine_suffix);
+ strcat (specs_file, "specs");
+ if (access (specs_file, R_OK) == 0)
+ read_specs (specs_file, TRUE);
+
/* Process any user specified specs in the order given on the command
line. */
for (uptr = user_specs_head; uptr; uptr = uptr->next)
{
char *filename = find_a_file (&startfile_prefixes, uptr->filename, R_OK);
- read_specs (filename ? filename : uptr->filename);
+ read_specs (filename ? filename : uptr->filename, FALSE);
}
/* If not cross-compiling, look for startfiles in the standard places. */
/* The fact that these are done here, after reading the specs file,
means that it cannot be found in these directories.
But that's okay. It should never be there anyway. */
- if (!cross_compile)
+ if (*cross_compile == '0')
{
#ifdef MD_EXEC_PREFIX
- add_prefix (&exec_prefixes, md_exec_prefix, 0, 0, NULL_PTR);
- add_prefix (&startfile_prefixes, md_exec_prefix, 0, 0, NULL_PTR);
+ add_prefix (&exec_prefixes, md_exec_prefix, "GCC", 0, 0, NULL_PTR);
+ add_prefix (&startfile_prefixes, md_exec_prefix, "GCC", 0, 0, NULL_PTR);
#endif
#ifdef MD_STARTFILE_PREFIX
- add_prefix (&startfile_prefixes, md_startfile_prefix, 0, 0, NULL_PTR);
+ add_prefix (&startfile_prefixes, md_startfile_prefix, "GCC",
+ 0, 0, NULL_PTR);
#endif
#ifdef MD_STARTFILE_PREFIX_1
- add_prefix (&startfile_prefixes, md_startfile_prefix_1, 0, 0, NULL_PTR);
+ add_prefix (&startfile_prefixes, md_startfile_prefix_1, "GCC",
+ 0, 0, NULL_PTR);
#endif
/* If standard_startfile_prefix is relative, base it on
standard_startfile_prefix on that as well. */
if (*standard_startfile_prefix == '/'
|| *standard_startfile_prefix == DIR_SEPARATOR)
- add_prefix (&startfile_prefixes, standard_startfile_prefix, 0, 0,
- NULL_PTR);
+ add_prefix (&startfile_prefixes, standard_startfile_prefix, "BINUTILS",
+ 0, 0, NULL_PTR);
else
{
if (gcc_exec_prefix)
add_prefix (&startfile_prefixes,
concat (gcc_exec_prefix, machine_suffix,
standard_startfile_prefix, NULL_PTR),
- 0, 0, NULL_PTR);
+ NULL_PTR, 0, 0, NULL_PTR);
add_prefix (&startfile_prefixes,
concat (standard_exec_prefix,
machine_suffix,
standard_startfile_prefix, NULL_PTR),
- 0, 0, NULL_PTR);
+ NULL_PTR, 0, 0, NULL_PTR);
}
- add_prefix (&startfile_prefixes, standard_startfile_prefix_1, 0, 0,
- NULL_PTR);
- add_prefix (&startfile_prefixes, standard_startfile_prefix_2, 0, 0,
- NULL_PTR);
+ add_prefix (&startfile_prefixes, standard_startfile_prefix_1,
+ "BINUTILS", 0, 0, NULL_PTR);
+ add_prefix (&startfile_prefixes, standard_startfile_prefix_2,
+ "BINUTILS", 0, 0, NULL_PTR);
#if 0 /* Can cause surprises, and one can use -B./ instead. */
- add_prefix (&startfile_prefixes, "./", 0, 1, NULL_PTR);
+ add_prefix (&startfile_prefixes, "./", NULL_PTR, 0, 1, NULL_PTR);
#endif
}
else
add_prefix (&startfile_prefixes,
concat (gcc_exec_prefix, machine_suffix,
standard_startfile_prefix, NULL_PTR),
- 0, 0, NULL_PTR);
+ "BINUTILS", 0, 0, NULL_PTR);
}
/* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake. */
if (verbose_flag)
{
- if (! strcmp (version_string, compiler_version))
+ int n;
+
+ /* compiler_version is truncated at the first space when initialized
+ from version string, so truncate version_string at the first space
+ before comparing. */
+ for (n = 0; version_string[n]; n++)
+ if (version_string[n] == ' ')
+ break;
+
+ if (! strncmp (version_string, compiler_version, n)
+ && compiler_version[n] == 0)
fprintf (stderr, "gcc version %s\n", version_string);
else
fprintf (stderr, "gcc driver version %s executing gcc version %s\n",
if (error_count == 0)
{
int tmp = execution_count;
- int i;
- int first_time;
/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
for collect. */
putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH=");
putenv_from_prefixes (&startfile_prefixes, "LIBRARY_PATH=");
- /* Build COLLECT_GCC_OPTIONS to have all of the options specified to
- the compiler. */
- obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
- sizeof ("COLLECT_GCC_OPTIONS=")-1);
-
- first_time = TRUE;
- for (i = 0; i < n_switches; i++)
- {
- char **args;
- if (!first_time)
- obstack_grow (&collect_obstack, " ", 1);
-
- first_time = FALSE;
- obstack_grow (&collect_obstack, "-", 1);
- obstack_grow (&collect_obstack, switches[i].part1,
- strlen (switches[i].part1));
-
- for (args = switches[i].args; args && *args; args++)
- {
- obstack_grow (&collect_obstack, " ", 1);
- obstack_grow (&collect_obstack, *args, strlen (*args));
- }
- }
- obstack_grow (&collect_obstack, "\0", 1);
- putenv (obstack_finish (&collect_obstack));
-
value = do_spec (link_command_spec);
if (value < 0)
error_count = 1;
for (i = 0; i < sizeof comp->spec / sizeof comp->spec[0] && comp->spec[i]; i++)
{
p = comp->spec[i];
- while (c = *p++)
+ while ((c = *p++))
if (c == '%' && *p == '{')
/* We have a switch spec. */
validate_switches (p + 1);
}
}
- /* look through the linked list of extra specs read from the specs file */
+ /* look through the linked list of specs read from the specs file */
for (spec = specs; spec ; spec = spec->next)
{
- p = spec->spec;
- while (c = *p++)
+ p = *(spec->ptr_spec);
+ while ((c = *p++))
if (c == '%' && *p == '{')
/* We have a switch spec. */
validate_switches (p + 1);
}
p = link_command_spec;
- while (c = *p++)
- if (c == '%' && *p == '{')
- /* We have a switch spec. */
- validate_switches (p + 1);
-
- /* Now notice switches mentioned in the machine-specific specs. */
-
- p = asm_spec;
- while (c = *p++)
- if (c == '%' && *p == '{')
- /* We have a switch spec. */
- validate_switches (p + 1);
-
- p = asm_final_spec;
- while (c = *p++)
- if (c == '%' && *p == '{')
- /* We have a switch spec. */
- validate_switches (p + 1);
-
- p = cpp_spec;
- while (c = *p++)
- if (c == '%' && *p == '{')
- /* We have a switch spec. */
- validate_switches (p + 1);
-
- p = signed_char_spec;
- while (c = *p++)
- if (c == '%' && *p == '{')
- /* We have a switch spec. */
- validate_switches (p + 1);
-
- p = cc1_spec;
- while (c = *p++)
- if (c == '%' && *p == '{')
- /* We have a switch spec. */
- validate_switches (p + 1);
-
- p = cc1plus_spec;
- while (c = *p++)
- if (c == '%' && *p == '{')
- /* We have a switch spec. */
- validate_switches (p + 1);
-
- p = link_spec;
- while (c = *p++)
- if (c == '%' && *p == '{')
- /* We have a switch spec. */
- validate_switches (p + 1);
-
- p = lib_spec;
- while (c = *p++)
- if (c == '%' && *p == '{')
- /* We have a switch spec. */
- validate_switches (p + 1);
-
- p = libgcc_spec;
- while (c = *p++)
+ while ((c = *p++))
if (c == '%' && *p == '{')
/* We have a switch spec. */
validate_switches (p + 1);
-
- p = startfile_spec;
- while (c = *p++)
- if (c == '%' && *p == '{')
- /* We have a switch spec. */
- validate_switches (p + 1);
-
-#ifdef EXTRA_SPECS
- {
- int i;
- for (i = 0; i < sizeof (extra_specs) / sizeof (extra_specs[0]); i++)
- {
- p = extra_specs[i].spec;
- while (c = *p++)
- if (c == '%' && *p == '{')
- /* We have a switch spec. */
- validate_switches (p + 1);
- }
- }
-#endif
-
}
/* Look at the switch-name that comes after START
}
\f
/* Check whether a particular argument was used. The first time we
- canonialize the switches to keep only the ones we care about. */
+ canonicalize the switches to keep only the ones we care about. */
static int
used_arg (p, len)
int len;
{
char *start, *end;
- int i;
for (start = multilib_defaults; *start != '\0'; start = end+1)
{