/* Compiler driver program that can handle many languages.
- Copyright (C) 1987, 89, 92-99, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
-#ifdef NEED_DECLARATION_GETRUSAGE
+#if defined (HAVE_DECL_GETRUSAGE) && !HAVE_DECL_GETRUSAGE
extern int getrusage PARAMS ((int, struct rusage *));
#endif
/* The compiler version. */
-static char *compiler_version;
+static const char *compiler_version;
/* The target version specified with -V */
-static char *spec_version = DEFAULT_TARGET_VERSION;
+static const char *spec_version = DEFAULT_TARGET_VERSION;
/* The target machine specified with -b. */
When -b is used, the value comes from the `specs' file. */
#ifdef CROSS_COMPILE
-static char *cross_compile = "1";
+static const char *cross_compile = "1";
#else
-static char *cross_compile = "0";
+static const char *cross_compile = "0";
#endif
/* The number of errors that have occurred; the link phase will not be
static void free_split_directories PARAMS ((char **));
static char *make_relative_prefix PARAMS ((const char *, const char *, const char *));
#endif /* VMS */
+static void store_arg PARAMS ((const char *, int, int));
+static char *load_specs PARAMS ((const char *));
static void read_specs PARAMS ((const char *, int));
static void set_spec PARAMS ((const char *, const char *));
static struct compiler *lookup_compiler PARAMS ((const char *, size_t, const char *));
static char *find_a_file PARAMS ((struct path_prefix *, const char *, int));
static void add_prefix PARAMS ((struct path_prefix *, const char *,
const char *, int, int, int *));
+static void translate_options PARAMS ((int *, const char ***));
static char *skip_whitespace PARAMS ((char *));
static void record_temp_file PARAMS ((const char *, int, int));
static void delete_if_ordinary PARAMS ((const char *));
static void add_preprocessor_option PARAMS ((const char *, int));
static void add_assembler_option PARAMS ((const char *, int));
static void add_linker_option PARAMS ((const char *, int));
-static void process_command PARAMS ((int, char **));
+static void process_command PARAMS ((int, const char **));
static int execute PARAMS ((void));
static void unused_prefix_warnings PARAMS ((struct path_prefix *));
static void clear_args PARAMS ((void));
%b substitute the basename of the input file being processed.
This is the substring up to (and not including) the last period
and not including the directory.
+ %B same as %b, but include the file suffix (text after the last period).
%gSUFFIX
substitute a file name that has suffix SUFFIX and is chosen
once per compilation, and mark the argument a la %d. To reduce
specified to CC. Note that the tail part of the -S option
(i.e. the part matched by the `*') will be substituted for each
occurrence of %* within X.
+ %{<S} remove all occurences of S from the command line.
+ Note - this option is position dependent. % commands in the
+ spec string before this option will see S, % commands in the
+ spec string after this option will not.
%{S:X} substitutes X, but only if the -S switch was given to CC.
%{!S:X} substitutes X, but only if the -S switch was NOT given to CC.
%{|S:X} like %{S:X}, but if no S switch, substitute `-'.
#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 *cc1plus_spec = CC1PLUS_SPEC;
-static char *signed_char_spec = SIGNED_CHAR_SPEC;
-static char *asm_spec = ASM_SPEC;
-static char *asm_final_spec = ASM_FINAL_SPEC;
-static char *link_spec = LINK_SPEC;
-static char *lib_spec = LIB_SPEC;
-static char *libgcc_spec = LIBGCC_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;
+/* Here is the spec for running the linker, after compiling all files. */
+
+/* -u* was put back because both BSD and SysV seem to support it. */
+/* %{static:} simply prevents an error message if the target machine
+ doesn't handle -static. */
+/* We want %{T*} after %{L*} and %D so that it can be used to specify linker
+ scripts which exist in user specified directories, or in standard
+ directories. */
+#ifndef LINK_COMMAND_SPEC
+#define LINK_COMMAND_SPEC "\
+%{!fsyntax-only:%{!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*} %(link_libgcc) %o %{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
+ %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
+#endif
+
+#ifndef LINK_LIBGCC_SPEC
+# ifdef LINK_LIBGCC_SPECIAL
+/* Don't generate -L options for startfile prefix list. */
+# define LINK_LIBGCC_SPEC ""
+# else
+/* Do generate them. */
+# define LINK_LIBGCC_SPEC "%D"
+# endif
+#endif
+
+static const char *cpp_spec = CPP_SPEC;
+static const char *cpp_predefines = CPP_PREDEFINES;
+static const char *cc1_spec = CC1_SPEC;
+static const char *cc1plus_spec = CC1PLUS_SPEC;
+static const char *signed_char_spec = SIGNED_CHAR_SPEC;
+static const char *asm_spec = ASM_SPEC;
+static const char *asm_final_spec = ASM_FINAL_SPEC;
+static const char *link_spec = LINK_SPEC;
+static const char *lib_spec = LIB_SPEC;
+static const char *libgcc_spec = LIBGCC_SPEC;
+static const char *endfile_spec = ENDFILE_SPEC;
+static const char *startfile_spec = STARTFILE_SPEC;
+static const char *switches_need_spaces = SWITCHES_NEED_SPACES;
+static const char *linker_name_spec = LINKER_NAME;
+static const char *link_command_spec = LINK_COMMAND_SPEC;
+static const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
+
+/* Standard options to cpp, cc1, and as, to reduce duplication in specs.
+ There should be no need to override these in target dependent files,
+ but we need to copy them to the specs file so that newer versions
+ of the GCC driver can correctly drive older tool chains with the
+ appropriate -B options. */
+
+static const char *trad_capable_cpp =
+"%{traditional|ftraditional|traditional-cpp:trad}cpp";
+
+static const char *cpp_options =
+"%{C:%{!E:%eGNU C does not support -C without using -E}}\
+ %{std*} %{nostdinc*}\
+ %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
+ %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
+ %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
+ %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{ffast-math:-D__FAST_MATH__}\
+ %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
+ %{fshow-column} %{fno-show-column}\
+ %{fleading-underscore} %{fno-leading-underscore}\
+ %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z %i\
+ %{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}}";
+
+static const char *cc1_options =
+"%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
+ %1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\
+ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*} %{ansi}\
+ %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
+ %{aux-info*} %{Qn:-fno-ident} %{--help:--help}\
+ %{S:%W{o*}%{!o*:-o %b.s}}";
+
+static const char *asm_options =
+"%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
/* 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
run time. */
static struct obstack multilib_obstack;
-static char *multilib_select;
-static char *multilib_matches;
-static char *multilib_defaults;
+static const char *multilib_select;
+static const char *multilib_matches;
+static const char *multilib_defaults;
+static const char *multilib_exclusions;
#include "multilib.h"
/* Check whether a particular argument is a default argument. */
static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
-struct user_specs {
+struct user_specs
+{
struct user_specs *next;
const char *filename;
};
const char *suffix; /* Use this compiler for input files
whose names end in this suffix. */
- const char *spec[4]; /* To use this compiler, concatenate these
- specs and pass to do_spec. */
+ const char *spec; /* To use this compiler, run this spec. */
};
/* Pointer to a vector of `struct compiler' that gives the spec for
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". */
- {".m", {"#Objective-C"}},
- {".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"}},
+ {".m", "#Objective-C"},
+ {".cc", "#C++"}, {".cxx", "#C++"}, {".cpp", "#C++"},
+ {".c++", "#C++"}, {".C", "#C++"},
+ {".ads", "#Ada"}, {".adb", "#Ada"}, {".ada", "#Ada"},
+ {".f", "#Fortran"}, {".for", "#Fortran"}, {".F", "#Fortran"},
+ {".fpp", "#Fortran"}, {".r", "#Ratfor"},
+ {".p", "#Pascal"}, {".pas", "#Pascal"},
+ {".ch", "#Chill"}, {".chi", "#Chill"},
+ {".java", "#Java"}, {".class", "#Java"},
+ {".zip", "#Java"}, {".jar", "#Java"},
/* Next come the entries for C. */
- {".c", {"@c"}},
+ {".c", "@c"},
{"@c",
- {
#if USE_CPPLIB
- "%{E|M|MM:cpp -lang-c %{ansi:-std=c89} %{std*} %{nostdinc*}\
- %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
- %{C:%{!E:%eGNU C does not support -C without using -E}}\
- %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
- %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
- %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
- %{ffast-math:-D__FAST_MATH__}\
- %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{traditional} %{ftraditional:-traditional}\
- %{traditional-cpp:-traditional}\
- %{fleading-underscore} %{fno-leading-underscore}\
- %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
- %i %{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}}\n}\
- %{!E:%{!M:%{!MM:cc1 %i %1 \
- %{std*} %{nostdinc*} %{A*} %{I*} %I\
- %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
- %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
- %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
- %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
- %{ffast-math:-D__FAST_MATH__}\
- %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{H} %C %{D*} %{U*} %{i*} %Z\
- %{ftraditional:-traditional}\
- %{traditional-cpp:-traditional}\
- %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
- %{aux-info*} %{Qn:-fno-ident}\
- %{--help:--help}\
- %{g*} %{O*} %{W*} %{w} %{pedantic*}\
- %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
- %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
- %{!S:as %a %Y\
- %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
- %{!pipe:%g.s} %A\n }}}}"
+ "%{E|M|MM:cpp -lang-c %{ansi:-std=c89} %(cpp_options)}\
+ %{!E:%{!M:%{!MM:cc1 -lang-c %{ansi:-std=c89} %(cpp_options)\
+ %(cc1_options) %{!S:-o %{|!pipe:%g.s} |\n\
+ as %(asm_options) %{!pipe:%g.s} %A }}}}"
#else /* ! USE_CPPLIB */
- "cpp -lang-c %{ansi:-std=c89} %{std*} %{nostdinc*}\
- %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
- %{C:%{!E:%eGNU C does not support -C without using -E}}\
- %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
- %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
- %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
- %{ffast-math:-D__FAST_MATH__}\
- %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{traditional} %{ftraditional:-traditional}\
- %{traditional-cpp:-traditional}\
- %{fleading-underscore} %{fno-leading-underscore}\
- %{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",
- "%{!M:%{!MM:%{!E:cc1 %{!pipe:%g.i} %1 \
- %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
- %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*}\
- %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
- %{aux-info*} %{Qn:-fno-ident}\
- %{--help:--help} \
- %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
- %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
- %{!S:as %a %Y\
- %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
- %{!pipe:%g.s} %A\n }}}}"
+ "%(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options) \
+ %{!M:%{!MM:%{!E:%{!pipe:%g.i} |\n\
+ cc1 %{!pipe:%g.i} %(cc1_options) %{!S:-o %{|!pipe:%g.s} |\n\
+ as %(asm_options) %{!pipe:%g.s} %A }}}}\n"
#endif /* ! USE_CPPLIB */
- }},
+ },
{"-",
- {"%{E:cpp -lang-c %{ansi:-std=c89} %{std*} %{nostdinc*}\
- %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
- %{C:%{!E:%eGNU C does not support -C without using -E}}\
- %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
- %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
- %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
- %{ffast-math:-D__FAST_MATH__}\
- %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{traditional} %{ftraditional:-traditional}\
- %{traditional-cpp:-traditional}\
- %{fleading-underscore} %{fno-leading-underscore}\
- %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
- %i %W{o*}}\
- %{!E:%e-E required when input is from standard input}"}},
- {".h", {"@c-header"}},
+ "%{!E:%e-E required when input is from standard input}\
+ %(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options)"},
+ {".h", "@c-header"},
{"@c-header",
- {"%{!E:%eCompilation of header file requested} \
- cpp %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
- %{C:%{!E:%eGNU C does not support -C without using -E}}\
- %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
- %{!undef:%{!std=*:%p}%{std=gnu*:%p} %P} %{trigraphs}\
- %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
- %{ffast-math:-D__FAST_MATH__}\
- %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{traditional} %{ftraditional:-traditional}\
- %{traditional-cpp:-traditional}\
- %{fleading-underscore} %{fno-leading-underscore}\
- %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
- %i %W{o*}"}},
- {".i", {"@cpp-output"}},
+ "%{!E:%eCompilation of header file requested} \
+ %(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options)"},
+ {".i", "@cpp-output"},
{"@cpp-output",
- {"%{!M:%{!MM:%{!E:cc1 %i %1 %{!Q:-quiet} %{d*} %{m*} %{a*}\
- %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*}\
- %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
- %{aux-info*} %{Qn:-fno-ident} -fpreprocessed\
- %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
- %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
- %{!S:as %a %Y\
- %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
- %{!pipe:%g.s} %A\n }}}}"}},
- {".s", {"@assembler"}},
+ "%{!M:%{!MM:%{!E:\
+ cc1 %i %(cc1_options) %{!S:|\n\
+ as %(asm_options) %{!pipe:%g.s} %A }}}}"},
+ {".s", "@assembler"},
{"@assembler",
- {"%{!M:%{!MM:%{!E:%{!S:as %a %Y\
- %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
- %i %A\n }}}}"}},
- {".S", {"@assembler-with-cpp"}},
+ "%{!M:%{!MM:%{!E:%{!S:as %(asm_options) %i %A }}}}"},
+ {".S", "@assembler-with-cpp"},
{"@assembler-with-cpp",
- {"cpp -lang-asm %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
- %{C:%{!E:%eGNU C does not support -C without using -E}}\
- %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG} %{trigraphs}\
- -$ %{!undef:%p %P} -D__ASSEMBLER__ \
- %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
- %{ffast-math:-D__FAST_MATH__}\
- %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{traditional} %{ftraditional:-traditional}\
- %{traditional-cpp:-traditional}\
- %{fleading-underscore} %{fno-leading-underscore}\
- %{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",
- "%{!M:%{!MM:%{!E:%{!S:as %a %Y\
- %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
- %{!pipe:%g.s} %A\n }}}}"}},
+ "%(trad_capable_cpp) -lang-asm %(cpp_options) \
+ %{!M:%{!MM:%{!E:%{!S: %{!pipe:%g.s} |\n\
+ as %(asm_options) %{!pipe:%g.s} %A }}}}"},
#include "specs.h"
/* Mark end of table */
- {0, {0}}
+ {0, 0}
};
/* Number of elements in default_compilers, not counting the terminator. */
static int n_default_compilers
= (sizeof default_compilers / sizeof (struct compiler)) - 1;
-/* Here is the spec for running the linker, after compiling all files. */
-
-/* -u* was put back because both BSD and SysV seem to support it. */
-/* %{static:} simply prevents an error message if the target machine
- doesn't handle -static. */
-/* We want %{T*} after %{L*} and %D so that it can be used to specify linker
- scripts which exist in user specified directories, or in standard
- directories. */
-#ifdef LINK_COMMAND_SPEC
-/* Provide option to override link_command_spec from machine specific
- configuration files. */
-static const char *link_command_spec =
- LINK_COMMAND_SPEC;
-#else
-#ifdef LINK_LIBGCC_SPECIAL
-/* Don't generate -L options. */
-static const char *link_command_spec = "\
-%{!fsyntax-only: \
- %{!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\
- %{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
- %{!A:%{!nostdlib:%{!nostartfiles:%E}}}\
- %{T*}\
- \n }}}}}}";
-#else
-/* Use -L. */
-static const char *link_command_spec = "\
-%{!fsyntax-only: \
- %{!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\
- %{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
- %{!A:%{!nostdlib:%{!nostartfiles:%E}}}\
- %{T*}\
- \n }}}}}}";
-#endif
-#endif
-
/* A vector of options to give to the linker.
These options are accumulated by %x,
and substituted into the linker command with %X. */
{
/* 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 */
+ const char *name; /* name of the spec. */
+ const 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. */
+ const 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 */
#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[] = {
+/* 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 ("asm_options", &asm_options),
INIT_STATIC_SPEC ("cpp", &cpp_spec),
+ INIT_STATIC_SPEC ("cpp_options", &cpp_options),
+ INIT_STATIC_SPEC ("trad_capable_cpp", &trad_capable_cpp),
INIT_STATIC_SPEC ("cc1", &cc1_spec),
+ INIT_STATIC_SPEC ("cc1_options", &cc1_options),
INIT_STATIC_SPEC ("cc1plus", &cc1plus_spec),
INIT_STATIC_SPEC ("endfile", &endfile_spec),
INIT_STATIC_SPEC ("link", &link_spec),
INIT_STATIC_SPEC ("multilib_defaults", &multilib_defaults),
INIT_STATIC_SPEC ("multilib_extra", &multilib_extra),
INIT_STATIC_SPEC ("multilib_matches", &multilib_matches),
+ INIT_STATIC_SPEC ("multilib_exclusions", &multilib_exclusions),
INIT_STATIC_SPEC ("linker", &linker_name_spec),
+ INIT_STATIC_SPEC ("link_libgcc", &link_libgcc_spec),
};
#ifdef EXTRA_SPECS /* additional specs needed */
/* Structure to keep track of just the first two args of a spec_list.
- That is all that the EXTRA_SPECS macro gives us. */
+ That is all that the EXTRA_SPECS macro gives us. */
struct spec_list_1
{
- char *name;
- char *ptr;
+ const char *name;
+ const char *ptr;
};
static struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
int i;
if (specs)
- return; /* already initialized */
+ return; /* Already initialized. */
if (verbose_flag)
notice ("Using builtin specs.\n");
const char *spec;
{
struct spec_list *sl;
- char *old_spec;
+ const char *old_spec;
int name_len = strlen (name);
int i;
- /* If this is the first call, initialize the statically allocated specs */
+ /* If this is the first call, initialize the statically allocated specs. */
if (!specs)
{
struct spec_list *next = (struct spec_list *)0;
specs = sl;
}
- /* See if the spec already exists */
+ /* See if the spec already exists. */
for (sl = specs; sl; sl = sl->next)
if (name_len == sl->name_len && !strcmp (sl->name, name))
break;
if (!sl)
{
- /* Not found - make it */
+ /* Not found - make it. */
sl = (struct spec_list *) xmalloc (sizeof (struct spec_list));
sl->name = xstrdup (name);
sl->name_len = name_len;
notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
#endif
- /* Free the old spec */
+ /* Free the old spec. */
if (old_spec && sl->alloc_p)
- free (old_spec);
+ free ((PTR) old_spec);
sl->alloc_p = 1;
}
/* Vector of pointers to arguments in the current line of specifications. */
-static char **argbuf;
+static const char **argbuf;
/* Number of elements allocated in argbuf. */
#ifndef STANDARD_BINDIR_PREFIX
#define STANDARD_BINDIR_PREFIX "/usr/local/bin"
#endif
-static char *standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
+static const char *standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
/* Subdirectory to use for locating libraries. Set by
set_multilib_dir based on the compilation options. */
static void
store_arg (arg, delete_always, delete_failure)
- char *arg;
+ const char *arg;
int delete_always, delete_failure;
{
if (argbuf_index + 1 == argbuf_length)
argbuf
- = (char **) xrealloc (argbuf, (argbuf_length *= 2) * sizeof (char *));
+ = (const char **) xrealloc (argbuf,
+ (argbuf_length *= 2) * sizeof (const 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. */
+/* Load specs from a file name named FILENAME, replacing occurances of
+ various different types of line-endings, \r\n, \n\r and just \r, with
+ a single \n. */
-static void
-read_specs (filename, main_p)
+static char*
+load_specs (filename)
const char *filename;
- int main_p;
{
int desc;
int readlen;
struct stat statbuf;
char *buffer;
- register char *p;
+ char *buffer_p;
+ char *specs;
+ char *specs_p;
if (verbose_flag)
notice ("Reading specs from %s\n", filename);
buffer[readlen] = 0;
close (desc);
+ specs = xmalloc (readlen + 1);
+ specs_p = specs;
+ for (buffer_p = buffer; buffer_p && *buffer_p; buffer_p++)
+ {
+ int skip = 0;
+ char c = *buffer_p;
+ if (c == '\r')
+ {
+ if (buffer_p > buffer && *(buffer_p-1) == '\n') /* \n\r */
+ skip = 1;
+ else if (*(buffer_p+1) == '\n') /* \r\n */
+ skip = 1;
+ else /* \r */
+ c = '\n';
+ }
+ if (! skip)
+ *specs_p++ = c;
+ }
+ *specs_p = '\0';
+
+ free (buffer);
+ return (specs);
+}
+
+/* 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)
+ const char *filename;
+ int main_p;
+{
+ char *buffer;
+ register char *p;
+
+ buffer = load_specs (filename);
+
/* Scan BUFFER for specs, putting them in the vector. */
p = buffer;
while (1)
set_spec (p2, *(sl->ptr_spec));
if (sl->alloc_p)
- free (*(sl->ptr_spec));
+ free ((PTR) *(sl->ptr_spec));
*(sl->ptr_spec) = "";
sl->alloc_p = 0;
(n_compilers + 2) * sizeof (struct compiler)));
compilers[n_compilers].suffix = suffix;
- memset (compilers[n_compilers].spec, 0,
- sizeof compilers[n_compilers].spec);
- compilers[n_compilers].spec[0] = spec;
+ compilers[n_compilers].spec = spec;
n_compilers++;
memset (&compilers[n_compilers], 0, sizeof compilers[n_compilers]);
}
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.
+ function will return /red/green/blue/../omega.
If no relative prefix can be found, return NULL. */
prefix_dirs = split_directories (prefix, &prefix_num);
- /* Find how many directories are in common between bin_prefix & prefix */
+ /* 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++)
{
struct command
{
const char *prog; /* program name. */
- char **argv; /* vector of args. */
+ const char **argv; /* vector of args. */
int pid; /* pid of process for this command. */
};
/* Print each piped command as a separate line. */
for (i = 0; i < n_commands ; i++)
{
- char **j;
+ const char **j;
for (j = commands[i].argv; *j; j++)
fprintf (stderr, " %s", *j);
for (i = 0; i < n_commands; i++)
{
char *errmsg_fmt, *errmsg_arg;
- char *string = commands[i].argv[0];
+ const char *string = commands[i].argv[0];
commands[i].pid = pexecute (string, commands[i].argv,
programname, temp_filename,
pfatal_pexecute (errmsg_fmt, errmsg_arg);
if (string != commands[i].prog)
- free (string);
+ free ((PTR) string);
}
execution_count++;
if (commands[j].pid == pid)
{
i++;
- if (status != 0)
+ if (WIFSIGNALED (status))
{
- if (WIFSIGNALED (status))
- {
- fatal ("Internal compiler error: program %s got fatal signal %d",
- commands[j].prog, WTERMSIG (status));
- signal_count++;
- ret_code = -1;
- }
- else if (WIFEXITED (status)
- && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
- {
- if (WEXITSTATUS (status) > greatest_status)
- greatest_status = WEXITSTATUS (status);
- ret_code = -1;
- }
+#ifdef SIGPIPE
+ /* SIGPIPE is a special case. It happens in -pipe mode
+ when the compiler dies before the preprocessor is
+ done, or the assembler dies before the compiler is
+ done. There's generally been an error already, and
+ this is just fallout. So don't generate another error
+ unless we would otherwise have succeeded. */
+ if (WTERMSIG (status) == SIGPIPE
+ && (signal_count || greatest_status >= MIN_FATAL_STATUS))
+ ;
+ else
+#endif
+ fatal ("\
+Internal error: %s (program %s)\n\
+Please submit a full bug report.\n\
+See %s for instructions.",
+ strsignal (WTERMSIG (status)), commands[j].prog,
+ GCCBUGURL);
+ signal_count++;
+ ret_code = -1;
+ }
+ else if (WIFEXITED (status)
+ && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
+ {
+ if (WEXITSTATUS (status) > greatest_status)
+ greatest_status = WEXITSTATUS (status);
+ ret_code = -1;
}
#ifdef HAVE_GETRUSAGE
if (report_times && ut + st != 0)
If a switch uses following arguments, then the `part1' field
is the switch itself and the `args' field
is a null-terminated vector containing the following arguments.
- The `live_cond' field is 1 if the switch is true in a conditional spec,
- -1 if false (overridden by a later switch), and is initialized to zero.
+ The `live_cond' field is:
+ 0 when initialized
+ 1 if the switch is true in a conditional spec,
+ -1 if false (overridden by a later switch)
+ -2 if this switch should be ignored (used in %{<S})
The `validated' field is nonzero if any spec has looked at this switch;
if it remains zero at the end of the run, it must be meaningless. */
+#define SWITCH_OK 0
+#define SWITCH_FALSE -1
+#define SWITCH_IGNORE -2
+#define SWITCH_LIVE 1
+
struct switchstr
{
const char *part1;
- char **args;
+ const char **args;
int live_cond;
int validated;
};
static void
display_help ()
{
- printf ("Usage: %s [options] file...\n", programname);
- printf ("Options:\n");
+ printf (_("Usage: %s [options] file...\n"), programname);
+ fputs (_("Options:\n"), stdout);
- printf (" -pass-exit-codes Exit with highest error code from a phase\n");
- printf (" --help Display this information\n");
+ fputs (_(" -pass-exit-codes Exit with highest error code from a phase\n"), stdout);
+ fputs (_(" --help Display this information\n"), stdout);
if (! verbose_flag)
- printf (" (Use '-v --help' to display command line options of sub-processes)\n");
- printf (" -dumpspecs Display all of the built in spec strings\n");
- printf (" -dumpversion Display the version of the compiler\n");
- printf (" -dumpmachine Display the compiler's target processor\n");
- printf (" -print-search-dirs Display the directories in the compiler's search path\n");
- printf (" -print-libgcc-file-name Display the name of the compiler's companion library\n");
- printf (" -print-file-name=<lib> Display the full path to library <lib>\n");
- printf (" -print-prog-name=<prog> Display the full path to compiler component <prog>\n");
- printf (" -print-multi-directory Display the root directory for versions of libgcc\n");
- printf (" -print-multi-lib Display the mapping between command line options and\n");
- printf (" multiple library search directories\n");
- printf (" -Wa,<options> Pass comma-separated <options> on to the assembler\n");
- printf (" -Wp,<options> Pass comma-separated <options> on to the preprocessor\n");
- printf (" -Wl,<options> Pass comma-separated <options> on to the linker\n");
- printf (" -Xlinker <arg> Pass <arg> on to the linker\n");
- printf (" -save-temps Do not delete intermediate files\n");
- printf (" -pipe Use pipes rather than intermediate files\n");
- printf (" -time Time the execution of each subprocess\n");
- printf (" -specs=<file> Override builtin specs with the contents of <file>\n");
- printf (" -std=<standard> Assume that the input sources are for <standard>\n");
- printf (" -B <directory> Add <directory> to the compiler's search paths\n");
- printf (" -b <machine> Run gcc for target <machine>, if installed\n");
- printf (" -V <version> Run gcc version number <version>, if installed\n");
- printf (" -v Display the programs invoked by the compiler\n");
- printf (" -E Preprocess only; do not compile, assemble or link\n");
- printf (" -S Compile only; do not assemble or link\n");
- printf (" -c Compile and assemble, but do not link\n");
- printf (" -o <file> Place the output into <file>\n");
- printf (" -x <language> Specify the language of the following input files\n");
- printf (" Permissable languages include: c c++ assembler none\n");
- printf (" 'none' means revert to the default behaviour of\n");
- printf (" guessing the language based on the file's extension\n");
-
- printf ("\nOptions starting with -g, -f, -m, -O or -W are automatically passed on to\n");
- printf ("the various sub-processes invoked by %s. In order to pass other options\n",
- programname);
- printf ("on to these processes the -W<letter> options must be used.\n");
+ fputs (_(" (Use '-v --help' to display command line options of sub-processes)\n"), stdout);
+ fputs (_(" -dumpspecs Display all of the built in spec strings\n"), stdout);
+ fputs (_(" -dumpversion Display the version of the compiler\n"), stdout);
+ fputs (_(" -dumpmachine Display the compiler's target processor\n"), stdout);
+ fputs (_(" -print-search-dirs Display the directories in the compiler's search path\n"), stdout);
+ fputs (_(" -print-libgcc-file-name Display the name of the compiler's companion library\n"), stdout);
+ fputs (_(" -print-file-name=<lib> Display the full path to library <lib>\n"), stdout);
+ fputs (_(" -print-prog-name=<prog> Display the full path to compiler component <prog>\n"), stdout);
+ fputs (_(" -print-multi-directory Display the root directory for versions of libgcc\n"), stdout);
+ fputs (_("\
+ -print-multi-lib Display the mapping between command line options and\n\
+ multiple library search directories\n"), stdout);
+ fputs (_(" -Wa,<options> Pass comma-separated <options> on to the assembler\n"), stdout);
+ fputs (_(" -Wp,<options> Pass comma-separated <options> on to the preprocessor\n"), stdout);
+ fputs (_(" -Wl,<options> Pass comma-separated <options> on to the linker\n"), stdout);
+ fputs (_(" -Xlinker <arg> Pass <arg> on to the linker\n"), stdout);
+ fputs (_(" -save-temps Do not delete intermediate files\n"), stdout);
+ fputs (_(" -pipe Use pipes rather than intermediate files\n"), stdout);
+ fputs (_(" -time Time the execution of each subprocess\n"), stdout);
+ fputs (_(" -specs=<file> Override builtin specs with the contents of <file>\n"), stdout);
+ fputs (_(" -std=<standard> Assume that the input sources are for <standard>\n"), stdout);
+ fputs (_(" -B <directory> Add <directory> to the compiler's search paths\n"), stdout);
+ fputs (_(" -b <machine> Run gcc for target <machine>, if installed\n"), stdout);
+ fputs (_(" -V <version> Run gcc version number <version>, if installed\n"), stdout);
+ fputs (_(" -v Display the programs invoked by the compiler\n"), stdout);
+ fputs (_(" -E Preprocess only; do not compile, assemble or link\n"), stdout);
+ fputs (_(" -S Compile only; do not assemble or link\n"), stdout);
+ fputs (_(" -c Compile and assemble, but do not link\n"), stdout);
+ fputs (_(" -o <file> Place the output into <file>\n"), stdout);
+ fputs (_("\
+ -x <language> Specify the language of the following input files\n\
+ Permissable languages include: c c++ assembler none\n\
+ 'none' means revert to the default behaviour of\n\
+ guessing the language based on the file's extension\n\
+"), stdout);
+
+ printf (_("\
+\nOptions starting with -g, -f, -m, -O or -W are automatically passed on to\n\
+the various sub-processes invoked by %s. In order to pass other options\n\
+on to these processes the -W<letter> options must be used.\n\
+"), programname);
/* The rest of the options are displayed by invocations of the various
sub-processes. */
static void
process_command (argc, argv)
int argc;
- char **argv;
+ const char **argv;
{
register int i;
const char *temp;
char *temp1;
- char *spec_lang = 0;
+ const char *spec_lang = 0;
int last_language_n_infiles;
int have_c = 0;
int have_o = 0;
report_times = 1;
else if (argv[i][0] == '-' && argv[i][1] != 0)
{
- register char *p = &argv[i][1];
+ register const char *p = &argv[i][1];
register int c = *p;
switch (c)
case 'B':
{
- char *value;
+ const char *value;
if (p[1] == 0 && i + 1 == argc)
fatal ("argument to `-B' is missing");
if (p[1] == 0)
cc1 spec string. */
switches[n_switches].part1 = "--help";
switches[n_switches].args = 0;
- switches[n_switches].live_cond = 0;
+ switches[n_switches].live_cond = SWITCH_OK;
switches[n_switches].validated = 0;
n_switches++;
-e0 or -e1 down into the linker. */
switches[n_switches].part1 = &argv[i][0];
switches[n_switches].args = 0;
- switches[n_switches].live_cond = 0;
+ switches[n_switches].live_cond = SWITCH_OK;
switches[n_switches].validated = 0;
n_switches++;
}
}
else if (argv[i][0] == '-' && argv[i][1] != 0)
{
- register char *p = &argv[i][1];
- register int c = *p;
+ const char *p = &argv[i][1];
+ int c = *p;
if (c == 'x')
{
if (i + n_args >= argc)
fatal ("argument to `-%s' is missing", p);
switches[n_switches].args
- = (char **) xmalloc ((n_args + 1) * sizeof (char *));
+ = (const char **) xmalloc ((n_args + 1) * sizeof(const char *));
while (j < n_args)
switches[n_switches].args[j++] = argv[++i];
/* Null-terminate the vector. */
/* On some systems, ld cannot handle some options without
a space. So split the option from its argument. */
char *part1 = (char *) xmalloc (2);
+ char *tmp;
part1[0] = c;
part1[1] = '\0';
switches[n_switches].part1 = part1;
- switches[n_switches].args = (char **) xmalloc (2 * sizeof (char *));
- switches[n_switches].args[0] = xmalloc (strlen (p));
- strcpy (switches[n_switches].args[0], &p[1]);
+ switches[n_switches].args
+ = (const char **) xmalloc (2 * sizeof (const char *));
+ switches[n_switches].args[0] = tmp = xmalloc (strlen (p));
+ strcpy (tmp, &p[1]);
switches[n_switches].args[1] = 0;
}
else
switches[n_switches].args = 0;
- switches[n_switches].live_cond = 0;
+ switches[n_switches].live_cond = SWITCH_OK;
switches[n_switches].validated = 0;
/* This is always valid, since gcc.c itself understands it. */
if (!strcmp (p, "save-temps"))
static int input_file_number;
size_t input_filename_length;
static int basename_length;
+static int suffixed_basename_length;
static const char *input_basename;
static const char *input_suffix;
arg_going = 1;
break;
+ case 'B':
+ obstack_grow (&obstack, input_basename, suffixed_basename_length);
+ arg_going = 1;
+ break;
+
case 'd':
delete_this_arg = 2;
break;
and use them to search for dynamic linking. */
/* Relative directories always come from -B,
and it is better not to use them for searching
- at run time. In particular, stage1 loses */
+ at run time. In particular, stage1 loses. */
if (!IS_DIR_SEPARATOR (pl->prefix[0]))
continue;
#endif
{
char *x = (char *) alloca (strlen (cpp_predefines) + 1);
char *buf = x;
- char *y;
+ const char *y;
/* Copy all of the -D options in CPP_PREDEFINES into BUF. */
y = cpp_predefines;
{
char *x = (char *) alloca (strlen (cpp_predefines) * 4 + 1);
char *buf = x;
- char *y;
+ const char *y;
/* Copy all of CPP_PREDEFINES into BUF,
- but force them all into the reserved name space if they aren't already there. The reserved name space is all
+ but force them all into the reserved name space if they
+ aren't already there. The reserved name space is all
identifiers beginning with two underscores or with one
underscore and a capital letter. We do the forcing by
adding up to two underscores to the beginning and end
else if (*y == ' ' || *y == '\t')
/* Copy whitespace to the result. */
*x++ = *y++;
- /* Don't copy -A options */
+ /* Don't copy -A options. */
else
y++;
}
break;
case '*':
- do_spec_1 (soft_matched_part, 1, NULL_PTR);
- do_spec_1 (" ", 0, NULL_PTR);
+ if (soft_matched_part)
+ {
+ do_spec_1 (soft_matched_part, 1, NULL_PTR);
+ do_spec_1 (" ", 0, NULL_PTR);
+ }
+ else
+ /* Catch the case where a spec string contains something like
+ '%{foo:%*}'. ie there is no * in the pattern on the left
+ hand side of the :. */
+ error ("Spec failure: '%%*' has not been initialised by pattern match");
break;
/* Process a string found as the value of a spec given by name.
while (*p && *p != ')' && *p != ']')
p++;
- /* See if it's in the list */
+ /* See if it's in the list. */
for (len = p - name, sl = specs; sl; sl = sl->next)
if (sl->name_len == len && !strncmp (sl->name, name, len))
{
int flag = 0;
/* Copy all of NAME into BUF, but put __ after
- every -D and at the end of each arg, */
+ every -D and at the end of each arg. */
while (1)
{
if (! strncmp (y, "-D", 2))
case 'v':
{
int c1 = *p++; /* Select first or second version number. */
- char *v = compiler_version;
- char *q;
+ const char *v = compiler_version;
+ const char *q;
static const char zeroc = '0';
/* The format of the version string is
q = v;
while (ISDIGIT (*q))
q++;
- if (*q != 0 && *q != ' ' && *q != '.' && *q != '-')
+ if (*q != 0 && q > v && *q != ' ' && *q != '.' && *q != '-')
abort ();
if (q > v)
break;
default:
- abort ();
+ error ("Spec failure: Unrecognised spec option '%c'", c);
+ break;
}
break;
int negate;
int suffix;
int include_blanks = 1;
+ int elide_switch = 0;
if (*p == '^')
- /* A '^' after the open-brace means to not give blanks before args. */
- include_blanks = 0, ++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,
- if the test fails, output a single minus sign rather than nothing.
- This is used in %{|!pipe:...}. */
- pipe_p = 1, ++p;
+ {
+ /* A `|' after the open-brace means,
+ if the test fails, output a single minus sign rather than nothing.
+ This is used in %{|!pipe:...}. */
+ pipe_p = 1;
+ ++p;
+ }
+
+ if (*p == '<')
+ {
+ /* A `<' after the open-brace means that the switch should be
+ removed from the command-line. */
+ elide_switch = 1;
+ ++p;
+ }
next_member:
negate = suffix = 0;
++p;
}
+ if (elide_switch && (negate || pipe_p || suffix))
+ {
+ /* It doesn't make sense to mix elision with other flags. We
+ could fatal() here, but the standard seems to be to abort. */
+ abort ();
+ }
+
filter = p;
while (*p != ':' && *p != '}' && *p != '|') p++;
&& check_live_switch (i, hard_match_len))
{
present = 1;
+ break;
}
}
}
conditional text. */
if (present != negate)
{
- if (*p == '}')
+ if (elide_switch)
+ {
+ switches[i].live_cond = SWITCH_IGNORE;
+ switches[i].validated = 1;
+ }
+ else if (*p == '}')
{
give_switch (i, 0, include_blanks);
}
if (switches[i].part1[0] == 'O')
{
switches[switchnum].validated = 1;
- switches[switchnum].live_cond = -1;
+ switches[switchnum].live_cond = SWITCH_FALSE;
return 0;
}
break;
&& ! strcmp (&switches[i].part1[1], &name[4]))
{
switches[switchnum].validated = 1;
- switches[switchnum].live_cond = -1;
+ switches[switchnum].live_cond = SWITCH_FALSE;
return 0;
}
}
&& !strcmp (&switches[i].part1[4], &name[1]))
{
switches[switchnum].validated = 1;
- switches[switchnum].live_cond = -1;
+ switches[switchnum].live_cond = SWITCH_FALSE;
return 0;
}
}
}
/* Otherwise the switch is live. */
- switches[switchnum].live_cond = 1;
+ switches[switchnum].live_cond = SWITCH_LIVE;
return 1;
}
\f
int omit_first_word;
int include_blanks;
{
+ if (switches[switchnum].live_cond == SWITCH_IGNORE)
+ return;
+
if (!omit_first_word)
{
do_spec_1 ("-", 0, NULL_PTR);
if (switches[switchnum].args != 0)
{
- char **p;
+ const char **p;
for (p = switches[switchnum].args; *p; p++)
{
if (include_blanks)
input_filename_length = strlen (input_filename);
input_basename = input_filename;
- for (p = input_filename; *p; p++)
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+ /* Skip drive name so 'x:foo' is handled properly. */
+ if (input_basename[1] == ':')
+ input_basename += 2;
+#endif
+ for (p = input_basename; *p; p++)
if (IS_DIR_SEPARATOR (*p))
input_basename = p + 1;
/* Find a suffix starting with the last period,
and set basename_length to exclude that suffix. */
basename_length = strlen (input_basename);
+ suffixed_basename_length = basename_length;
p = input_basename + basename_length;
while (p != input_basename && *p != '.') --p;
if (*p == '.' && p != input_basename)
int argc;
char **argv;
{
- register size_t i;
- size_t j;
+ size_t i;
int value;
int linker_was_run = 0;
char *explicit_link_files;
#endif
argbuf_length = 10;
- argbuf = (char **) xmalloc (argbuf_length * sizeof (char *));
+ argbuf = (const char **) xmalloc (argbuf_length * sizeof (const char *));
obstack_init (&obstack);
/* Build multilib_select, et. al from the separate lines that make up each
multilib selection. */
{
- char **q = multilib_raw;
+ const char *const *q = multilib_raw;
int need_space;
obstack_init (&multilib_obstack);
obstack_1grow (&multilib_obstack, 0);
multilib_matches = obstack_finish (&multilib_obstack);
+ q = multilib_exclusions_raw;
+ while ((p = *q++) != (char *) 0)
+ obstack_grow (&multilib_obstack, p, strlen (p));
+
+ obstack_1grow (&multilib_obstack, 0);
+ multilib_exclusions = obstack_finish (&multilib_obstack);
+
need_space = FALSE;
for (i = 0;
i < sizeof (multilib_defaults_raw) / sizeof (multilib_defaults_raw[0]);
first_time = TRUE;
for (i = 0; (int)i < n_switches; i++)
{
- char **args;
+ const char **args;
const char *p, *q;
if (!first_time)
obstack_grow (&collect_obstack, " ", 1);
init_spec ();
/* We need to check standard_exec_prefix/just_machine_suffix/specs
- for any override of as, ld and libraries. */
+ for any override of as, ld and libraries. */
specs_file = (char *) alloca (strlen (standard_exec_prefix)
+ strlen (just_machine_suffix)
+ sizeof ("specs"));
if (print_search_dirs)
{
- printf ("install: %s%s\n", standard_exec_prefix, machine_suffix);
- printf ("programs: %s\n", build_search_list (&exec_prefixes, "", 0));
- printf ("libraries: %s\n", build_search_list (&startfile_prefixes, "", 0));
+ printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix);
+ printf (_("programs: %s\n"), build_search_list (&exec_prefixes, "", 0));
+ printf (_("libraries: %s\n"), build_search_list (&startfile_prefixes, "", 0));
return (0);
}
if (! verbose_flag)
{
- printf ("\nFor bug reporting instructions, please see:\n");
+ printf (_("\nFor bug reporting instructions, please see:\n"));
printf ("%s.\n", GCCBUGURL);
return (0);
if (cp)
{
/* Ok, we found an applicable compiler. Run its spec. */
- /* First say how much of input_filename to substitute for %b */
- int len;
- if (cp->spec[0][0] == '#')
+ if (cp->spec[0] == '#')
error ("%s: %s compiler not installed on this system",
- input_filename, &cp->spec[0][1]);
-
- len = 0;
- for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++)
- if (cp->spec[j])
- len += strlen (cp->spec[j]);
-
- {
- char *p1 = (char *) xmalloc (len + 1);
-
- len = 0;
- for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++)
- if (cp->spec[j])
- {
- strcpy (p1 + len, cp->spec[j]);
- len += strlen (cp->spec[j]);
- }
-
- value = do_spec (p1);
- free (p1);
- }
+ input_filename, &cp->spec[1]);
+ value = do_spec (cp->spec);
if (value < 0)
this_file_error = 1;
}
if (print_help_list)
{
- printf ("\nFor bug reporting instructions, please see:\n");
+ printf (("\nFor bug reporting instructions, please see:\n"));
printf ("%s\n", GCCBUGURL);
}
{
struct compiler *cp;
- /* If this was specified by the user to be a linker input, indicate that. */
+ /* If this was specified by the user to be a linker input, indicate that. */
if (language != 0 && language[0] == '*')
return 0;
(!strcmp (cp->suffix, "-") && !strcmp (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)))
-#else
&& !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.
- Construct the new compiler spec. */
- language = cp->spec[0] + 1;
- new = (struct compiler *) xmalloc (sizeof (struct compiler));
- new->suffix = cp->suffix;
- memcpy (new->spec,
- lookup_compiler (NULL_PTR, 0, language)->spec,
- sizeof new->spec);
- return new;
- }
-
- /* A non-alias entry: return it. */
- return cp;
- }
+ break;
}
+#if defined (OS2) ||defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ /* look again, but case-insensitively this time. */
+ if (cp < compilers)
+ for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
+ {
+ 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. */
+ && ((!strcmp (cp->suffix,
+ name + length - strlen (cp->suffix))
+ || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
+ && !strcasecmp (cp->suffix,
+ name + length - strlen (cp->suffix)))
+ ))
+ break;
+ }
+#endif
+
+ if (cp >= compilers)
+ {
+ if (cp->spec[0] != '@')
+ /* A non-alias entry: return it. */
+ return cp;
+
+ /* 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. */
+ return lookup_compiler (NULL_PTR, 0, cp->spec + 1);
+ }
return 0;
}
\f
register char c;
struct spec_list *spec;
- for (comp = compilers; comp->spec[0]; comp++)
+ for (comp = compilers; comp->spec; comp++)
{
- size_t i;
- for (i = 0; i < sizeof comp->spec / sizeof comp->spec[0] && comp->spec[i]; i++)
- {
- p = comp->spec[i];
- while ((c = *p++))
- if (c == '%' && *p == '{')
- /* We have a switch spec. */
- validate_switches (p + 1);
- }
+ p = comp->spec;
+ while ((c = *p++))
+ if (c == '%' && *p == '{')
+ /* We have a switch spec. */
+ validate_switches (p + 1);
}
- /* look through the linked list of 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->ptr_spec);
const char *p;
int len;
{
- struct mswitchstr {
- char *str;
- char *replace;
+ struct mswitchstr
+ {
+ const char *str;
+ const char *replace;
int len;
int rep_len;
};
if (!mswitches)
{
struct mswitchstr *matches;
- char *q;
+ const char *q;
int cnt = 0;
/* Break multilib_matches into the component strings of string and replacement
- string */
+ string. */
for (q = multilib_matches; *q != '\0'; q++)
if (*q == ';')
cnt++;
abort ();
q++;
}
- *q = '\0';
matches[i].len = q - matches[i].str;
matches[i].replace = ++q;
matches[i].rep_len = q - matches[i].replace;
i++;
if (*q == ';')
- *q++ = '\0';
- else
- break;
+ q++;
}
/* Now build a list of the replacement string for switches that we care
{
int xlen = strlen (switches[i].part1);
for (j = 0; j < cnt; j++)
- if (xlen == matches[j].len && ! strcmp (switches[i].part1, matches[j].str))
+ if (xlen == matches[j].len
+ && ! strncmp (switches[i].part1, matches[j].str, xlen))
{
mswitches[n_mswitches].str = matches[j].replace;
mswitches[n_mswitches].len = matches[j].rep_len;
const char *p;
int len;
{
- char *start, *end;
+ const char *start, *end;
for (start = multilib_defaults; *start != '\0'; start = end+1)
{
return 0;
}
-/* Work out the subdirectory to use based on the
- options. The format of multilib_select is a list of elements.
- Each element is a subdirectory name followed by a list of options
- followed by a semicolon. gcc will consider each line in turn. If
- none of the options beginning with an exclamation point are
- present, and all of the other options are present, that
- subdirectory will be used. */
+/* Work out the subdirectory to use based on the options. The format of
+ multilib_select is a list of elements. Each element is a subdirectory
+ name followed by a list of options followed by a semicolon. The format
+ of multilib_exclusions is the same, but without the preceding
+ directory. First gcc will check the exclusions, if none of the options
+ beginning with an exclamation point are present, and all of the other
+ options are present, then we will ignore this completely. Passing
+ that, gcc will consider each multilib_select in turn using the same
+ rules for matching the options. If a match is found, that subdirectory
+ will be used. */
static void
set_multilib_dir ()
{
- char *p = multilib_select;
- int this_path_len;
- char *this_path, *this_arg;
+ const char *p;
+ unsigned int this_path_len;
+ const char *this_path, *this_arg;
int not_arg;
int ok;
+ p = multilib_exclusions;
+ while (*p != '\0')
+ {
+ /* Ignore newlines. */
+ if (*p == '\n')
+ {
+ ++p;
+ continue;
+ }
+
+ /* Check the arguments. */
+ ok = 1;
+ while (*p != ';')
+ {
+ if (*p == '\0')
+ abort ();
+
+ if (! ok)
+ {
+ ++p;
+ continue;
+ }
+
+ this_arg = p;
+ while (*p != ' ' && *p != ';')
+ {
+ if (*p == '\0')
+ abort ();
+ ++p;
+ }
+
+ if (*this_arg != '!')
+ not_arg = 0;
+ else
+ {
+ not_arg = 1;
+ ++this_arg;
+ }
+
+ ok = used_arg (this_arg, p - this_arg);
+ if (not_arg)
+ ok = ! ok;
+
+ if (*p == ' ')
+ ++p;
+ }
+
+ if (ok)
+ return;
+
+ ++p;
+ }
+
+ p = multilib_select;
while (*p != '\0')
{
/* Ignore newlines. */
matches. The options are print without a leading dash. There are
no spaces to make it easy to use the information in the shell.
Each subdirectory is printed only once. This assumes the ordering
- generated by the genmultilib script. */
+ generated by the genmultilib script. Also, we leave out ones that match
+ the exclusions. */
static void
print_multilib_info ()
{
- char *p = multilib_select;
- char *last_path = 0, *this_path;
+ const char *p = multilib_select;
+ const char *last_path = 0, *this_path;
int skip;
- int last_path_len = 0;
+ unsigned int last_path_len = 0;
while (*p != '\0')
{
+ skip = 0;
/* Ignore newlines. */
if (*p == '\n')
{
++p;
}
- /* If this is a duplicate, skip it. */
- skip = (last_path != 0 && p - this_path == last_path_len
- && ! strncmp (last_path, this_path, last_path_len));
+ /* Check for matches with the multilib_exclusions. We don't bother
+ with the '!' in either list. If any of the exclusion rules match
+ all of its options with the select rule, we skip it. */
+ {
+ const char *e = multilib_exclusions;
+ const char *this_arg;
+
+ while (*e != '\0')
+ {
+ int m = 1;
+ /* Ignore newlines. */
+ if (*e == '\n')
+ {
+ ++e;
+ continue;
+ }
+
+ /* Check the arguments. */
+ while (*e != ';')
+ {
+ const char *q;
+ int mp = 0;
+
+ if (*e == '\0')
+ abort ();
+
+ if (! m)
+ {
+ ++e;
+ continue;
+ }
- last_path = this_path;
- last_path_len = p - this_path;
+ this_arg = e;
+
+ while (*e != ' ' && *e != ';')
+ {
+ if (*e == '\0')
+ abort ();
+ ++e;
+ }
+
+ q = p + 1;
+ while (*q != ';')
+ {
+ const char *arg;
+ int len = e - this_arg;
+
+ if (*q == '\0')
+ abort ();
+
+ arg = q;
+
+ while (*q != ' ' && *q != ';')
+ {
+ if (*q == '\0')
+ abort ();
+ ++q;
+ }
+
+ if (! strncmp (arg, this_arg, (len < q - arg) ? q - arg : len) ||
+ default_arg (this_arg, e - this_arg))
+ {
+ mp = 1;
+ break;
+ }
+
+ if (*q == ' ')
+ ++q;
+ }
+
+ if (! mp)
+ m = 0;
+
+ if (*e == ' ')
+ ++e;
+ }
+
+ if (m)
+ {
+ skip = 1;
+ break;
+ }
+
+ if (*e != '\0')
+ ++e;
+ }
+ }
+
+ if (! skip)
+ {
+ /* If this is a duplicate, skip it. */
+ skip = (last_path != 0 && (unsigned int)(p - this_path) == last_path_len
+ && ! strncmp (last_path, this_path, last_path_len));
+
+ last_path = this_path;
+ last_path_len = p - this_path;
+ }
/* If this directory requires any default arguments, we can skip
it. We will already have printed a directory identical to
this one which does not require that default argument. */
if (! skip)
{
- char *q;
+ const char *q;
q = p + 1;
while (*q != ';')
{
- char *arg;
+ const char *arg;
if (*q == '\0')
abort ();
if (! skip)
{
- char *p1;
+ const char *p1;
for (p1 = last_path; p1 < p; p1++)
putchar (*p1);
if (! skip)
{
- /* If there are extra options, print them now */
+ /* If there are extra options, print them now. */
if (multilib_extra && *multilib_extra)
{
int print_at = TRUE;
- char *q;
+ const char *q;
for (q = multilib_extra; *q != '\0'; q++)
{
}
}
}
+
putchar ('\n');
}