/* Compiler driver program that can handle many languages.
Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+ 2010
Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.
-
-This paragraph is here to try to keep Sun CC from dying.
-The number of chars here seems crucial!!!! */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* This program is the user interface to the C compiler and possibly to
other compilers. It is used because compilation is a complicated procedure
#include "intl.h"
#include "prefix.h"
#include "gcc.h"
+#include "diagnostic.h"
#include "flags.h"
#include "opts.h"
+#ifdef HAVE_MMAP_FILE
+# include <sys/mman.h>
+# ifdef HAVE_MINCORE
+/* This is on Solaris. */
+# include <sys/types.h>
+# endif
+#endif
+
+#ifndef MAP_FAILED
+# define MAP_FAILED ((void *)-1)
+#endif
+
/* By default there is no special suffix for target executables. */
/* FIXME: when autoconf is fixed, remove the host check - dj */
#if defined(TARGET_EXECUTABLE_SUFFIX) && defined(HOST_EXECUTABLE_SUFFIX)
static int print_multi_directory;
+static int print_sysroot;
+
/* Flag saying to print the relative path we'd use to
find OS libraries given the current compiler flags. */
static int print_help_list;
+/* Flag saying to print the version of gcc and its sub-processes. */
+
+static int print_version;
+
/* Flag saying to print the sysroot suffix used for searching for
headers. */
static int report_times;
+/* Whether we should report subprocess execution times to a file. */
+
+FILE *report_times_to_file = NULL;
+
/* Nonzero means place this string before uses of /, so that include
and library files can be found in an alternate location. */
/* Nonzero means write "temp" files in source directory
and use the source file's name in them, and don't delete them. */
-static int save_temps_flag;
+static enum save_temps {
+ SAVE_TEMPS_NONE, /* no -save-temps */
+ SAVE_TEMPS_CWD, /* -save-temps in current directory */
+ SAVE_TEMPS_OBJ /* -save-temps in object directory */
+} save_temps_flag;
+
+/* Output file to use to get the object directory for -save-temps=obj */
+static char *save_temps_prefix = 0;
+static size_t save_temps_length = 0;
/* Nonzero means pass multiple source files to the compiler at one time. */
static const char *compiler_version;
-/* The target version specified with -V */
+/* The target version. */
static const char *const spec_version = DEFAULT_TARGET_VERSION;
-/* The target machine specified with -b. */
+/* The target machine. */
static const char *spec_machine = DEFAULT_TARGET_MACHINE;
static const char *cross_compile = "0";
#endif
-#ifdef MODIFY_TARGET_NAME
-
-/* Information on how to alter the target name based on a command-line
- switch. The only case we support now is simply appending or deleting a
- string to or from the end of the first part of the configuration name. */
-
-static const struct modify_target
-{
- const char *const sw;
- const enum add_del {ADD, DELETE} add_del;
- const char *const str;
-}
-modify_target[] = MODIFY_TARGET_NAME;
-#endif
-
-/* The number of errors that have occurred; the link phase will not be
- run if this is nonzero. */
-static int error_count = 0;
-
/* Greatest exit code of sub-processes that has been encountered up to
now. */
static int greatest_status = 1;
static struct obstack collect_obstack;
+/* This is a list of a wrapper program and its arguments.
+ e.g. wrapper_string of "strace,-c"
+ will cause all programs to run as
+ strace -c program arguments
+ instead of just
+ program arguments */
+static const char *wrapper_string;
+
/* Forward declaration for prototypes. */
struct path_prefix;
struct prefix_list;
static void init_spec (void);
static void store_arg (const char *, int, int);
+static void insert_wrapper (const char *);
static char *load_specs (const char *);
static void read_specs (const char *, int);
static void set_spec (const char *, const char *);
static struct compiler *lookup_compiler (const char *, size_t, const char *);
static char *build_search_list (const struct path_prefix *, const char *,
bool, bool);
+static void xputenv (const char *);
static void putenv_from_prefixes (const struct path_prefix *, const char *,
bool);
static int access_check (const char *, int);
static void set_multilib_dir (void);
static void print_multilib_info (void);
static void perror_with_name (const char *);
-static void fatal_ice (const char *, ...) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
-static void notice (const char *, ...) ATTRIBUTE_PRINTF_1;
static void display_help (void);
static void add_preprocessor_option (const char *, int);
static void add_assembler_option (const char *, int);
static int execute (void);
static void alloc_args (void);
static void clear_args (void);
-static void fatal_error (int);
+static void fatal_signal (int);
#if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC)
static void init_gcc_specs (struct obstack *, const char *, const char *,
const char *);
static const char *replace_outfile_spec_function (int, const char **);
static const char *version_compare_spec_function (int, const char **);
static const char *include_spec_function (int, const char **);
+static const char *find_file_spec_function (int, const char **);
+static const char *find_plugindir_spec_function (int, const char **);
static const char *print_asm_header_spec_function (int, const char **);
+static const char *compare_debug_dump_opt_spec_function (int, const char **);
+static const char *compare_debug_self_opt_spec_function (int, const char **);
+static const char *compare_debug_auxbase_opt_spec_function (int, const char **);
\f
/* The Specs Language
%i substitute the name of the input file being processed.
%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.
+ and not including the directory unless -save-temps was specified
+ to put temporaries in a different location.
%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
it is subsequently output with %*. SUFFIX is terminated by the next
space or %.
%d marks the argument containing or following the %d as a
- temporary file name, so that that file will be deleted if CC exits
+ temporary file name, so that that file will be deleted if GCC exits
successfully. Unlike %g, this contributes no text to the argument.
%w marks the argument containing or following the %w as the
"output file" of this compilation. This puts the argument
argument vector in the usual fashion. The function returns
a string which is processed as if it had appeared literally
as part of the current spec.
- %{S} substitutes the -S switch, if that switch was given to CC.
+ %{S} substitutes the -S switch, if that switch was given to GCC.
If that switch was not specified, this substitutes nothing.
Here S is a metasyntactic variable.
- %{S*} substitutes all the switches specified to CC whose names start
+ %{S*} substitutes all the switches specified to GCC whose names start
with -S. This is used for -o, -I, etc; switches that take
- arguments. CC considers `-o foo' as being one switch whose
+ arguments. GCC 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*&T*} likewise, but preserve order of S and T options (the order
of ampersand-separated variables; for each the wild card is
optional. Useful for CPP as %{D*&U*&A*}.
- %{S:X} substitutes X, if the -S switch was given to CC.
- %{!S:X} substitutes X, if the -S switch was NOT given to CC.
+ %{S:X} substitutes X, if the -S switch was given to GCC.
+ %{!S:X} substitutes X, if the -S switch was NOT given to GCC.
%{S*:X} substitutes X if one or more switches whose names start
- with -S was given to CC. Normally X is substituted only
+ with -S was given to GCC. Normally X is substituted only
once, no matter how many such switches appeared. However,
if %* appears somewhere in X, then X will be substituted
once for each matching switch, with the %* replaced by the
%{!.S:X} substitutes X, if NOT processing a file with suffix S.
%{,S:X} substitutes X, if processing a file which will use spec S.
%{!,S:X} substitutes X, if NOT processing a file which will use spec S.
-
- %{S|T:X} substitutes X if either -S or -T was given to CC. This may be
+
+ %{S|T:X} substitutes X if either -S or -T was given to GCC. This may be
combined with '!', '.', ',', and '*' as above binding stronger
than the OR.
If %* appears in X, all of the alternatives must be starred, and
only the first matching alternative is substituted.
- %{S:X; if S was given to CC, substitutes X;
- T:Y; else if T was given to CC, substitutes Y;
+ %{S:X; if S was given to GCC, substitutes X;
+ T:Y; else if T was given to GCC, substitutes Y;
:D} else substitutes D. There can be as many clauses as you need.
This may be combined with '.', '!', ',', '|', and '*' as above.
that a command should be piped to the following command, but only if -pipe
is specified.
-Note that it is built into CC which switches take arguments and which
+Note that it is built into GCC which switches take arguments and which
do not. You might think it would be useful to generalize this to
allow each compiler's spec to say which switches take arguments. But
-this cannot be done in a consistent fashion. CC cannot even decide
+this cannot be done in a consistent fashion. GCC cannot even decide
which input files have been specified without knowing which switches
take arguments, and it must know which input files to compile in order
to tell which compilers to run.
-CC also knows implicitly that arguments starting in `-l' are to be
+GCC also knows implicitly that arguments starting in `-l' are to be
treated as compiler output files, and passed to the linker in their
proper position among the other output files. */
\f
"%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}"
#endif
-/* config.h can define SWITCHES_NEED_SPACES to control which options
- require spaces between the option and the argument. */
-#ifndef SWITCHES_NEED_SPACES
-#define SWITCHES_NEED_SPACES ""
-#endif
-
/* config.h can define ENDFILE_SPEC to override the default crtn files. */
#ifndef ENDFILE_SPEC
#define ENDFILE_SPEC ""
#define LINKER_NAME "collect2"
#endif
+#ifdef HAVE_AS_DEBUG_PREFIX_MAP
+#define ASM_MAP " %{fdebug-prefix-map=*:--debug-prefix-map %*}"
+#else
+#define ASM_MAP ""
+#endif
+
/* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g'
to the assembler. */
#ifndef ASM_DEBUG_SPEC
# if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \
&& defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
-# define ASM_DEBUG_SPEC \
- (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG \
- ? "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}" \
- : "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}")
+# define ASM_DEBUG_SPEC \
+ (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG \
+ ? "%{!g0:%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}}" ASM_MAP \
+ : "%{!g0:%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}}" ASM_MAP)
# else
# if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
-# define ASM_DEBUG_SPEC "%{g*:--gstabs}"
+# define ASM_DEBUG_SPEC "%{g*:%{!g0:--gstabs}}" ASM_MAP
# endif
# if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG)
-# define ASM_DEBUG_SPEC "%{g*:--gdwarf2}"
+# define ASM_DEBUG_SPEC "%{g*:%{!g0:--gdwarf2}}" ASM_MAP
# endif
# endif
#endif
#endif
#endif
+#ifndef LINK_BUILDID_SPEC
+# if defined(HAVE_LD_BUILDID) && defined(ENABLE_LD_BUILDID)
+# define LINK_BUILDID_SPEC "%{!r:--build-id} "
+# endif
+#endif
+
+
/* -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. */
+/* We pass any -flto and -fwhopr flags on to the linker, which is expected
+ to understand them. In practice, this means it had better be collect2. */
#ifndef LINK_COMMAND_SPEC
#define LINK_COMMAND_SPEC "\
%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
- %(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
+ %(linker) \
+ %{fuse-linker-plugin: \
+ -plugin %(linker_plugin_file) \
+ -plugin-opt=%(lto_wrapper) \
+ -plugin-opt=-fresolution=%u.res \
+ %{static|static-libgcc:-plugin-opt=-pass-through=%(lto_libgcc)} \
+ %{static:-plugin-opt=-pass-through=-lc} \
+ } \
+ %{flto} %{fwhopr*} %l " LINK_PIE_SPEC \
+ "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
%{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
%{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
- %{fopenmp:%:include(libgomp.spec)%(link_gomp)} %(mflib)\
- %{fprofile-arcs|fprofile-generate|coverage:-lgcov}\
+ %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)} %(mflib)\
+ %{fprofile-arcs|fprofile-generate*|coverage:-lgcov}\
%{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
%{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
#endif
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 *linker_plugin_file_spec = "";
+static const char *lto_wrapper_spec = "";
+static const char *lto_gcc_spec = "";
+static const char *lto_libgcc_spec = "";
static const char *link_command_spec = LINK_COMMAND_SPEC;
static const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
static const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC;
therefore no dependency entry, confuses make into thinking a .o
file that happens to exist is up-to-date. */
static const char *cpp_unique_options =
-"%{C|CC:%{!E:%eGCC does not support -C or -CC without -E}}\
- %{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*&F*} %{P} %I\
+"%{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*&F*} %{P} %I\
%{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\
%{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\
%{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\
%{!E:%{!M:%{!MM:%{!MT:%{!MQ:%{MD|MMD:%{o*:-MQ %*}}}}}}}\
%{remap} %{g3|ggdb3|gstabs3|gcoff3|gxcoff3|gvms3:-dD}\
+ %{!iplugindir*:%{fplugin*:%:find-plugindir()}}\
%{H} %C %{D*&U*&A*} %{i*} %Z %i\
%{fmudflap:-D_MUDFLAP -include mf-runtime.h}\
%{fmudflapth:-D_MUDFLAP -D_MUDFLAPTH -include mf-runtime.h}\
in turn cause preprocessor symbols to be defined specially. */
static const char *cpp_options =
"%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w}\
- %{f*} %{g*:%{!g0:%{!fno-working-directory:-fworking-directory}}} %{O*}\
- %{undef} %{save-temps:-fpch-preprocess}";
+ %{f*} %{g*:%{!g0:%{g*} %{!fno-working-directory:-fworking-directory}}} %{O*}\
+ %{undef} %{save-temps*:-fpch-preprocess}";
/* This contains cpp options which are not passed when the preprocessor
output will be used by another program. */
static const char *cpp_debug_options = "%{d*}";
-/* NB: This is shared amongst all front-ends. */
+/* NB: This is shared amongst all front-ends, except for Ada. */
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*}\
- %{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}%{!c:%{!S:-auxbase %b}}\
+ %{!iplugindir*:%{fplugin*:%:find-plugindir()}}\
+ %1 %{!Q:-quiet} %{!dumpbase:-dumpbase %B} %{d*} %{m*} %{a*}\
+ %{fcompare-debug-second:%:compare-debug-auxbase-opt(%b)} \
+ %{!fcompare-debug-second:%{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}}%{!c:%{!S:-auxbase %b}} \
%{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs}\
%{v:-version} %{pg:-p} %{p} %{f*} %{undef}\
%{Qn:-fno-ident} %{--help:--help}\
%{coverage:-fprofile-arcs -ftest-coverage}";
static const char *asm_options =
-"%{ftarget-help:%:print-asm-header()} \
-%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
+"%{--target-help:%:print-asm-header()} "
+#if HAVE_GNU_AS
+/* If GNU AS is used, then convert -w (no warnings), -I, and -v
+ to the assembler equivalents. */
+"%{v} %{w:-W} %{I*} "
+#endif
+"%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
static const char *invoke_as =
#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
-"%{!S:-o %|.s |\n as %(asm_options) %|.s %A }";
+"%{!fwpa:\
+ %{fcompare-debug=*|fdump-final-insns=*:%:compare-debug-dump-opt()}\
+ %{!S:-o %|.s |\n as %(asm_options) %|.s %A }\
+ }";
#else
-"%{!S:-o %|.s |\n as %(asm_options) %m.s %A }";
+"%{!fwpa:\
+ %{fcompare-debug=*|fdump-final-insns=*:%:compare-debug-dump-opt()}\
+ %{!S:-o %|.s |\n as %(asm_options) %m.s %A }\
+ }";
#endif
/* Some compilers have limits on line lengths, and the multilib_select
/* Adding -fopenmp should imply pthreads. This is particularly important
for targets that use different start files and suchlike. */
#ifndef GOMP_SELF_SPECS
-#define GOMP_SELF_SPECS "%{fopenmp: -pthread}"
+#define GOMP_SELF_SPECS "%{fopenmp|ftree-parallelize-loops=*: -pthread}"
#endif
static const char *const driver_self_specs[] = {
- DRIVER_SELF_SPECS, GOMP_SELF_SPECS
+ "%{fdump-final-insns:-fdump-final-insns=.} %<fdump-final-insns",
+ DRIVER_SELF_SPECS, CONFIGURE_SPECS, GOMP_SELF_SPECS
};
#ifndef OPTION_DEFAULT_SPECS
#ifdef HAVE_TARGET_EXECUTABLE_SUFFIX
/* This defines which switches stop a full compilation. */
#define DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) \
- ((CHAR) == 'c' || (CHAR) == 'S')
+ ((CHAR) == 'c' || (CHAR) == 'S' || (CHAR) == 'E')
#ifndef SWITCH_CURTAILS_COMPILATION
#define SWITCH_CURTAILS_COMPILATION(CHAR) \
{".c++", "#C++", 0, 0, 0}, {".C", "#C++", 0, 0, 0},
{".CPP", "#C++", 0, 0, 0}, {".ii", "#C++", 0, 0, 0},
{".ads", "#Ada", 0, 0, 0}, {".adb", "#Ada", 0, 0, 0},
- {".f", "#Fortran", 0, 0, 0}, {".for", "#Fortran", 0, 0, 0},
- {".fpp", "#Fortran", 0, 0, 0}, {".F", "#Fortran", 0, 0, 0},
- {".FOR", "#Fortran", 0, 0, 0}, {".FPP", "#Fortran", 0, 0, 0},
- {".f90", "#Fortran", 0, 0, 0}, {".f95", "#Fortran", 0, 0, 0},
- {".F90", "#Fortran", 0, 0, 0}, {".F95", "#Fortran", 0, 0, 0},
+ {".f", "#Fortran", 0, 0, 0}, {".F", "#Fortran", 0, 0, 0},
+ {".for", "#Fortran", 0, 0, 0}, {".FOR", "#Fortran", 0, 0, 0},
+ {".ftn", "#Fortran", 0, 0, 0}, {".FTN", "#Fortran", 0, 0, 0},
+ {".fpp", "#Fortran", 0, 0, 0}, {".FPP", "#Fortran", 0, 0, 0},
+ {".f90", "#Fortran", 0, 0, 0}, {".F90", "#Fortran", 0, 0, 0},
+ {".f95", "#Fortran", 0, 0, 0}, {".F95", "#Fortran", 0, 0, 0},
+ {".f03", "#Fortran", 0, 0, 0}, {".F03", "#Fortran", 0, 0, 0},
+ {".f08", "#Fortran", 0, 0, 0}, {".F08", "#Fortran", 0, 0, 0},
{".r", "#Ratfor", 0, 0, 0},
{".p", "#Pascal", 0, 0, 0}, {".pas", "#Pascal", 0, 0, 0},
{".java", "#Java", 0, 0, 0}, {".class", "#Java", 0, 0, 0},
%{traditional|ftraditional:\
%eGNU C no longer supports -traditional without -E}\
%{!combine:\
- %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
- %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\
- cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \
+ %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
+ %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\
+ cc1 -fpreprocessed %{save-temps*:%b.i} %{!save-temps*:%g.i} \
%(cc1_options)}\
- %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
+ %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\
cc1 %(cpp_unique_options) %(cc1_options)}}}\
%{!fsyntax-only:%(invoke_as)}} \
%{combine:\
- %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
- %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i}}\
- %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
+ %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
+ %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i}}\
+ %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\
cc1 %(cpp_unique_options) %(cc1_options)}}\
%{!fsyntax-only:%(invoke_as)}}}}}}", 0, 1, 1},
{"-",
external preprocessor if -save-temps is given. */
"%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
%{!E:%{!M:%{!MM:\
- %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
- %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\
- cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \
+ %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
+ %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\
+ cc1 -fpreprocessed %{save-temps*:%b.i} %{!save-temps*:%g.i} \
%(cc1_options)\
- -o %g.s %{!o*:--output-pch=%i.gch}\
- %W{o*:--output-pch=%*}%V}\
- %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
+ %{!fdump-ada-spec*:-o %g.s %{!o*:--output-pch=%i.gch}\
+ %W{o*:--output-pch=%*}}%V}\
+ %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\
cc1 %(cpp_unique_options) %(cc1_options)\
- -o %g.s %{!o*:--output-pch=%i.gch}\
- %W{o*:--output-pch=%*}%V}}}}}}", 0, 0, 0},
+ %{!fdump-ada-spec*:-o %g.s %{!o*:--output-pch=%i.gch}\
+ %W{o*:--output-pch=%*}}%V}}}}}}", 0, 0, 0},
{".i", "@cpp-output", 0, 1, 0},
{"@cpp-output",
"%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 1, 0},
{".s", "@assembler", 0, 1, 0},
{"@assembler",
"%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0, 1, 0},
+ {".sx", "@assembler-with-cpp", 0, 1, 0},
{".S", "@assembler-with-cpp", 0, 1, 0},
{"@assembler-with-cpp",
#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
- "%(trad_capable_cpp) -lang-asm %(cpp_options)\
+ "%(trad_capable_cpp) -lang-asm %(cpp_options) -fno-directives-only\
%{E|M|MM:%(cpp_debug_options)}\
%{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
as %(asm_debug) %(asm_options) %|.s %A }}}}"
#else
- "%(trad_capable_cpp) -lang-asm %(cpp_options)\
+ "%(trad_capable_cpp) -lang-asm %(cpp_options) -fno-directives-only\
%{E|M|MM:%(cpp_debug_options)}\
%{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
as %(asm_debug) %(asm_options) %m.s %A }}}}"
{"--dependencies", "-M", 0},
{"--dump", "-d", "a"},
{"--dumpbase", "-dumpbase", "a"},
+ {"--dumpdir", "-dumpdir", "a"},
{"--encoding", "-fencoding=", "aj"},
{"--entry", "-e", 0},
{"--extra-warnings", "-W", 0},
{"--library-directory", "-L", "a"},
{"--machine", "-m", "aj"},
{"--machine-", "-m", "*j"},
+ {"--no-canonical-prefixes", "-no-canonical-prefixes", 0},
{"--no-integrated-cpp", "-no-integrated-cpp", 0},
{"--no-line-commands", "-P", 0},
{"--no-precompiled-includes", "-noprecomp", 0},
{"--print-multi-directory", "-print-multi-directory", 0},
{"--print-multi-os-directory", "-print-multi-os-directory", 0},
{"--print-prog-name", "-print-prog-name=", "aj"},
+ {"--print-sysroot", "-print-sysroot", 0},
{"--print-sysroot-headers-suffix", "-print-sysroot-headers-suffix", 0},
{"--profile", "-p", 0},
{"--profile-blocks", "-a", 0},
/* Translate the options described by *ARGCP and *ARGVP.
Make a new vector and store it back in *ARGVP,
- and store its length in *ARGVC. */
+ and store its length in *ARGCP. */
static void
translate_options (int *argcp, const char *const **argvp)
int argc = *argcp;
const char *const *argv = *argvp;
int newvsize = (argc + 2) * 2 * sizeof (const char *);
- const char **newv = xmalloc (newvsize);
+ const char **newv = XNEWVAR (const char *, newvsize);
int newindex = 0;
i = 0;
}
newvsize += spaces * sizeof (const char *);
- newv = xrealloc (newv, newvsize);
+ newv = XRESIZEVAR (const char *, newv, newvsize);
sp = target_option_translations[tott_idx].replacements;
np = xstrdup (sp);
else if (strchr (arginfo, '*') != 0)
{
- error ("incomplete '%s' option", option_map[j].name);
+ error ("incomplete %qs option", option_map[j].name);
break;
}
{
if (i + 1 == argc)
{
- error ("missing argument to '%s' option",
+ error ("missing argument to %qs option",
option_map[j].name);
break;
}
else if (strchr (arginfo, 'o') == 0)
{
if (arg != 0)
- error ("extraneous argument to '%s' option",
+ error ("extraneous argument to %qs option",
option_map[j].name);
arg = 0;
}
}
}
else
- /* Ordinary operands, or +e options. */
+ /* Ordinary operands. */
newv[newindex++] = argv[i++];
}
/* For native compilers, these are well-known paths containing
components that may be provided by the system. For cross
compilers, these paths are not used. */
-static const char *const standard_exec_prefix_1 = "/usr/libexec/gcc/";
-static const char *const standard_exec_prefix_2 = "/usr/lib/gcc/";
static const char *md_exec_prefix = MD_EXEC_PREFIX;
static const char *md_startfile_prefix = MD_STARTFILE_PREFIX;
static const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
INIT_STATIC_SPEC ("link_gomp", &link_gomp_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 ("cross_compile", &cross_compile),
INIT_STATIC_SPEC ("version", &compiler_version),
INIT_STATIC_SPEC ("multilib", &multilib_select),
INIT_STATIC_SPEC ("multilib_exclusions", &multilib_exclusions),
INIT_STATIC_SPEC ("multilib_options", &multilib_options),
INIT_STATIC_SPEC ("linker", &linker_name_spec),
+ INIT_STATIC_SPEC ("linker_plugin_file", &linker_plugin_file_spec),
+ INIT_STATIC_SPEC ("lto_wrapper", <o_wrapper_spec),
+ INIT_STATIC_SPEC ("lto_gcc", <o_gcc_spec),
+ INIT_STATIC_SPEC ("lto_libgcc", <o_libgcc_spec),
INIT_STATIC_SPEC ("link_libgcc", &link_libgcc_spec),
INIT_STATIC_SPEC ("md_exec_prefix", &md_exec_prefix),
INIT_STATIC_SPEC ("md_startfile_prefix", &md_startfile_prefix),
{ "replace-outfile", replace_outfile_spec_function },
{ "version-compare", version_compare_spec_function },
{ "include", include_spec_function },
+ { "find-file", find_file_spec_function },
+ { "find-plugindir", find_plugindir_spec_function },
{ "print-asm-header", print_asm_header_spec_function },
+ { "compare-debug-dump-opt", compare_debug_dump_opt_spec_function },
+ { "compare-debug-self-opt", compare_debug_self_opt_spec_function },
+ { "compare-debug-auxbase-opt", compare_debug_auxbase_opt_spec_function },
#ifdef EXTRA_SPEC_FUNCTIONS
EXTRA_SPEC_FUNCTIONS
#endif
return; /* Already initialized. */
if (verbose_flag)
- notice ("Using built-in specs.\n");
+ fnotice (stderr, "Using built-in specs.\n");
#ifdef EXTRA_SPECS
- extra_specs = xcalloc (sizeof (struct spec_list),
- ARRAY_SIZE (extra_specs_1));
+ extra_specs = XCNEWVEC (struct spec_list, ARRAY_SIZE (extra_specs_1));
for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--)
{
}
#endif
- /* Initialize here, not in definition. The IRIX 6 O32 cc sometimes chokes
- on ?: in file-scope variable initializations. */
- asm_debug = ASM_DEBUG_SPEC;
-
for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
{
sl = &static_specs[i];
asm_spec = XOBFINISH (&obstack, const char *);
}
#endif
-#ifdef LINK_EH_SPEC
+
+#if defined LINK_EH_SPEC || defined LINK_BUILDID_SPEC
+# ifdef LINK_BUILDID_SPEC
+ /* Prepend LINK_BUILDID_SPEC to whatever link_spec we had before. */
+ obstack_grow (&obstack, LINK_BUILDID_SPEC, sizeof(LINK_BUILDID_SPEC) - 1);
+# endif
+# ifdef LINK_EH_SPEC
/* Prepend LINK_EH_SPEC to whatever link_spec we had before. */
obstack_grow (&obstack, LINK_EH_SPEC, sizeof(LINK_EH_SPEC) - 1);
+# endif
obstack_grow0 (&obstack, link_spec, strlen (link_spec));
link_spec = XOBFINISH (&obstack, const char *);
#endif
#ifdef DEBUG_SPECS
if (verbose_flag)
- notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
+ fnotice (stderr, "Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
#endif
/* Free the old spec. */
if (old_spec && sl->alloc_p)
- free ((void *) old_spec);
+ free (CONST_CAST(char *, old_spec));
sl->alloc_p = 1;
}
static int have_o_argbuf_index = 0;
-/* Were the options -c or -S passed. */
+/* Were the options -c, -S or -E passed. */
static int have_c = 0;
/* Was the option -o passed. */
/* Number of commands that exited with a signal. */
static int signal_count;
-
-/* Name with which this program was invoked. */
-
-static const char *programname;
\f
/* Allocate the argument vector. */
store_arg (const char *arg, int delete_always, int delete_failure)
{
if (argbuf_index + 1 == argbuf_length)
- argbuf = xrealloc (argbuf, (argbuf_length *= 2) * sizeof (const char *));
+ argbuf = XRESIZEVEC (const char *, argbuf, (argbuf_length *= 2));
argbuf[argbuf_index++] = arg;
argbuf[argbuf_index] = 0;
if (strcmp (arg, "-o") == 0)
have_o_argbuf_index = argbuf_index;
if (delete_always || delete_failure)
- record_temp_file (arg, delete_always, delete_failure);
+ {
+ const char *p;
+ /* If the temporary file we should delete is specified as
+ part of a joined argument extract the filename. */
+ if (arg[0] == '-'
+ && (p = strrchr (arg, '=')))
+ arg = p + 1;
+ record_temp_file (arg, delete_always, delete_failure);
+ }
}
\f
/* Load specs from a file name named FILENAME, replacing occurrences of
char *specs_p;
if (verbose_flag)
- notice ("Reading specs from %s\n", filename);
+ fnotice (stderr, "Reading specs from %s\n", filename);
/* Open and stat the file. */
desc = open (filename, O_RDONLY, 0);
p1++;
if (*p1++ != '<' || p[-2] != '>')
- fatal ("specs %%include syntax malformed after %ld characters",
- (long) (p1 - buffer + 1));
+ fatal_error ("specs %%include syntax malformed after "
+ "%ld characters",
+ (long) (p1 - buffer + 1));
p[-2] = '\0';
new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
p1++;
if (*p1++ != '<' || p[-2] != '>')
- fatal ("specs %%include syntax malformed after %ld characters",
- (long) (p1 - buffer + 1));
+ fatal_error ("specs %%include syntax malformed after "
+ "%ld characters",
+ (long) (p1 - buffer + 1));
p[-2] = '\0';
new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
if (new_filename)
read_specs (new_filename, FALSE);
else if (verbose_flag)
- notice ("could not find specs file %s\n", p1);
+ fnotice (stderr, "could not find specs file %s\n", p1);
continue;
}
else if (!strncmp (p1, "%rename", sizeof "%rename" - 1)
p1++;
if (! ISALPHA ((unsigned char) *p1))
- fatal ("specs %%rename syntax malformed after %ld characters",
- (long) (p1 - buffer));
+ fatal_error ("specs %%rename syntax malformed after "
+ "%ld characters",
+ (long) (p1 - buffer));
p2 = p1;
while (*p2 && !ISSPACE ((unsigned char) *p2))
p2++;
if (*p2 != ' ' && *p2 != '\t')
- fatal ("specs %%rename syntax malformed after %ld characters",
- (long) (p2 - buffer));
+ fatal_error ("specs %%rename syntax malformed after "
+ "%ld characters",
+ (long) (p2 - buffer));
name_len = p2 - p1;
*p2++ = '\0';
p2++;
if (! ISALPHA ((unsigned char) *p2))
- fatal ("specs %%rename syntax malformed after %ld characters",
- (long) (p2 - buffer));
+ fatal_error ("specs %%rename syntax malformed after "
+ "%ld characters",
+ (long) (p2 - buffer));
/* Get new spec name. */
p3 = p2;
p3++;
if (p3 != p - 1)
- fatal ("specs %%rename syntax malformed after %ld characters",
- (long) (p3 - buffer));
+ fatal_error ("specs %%rename syntax malformed after "
+ "%ld characters",
+ (long) (p3 - buffer));
*p3 = '\0';
for (sl = specs; sl; sl = sl->next)
break;
if (!sl)
- fatal ("specs %s spec was not found to be renamed", p1);
+ fatal_error ("specs %s spec was not found to be renamed", p1);
if (strcmp (p1, p2) == 0)
continue;
for (newsl = specs; newsl; newsl = newsl->next)
if (strcmp (newsl->name, p2) == 0)
- fatal ("%s: attempt to rename spec '%s' to already defined spec '%s'",
+ fatal_error ("%s: attempt to rename spec %qs to "
+ "already defined spec %qs",
filename, p1, p2);
if (verbose_flag)
{
- notice ("rename spec %s to %s\n", p1, p2);
+ fnotice (stderr, "rename spec %s to %s\n", p1, p2);
#ifdef DEBUG_SPECS
- notice ("spec is '%s'\n\n", *(sl->ptr_spec));
+ fnotice (stderr, "spec is '%s'\n\n", *(sl->ptr_spec));
#endif
}
set_spec (p2, *(sl->ptr_spec));
if (sl->alloc_p)
- free ((void *) *(sl->ptr_spec));
+ free (CONST_CAST (char *, *(sl->ptr_spec)));
*(sl->ptr_spec) = "";
sl->alloc_p = 0;
continue;
}
else
- fatal ("specs unknown %% command after %ld characters",
- (long) (p1 - buffer));
+ fatal_error ("specs unknown %% command after %ld characters",
+ (long) (p1 - buffer));
}
/* Find the colon that should end the suffix. */
/* The colon shouldn't be missing. */
if (*p1 != ':')
- fatal ("specs file malformed after %ld characters",
- (long) (p1 - buffer));
+ fatal_error ("specs file malformed after %ld characters",
+ (long) (p1 - buffer));
/* Skip back over trailing whitespace. */
p2 = p1;
/* Find the next line. */
p = skip_whitespace (p1 + 1);
if (p[1] == 0)
- fatal ("specs file malformed after %ld characters",
- (long) (p - buffer));
+ fatal_error ("specs file malformed after %ld characters",
+ (long) (p - buffer));
p1 = p;
/* Find next blank line or end of string. */
{
/* Add this pair to the vector. */
compilers
- = xrealloc (compilers,
- (n_compilers + 2) * sizeof (struct compiler));
+ = XRESIZEVEC (struct compiler, compilers, n_compilers + 2);
compilers[n_compilers].suffix = suffix;
compilers[n_compilers].spec = spec;
}
if (link_command_spec == 0)
- fatal ("spec file has no spec for linking");
+ fatal_error ("spec file has no spec for linking");
}
\f
/* Record the names of temporary files we tell compilers to write,
Don't repeat any we have already seen. */
if (multi_dir)
{
- free ((char *) multi_dir);
+ free (CONST_CAST (char *, multi_dir));
multi_dir = NULL;
- free ((char *) multi_suffix);
+ free (CONST_CAST (char *, multi_suffix));
multi_suffix = machine_suffix;
- free ((char *) just_multi_suffix);
+ free (CONST_CAST (char *, just_multi_suffix));
just_multi_suffix = just_machine_suffix;
}
else
skip_multi_dir = true;
if (multi_os_dir)
{
- free ((char *) multi_os_dir);
+ free (CONST_CAST (char *, multi_os_dir));
multi_os_dir = NULL;
}
else
if (multi_dir)
{
- free ((char *) multi_dir);
- free ((char *) multi_suffix);
- free ((char *) just_multi_suffix);
+ free (CONST_CAST (char *, multi_dir));
+ free (CONST_CAST (char *, multi_suffix));
+ free (CONST_CAST (char *, just_multi_suffix));
}
if (multi_os_dir)
- free ((char *) multi_os_dir);
+ free (CONST_CAST (char *, multi_os_dir));
if (ret != path)
free (path);
return ret;
static void *
add_to_obstack (char *path, void *data)
{
- struct add_to_obstack_info *info = data;
+ struct add_to_obstack_info *info = (struct add_to_obstack_info *) data;
if (info->check_dir && !is_directory (path, false))
return NULL;
return NULL;
}
+/* Add or change the value of an environment variable, outputting the
+ change to standard error if in verbose mode. */
+static void
+xputenv (const char *string)
+{
+ if (verbose_flag)
+ fnotice (stderr, "%s\n", string);
+ putenv (CONST_CAST (char *, string));
+}
+
/* Build a list of search directories from PATHS.
PREFIX is a string to prepend to the list.
If CHECK_DIR_P is true we ensure the directory exists.
putenv_from_prefixes (const struct path_prefix *paths, const char *env_var,
bool do_multi)
{
- putenv (build_search_list (paths, env_var, true, do_multi));
+ xputenv (build_search_list (paths, env_var, true, do_multi));
}
\f
/* Check whether NAME can be accessed in MODE. This is like access,
static void *
file_at_path (char *path, void *data)
{
- struct file_at_path_info *info = data;
+ struct file_at_path_info *info = (struct file_at_path_info *) data;
size_t len = strlen (path);
memcpy (path + len, info->name, info->name_len);
info.suffix_len = strlen (info.suffix);
info.mode = mode;
- return for_each_path (pprefix, do_multi, info.name_len + info.suffix_len,
- file_at_path, &info);
+ return (char*) for_each_path (pprefix, do_multi,
+ info.name_len + info.suffix_len,
+ file_at_path, &info);
}
/* Ranking of prefixes in the sort list. -B prefixes are put before
int require_machine_suffix, int os_multilib)
{
if (!IS_ABSOLUTE_PATH (prefix))
- fatal ("system path '%s' is not absolute", prefix);
+ fatal_error ("system path %qs is not absolute", prefix);
if (target_system_root)
{
gcc_assert (!processing_spec_function);
+ if (wrapper_string)
+ {
+ string = find_a_file (&exec_prefixes, argbuf[0], X_OK, false);
+ argbuf[0] = (string) ? string : argbuf[0];
+ insert_wrapper (wrapper_string);
+ }
+
/* Count # of piped commands. */
for (n_commands = 1, i = 0; i < argbuf_index; i++)
if (strcmp (argbuf[i], "|") == 0)
n_commands++;
/* Get storage for each command. */
- commands = alloca (n_commands * sizeof (struct command));
+ commands = (struct command *) alloca (n_commands * sizeof (struct command));
/* Split argbuf into its separate piped processes,
and record info about each one.
commands[0].prog = argbuf[0]; /* first command. */
commands[0].argv = &argbuf[0];
- string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
- if (string)
- commands[0].argv[0] = string;
+ if (!wrapper_string)
+ {
+ string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
+ commands[0].argv[0] = (string) ? string : commands[0].argv[0];
+ }
for (n_commands = 1, i = 0; i < argbuf_index; i++)
if (strcmp (argbuf[i], "|") == 0)
{ /* each command. */
#if defined (__MSDOS__) || defined (OS2) || defined (VMS)
- fatal ("-pipe not supported");
+ fatal_error ("-pipe not supported");
#endif
argbuf[i] = 0; /* termination of command args. */
commands[n_commands].prog = argbuf[i + 1];
for (j = commands[i].argv; *j; j++)
{
const char *p;
- fprintf (stderr, " \"");
for (p = *j; *p; ++p)
+ if (!ISALNUM ((unsigned char) *p)
+ && *p != '_' && *p != '/' && *p != '-' && *p != '.')
+ break;
+ if (*p || !*j)
{
- if (*p == '"' || *p == '\\' || *p == '$')
- fputc ('\\', stderr);
- fputc (*p, stderr);
+ fprintf (stderr, " \"");
+ for (p = *j; *p; ++p)
+ {
+ if (*p == '"' || *p == '\\' || *p == '$')
+ fputc ('\\', stderr);
+ fputc (*p, stderr);
+ }
+ fputc ('"', stderr);
}
- fputc ('"', stderr);
+ else
+ fprintf (stderr, " %s", *j);
}
}
else
return 0;
}
#ifdef DEBUG
- notice ("\nGo ahead? (y or n) ");
+ fnotice (stderr, "\nGo ahead? (y or n) ");
fflush (stderr);
i = getchar ();
if (i != '\n')
for (argc = 0; commands[i].argv[argc] != NULL; argc++)
;
- argv = alloca ((argc + 3) * sizeof (char *));
+ argv = XALLOCAVEC (const char *, argc + 3);
argv[0] = VALGRIND_PATH;
argv[1] = "-q";
/* Run each piped subprocess. */
- pex = pex_init (PEX_USE_PIPES | (report_times ? PEX_RECORD_TIMES : 0),
- programname, temp_filename);
+ pex = pex_init (PEX_USE_PIPES | ((report_times || report_times_to_file)
+ ? PEX_RECORD_TIMES : 0),
+ progname, temp_filename);
if (pex == NULL)
- pfatal_with_name (_("pex_init failed"));
+ fatal_error ("pex_init failed: %m");
for (i = 0; i < n_commands; i++)
{
errmsg = pex_run (pex,
((i + 1 == n_commands ? PEX_LAST : 0)
| (string == commands[i].prog ? PEX_SEARCH : 0)),
- string, (char * const *) commands[i].argv,
+ string, CONST_CAST (char **, commands[i].argv),
NULL, NULL, &err);
if (errmsg != NULL)
{
if (err == 0)
- fatal (errmsg);
+ fatal_error (errmsg);
else
{
errno = err;
}
if (string != commands[i].prog)
- free ((void *) string);
+ free (CONST_CAST (char *, string));
}
execution_count++;
struct pex_time *times = NULL;
int ret_code = 0;
- statuses = alloca (n_commands * sizeof (int));
+ statuses = (int *) alloca (n_commands * sizeof (int));
if (!pex_get_status (pex, n_commands, statuses))
- pfatal_with_name (_("failed to get exit status"));
+ fatal_error ("failed to get exit status: %m");
- if (report_times)
+ if (report_times || report_times_to_file)
{
- times = alloca (n_commands * sizeof (struct pex_time));
+ times = (struct pex_time *) alloca (n_commands * sizeof (struct pex_time));
if (!pex_get_times (pex, n_commands, times))
- pfatal_with_name (_("failed to get process times"));
+ fatal_error ("failed to get process times: %m");
}
pex_free (pex);
}
else
#endif
- fatal_ice ("\
-Internal error: %s (program %s)\n\
-Please submit a full bug report.\n\
-See %s for instructions.",
- strsignal (WTERMSIG (status)), commands[i].prog,
- bug_report_url);
+ internal_error ("%s (program %s)",
+ strsignal (WTERMSIG (status)), commands[i].prog);
}
else if (WIFEXITED (status)
&& WEXITSTATUS (status) >= MIN_FATAL_STATUS)
ret_code = -1;
}
- if (report_times)
+ if (report_times || report_times_to_file)
{
struct pex_time *pt = ×[i];
double ut, st;
+ (double) pt->system_microseconds / 1.0e6);
if (ut + st != 0)
- notice ("# %s %.2f %.2f\n", commands[i].prog, ut, st);
+ {
+ if (report_times)
+ fnotice (stderr, "# %s %.2f %.2f\n",
+ commands[i].prog, ut, st);
+
+ if (report_times_to_file)
+ {
+ int c = 0;
+ const char *const *j;
+
+ fprintf (report_times_to_file, "%g %g", ut, st);
+
+ for (j = &commands[i].prog; *j; j = &commands[i].argv[++c])
+ {
+ const char *p;
+ for (p = *j; *p; ++p)
+ if (*p == '"' || *p == '\\' || *p == '$'
+ || ISSPACE (*p))
+ break;
+
+ if (*p)
+ {
+ fprintf (report_times_to_file, " \"");
+ for (p = *j; *p; ++p)
+ {
+ if (*p == '"' || *p == '\\' || *p == '$')
+ fputc ('\\', report_times_to_file);
+ fputc (*p, report_times_to_file);
+ }
+ fputc ('"', report_times_to_file);
+ }
+ else
+ fprintf (report_times_to_file, " %s", *j);
+ }
+
+ fputc ('\n', report_times_to_file);
+ }
+ }
}
}
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:
- 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)
+ Bits in the `live_cond' field are:
+ SWITCH_LIVE to indicate this switch is true in a conditional spec.
+ SWITCH_FALSE to indicate this switch is overridden by a later switch.
+ SWITCH_IGNORE to indicate this switch should be ignored (used in %<S).
+ SWITCH_IGNORE_PERMANENTLY to indicate this switch should be ignored
+ in all do_spec calls afterwards. Used for %<S from self specs.
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
+#define SWITCH_LIVE 0x1
+#define SWITCH_FALSE 0x2
+#define SWITCH_IGNORE 0x4
+#define SWITCH_IGNORE_PERMANENTLY 0x8
struct switchstr
{
const char *part1;
const char **args;
- int live_cond;
+ unsigned int live_cond;
unsigned char validated;
unsigned char ordering;
};
static int n_switches;
+static int n_switches_alloc;
+
+/* Set to zero if -fcompare-debug is disabled, positive if it's
+ enabled and we're running the first compilation, negative if it's
+ enabled and we're running the second compilation. For most of the
+ time, it's in the range -1..1, but it can be temporarily set to 2
+ or 3 to indicate that the -fcompare-debug flags didn't come from
+ the command-line, but rather from the GCC_COMPARE_DEBUG environment
+ variable, until a synthesized -fcompare-debug flag is added to the
+ command line. */
+int compare_debug;
+
+/* Set to nonzero if we've seen the -fcompare-debug-second flag. */
+int compare_debug_second;
+
+/* Set to the flags that should be passed to the second compilation in
+ a -fcompare-debug compilation. */
+const char *compare_debug_opt;
+
+static struct switchstr *switches_debug_check[2];
+
+static int n_switches_debug_check[2];
+
+static char *debug_check_temp_file[2];
+
/* Language is one of three things:
1) The name of a real programming language.
int n_infiles;
+static int n_infiles_alloc;
+
/* True if multiple input files are being compiled to a single
assembly file. */
static void
display_help (void)
{
- printf (_("Usage: %s [options] file...\n"), programname);
+ printf (_("Usage: %s [options] file...\n"), progname);
fputs (_("Options:\n"), stdout);
fputs (_(" -pass-exit-codes Exit with highest error code from a phase\n"), stdout);
fputs (_(" --help Display this information\n"), stdout);
fputs (_(" --target-help Display target specific command line options\n"), stdout);
- fputs (_(" --help={target|optimizers|warnings|undocumented|params}[,{[^]joined|[^]separate}]\n"), stdout);
+ fputs (_(" --help={target|optimizers|warnings|params|[^]{joined|separate|undocumented}}[,...]\n"), stdout);
fputs (_(" Display specific types of command line options\n"), stdout);
if (! verbose_flag)
fputs (_(" (Use '-v --help' to display command line options of sub-processes)\n"), stdout);
+ fputs (_(" --version Display compiler version information\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);
-print-multi-lib Display the mapping between command line options and\n\
multiple library search directories\n"), stdout);
fputs (_(" -print-multi-os-directory Display the relative path to OS libraries\n"), stdout);
+ fputs (_(" -print-sysroot Display the target libraries directory\n"), stdout);
fputs (_(" -print-sysroot-headers-suffix Display the sysroot suffix used to find headers\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 (_(" -Xlinker <arg> Pass <arg> on to the linker\n"), stdout);
fputs (_(" -combine Pass multiple source files to compiler at once\n"), stdout);
fputs (_(" -save-temps Do not delete intermediate files\n"), stdout);
+ fputs (_(" -save-temps=<arg> Do not delete intermediate files\n"), stdout);
+ fputs (_("\
+ -no-canonical-prefixes Do not canonicalize paths when building relative\n\
+ prefixes to other gcc components\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 built-in specs with the contents of <file>\n"), stdout);
--sysroot=<directory> Use <directory> as the root directory for headers\n\
and libraries\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 (_(" -### Like -v but options quoted and commands not executed\n"), stdout);
fputs (_(" -E Preprocess only; do not compile, assemble or link\n"), stdout);
\nOptions starting with -g, -f, -m, -O, -W, or --param are automatically\n\
passed on to the various sub-processes invoked by %s. In order to pass\n\
other options on to these processes the -W<letter> options must be used.\n\
-"), programname);
+"), progname);
/* The rest of the options are displayed by invocations of the various
sub-processes. */
if (! preprocessor_options)
preprocessor_options = XNEWVEC (char *, n_preprocessor_options);
else
- preprocessor_options = xrealloc (preprocessor_options,
- n_preprocessor_options * sizeof (char *));
+ preprocessor_options = XRESIZEVEC (char *, preprocessor_options,
+ n_preprocessor_options);
preprocessor_options [n_preprocessor_options - 1] =
save_string (option, len);
if (! assembler_options)
assembler_options = XNEWVEC (char *, n_assembler_options);
else
- assembler_options = xrealloc (assembler_options,
- n_assembler_options * sizeof (char *));
+ assembler_options = XRESIZEVEC (char *, assembler_options,
+ n_assembler_options);
assembler_options [n_assembler_options - 1] = save_string (option, len);
}
if (! linker_options)
linker_options = XNEWVEC (char *, n_linker_options);
else
- linker_options = xrealloc (linker_options,
- n_linker_options * sizeof (char *));
+ linker_options = XRESIZEVEC (char *, linker_options, n_linker_options);
linker_options [n_linker_options - 1] = save_string (option, len);
}
\f
+/* Allocate space for an input file in infiles. */
+
+static void
+alloc_infile (void)
+{
+ if (n_infiles_alloc == 0)
+ {
+ n_infiles_alloc = 16;
+ infiles = XNEWVEC (struct infile, n_infiles_alloc);
+ }
+ else if (n_infiles_alloc == n_infiles)
+ {
+ n_infiles_alloc *= 2;
+ infiles = XRESIZEVEC (struct infile, infiles, n_infiles_alloc);
+ }
+}
+
+/* Store an input file with the given NAME and LANGUAGE in
+ infiles. */
+
+static void
+add_infile (const char *name, const char *language)
+{
+ alloc_infile ();
+ infiles[n_infiles].name = name;
+ infiles[n_infiles++].language = language;
+}
+
+/* Allocate space for a switch in switches. */
+
+static void
+alloc_switch (void)
+{
+ if (n_switches_alloc == 0)
+ {
+ n_switches_alloc = 16;
+ switches = XNEWVEC (struct switchstr, n_switches_alloc);
+ }
+ else if (n_switches_alloc == n_switches)
+ {
+ n_switches_alloc *= 2;
+ switches = XRESIZEVEC (struct switchstr, switches, n_switches_alloc);
+ }
+}
+
/* Create the vector `switches' and its contents.
Store its length in `n_switches'. */
char *temp1;
const char *spec_lang = 0;
int last_language_n_infiles;
- int lang_n_infiles = 0;
-#ifdef MODIFY_TARGET_NAME
- int is_modify_target_name;
- unsigned int j;
-#endif
const char *tooldir_prefix;
+ char *(*get_relative_prefix) (const char *, const char *,
+ const char *) = NULL;
GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
}
}
- /* If there is a -V or -b option (or both), process it now, before
- trying to interpret the rest of the command line.
- Use heuristic that all configuration names must have at least
- one dash '-'. This allows us to pass options starting with -b. */
- if (argc > 1 && argv[1][0] == '-'
- && (argv[1][1] == 'V' ||
- ((argv[1][1] == 'b') && (NULL != strchr(argv[1] + 2,'-')))))
+ /* Convert new-style -- options to old-style. */
+ translate_options (&argc,
+ CONST_CAST2 (const char *const **, const char ***,
+ &argv));
+
+ /* Handle any -no-canonical-prefixes flag early, to assign the function
+ that builds relative prefixes. This function creates default search
+ paths that are needed later in normal option handling. */
+
+ for (i = 1; i < argc; i++)
{
- const char *new_version = DEFAULT_TARGET_VERSION;
- const char *new_machine = DEFAULT_TARGET_MACHINE;
- const char *progname = argv[0];
- char **new_argv;
- char *new_argv0;
- int baselen;
-
- while (argc > 1 && argv[1][0] == '-'
- && (argv[1][1] == 'V' ||
- ((argv[1][1] == 'b') && ( NULL != strchr(argv[1] + 2,'-')))))
+ if (! strcmp (argv[i], "-no-canonical-prefixes"))
{
- char opt = argv[1][1];
- const char *arg;
- if (argv[1][2] != '\0')
- {
- arg = argv[1] + 2;
- argc -= 1;
- argv += 1;
- }
- else if (argc > 2)
- {
- arg = argv[2];
- argc -= 2;
- argv += 2;
- }
- else
- fatal ("'-%c' option must have argument", opt);
- if (opt == 'V')
- new_version = arg;
- else
- new_machine = arg;
- }
-
- for (baselen = strlen (progname); baselen > 0; baselen--)
- if (IS_DIR_SEPARATOR (progname[baselen-1]))
+ get_relative_prefix = make_relative_prefix_ignore_links;
break;
- new_argv0 = xmemdup (progname, baselen,
- baselen + concat_length (new_version, new_machine,
- "-gcc-", NULL) + 1);
- strcpy (new_argv0 + baselen, new_machine);
- strcat (new_argv0, "-gcc-");
- strcat (new_argv0, new_version);
-
- new_argv = xmemdup (argv, (argc + 1) * sizeof (argv[0]),
- (argc + 1) * sizeof (argv[0]));
- new_argv[0] = new_argv0;
-
- execvp (new_argv0, new_argv);
- fatal ("couldn't run '%s': %s", new_argv0, xstrerror (errno));
+ }
}
+ if (! get_relative_prefix)
+ get_relative_prefix = make_relative_prefix;
/* Set up the default search paths. If there is no GCC_EXEC_PREFIX,
see if we can create it from the pathname specified in argv[0]. */
/* FIXME: make_relative_prefix doesn't yet work for VMS. */
if (!gcc_exec_prefix)
{
- gcc_exec_prefix = make_relative_prefix (argv[0], standard_bindir_prefix,
- standard_exec_prefix);
- gcc_libexec_prefix = make_relative_prefix (argv[0],
- standard_bindir_prefix,
- standard_libexec_prefix);
+ gcc_exec_prefix = get_relative_prefix (argv[0],
+ standard_bindir_prefix,
+ standard_exec_prefix);
+ gcc_libexec_prefix = get_relative_prefix (argv[0],
+ standard_bindir_prefix,
+ standard_libexec_prefix);
if (gcc_exec_prefix)
- putenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL));
+ xputenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL));
}
else
{
/ (which is ignored by make_relative_prefix), so append a
program name. */
char *tmp_prefix = concat (gcc_exec_prefix, "gcc", NULL);
- gcc_libexec_prefix = make_relative_prefix (tmp_prefix,
- standard_exec_prefix,
- standard_libexec_prefix);
+ gcc_libexec_prefix = get_relative_prefix (tmp_prefix,
+ standard_exec_prefix,
+ standard_libexec_prefix);
/* The path is unrelocated, so fallback to the original setting. */
if (!gcc_libexec_prefix)
is relocated. The toolchain was either relocated using GCC_EXEC_PREFIX
or an automatically created GCC_EXEC_PREFIX from argv[0]. */
+ /* Do language-specific adjustment/addition of flags. */
+ lang_specific_driver (&argc,
+ CONST_CAST2 (const char *const **, const char ***,
+ &argv),
+ &added_libraries);
+
if (gcc_exec_prefix)
{
int len = strlen (gcc_exec_prefix);
if (temp)
{
const char *startp, *endp;
- char *nstore = alloca (strlen (temp) + 3);
+ char *nstore = (char *) alloca (strlen (temp) + 3);
startp = endp = temp;
while (1)
if (temp && *cross_compile == '0')
{
const char *startp, *endp;
- char *nstore = alloca (strlen (temp) + 3);
+ char *nstore = (char *) alloca (strlen (temp) + 3);
startp = endp = temp;
while (1)
if (temp && *cross_compile == '0')
{
const char *startp, *endp;
- char *nstore = alloca (strlen (temp) + 3);
+ char *nstore = (char *) alloca (strlen (temp) + 3);
startp = endp = temp;
while (1)
}
}
- /* Convert new-style -- options to old-style. */
- translate_options (&argc, (const char *const **) &argv);
-
- /* Do language-specific adjustment/addition of flags. */
- lang_specific_driver (&argc, (const char *const **) &argv, &added_libraries);
+ /* Process the options and store input files and switches in their
+ vectors. */
- /* Scan argv twice. Here, the first time, just count how many switches
- there will be in their vector, and how many input files in theirs.
- Here we also parse the switches that cc itself uses (e.g. -v). */
+ last_language_n_infiles = -1;
for (i = 1; i < argc; i++)
{
+ const char *p = NULL;
+ int c = 0;
+
+ if (argv[i][0] == '-' && argv[i][1] != 0)
+ {
+ p = &argv[i][1];
+ c = *p;
+ }
+
if (! strcmp (argv[i], "-dumpspecs"))
{
struct spec_list *sl;
else if (strcmp (argv[i], "-fversion") == 0)
{
/* translate_options () has turned --version into -fversion. */
- printf (_("%s (GCC) %s\n"), programname, version_string);
- printf ("Copyright %s 2007 Free Software Foundation, Inc.\n",
- _("(C)"));
- fputs (_("This is free software; see the source for copying conditions. There is NO\n\
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
- stdout);
- exit (0);
+ print_version = 1;
+
+ /* CPP driver cannot obtain switch from cc1_options. */
+ if (is_cpp_driver)
+ add_preprocessor_option ("--version", strlen ("--version"));
+ add_assembler_option ("--version", strlen ("--version"));
+ add_linker_option ("--version", strlen ("--version"));
+
+ goto normal_switch;
}
else if (strcmp (argv[i], "-fhelp") == 0)
{
/* translate_options () has turned --help into -fhelp. */
print_help_list = 1;
- /* We will be passing a dummy file on to the sub-processes. */
- n_infiles++;
- n_switches++;
-
/* CPP driver cannot obtain switch from cc1_options. */
if (is_cpp_driver)
add_preprocessor_option ("--help", 6);
add_assembler_option ("--help", 6);
add_linker_option ("--help", 6);
+
+ goto normal_switch;
}
else if (strncmp (argv[i], "-fhelp=", 7) == 0)
{
/* translate_options () has turned --help into -fhelp. */
print_subprocess_help = 2;
- /* We will be passing a dummy file on to the sub-processes. */
- n_infiles++;
- n_switches++;
+ goto normal_switch;
}
else if (strcmp (argv[i], "-ftarget-help") == 0)
{
/* translate_options() has turned --target-help into -ftarget-help. */
print_subprocess_help = 1;
- /* We will be passing a dummy file on to the sub-processes. */
- n_infiles++;
- n_switches++;
-
/* CPP driver cannot obtain switch from cc1_options. */
if (is_cpp_driver)
add_preprocessor_option ("--target-help", 13);
add_assembler_option ("--target-help", 13);
add_linker_option ("--target-help", 13);
+
+ goto normal_switch;
}
else if (! strcmp (argv[i], "-pass-exit-codes"))
{
pass_exit_codes = 1;
- n_switches++;
}
else if (! strcmp (argv[i], "-print-search-dirs"))
print_search_dirs = 1;
print_multi_lib = 1;
else if (! strcmp (argv[i], "-print-multi-directory"))
print_multi_directory = 1;
+ else if (! strcmp (argv[i], "-print-sysroot"))
+ print_sysroot = 1;
else if (! strcmp (argv[i], "-print-multi-os-directory"))
print_multi_os_directory = 1;
else if (! strcmp (argv[i], "-print-sysroot-headers-suffix"))
print_sysroot_headers_suffix = 1;
+ else if (! strcmp (argv[i], "-fcompare-debug-second"))
+ {
+ compare_debug_second = 1;
+ goto normal_switch;
+ }
+ else if (! strcmp (argv[i], "-fno-compare-debug"))
+ {
+ argv[i] = "-fcompare-debug=";
+ p = &argv[i][1];
+ goto compare_debug_with_arg;
+ }
+ else if (! strcmp (argv[i], "-fcompare-debug"))
+ {
+ argv[i] = "-fcompare-debug=-gtoggle";
+ p = &argv[i][1];
+ goto compare_debug_with_arg;
+ }
+#define OPT "-fcompare-debug="
+ else if (! strncmp (argv[i], OPT, sizeof (OPT) - 1))
+ {
+ const char *opt;
+ compare_debug_with_arg:
+ opt = argv[i] + sizeof (OPT) - 1;
+#undef OPT
+ if (*opt)
+ compare_debug = 1;
+ else
+ compare_debug = -1;
+ if (compare_debug < 0)
+ compare_debug_opt = NULL;
+ else
+ compare_debug_opt = opt;
+ goto normal_switch;
+ }
else if (! strncmp (argv[i], "-Wa,", 4))
{
int prev, j;
/* Record the part after the last comma. */
add_preprocessor_option (argv[i] + prev, j - prev);
}
- else if (argv[i][0] == '+' && argv[i][1] == 'e')
- /* The +e options to the C++ front-end. */
- n_switches++;
else if (strncmp (argv[i], "-Wl,", 4) == 0)
{
- int j;
+ int prev, j;
/* Split the argument at commas. */
- for (j = 3; argv[i][j]; j++)
- n_infiles += (argv[i][j] == ',');
+ prev = 4;
+ for (j = 4; argv[i][j]; j++)
+ if (argv[i][j] == ',')
+ {
+ add_infile (save_string (argv[i] + prev, j - prev), "*");
+ prev = j + 1;
+ }
+ /* Record the part after the last comma. */
+ add_infile (argv[i] + prev, "*");
}
else if (strcmp (argv[i], "-Xlinker") == 0)
{
if (i + 1 == argc)
- fatal ("argument to '-Xlinker' is missing");
+ fatal_error ("argument to %<-Xlinker%> is missing");
- n_infiles++;
+ add_infile (argv[i+1], "*");
i++;
}
else if (strcmp (argv[i], "-Xpreprocessor") == 0)
{
if (i + 1 == argc)
- fatal ("argument to '-Xpreprocessor' is missing");
+ fatal_error ("argument to %<-Xpreprocessor%> is missing");
add_preprocessor_option (argv[i+1], strlen (argv[i+1]));
+ i++;
}
else if (strcmp (argv[i], "-Xassembler") == 0)
{
if (i + 1 == argc)
- fatal ("argument to '-Xassembler' is missing");
+ fatal_error ("argument to %<-Xassembler%> is missing");
add_assembler_option (argv[i+1], strlen (argv[i+1]));
+ i++;
}
else if (strcmp (argv[i], "-l") == 0)
{
if (i + 1 == argc)
- fatal ("argument to '-l' is missing");
+ fatal_error ("argument to %<-l%> is missing");
- n_infiles++;
+ /* POSIX allows separation of -l and the lib arg;
+ canonicalize by concatenating -l with its arg */
+ add_infile (concat ("-l", argv[i + 1], NULL), "*");
i++;
}
else if (strncmp (argv[i], "-l", 2) == 0)
- n_infiles++;
+ {
+ add_infile (argv[i], "*");
+ }
else if (strcmp (argv[i], "-save-temps") == 0)
{
- save_temps_flag = 1;
- n_switches++;
+ save_temps_flag = SAVE_TEMPS_CWD;
+ goto normal_switch;
+ }
+ else if (strncmp (argv[i], "-save-temps=", 12) == 0)
+ {
+ if (strcmp (argv[i]+12, "cwd") == 0)
+ save_temps_flag = SAVE_TEMPS_CWD;
+ else if (strcmp (argv[i]+12, "obj") == 0
+ || strcmp (argv[i]+12, "object") == 0)
+ save_temps_flag = SAVE_TEMPS_OBJ;
+ else
+ fatal_error ("%qs is an unknown -save-temps option", argv[i]);
+ goto normal_switch;
}
+ else if (strcmp (argv[i], "-no-canonical-prefixes") == 0)
+ /* Already handled as a special case, so ignored here. */
+ ;
else if (strcmp (argv[i], "-combine") == 0)
{
combine_flag = 1;
- n_switches++;
+ goto normal_switch;
}
else if (strcmp (argv[i], "-specs") == 0)
{
struct user_specs *user = XNEW (struct user_specs);
if (++i >= argc)
- fatal ("argument to '-specs' is missing");
+ fatal_error ("argument to %<-specs%> is missing");
user->next = (struct user_specs *) 0;
user->filename = argv[i];
{
struct user_specs *user = XNEW (struct user_specs);
if (strlen (argv[i]) == 7)
- fatal ("argument to '-specs=' is missing");
+ fatal_error ("argument to %<-specs=%> is missing");
user->next = (struct user_specs *) 0;
user->filename = argv[i] + 7;
user_specs_head = user;
user_specs_tail = user;
}
+ else if (! strncmp (argv[i], "--sysroot=", strlen ("--sysroot=")))
+ {
+ target_system_root = argv[i] + strlen ("--sysroot=");
+ target_system_root_changed = 1;
+ }
else if (strcmp (argv[i], "-time") == 0)
report_times = 1;
+ else if (strncmp (argv[i], "-time=", sizeof ("-time=") - 1) == 0)
+ {
+ if (report_times_to_file)
+ fclose (report_times_to_file);
+ report_times_to_file = fopen (argv[i] + sizeof ("-time=") - 1, "a");
+ }
else if (strcmp (argv[i], "-pipe") == 0)
{
/* -pipe has to go into the switches array as well as
setting a flag. */
use_pipes = 1;
- n_switches++;
+ goto normal_switch;
}
+ else if (strcmp (argv[i], "-wrapper") == 0)
+ {
+ if (++i >= argc)
+ fatal_error ("argument to %<-wrapper%> is missing");
+
+ wrapper_string = argv[i];
+ }
else if (strcmp (argv[i], "-###") == 0)
{
/* This is similar to -v except that there is no execution
}
else if (argv[i][0] == '-' && argv[i][1] != 0)
{
- const char *p = &argv[i][1];
- int c = *p;
-
switch (c)
{
- case 'b':
- if (NULL == strchr(argv[i] + 2, '-'))
- goto normal_switch;
-
- /* Fall through. */
- case 'V':
- fatal ("'-%c' must come at the start of the command line", c);
- break;
-
case 'B':
{
const char *value;
int len;
if (p[1] == 0 && i + 1 == argc)
- fatal ("argument to '-B' is missing");
+ fatal_error ("argument to %<-B%> is missing");
if (p[1] == 0)
- value = argv[++i];
+ value = argv[i + 1];
else
value = p + 1;
PREFIX_PRIORITY_B_OPT, 0, 0);
add_prefix (&include_prefixes, value, NULL,
PREFIX_PRIORITY_B_OPT, 0, 0);
- n_switches++;
}
- break;
+ goto normal_switch;
case 'v': /* Print our subcommands and print versions. */
- n_switches++;
/* If they do anything other than exactly `-v', don't set
verbose_flag; rather, continue on to give the error. */
if (p[1] != 0)
break;
verbose_flag++;
+ goto normal_switch;
+
+ case 'x':
+ if (p[1] == 0 && i + 1 == argc)
+ fatal_error ("argument to %<-x%> is missing");
+ if (p[1] == 0)
+ spec_lang = argv[++i];
+ else
+ spec_lang = p + 1;
+ if (! strcmp (spec_lang, "none"))
+ /* Suppress the warning if -xnone comes after the last input
+ file, because alternate command interfaces like g++ might
+ find it useful to place -xnone after each input file. */
+ spec_lang = 0;
+ else
+ last_language_n_infiles = n_infiles;
break;
case 'S':
case 'c':
+ case 'E':
if (p[1] == 0)
- {
- have_c = 1;
- n_switches++;
- break;
- }
+ have_c = 1;
goto normal_switch;
case 'o':
{
int skip;
- /* Forward scan, just in case -S or -c is specified
+ /* Forward scan, just in case -S, -E or -c is specified
after -o. */
int j = i + 1;
if (p[1] == 0)
if (p[1] == 0)
argv[i + 1] = convert_filename (argv[i + 1], ! have_c, 0);
else
- argv[i] = convert_filename (argv[i], ! have_c, 0);
+ {
+ argv[i] = convert_filename (argv[i], ! have_c, 0);
+ p = &argv[i][1];
+ }
#endif
+ /* Save the output name in case -save-temps=obj was used. */
+ if ((p[1] == 0) && argv[i + 1])
+ save_temps_prefix = xstrdup(argv[i + 1]);
+ else
+ save_temps_prefix = xstrdup(argv[i] + 1);
goto normal_switch;
default:
normal_switch:
-#ifdef MODIFY_TARGET_NAME
- is_modify_target_name = 0;
-
- for (j = 0; j < ARRAY_SIZE (modify_target); j++)
- if (! strcmp (argv[i], modify_target[j].sw))
- {
- char *new_name = xmalloc (strlen (modify_target[j].str)
- + strlen (spec_machine));
- const char *p, *r;
- char *q;
- int made_addition = 0;
-
- is_modify_target_name = 1;
- for (p = spec_machine, q = new_name; *p != 0; )
- {
- if (modify_target[j].add_del == DELETE
- && (! strncmp (q, modify_target[j].str,
- strlen (modify_target[j].str))))
- p += strlen (modify_target[j].str);
- else if (modify_target[j].add_del == ADD
- && ! made_addition && *p == '-')
- {
- for (r = modify_target[j].str; *r != 0; )
- *q++ = *r++;
- made_addition = 1;
- }
-
- *q++ = *p++;
- }
-
- spec_machine = new_name;
- }
-
- if (is_modify_target_name)
- break;
-#endif
+ alloc_switch ();
+ switches[n_switches].part1 = p;
+ /* Deal with option arguments in separate argv elements. */
+ if ((SWITCH_TAKES_ARG (c) > (p[1] != 0))
+ || WORD_SWITCH_TAKES_ARG (p))
+ {
+ int j = 0;
+ int n_args = WORD_SWITCH_TAKES_ARG (p);
+ if (n_args == 0)
+ {
+ /* Count only the option arguments in separate
+ argv elements. */
+ n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0);
+ }
+ if (i + n_args >= argc)
+ fatal_error ("argument to %<-%s%> is missing", p);
+ switches[n_switches].args
+ = XNEWVEC (const char *, n_args + 1);
+ while (j < n_args)
+ switches[n_switches].args[j++] = argv[++i];
+ /* Null-terminate the vector. */
+ switches[n_switches].args[j] = 0;
+ }
+ else if (c == 'o')
+ {
+ /* On some systems, ld cannot handle "-o" without
+ a space. So split the option from its argument. */
+ char *part1 = XNEWVEC (char, 2);
+ part1[0] = c;
+ part1[1] = '\0';
+
+ switches[n_switches].part1 = part1;
+ switches[n_switches].args = XNEWVEC (const char *, 2);
+ switches[n_switches].args[0] = xstrdup (p+1);
+ switches[n_switches].args[1] = 0;
+ }
+ else
+ switches[n_switches].args = 0;
+
+ switches[n_switches].live_cond = 0;
+ switches[n_switches].validated = 0;
+ switches[n_switches].ordering = 0;
+ /* These are always valid, since gcc.c itself understands the
+ first four, gfortranspec.c understands -static-libgfortran
+ and g++spec.c understands -static-libstdc++ */
+ if (!strcmp (p, "save-temps")
+ || !strcmp (p, "static-libgcc")
+ || !strcmp (p, "shared-libgcc")
+ || !strcmp (p, "pipe")
+ || !strcmp (p, "static-libgfortran")
+ || !strcmp (p, "static-libstdc++"))
+ switches[n_switches].validated = 1;
+ else
+ {
+ char ch = switches[n_switches].part1[0];
+ if (ch == 'B')
+ switches[n_switches].validated = 1;
+ }
n_switches++;
-
- if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
- i += SWITCH_TAKES_ARG (c) - (p[1] != 0);
- else if (WORD_SWITCH_TAKES_ARG (p))
- i += WORD_SWITCH_TAKES_ARG (p);
}
}
else
{
- n_infiles++;
- lang_n_infiles++;
+ const char *p = strrchr (argv[i], '@');
+ char *fname;
+ long offset;
+ int consumed;
+#ifdef HAVE_TARGET_OBJECT_SUFFIX
+ argv[i] = convert_filename (argv[i], 0, access (argv[i], F_OK));
+#endif
+ /* For LTO static archive support we handle input file
+ specifications that are composed of a filename and
+ an offset like FNAME@OFFSET. */
+ if (p
+ && p != argv[i]
+ && sscanf (p, "@%li%n", &offset, &consumed) >= 1
+ && strlen (p) == (unsigned int)consumed)
+ {
+ fname = (char *)xmalloc (p - argv[i] + 1);
+ memcpy (fname, argv[i], p - argv[i]);
+ fname[p - argv[i]] = '\0';
+ /* Only accept non-stdin and existing FNAME parts, otherwise
+ try with the full name. */
+ if (strcmp (fname, "-") == 0 || access (fname, F_OK) < 0)
+ {
+ free (fname);
+ fname = xstrdup (argv[i]);
+ }
+ }
+ else
+ fname = xstrdup (argv[i]);
+
+ if (strcmp (fname, "-") != 0 && access (fname, F_OK) < 0)
+ perror_with_name (fname);
+ else
+ add_infile (argv[i], spec_lang);
+
+ free (fname);
+ }
+ }
+
+ /* If -save-temps=obj and -o name, create the prefix to use for %b.
+ Otherwise just make -save-temps=obj the same as -save-temps=cwd. */
+ if (save_temps_flag == SAVE_TEMPS_OBJ && save_temps_prefix != NULL)
+ {
+ save_temps_length = strlen (save_temps_prefix);
+ temp = strrchr (lbasename (save_temps_prefix), '.');
+ if (temp)
+ {
+ save_temps_length -= strlen (temp);
+ save_temps_prefix[save_temps_length] = '\0';
}
+
+ }
+ else if (save_temps_prefix != NULL)
+ {
+ free (save_temps_prefix);
+ save_temps_prefix = NULL;
}
if (save_temps_flag && use_pipes)
{
/* -save-temps overrides -pipe, so that temp files are produced */
if (save_temps_flag)
- error ("warning: -pipe ignored because -save-temps specified");
+ warning (0, "-pipe ignored because -save-temps specified");
use_pipes = 0;
}
+ if (!compare_debug)
+ {
+ const char *gcd = getenv ("GCC_COMPARE_DEBUG");
+
+ if (gcd && gcd[0] == '-')
+ {
+ compare_debug = 2;
+ compare_debug_opt = gcd;
+ }
+ else if (gcd && *gcd && strcmp (gcd, "0"))
+ {
+ compare_debug = 3;
+ compare_debug_opt = "-gtoggle";
+ }
+ }
+ else if (compare_debug < 0)
+ {
+ compare_debug = 0;
+ gcc_assert (!compare_debug_opt);
+ }
+
/* Set up the search paths. We add directories that we expect to
contain GNU Toolchain components before directories specified by
the machine description so that we will find GNU components (like
- the GNU assembler) before those of the host system. */
+ the GNU assembler) before those of the host system. */
/* If we don't know where the toolchain has been installed, use the
configured-in locations. */
PREFIX_PRIORITY_LAST, 1, 0);
}
- /* If not cross-compiling, search well-known system locations. */
- if (*cross_compile == '0')
- {
-#ifndef OS2
- add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS",
- PREFIX_PRIORITY_LAST, 2, 0);
- add_prefix (&exec_prefixes, standard_exec_prefix_2, "BINUTILS",
- PREFIX_PRIORITY_LAST, 2, 0);
-#endif
- add_prefix (&startfile_prefixes, standard_exec_prefix_2, "BINUTILS",
- PREFIX_PRIORITY_LAST, 1, 0);
- }
-
gcc_assert (!IS_ABSOLUTE_PATH (tooldir_base_prefix));
tooldir_prefix = concat (tooldir_base_prefix, spec_machine,
dir_separator_str, NULL);
then consider it to relocate with the rest of the GCC installation
if GCC_EXEC_PREFIX is set.
``make_relative_prefix'' is not compiled for VMS, so don't call it. */
- if (target_system_root && gcc_exec_prefix)
+ if (target_system_root && !target_system_root_changed && gcc_exec_prefix)
{
- char *tmp_prefix = make_relative_prefix (argv[0],
- standard_bindir_prefix,
- target_system_root);
+ char *tmp_prefix = get_relative_prefix (argv[0],
+ standard_bindir_prefix,
+ target_system_root);
if (tmp_prefix && access_check (tmp_prefix, F_OK) == 0)
{
target_system_root = tmp_prefix;
/* More prefixes are enabled in main, after we read the specs file
and determine whether this is cross-compilation or not. */
- /* Then create the space for the vectors and scan again. */
-
- switches = XNEWVEC (struct switchstr, n_switches + 1);
- infiles = XNEWVEC (struct infile, n_infiles + 1);
- n_switches = 0;
- n_infiles = 0;
- last_language_n_infiles = -1;
-
- /* This, time, copy the text of each switch and store a pointer
- to the copy in the vector of switches.
- Store all the infiles in their vector. */
+ if (n_infiles == last_language_n_infiles && spec_lang != 0)
+ warning (0, "%<-x %s%> after last input file has no effect", spec_lang);
- for (i = 1; i < argc; i++)
+ if (compare_debug == 2 || compare_debug == 3)
{
- /* Just skip the switches that were handled by the preceding loop. */
-#ifdef MODIFY_TARGET_NAME
- is_modify_target_name = 0;
-
- for (j = 0; j < ARRAY_SIZE (modify_target); j++)
- if (! strcmp (argv[i], modify_target[j].sw))
- is_modify_target_name = 1;
-
- if (is_modify_target_name)
- ;
- else
-#endif
- if (! strncmp (argv[i], "-Wa,", 4))
- ;
- else if (! strncmp (argv[i], "-Wp,", 4))
- ;
- else if (! strcmp (argv[i], "-pass-exit-codes"))
- ;
- else if (! strcmp (argv[i], "-print-search-dirs"))
- ;
- else if (! strcmp (argv[i], "-print-libgcc-file-name"))
- ;
- else if (! strncmp (argv[i], "-print-file-name=", 17))
- ;
- else if (! strncmp (argv[i], "-print-prog-name=", 17))
- ;
- else if (! strcmp (argv[i], "-print-multi-lib"))
- ;
- else if (! strcmp (argv[i], "-print-multi-directory"))
- ;
- else if (! strcmp (argv[i], "-print-multi-os-directory"))
- ;
- else if (! strcmp (argv[i], "-print-sysroot-headers-suffix"))
- ;
- else if (! strncmp (argv[i], "--sysroot=", strlen ("--sysroot=")))
- {
- target_system_root = argv[i] + strlen ("--sysroot=");
- target_system_root_changed = 1;
- }
- else if (argv[i][0] == '+' && argv[i][1] == 'e')
- {
- /* Compensate for the +e options to the C++ front-end;
- they're there simply for cfront call-compatibility. We do
- some magic in default_compilers to pass them down properly.
- Note we deliberately start at the `+' here, to avoid passing
- -e0 or -e1 down into the linker. */
- switches[n_switches].part1 = &argv[i][0];
- switches[n_switches].args = 0;
- switches[n_switches].live_cond = SWITCH_OK;
- switches[n_switches].validated = 0;
- n_switches++;
- }
- else if (strncmp (argv[i], "-Wl,", 4) == 0)
- {
- int prev, j;
- /* Split the argument at commas. */
- prev = 4;
- for (j = 4; argv[i][j]; j++)
- if (argv[i][j] == ',')
- {
- infiles[n_infiles].language = "*";
- infiles[n_infiles++].name
- = save_string (argv[i] + prev, j - prev);
- prev = j + 1;
- }
- /* Record the part after the last comma. */
- infiles[n_infiles].language = "*";
- infiles[n_infiles++].name = argv[i] + prev;
- }
- else if (strcmp (argv[i], "-Xlinker") == 0)
- {
- infiles[n_infiles].language = "*";
- infiles[n_infiles++].name = argv[++i];
- }
- /* Xassembler and Xpreprocessor were already handled in the first argv
- scan, so all we need to do here is ignore them and their argument. */
- else if (strcmp (argv[i], "-Xassembler") == 0)
- i++;
- else if (strcmp (argv[i], "-Xpreprocessor") == 0)
- i++;
- else if (strcmp (argv[i], "-l") == 0)
- { /* POSIX allows separation of -l and the lib arg;
- canonicalize by concatenating -l with its arg */
- infiles[n_infiles].language = "*";
- infiles[n_infiles++].name = concat ("-l", argv[++i], NULL);
- }
- else if (strncmp (argv[i], "-l", 2) == 0)
- {
- infiles[n_infiles].language = "*";
- infiles[n_infiles++].name = argv[i];
- }
- else if (strcmp (argv[i], "-specs") == 0)
- i++;
- else if (strncmp (argv[i], "-specs=", 7) == 0)
- ;
- else if (strcmp (argv[i], "-time") == 0)
- ;
- else if (strcmp (argv[i], "-###") == 0)
- ;
- else if (argv[i][0] == '-' && argv[i][1] != 0)
- {
- const char *p = &argv[i][1];
- int c = *p;
-
- if (c == 'x')
- {
- if (p[1] == 0 && i + 1 == argc)
- fatal ("argument to '-x' is missing");
- if (p[1] == 0)
- spec_lang = argv[++i];
- else
- spec_lang = p + 1;
- if (! strcmp (spec_lang, "none"))
- /* Suppress the warning if -xnone comes after the last input
- file, because alternate command interfaces like g++ might
- find it useful to place -xnone after each input file. */
- spec_lang = 0;
- else
- last_language_n_infiles = n_infiles;
- continue;
- }
- switches[n_switches].part1 = p;
- /* Deal with option arguments in separate argv elements. */
- if ((SWITCH_TAKES_ARG (c) > (p[1] != 0))
- || WORD_SWITCH_TAKES_ARG (p))
- {
- int j = 0;
- int n_args = WORD_SWITCH_TAKES_ARG (p);
-
- if (n_args == 0)
- {
- /* Count only the option arguments in separate argv elements. */
- n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0);
- }
- if (i + n_args >= argc)
- fatal ("argument to '-%s' is missing", p);
- switches[n_switches].args
- = XNEWVEC (const char *, n_args + 1);
- while (j < n_args)
- switches[n_switches].args[j++] = argv[++i];
- /* Null-terminate the vector. */
- switches[n_switches].args[j] = 0;
- }
- else if (strchr (switches_need_spaces, c))
- {
- /* On some systems, ld cannot handle some options without
- a space. So split the option from its argument. */
- char *part1 = XNEWVEC (char, 2);
- part1[0] = c;
- part1[1] = '\0';
-
- switches[n_switches].part1 = part1;
- switches[n_switches].args = XNEWVEC (const char *, 2);
- switches[n_switches].args[0] = xstrdup (p+1);
- switches[n_switches].args[1] = 0;
- }
- else
- switches[n_switches].args = 0;
-
- switches[n_switches].live_cond = SWITCH_OK;
- switches[n_switches].validated = 0;
- switches[n_switches].ordering = 0;
- /* These are always valid, since gcc.c itself understands them. */
- if (!strcmp (p, "save-temps")
- || !strcmp (p, "static-libgcc")
- || !strcmp (p, "shared-libgcc")
- || !strcmp (p, "pipe"))
- switches[n_switches].validated = 1;
- else
- {
- char ch = switches[n_switches].part1[0];
- if (ch == 'B')
- switches[n_switches].validated = 1;
- }
- n_switches++;
- }
- else
- {
-#ifdef HAVE_TARGET_OBJECT_SUFFIX
- argv[i] = convert_filename (argv[i], 0, access (argv[i], F_OK));
-#endif
-
- if (strcmp (argv[i], "-") != 0 && access (argv[i], F_OK) < 0)
- {
- perror_with_name (argv[i]);
- error_count++;
- }
- else
- {
- infiles[n_infiles].language = spec_lang;
- infiles[n_infiles++].name = argv[i];
- }
- }
+ alloc_switch ();
+ switches[n_switches].part1 = concat ("fcompare-debug=",
+ compare_debug_opt,
+ NULL);
+ switches[n_switches].args = 0;
+ switches[n_switches].live_cond = 0;
+ switches[n_switches].validated = 0;
+ switches[n_switches].ordering = 0;
+ n_switches++;
+ compare_debug = 1;
}
- if (n_infiles == last_language_n_infiles && spec_lang != 0)
- error ("warning: '-x %s' after last input file has no effect", spec_lang);
-
/* Ensure we only invoke each subprocess once. */
- if (print_subprocess_help || print_help_list)
+ if (print_subprocess_help || print_help_list || print_version)
{
- n_infiles = 1;
+ n_infiles = 0;
/* Create a dummy input file, so that we can pass
the help option on to the various sub-processes. */
- infiles[0].language = "c";
- infiles[0].name = "help-dummy";
+ add_infile ("help-dummy", "c");
}
+ alloc_switch ();
switches[n_switches].part1 = 0;
+ alloc_infile ();
infiles[n_infiles].name = 0;
}
first_time = FALSE;
/* Ignore elided switches. */
- if (switches[i].live_cond == SWITCH_IGNORE)
+ if ((switches[i].live_cond & SWITCH_IGNORE) != 0)
continue;
obstack_grow (&collect_obstack, "'-", 2);
}
}
obstack_grow (&collect_obstack, "\0", 1);
- putenv (XOBFINISH (&collect_obstack, char *));
+ xputenv (XOBFINISH (&collect_obstack, char *));
}
\f
/* Process a spec string, accumulating and running commands. */
sans all directory names, and basename_length is the number
of characters starting there excluding the suffix .c or whatever. */
-static const char *input_filename;
+static const char *gcc_input_filename;
static int input_file_number;
size_t input_filename_length;
static int basename_length;
search dirs for it. */
static int this_is_library_file;
+/* Nonzero means %T has been seen; the next arg to be terminated
+ is the name of a linker script and we should try all of the
+ standard search dirs for it. If it is found insert a --script
+ command line switch and then substitute the full path in place,
+ otherwise generate an error message. */
+static int this_is_linker_script;
+
/* Nonzero means that the input of this command is coming from a pipe. */
static int input_from_pipe;
arguments. */
static const char *suffix_subst;
+/* If there is an argument being accumulated, terminate it and store it. */
+
+static void
+end_going_arg (void)
+{
+ if (arg_going)
+ {
+ const char *string;
+
+ obstack_1grow (&obstack, 0);
+ string = XOBFINISH (&obstack, const char *);
+ if (this_is_library_file)
+ string = find_file (string);
+ if (this_is_linker_script)
+ {
+ char * full_script_path = find_a_file (&startfile_prefixes, string, R_OK, true);
+
+ if (full_script_path == NULL)
+ {
+ error ("unable to locate default linker script %qs in the library search paths", string);
+ /* Script was not found on search path. */
+ return;
+ }
+ store_arg ("--script", false, false);
+ string = full_script_path;
+ }
+ store_arg (string, delete_this_arg, this_is_output_file);
+ if (this_is_output_file)
+ outfiles[input_file_number] = string;
+ arg_going = 0;
+ }
+}
+
+
+/* Parse the WRAPPER string which is a comma separated list of the command line
+ and insert them into the beginning of argbuf. */
+
+static void
+insert_wrapper (const char *wrapper)
+{
+ int n = 0;
+ int i;
+ char *buf = xstrdup (wrapper);
+ char *p = buf;
+
+ do
+ {
+ n++;
+ while (*p == ',')
+ p++;
+ }
+ while ((p = strchr (p, ',')) != NULL);
+
+ if (argbuf_index + n >= argbuf_length)
+ {
+ argbuf_length = argbuf_length * 2;
+ while (argbuf_length < argbuf_index + n)
+ argbuf_length *= 2;
+ argbuf = XRESIZEVEC (const char *, argbuf, argbuf_length);
+ }
+ for (i = argbuf_index - 1; i >= 0; i--)
+ argbuf[i + n] = argbuf[i];
+
+ i = 0;
+ p = buf;
+ do
+ {
+ while (*p == ',')
+ {
+ *p = 0;
+ p++;
+ }
+ argbuf[i++] = p;
+ }
+ while ((p = strchr (p, ',')) != NULL);
+ gcc_assert (i == n);
+ argbuf_index += n;
+}
+
/* Process the spec SPEC and run the commands specified therein.
Returns 0 if the spec is successfully processed; -1 if failed. */
static int
do_spec_2 (const char *spec)
{
- const char *string;
int result;
clear_args ();
delete_this_arg = 0;
this_is_output_file = 0;
this_is_library_file = 0;
+ this_is_linker_script = 0;
input_from_pipe = 0;
suffix_subst = NULL;
result = do_spec_1 (spec, 0, NULL);
- /* End any pending argument. */
- if (arg_going)
- {
- obstack_1grow (&obstack, 0);
- string = XOBFINISH (&obstack, const char *);
- if (this_is_library_file)
- string = find_file (string);
- store_arg (string, delete_this_arg, this_is_output_file);
- if (this_is_output_file)
- outfiles[input_file_number] = string;
- arg_going = 0;
- }
+ end_going_arg ();
return result;
}
}
/* Replace each %(VALUE) by the specified value. */
- tmp_spec = alloca (strlen (spec) + 1
+ tmp_spec = (char *) alloca (strlen (spec) + 1
+ value_count * (value_len - strlen ("%(VALUE)")));
tmp_spec_p = tmp_spec;
q = spec;
static void
do_self_spec (const char *spec)
{
+ int i;
+
do_spec_2 (spec);
do_spec_1 (" ", 0, NULL);
+ /* Mark %<S switches processed by do_self_spec to be ignored permanently.
+ do_self_specs adds the replacements to switches array, so it shouldn't
+ be processed afterwards. */
+ for (i = 0; i < n_switches; i++)
+ if ((switches[i].live_cond & SWITCH_IGNORE))
+ switches[i].live_cond |= SWITCH_IGNORE_PERMANENTLY;
+
if (argbuf_index > 0)
{
- int i, first;
-
- first = n_switches;
- n_switches += argbuf_index;
- switches = xrealloc (switches,
- sizeof (struct switchstr) * (n_switches + 1));
+ switches = XRESIZEVEC (struct switchstr, switches,
+ n_switches + argbuf_index + 1);
- switches[n_switches] = switches[first];
for (i = 0; i < argbuf_index; i++)
{
struct switchstr *sw;
+ const char *p = argbuf[i];
+ int c = *p;
/* Each switch should start with '-'. */
- if (argbuf[i][0] != '-')
- fatal ("switch '%s' does not start with '-'", argbuf[i]);
+ if (c != '-')
+ fatal_error ("switch %qs does not start with %<-%>", argbuf[i]);
- sw = &switches[i + first];
- sw->part1 = &argbuf[i][1];
- sw->args = 0;
- sw->live_cond = SWITCH_OK;
+ p++;
+ c = *p;
+
+ sw = &switches[n_switches++];
+ sw->part1 = p;
+ sw->live_cond = 0;
sw->validated = 0;
sw->ordering = 0;
+
+ /* Deal with option arguments in separate argv elements. */
+ if ((SWITCH_TAKES_ARG (c) > (p[1] != 0))
+ || WORD_SWITCH_TAKES_ARG (p))
+ {
+ int j = 0;
+ int n_args = WORD_SWITCH_TAKES_ARG (p);
+
+ if (n_args == 0)
+ {
+ /* Count only the option arguments in separate argv elements. */
+ n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0);
+ }
+ if (i + n_args >= argbuf_index)
+ fatal_error ("argument to %<-%s%> is missing", p);
+ sw->args
+ = XNEWVEC (const char *, n_args + 1);
+ while (j < n_args)
+ sw->args[j++] = argbuf[++i];
+ /* Null-terminate the vector. */
+ sw->args[j] = 0;
+ }
+ else if (c == 'o')
+ {
+ /* On some systems, ld cannot handle "-o" without
+ a space. So split the option from its argument. */
+ char *part1 = XNEWVEC (char, 2);
+ part1[0] = c;
+ part1[1] = '\0';
+
+ sw->part1 = part1;
+ sw->args = XNEWVEC (const char *, 2);
+ sw->args[0] = xstrdup (p+1);
+ sw->args[1] = 0;
+ }
+ else
+ sw->args = 0;
}
+
+ switches[n_switches].part1 = 0;
}
}
static void *
spec_path (char *path, void *data)
{
- struct spec_path_info *info = data;
+ struct spec_path_info *info = (struct spec_path_info *) data;
size_t len = 0;
char save = 0;
return NULL;
}
+/* Create a temporary FILE with the contents of ARGV. Add @FILE to the
+ argument list. */
+
+static void
+create_at_file (char **argv)
+{
+ char *temp_file = make_temp_file ("");
+ char *at_argument = concat ("@", temp_file, NULL);
+ FILE *f = fopen (temp_file, "w");
+ int status;
+
+ if (f == NULL)
+ fatal_error ("could not open temporary response file %s",
+ temp_file);
+
+ status = writeargv (argv, f);
+
+ if (status)
+ fatal_error ("could not write to temporary response file %s",
+ temp_file);
+
+ status = fclose (f);
+
+ if (EOF == status)
+ fatal_error ("could not close temporary response file %s",
+ temp_file);
+
+ store_arg (at_argument, 0, 0);
+
+ record_temp_file (temp_file, !save_temps_flag, !save_temps_flag);
+}
+
+/* True if we should compile INFILE. */
+
+static bool
+compile_input_file_p (struct infile *infile)
+{
+ if ((!infile->language) || (infile->language[0] != '*'))
+ if (infile->incompiler == input_file_compiler)
+ return true;
+ return false;
+}
+
/* Process the sub-spec SPEC as a portion of a larger spec.
This is like processing a whole spec except that we do
not initialize at the beginning and we do not supply a
const char *p = spec;
int c;
int i;
- const char *string;
int value;
while ((c = *p++))
switch (inswitch ? 'a' : c)
{
case '\n':
- /* End of line: finish any pending argument,
- then run the pending command if one has been started. */
- if (arg_going)
- {
- obstack_1grow (&obstack, 0);
- string = XOBFINISH (&obstack, const char *);
- if (this_is_library_file)
- string = find_file (string);
- store_arg (string, delete_this_arg, this_is_output_file);
- if (this_is_output_file)
- outfiles[input_file_number] = string;
- }
- arg_going = 0;
+ end_going_arg ();
if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
{
delete_this_arg = 0;
this_is_output_file = 0;
this_is_library_file = 0;
+ this_is_linker_script = 0;
input_from_pipe = 0;
break;
case '|':
- /* End any pending argument. */
- if (arg_going)
- {
- obstack_1grow (&obstack, 0);
- string = XOBFINISH (&obstack, const char *);
- if (this_is_library_file)
- string = find_file (string);
- store_arg (string, delete_this_arg, this_is_output_file);
- if (this_is_output_file)
- outfiles[input_file_number] = string;
- }
+ end_going_arg ();
/* Use pipe */
obstack_1grow (&obstack, c);
case '\t':
case ' ':
- /* Space or tab ends an argument if one is pending. */
- if (arg_going)
- {
- obstack_1grow (&obstack, 0);
- string = XOBFINISH (&obstack, const char *);
- if (this_is_library_file)
- string = find_file (string);
- store_arg (string, delete_this_arg, this_is_output_file);
- if (this_is_output_file)
- outfiles[input_file_number] = string;
- }
+ end_going_arg ();
+
/* Reinitialize for a new argument. */
- arg_going = 0;
delete_this_arg = 0;
this_is_output_file = 0;
this_is_library_file = 0;
+ this_is_linker_script = 0;
break;
case '%':
switch (c = *p++)
{
case 0:
- fatal ("spec '%s' invalid", spec);
+ fatal_error ("spec %qs invalid", spec);
case 'b':
- obstack_grow (&obstack, input_basename, basename_length);
+ if (save_temps_length)
+ obstack_grow (&obstack, save_temps_prefix, save_temps_length);
+ else
+ obstack_grow (&obstack, input_basename, basename_length);
+ if (compare_debug < 0)
+ obstack_grow (&obstack, ".gk", 3);
arg_going = 1;
break;
case 'B':
- obstack_grow (&obstack, input_basename, suffixed_basename_length);
+ if (save_temps_length)
+ obstack_grow (&obstack, save_temps_prefix, save_temps_length);
+ else
+ obstack_grow (&obstack, input_basename, suffixed_basename_length);
+ if (compare_debug < 0)
+ obstack_grow (&obstack, ".gk", 3);
arg_going = 1;
break;
char *buf;
while (*p != 0 && *p != '\n')
p++;
- buf = alloca (p - q + 1);
+ buf = (char *) alloca (p - q + 1);
strncpy (buf, q, p - q);
buf[p - q] = 0;
- error ("%s", buf);
+ error ("%s", _(buf));
return -1;
}
break;
char *buf;
while (*p != 0 && *p != '\n')
p++;
- buf = alloca (p - q + 1);
+ buf = (char *) alloca (p - q + 1);
strncpy (buf, q, p - q);
buf[p - q] = 0;
- notice ("%s\n", buf);
+ inform (0, "%s", _(buf));
if (*p)
p++;
}
p += 2;
/* We don't support extra suffix characters after %O. */
if (*p == '.' || ISALNUM ((unsigned char) *p))
- fatal ("spec '%s' has invalid '%%0%c'", spec, *p);
+ fatal_error ("spec %qs has invalid %<%%0%c%>", spec, *p);
if (suffix_length == 0)
suffix = TARGET_OBJECT_SUFFIX;
else
suffix_length += strlen (TARGET_OBJECT_SUFFIX);
}
- /* If the input_filename has the same suffix specified
+ if (compare_debug < 0)
+ {
+ suffix = concat (".gk", suffix, NULL);
+ suffix_length += 3;
+ }
+
+ /* If -save-temps=obj and -o were specified, use that for the
+ temp file. */
+ if (save_temps_length)
+ {
+ char *tmp;
+ temp_filename_length
+ = save_temps_length + suffix_length + 1;
+ tmp = (char *) alloca (temp_filename_length);
+ memcpy (tmp, save_temps_prefix, save_temps_length);
+ memcpy (tmp + save_temps_length, suffix, suffix_length);
+ tmp[save_temps_length + suffix_length] = '\0';
+ temp_filename = save_string (tmp,
+ temp_filename_length + 1);
+ obstack_grow (&obstack, temp_filename,
+ temp_filename_length);
+ arg_going = 1;
+ delete_this_arg = 0;
+ break;
+ }
+
+ /* If the gcc_input_filename has the same suffix specified
for the %g, %u, or %U, and -save-temps is specified,
we could end up using that file as an intermediate
thus clobbering the user's source file (.e.g.,
if (save_temps_flag)
{
- temp_filename_length = basename_length + suffix_length;
- temp_filename = alloca (temp_filename_length + 1);
- strncpy ((char *) temp_filename, input_basename, basename_length);
- strncpy ((char *) temp_filename + basename_length, suffix,
- suffix_length);
- *((char *) temp_filename + temp_filename_length) = '\0';
- if (strcmp (temp_filename, input_filename) != 0)
+ char *tmp;
+ temp_filename_length = basename_length + suffix_length + 1;
+ tmp = (char *) alloca (temp_filename_length);
+ memcpy (tmp, input_basename, basename_length);
+ memcpy (tmp + basename_length, suffix, suffix_length);
+ tmp[basename_length + suffix_length] = '\0';
+ temp_filename = tmp;
+
+ if (strcmp (temp_filename, gcc_input_filename) != 0)
{
#ifndef HOST_LACKS_INODE_NUMBERS
struct stat st_temp;
/* Note, set_input() resets input_stat_set to 0. */
if (input_stat_set == 0)
{
- input_stat_set = stat (input_filename, &input_stat);
+ input_stat_set = stat (gcc_input_filename,
+ &input_stat);
if (input_stat_set >= 0)
input_stat_set = 1;
}
- /* If we have the stat for the input_filename
+ /* If we have the stat for the gcc_input_filename
and we can do the stat for the temp_filename
then the they could still refer to the same
file if st_dev/st_ino's are the same. */
|| input_stat.st_ino != st_temp.st_ino)
#else
/* Just compare canonical pathnames. */
- char* input_realname = lrealpath (input_filename);
+ char* input_realname = lrealpath (gcc_input_filename);
char* temp_realname = lrealpath (temp_filename);
bool files_differ = strcmp (input_realname, temp_realname);
free (input_realname);
{
if (t == 0)
{
- t = xmalloc (sizeof (struct temp_name));
+ t = XNEW (struct temp_name);
t->next = temp_names;
temp_names = t;
}
case 'i':
if (combine_inputs)
{
- for (i = 0; (int) i < n_infiles; i++)
- if ((!infiles[i].language) || (infiles[i].language[0] != '*'))
- if (infiles[i].incompiler == input_file_compiler)
+ if (at_file_supplied)
+ {
+ /* We are going to expand `%i' to `@FILE', where FILE
+ is a newly-created temporary filename. The filenames
+ that would usually be expanded in place of %o will be
+ written to the temporary file. */
+ char **argv;
+ int n_files = 0;
+ int j;
+
+ for (i = 0; i < n_infiles; i++)
+ if (compile_input_file_p (&infiles[i]))
+ n_files++;
+
+ argv = (char **) alloca (sizeof (char *) * (n_files + 1));
+
+ /* Copy the strings over. */
+ for (i = 0, j = 0; i < n_infiles; i++)
+ if (compile_input_file_p (&infiles[i]))
+ {
+ argv[j] = CONST_CAST (char *, infiles[i].name);
+ infiles[i].compiled = true;
+ j++;
+ }
+ argv[j] = NULL;
+
+ create_at_file (argv);
+ }
+ else
+ for (i = 0; (int) i < n_infiles; i++)
+ if (compile_input_file_p (&infiles[i]))
{
store_arg (infiles[i].name, 0, 0);
infiles[i].compiled = true;
}
else
{
- obstack_grow (&obstack, input_filename, input_filename_length);
+ obstack_grow (&obstack, gcc_input_filename,
+ input_filename_length);
arg_going = 1;
}
break;
that would usually be expanded in place of %o will be
written to the temporary file. */
- char *temp_file = make_temp_file ("");
- char *at_argument;
char **argv;
- int n_files, j, status;
- FILE *f;
-
- at_argument = concat ("@", temp_file, NULL);
- store_arg (at_argument, 0, 0);
+ int n_files, j;
/* Convert OUTFILES into a form suitable for writeargv. */
for (n_files = 0, i = 0; i < max; i++)
n_files += outfiles[i] != NULL;
- argv = alloca (sizeof (char *) * (n_files + 1));
+ argv = (char **) alloca (sizeof (char *) * (n_files + 1));
/* Copy the strings over. */
for (i = 0, j = 0; i < max; i++)
if (outfiles[i])
{
- argv[j] = (char *) outfiles[i];
+ argv[j] = CONST_CAST (char *, outfiles[i]);
j++;
}
argv[j] = NULL;
- f = fopen (temp_file, "w");
-
- if (f == NULL)
- fatal ("could not open temporary response file %s",
- temp_file);
-
- status = writeargv (argv, f);
-
- if (status)
- fatal ("could not write to temporary response file %s",
- temp_file);
-
- status = fclose (f);
-
- if (EOF == status)
- fatal ("could not close temporary response file %s",
- temp_file);
-
- record_temp_file (temp_file, !save_temps_flag, !save_temps_flag);
+ create_at_file (argv);
}
else
for (i = 0; i < max; i++)
this_is_library_file = 1;
break;
+ case 'T':
+ this_is_linker_script = 1;
+ break;
+
case 'V':
outfiles[input_file_number] = NULL;
break;
int cur_index = argbuf_index;
/* Handle the {...} following the %W. */
if (*p != '{')
- fatal ("spec '%s' has invalid '%%W%c", spec, *p);
+ fatal_error ("spec %qs has invalid %<%%W%c%>", spec, *p);
p = handle_braces (p + 1);
if (p == 0)
return -1;
- /* End any pending argument. */
- if (arg_going)
- {
- obstack_1grow (&obstack, 0);
- string = XOBFINISH (&obstack, const char *);
- if (this_is_library_file)
- string = find_file (string);
- store_arg (string, delete_this_arg, this_is_output_file);
- if (this_is_output_file)
- outfiles[input_file_number] = string;
- arg_going = 0;
- }
+ end_going_arg ();
/* If any args were output, mark the last one for deletion
on failure. */
if (argbuf_index != cur_index)
/* Skip past the option value and make a copy. */
if (*p != '{')
- fatal ("spec '%s' has invalid '%%x%c'", spec, *p);
+ fatal_error ("spec %qs has invalid %<%%x%c%>", spec, *p);
while (*p++ != '}')
;
string = save_string (p1 + 1, p - p1 - 2);
if (!strncmp (switches[i].part1, p, len - have_wildcard)
&& (have_wildcard || switches[i].part1[len] == '\0'))
{
- switches[i].live_cond = SWITCH_IGNORE;
+ switches[i].live_cond |= SWITCH_IGNORE;
switches[i].validated = 1;
}
/* Catch the case where a spec string contains something like
'%{foo:%*}'. i.e. there is no * in the pattern on the left
hand side of the :. */
- error ("spec failure: '%%*' has not been initialized by pattern match");
+ error ("spec failure: %<%%*%> has not been initialized by pattern match");
break;
/* Process a string found as the value of a spec given by name.
%[...] modifies -D options the way %P does;
%(...) uses the spec unmodified. */
case '[':
- error ("warning: use of obsolete %%[ operator in specs");
+ warning (0, "use of obsolete %%[ operator in specs");
case '(':
{
const char *name = p;
{
name = *(sl->ptr_spec);
#ifdef DEBUG_SPECS
- notice ("Processing spec %c%s%c, which is '%s'\n",
+ fnotice (stderr, "Processing spec %c%s%c, which is '%s'\n",
c, sl->name, (c == '(') ? ')' : ']', name);
#endif
break;
}
else
{
- char *x = alloca (strlen (name) * 2 + 1);
+ char *x = (char *) alloca (strlen (name) * 2 + 1);
char *buf = x;
const char *y = name;
int flag = 0;
break;
default:
- error ("spec failure: unrecognized spec option '%c'", c);
+ error ("spec failure: unrecognized spec option %qc", c);
break;
}
break;
/* End of string. If we are processing a spec function, we need to
end any pending argument. */
- if (processing_spec_function && arg_going)
- {
- obstack_1grow (&obstack, 0);
- string = XOBFINISH (&obstack, const char *);
- if (this_is_library_file)
- string = find_file (string);
- store_arg (string, delete_this_arg, this_is_output_file);
- if (this_is_output_file)
- outfiles[input_file_number] = string;
- arg_going = 0;
- }
+ if (processing_spec_function)
+ end_going_arg ();
return 0;
}
int save_this_is_output_file;
int save_this_is_library_file;
int save_input_from_pipe;
+ int save_this_is_linker_script;
const char *save_suffix_subst;
sf = lookup_spec_function (func);
if (sf == NULL)
- fatal ("unknown spec function '%s'", func);
+ fatal_error ("unknown spec function %qs", func);
/* Push the spec processing context. */
save_argbuf_index = argbuf_index;
save_delete_this_arg = delete_this_arg;
save_this_is_output_file = this_is_output_file;
save_this_is_library_file = this_is_library_file;
+ save_this_is_linker_script = this_is_linker_script;
save_input_from_pipe = input_from_pipe;
save_suffix_subst = suffix_subst;
alloc_args ();
if (do_spec_2 (args) < 0)
- fatal ("error in args to spec function '%s'", func);
+ fatal_error ("error in args to spec function %qs", func);
/* argbuf_index is an index for the next argument to be inserted, and
so contains the count of the args already inserted. */
delete_this_arg = save_delete_this_arg;
this_is_output_file = save_this_is_output_file;
this_is_library_file = save_this_is_library_file;
+ this_is_linker_script = save_this_is_linker_script;
input_from_pipe = save_input_from_pipe;
suffix_subst = save_suffix_subst;
break;
/* Only allow [A-Za-z0-9], -, and _ in function names. */
if (!ISALNUM (*endp) && !(*endp == '-' || *endp == '_'))
- fatal ("malformed spec function name");
+ fatal_error ("malformed spec function name");
}
if (*endp != '(') /* ) */
- fatal ("no arguments for spec function");
+ fatal_error ("no arguments for spec function");
func = save_string (p, endp - p);
p = ++endp;
}
/* ( */
if (*endp != ')')
- fatal ("malformed spec function arguments");
+ fatal_error ("malformed spec function arguments");
args = save_string (p, endp - p);
p = ++endp;
if (atom == end_atom)
{
if (!n_way_choice || disj_matched || *p == '|'
- || a_is_negated || a_is_suffix || a_is_spectype
+ || a_is_negated || a_is_suffix || a_is_spectype
|| a_is_starred)
goto invalid;
{
if ((a_is_suffix || a_is_spectype) && a_is_starred)
goto invalid;
-
+
if (!a_is_starred)
disj_starred = false;
a_matched = input_spec_matches (atom, end_atom);
else
a_matched = switch_matches (atom, end_atom, a_is_starred);
-
+
if (a_matched != a_is_negated)
{
disj_matched = true;
return p;
invalid:
- fatal ("braced spec '%s' is invalid at '%c'", orig, *p);
+ fatal_error ("braced spec %qs is invalid at %qc", orig, *p);
#undef SKIP_WHITE
}
return p;
invalid:
- fatal ("braced spec body '%s' is invalid", body);
+ fatal_error ("braced spec body %qs is invalid", body);
}
\f
/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch
const char *name = switches[switchnum].part1;
int i;
+ /* If we already processed this switch and determined if it was
+ live or not, return our past determination. */
+ if (switches[switchnum].live_cond != 0)
+ return ((switches[switchnum].live_cond & SWITCH_LIVE) != 0
+ && (switches[switchnum].live_cond & SWITCH_FALSE) == 0
+ && (switches[switchnum].live_cond & SWITCH_IGNORE_PERMANENTLY)
+ == 0);
+
/* In the common case of {<at-most-one-letter>*}, a negating
switch would always match, so ignore that case. We will just
send the conflicting switches to the compiler phase. */
if (prefix_length >= 0 && prefix_length <= 1)
return 1;
- /* If we already processed this switch and determined if it was
- live or not, return our past determination. */
- if (switches[switchnum].live_cond != 0)
- return switches[switchnum].live_cond > 0;
-
/* Now search for duplicate in a manner that depends on the name. */
switch (*name)
{
}
/* Otherwise the switch is live. */
- switches[switchnum].live_cond = SWITCH_LIVE;
+ switches[switchnum].live_cond |= SWITCH_LIVE;
return 1;
}
\f
static void
give_switch (int switchnum, int omit_first_word)
{
- if (switches[switchnum].live_cond == SWITCH_IGNORE)
+ if ((switches[switchnum].live_cond & SWITCH_IGNORE) != 0)
return;
if (!omit_first_word)
while (length-- && !IS_DIR_SEPARATOR (arg[length]))
if (arg[length] == '.')
{
- ((char *)arg)[length] = 0;
+ (CONST_CAST(char *, arg))[length] = 0;
dot = 1;
break;
}
do_spec_1 (arg, 1, NULL);
if (dot)
- ((char *)arg)[length] = '.';
+ (CONST_CAST(char *, arg))[length] = '.';
do_spec_1 (suffix_subst, 1, NULL);
}
else
/* Ensure the string ends with "/.". The resulting path will be a
directory even if the given path is a symbolic link. */
len1 = strlen (path1);
- path = alloca (3 + len1);
+ path = (char *) alloca (3 + len1);
memcpy (path, path1, len1);
cp = path + len1;
if (!IS_DIR_SEPARATOR (cp[-1]))
{
const char *p;
- input_filename = filename;
- input_filename_length = strlen (input_filename);
+ gcc_input_filename = filename;
+ input_filename_length = strlen (gcc_input_filename);
+ input_basename = lbasename (gcc_input_filename);
+
+ /* 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)
+ {
+ basename_length = p - input_basename;
+ input_suffix = p + 1;
+ }
+ else
+ input_suffix = "";
+
+ /* If a spec for 'g', 'u', or 'U' is seen with -save-temps then
+ we will need to do a stat on the gcc_input_filename. The
+ INPUT_STAT_SET signals that the stat is needed. */
+ input_stat_set = 0;
+}
+\f
+/* On fatal signals, delete all the temporary files. */
+
+static void
+fatal_signal (int signum)
+{
+ signal (signum, SIG_DFL);
+ delete_failure_queue ();
+ delete_temp_files ();
+ /* Get the same signal again, this time not handled,
+ so its normal effect occurs. */
+ kill (getpid (), signum);
+}
+
+/* Compare the contents of the two files named CMPFILE[0] and
+ CMPFILE[1]. Return zero if they're identical, nonzero
+ otherwise. */
+
+static int
+compare_files (char *cmpfile[])
+{
+ int ret = 0;
+ FILE *temp[2] = { NULL, NULL };
+ int i;
+
+#if HAVE_MMAP_FILE
+ {
+ size_t length[2];
+ void *map[2] = { NULL, NULL };
+
+ for (i = 0; i < 2; i++)
+ {
+ struct stat st;
+
+ if (stat (cmpfile[i], &st) < 0 || !S_ISREG (st.st_mode))
+ {
+ error ("%s: could not determine length of compare-debug file %s",
+ gcc_input_filename, cmpfile[i]);
+ ret = 1;
+ break;
+ }
+
+ length[i] = st.st_size;
+ }
+
+ if (!ret && length[0] != length[1])
+ {
+ error ("%s: -fcompare-debug failure (length)", gcc_input_filename);
+ ret = 1;
+ }
+
+ if (!ret)
+ for (i = 0; i < 2; i++)
+ {
+ int fd = open (cmpfile[i], O_RDONLY);
+ if (fd < 0)
+ {
+ error ("%s: could not open compare-debug file %s",
+ gcc_input_filename, cmpfile[i]);
+ ret = 1;
+ break;
+ }
+
+ map[i] = mmap (NULL, length[i], PROT_READ, MAP_PRIVATE, fd, 0);
+ close (fd);
+
+ if (map[i] == (void *) MAP_FAILED)
+ {
+ ret = -1;
+ break;
+ }
+ }
+
+ if (!ret)
+ {
+ if (memcmp (map[0], map[1], length[0]) != 0)
+ {
+ error ("%s: -fcompare-debug failure", gcc_input_filename);
+ ret = 1;
+ }
+ }
+
+ for (i = 0; i < 2; i++)
+ if (map[i])
+ munmap ((caddr_t) map[i], length[i]);
- input_basename = input_filename;
-#ifdef HAVE_DOS_BASED_FILE_SYSTEM
- /* Skip drive name so 'x:foo' is handled properly. */
- if (input_basename[1] == ':')
- input_basename += 2;
+ if (ret >= 0)
+ return ret;
+
+ ret = 0;
+ }
#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)
+ for (i = 0; i < 2; i++)
{
- basename_length = p - input_basename;
- input_suffix = p + 1;
+ temp[i] = fopen (cmpfile[i], "r");
+ if (!temp[i])
+ {
+ error ("%s: could not open compare-debug file %s",
+ gcc_input_filename, cmpfile[i]);
+ ret = 1;
+ break;
+ }
}
- else
- input_suffix = "";
- /* If a spec for 'g', 'u', or 'U' is seen with -save-temps then
- we will need to do a stat on the input_filename. The
- INPUT_STAT_SET signals that the stat is needed. */
- input_stat_set = 0;
-}
-\f
-/* On fatal signals, delete all the temporary files. */
+ if (!ret && temp[0] && temp[1])
+ for (;;)
+ {
+ int c0, c1;
+ c0 = fgetc (temp[0]);
+ c1 = fgetc (temp[1]);
-static void
-fatal_error (int signum)
-{
- signal (signum, SIG_DFL);
- delete_failure_queue ();
- delete_temp_files ();
- /* Get the same signal again, this time not handled,
- so its normal effect occurs. */
- kill (getpid (), signum);
+ if (c0 != c1)
+ {
+ error ("%s: -fcompare-debug failure",
+ gcc_input_filename);
+ ret = 1;
+ break;
+ }
+
+ if (c0 == EOF)
+ break;
+ }
+
+ for (i = 1; i >= 0; i--)
+ {
+ if (temp[i])
+ fclose (temp[i]);
+ }
+
+ return ret;
}
extern int main (int, char **);
struct user_specs *uptr;
char **old_argv = argv;
+ /* Initialize here, not in definition. The IRIX 6 O32 cc sometimes chokes
+ on ?: in file-scope variable initializations. */
+ asm_debug = ASM_DEBUG_SPEC;
+
p = argv[0] + strlen (argv[0]);
while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
--p;
- programname = p;
+ progname = p;
- xmalloc_set_program_name (programname);
+ xmalloc_set_program_name (progname);
expandargv (&argc, &argv);
gcc_init_libintl ();
+ diagnostic_initialize (global_dc, 0);
+ if (atexit (delete_temp_files) != 0)
+ fatal_error ("atexit failed");
+
if (signal (SIGINT, SIG_IGN) != SIG_IGN)
- signal (SIGINT, fatal_error);
+ signal (SIGINT, fatal_signal);
#ifdef SIGHUP
if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
- signal (SIGHUP, fatal_error);
+ signal (SIGHUP, fatal_signal);
#endif
if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
- signal (SIGTERM, fatal_error);
+ signal (SIGTERM, fatal_signal);
#ifdef SIGPIPE
if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
- signal (SIGPIPE, fatal_error);
+ signal (SIGPIPE, fatal_signal);
#endif
#ifdef SIGCHLD
/* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
multilib_defaults = XOBFINISH (&multilib_obstack, const char *);
}
- /* Set up to remember the pathname of gcc and any options
- needed for collect. We use argv[0] instead of programname because
- we need the complete pathname. */
- obstack_init (&collect_obstack);
- obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1);
- obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1);
- putenv (XOBFINISH (&collect_obstack, char *));
-
#ifdef INIT_ENVIRONMENT
/* Set up any other necessary machine specific environment variables. */
- putenv (INIT_ENVIRONMENT);
+ xputenv (INIT_ENVIRONMENT);
#endif
/* Make a table of what switches there are (switches, n_switches).
Make a table of specified input files (infiles, n_infiles).
Decode switches that are handled locally. */
- process_command (argc, (const char **) argv);
+ process_command (argc, CONST_CAST2 (const char **, char **, argv));
/* Initialize the vector of specs to just the default.
This means one element containing 0s, as a terminator. */
- compilers = xmalloc (sizeof default_compilers);
+ compilers = XNEWVAR (struct compiler, sizeof default_compilers);
memcpy (compilers, default_compilers, sizeof default_compilers);
n_compilers = n_default_compilers;
/* We need to check standard_exec_prefix/just_machine_suffix/specs
for any override of as, ld and libraries. */
- specs_file = alloca (strlen (standard_exec_prefix)
+ specs_file = (char *) alloca (strlen (standard_exec_prefix)
+ strlen (just_machine_suffix) + sizeof ("specs"));
strcpy (specs_file, standard_exec_prefix);
for (i = 0; i < ARRAY_SIZE (driver_self_specs); i++)
do_self_spec (driver_self_specs[i]);
+ if (compare_debug)
+ {
+ enum save_temps save;
+
+ if (!compare_debug_second)
+ {
+ n_switches_debug_check[1] = n_switches;
+ switches_debug_check[1] = XDUPVEC (struct switchstr, switches,
+ n_switches + 1);
+
+ do_self_spec ("%:compare-debug-self-opt()");
+ n_switches_debug_check[0] = n_switches;
+ switches_debug_check[0] = switches;
+
+ n_switches = n_switches_debug_check[1];
+ switches = switches_debug_check[1];
+ }
+
+ /* Avoid crash when computing %j in this early. */
+ save = save_temps_flag;
+ save_temps_flag = SAVE_TEMPS_NONE;
+
+ compare_debug = -compare_debug;
+ do_self_spec ("%:compare-debug-self-opt()");
+
+ save_temps_flag = save;
+
+ if (!compare_debug_second)
+ {
+ n_switches_debug_check[1] = n_switches;
+ switches_debug_check[1] = switches;
+ compare_debug = -compare_debug;
+ n_switches = n_switches_debug_check[0];
+ switches = switches_debug_check[0];
+ }
+ }
+
/* If not cross-compiling, look for executables in the standard
places. */
if (*cross_compile == '0')
else if (*cross_compile == '0')
{
add_prefix (&startfile_prefixes,
- concat (gcc_exec_prefix
- ? gcc_exec_prefix : standard_exec_prefix,
- machine_suffix,
+ concat (gcc_exec_prefix
+ ? gcc_exec_prefix : standard_exec_prefix,
+ machine_suffix,
standard_startfile_prefix, NULL),
NULL, PREFIX_PRIORITY_LAST, 0, 1);
}
the subdirectory based on the options. */
set_multilib_dir ();
+ /* Set up to remember the pathname of gcc and any options
+ needed for collect. We use argv[0] instead of progname because
+ we need the complete pathname. */
+ obstack_init (&collect_obstack);
+ obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1);
+ obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1);
+ xputenv (XOBFINISH (&collect_obstack, char *));
+
+ /* Set up to remember the pathname of the lto wrapper. */
+
+ lto_wrapper_spec = find_a_file (&exec_prefixes, "lto-wrapper", X_OK, false);
+ if (lto_wrapper_spec)
+ {
+ obstack_init (&collect_obstack);
+ obstack_grow (&collect_obstack, "COLLECT_LTO_WRAPPER=",
+ sizeof ("COLLECT_LTO_WRAPPER=") - 1);
+ obstack_grow (&collect_obstack, lto_wrapper_spec,
+ strlen (lto_wrapper_spec) + 1);
+ xputenv (XOBFINISH (&collect_obstack, char *));
+ }
+
/* Warn about any switches that no pass was interested in. */
for (i = 0; (int) i < n_switches; i++)
if (! switches[i].validated)
- error ("unrecognized option '-%s'", switches[i].part1);
+ error ("unrecognized option %<-%s%>", switches[i].part1);
/* Obey some of the options. */
return (0);
}
+ if (print_sysroot)
+ {
+ if (target_system_root)
+ {
+ if (target_sysroot_suffix)
+ printf ("%s%s\n", target_system_root, target_sysroot_suffix);
+ else
+ printf ("%s\n", target_system_root);
+ }
+ return (0);
+ }
+
if (print_multi_os_directory)
{
if (multilib_os_dir == NULL)
else
/* The error status indicates that only one set of fixed
headers should be built. */
- fatal ("not configured with sysroot headers suffix");
+ fatal_error ("not configured with sysroot headers suffix");
}
if (print_help_list)
/* We do not exit here. Instead we have created a fake input file
called 'help-dummy' which needs to be compiled, and we pass this
- on the various sub-processes, along with the --help switch. */
+ on the various sub-processes, along with the --help switch.
+ Ensure their output appears after ours. */
+ fputc ('\n', stdout);
+ fflush (stdout);
+ }
+
+ if (print_version)
+ {
+ printf (_("%s %s%s\n"), progname, pkgversion_string,
+ version_string);
+ printf ("Copyright %s 2010 Free Software Foundation, Inc.\n",
+ _("(C)"));
+ fputs (_("This is free software; see the source for copying conditions. There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
+ stdout);
+ if (! verbose_flag)
+ return 0;
+
+ /* We do not exit here. We use the same mechanism of --help to print
+ the version of the sub-processes. */
+ fputc ('\n', stdout);
+ fflush (stdout);
}
if (verbose_flag)
int n;
const char *thrmod;
- notice ("Target: %s\n", spec_machine);
- notice ("Configured with: %s\n", configuration_arguments);
+ fnotice (stderr, "Target: %s\n", spec_machine);
+ fnotice (stderr, "Configured with: %s\n", configuration_arguments);
#ifdef THREAD_MODEL_SPEC
/* We could have defined THREAD_MODEL_SPEC to "%*" by default,
thrmod = thread_model;
#endif
- notice ("Thread model: %s\n", thrmod);
+ fnotice (stderr, "Thread model: %s\n", thrmod);
/* compiler_version is truncated at the first space when initialized
from version string, so truncate version_string at the first space
if (! strncmp (version_string, compiler_version, n)
&& compiler_version[n] == 0)
- notice ("gcc version %s\n", version_string);
+ fnotice (stderr, "gcc version %s %s\n", version_string,
+ pkgversion_string);
else
- notice ("gcc driver version %s executing gcc version %s\n",
- version_string, compiler_version);
+ fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n",
+ version_string, pkgversion_string, compiler_version);
if (n_infiles == 0)
return (0);
}
if (n_infiles == added_libraries)
- fatal ("no input files");
+ fatal_error ("no input files");
/* Make a place to record the compiler output file names
that correspond to the input files. */
}
if (!combine_inputs && have_c && have_o && lang_n_infiles > 1)
- fatal ("cannot specify -o with -c or -S with multiple files");
+ fatal_error ("cannot specify -o with -c, -S or -E with multiple files");
if (combine_flag && save_temps_flag)
{
if (input_file_compiler->spec[0] == '#')
{
error ("%s: %s compiler not installed on this system",
- input_filename, &input_file_compiler->spec[1]);
+ gcc_input_filename, &input_file_compiler->spec[1]);
this_file_error = 1;
}
else
value = do_spec (input_file_compiler->spec);
infiles[i].preprocessed = true;
if (!have_o_argbuf_index)
- fatal ("spec '%s' is invalid", input_file_compiler->spec);
+ fatal_error ("spec %qs is invalid",
+ input_file_compiler->spec);
infiles[i].name = argbuf[have_o_argbuf_index];
infiles[i].incompiler
= lookup_compiler (infiles[i].name,
if (this_file_error)
{
delete_failure_queue ();
- error_count++;
+ errorcount++;
break;
}
clear_failure_queue ();
/* Use the same thing in %o, unless cp->spec says otherwise. */
- outfiles[i] = input_filename;
+ outfiles[i] = gcc_input_filename;
/* Figure out which compiler from the file's suffix. */
if (input_file_compiler->spec[0] == '#')
{
error ("%s: %s compiler not installed on this system",
- input_filename, &input_file_compiler->spec[1]);
+ gcc_input_filename, &input_file_compiler->spec[1]);
this_file_error = 1;
}
else
{
+ if (compare_debug)
+ {
+ if (debug_check_temp_file[0])
+ free (debug_check_temp_file[0]);
+ debug_check_temp_file[0] = NULL;
+
+ if (debug_check_temp_file[1])
+ free (debug_check_temp_file[1]);
+ debug_check_temp_file[1] = NULL;
+ }
+
value = do_spec (input_file_compiler->spec);
infiles[i].compiled = true;
if (value < 0)
this_file_error = 1;
+ else if (compare_debug && debug_check_temp_file[0])
+ {
+ if (verbose_flag)
+ inform (0, "recompiling with -fcompare-debug");
+
+ compare_debug = -compare_debug;
+ n_switches = n_switches_debug_check[1];
+ switches = switches_debug_check[1];
+
+ value = do_spec (input_file_compiler->spec);
+
+ compare_debug = -compare_debug;
+ n_switches = n_switches_debug_check[0];
+ switches = switches_debug_check[0];
+
+ if (value < 0)
+ {
+ error ("during -fcompare-debug recompilation");
+ this_file_error = 1;
+ }
+
+ gcc_assert (debug_check_temp_file[1]
+ && strcmp (debug_check_temp_file[0],
+ debug_check_temp_file[1]));
+
+ if (verbose_flag)
+ inform (0, "comparing final insns dumps");
+
+ if (compare_files (debug_check_temp_file))
+ this_file_error = 1;
+ }
+
+ if (compare_debug)
+ {
+ if (debug_check_temp_file[0])
+ free (debug_check_temp_file[0]);
+ debug_check_temp_file[0] = NULL;
+
+ if (debug_check_temp_file[1])
+ free (debug_check_temp_file[1]);
+ debug_check_temp_file[1] = NULL;
+ }
}
}
if (this_file_error)
{
delete_failure_queue ();
- error_count++;
+ errorcount++;
}
/* If this compilation succeeded, don't delete those files later. */
clear_failure_queue ();
}
}
- if (error_count == 0)
+ if (!seen_error ())
{
/* Make sure INPUT_FILE_NUMBER points to first available open
slot. */
input_file_number = n_infiles;
if (lang_specific_pre_link ())
- error_count++;
+ errorcount++;
}
/* Determine if there are any linker input files. */
/* Run ld to link all the compiler output files. */
- if (num_linker_inputs > 0 && error_count == 0 && print_subprocess_help < 2)
+ if (num_linker_inputs > 0 && !seen_error () && print_subprocess_help < 2)
{
int tmp = execution_count;
+ const char *fuse_linker_plugin = "fuse-linker-plugin";
/* We'll use ld if we can't find collect2. */
if (! strcmp (linker_name_spec, "collect2"))
if (s == NULL)
linker_name_spec = "ld";
}
+
+ if (switch_matches (fuse_linker_plugin,
+ fuse_linker_plugin + strlen (fuse_linker_plugin), 0))
+ {
+ linker_plugin_file_spec = find_a_file (&exec_prefixes,
+ "liblto_plugin.so", R_OK,
+ false);
+ if (!linker_plugin_file_spec)
+ fatal_error ("-fuse-linker-plugin, but liblto_plugin.so not found");
+
+ lto_libgcc_spec = find_a_file (&startfile_prefixes, "libgcc.a",
+ R_OK, true);
+ if (!lto_libgcc_spec)
+ fatal_error ("could not find libgcc.a");
+ }
+ lto_gcc_spec = argv[0];
+
/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
for collect. */
putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH", false);
}
value = do_spec (link_command_spec);
if (value < 0)
- error_count = 1;
+ errorcount = 1;
linker_was_run = (tmp != execution_count);
}
/* If options said don't run linker,
complain about input files to be given to the linker. */
- if (! linker_was_run && error_count == 0)
+ if (! linker_was_run && !seen_error ())
for (i = 0; (int) i < n_infiles; i++)
- if (explicit_link_files[i])
- error ("%s: linker input file unused because linking not done",
- outfiles[i]);
+ if (explicit_link_files[i]
+ && !(infiles[i].language && infiles[i].language[0] == '*'))
+ warning (0, "%s: linker input file unused because linking not done",
+ outfiles[i]);
/* Delete some or all of the temporary files we made. */
- if (error_count)
+ if (seen_error ())
delete_failure_queue ();
delete_temp_files ();
}
return (signal_count != 0 ? 2
- : error_count > 0 ? (pass_exit_codes ? greatest_status : 1)
+ : seen_error () ? (pass_exit_codes ? greatest_status : 1)
: 0);
}
static void
perror_with_name (const char *name)
{
- error ("%s: %s", name, xstrerror (errno));
-}
-
-/* Output an error message and exit. */
-
-void
-fancy_abort (const char *file, int line, const char *func)
-{
- fatal_ice ("internal gcc abort in %s, at %s:%d", func, file, line);
-}
-\f
-/* Output an error message and exit. */
-
-void
-fatal_ice (const char *cmsgid, ...)
-{
- va_list ap;
-
- va_start (ap, cmsgid);
-
- fprintf (stderr, "%s: ", programname);
- vfprintf (stderr, _(cmsgid), ap);
- va_end (ap);
- fprintf (stderr, "\n");
- delete_temp_files ();
- exit (pass_exit_codes ? ICE_EXIT_CODE : 1);
-}
-
-void
-fatal (const char *cmsgid, ...)
-{
- va_list ap;
-
- va_start (ap, cmsgid);
-
- fprintf (stderr, "%s: ", programname);
- vfprintf (stderr, _(cmsgid), ap);
- va_end (ap);
- fprintf (stderr, "\n");
- delete_temp_files ();
- exit (1);
-}
-
-/* The argument is actually c-format, not gcc-internal-format,
- but because functions with identical names are used through
- the rest of the compiler with gcc-internal-format, we just
- need to hope all users of these functions use the common
- subset between c-format and gcc-internal-format. */
-
-void
-error (const char *gmsgid, ...)
-{
- va_list ap;
-
- va_start (ap, gmsgid);
- fprintf (stderr, "%s: ", programname);
- vfprintf (stderr, _(gmsgid), ap);
- va_end (ap);
-
- fprintf (stderr, "\n");
-}
-
-static void
-notice (const char *cmsgid, ...)
-{
- va_list ap;
-
- va_start (ap, cmsgid);
- vfprintf (stderr, _(cmsgid), ap);
- va_end (ap);
+ error ("%s: %m", name);
}
\f
static inline void
if (*q == ';')
cnt++;
- matches = alloca ((sizeof (struct mswitchstr)) * cnt);
+ matches
+ = (struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt);
i = 0;
q = multilib_matches;
while (*q != '\0')
if (*q == '\0')
{
invalid_matches:
- fatal ("multilib spec '%s' is invalid", multilib_matches);
+ fatal_error ("multilib spec %qs is invalid",
+ multilib_matches);
}
q++;
}
mswitches
= XNEWVEC (struct mswitchstr, n_mdswitches + (n_switches ? n_switches : 1));
for (i = 0; i < n_switches; i++)
- if (switches[i].live_cond != SWITCH_IGNORE)
+ if ((switches[i].live_cond & SWITCH_IGNORE) == 0)
{
int xlen = strlen (switches[i].part1);
for (j = 0; j < cnt; j++)
if (*p == '\0')
{
invalid_exclusions:
- fatal ("multilib exclusions '%s' is invalid",
- multilib_exclusions);
+ fatal_error ("multilib exclusions %qs is invalid",
+ multilib_exclusions);
}
if (! ok)
if (*p == '\0')
{
invalid_select:
- fatal ("multilib select '%s' is invalid",
- multilib_select);
+ fatal_error ("multilib select %qs is invalid",
+ multilib_select);
}
++p;
}
if (multilib_dir == NULL && multilib_os_dir != NULL
&& strcmp (multilib_os_dir, ".") == 0)
{
- free ((char *) multilib_os_dir);
+ free (CONST_CAST (char *, multilib_os_dir));
multilib_os_dir = NULL;
}
else if (multilib_dir != NULL && multilib_os_dir == NULL)
if (*p == '\0')
{
invalid_select:
- fatal ("multilib select '%s' is invalid", multilib_select);
+ fatal_error ("multilib select %qs is invalid", multilib_select);
}
++p;
if (*e == '\0')
{
invalid_exclusion:
- fatal ("multilib exclusion '%s' is invalid",
- multilib_exclusions);
+ fatal_error ("multilib exclusion %qs is invalid",
+ multilib_exclusions);
}
if (! m)
getenv_spec_function (int argc, const char **argv)
{
char *value;
+ char *result;
+ char *ptr;
+ size_t len;
if (argc != 2)
return NULL;
value = getenv (argv[0]);
if (!value)
- fatal ("environment variable \"%s\" not defined", argv[0]);
+ fatal_error ("environment variable %qs not defined", argv[0]);
+
+ /* We have to escape every character of the environment variable so
+ they are not interpreted as active spec characters. A
+ particularly painful case is when we are reading a variable
+ holding a windows path complete with \ separators. */
+ len = strlen (value) * 2 + strlen (argv[1]) + 1;
+ result = XNEWVAR (char, len);
+ for (ptr = result; *value; ptr += 2)
+ {
+ ptr[0] = '\\';
+ ptr[1] = *value++;
+ }
+
+ strcpy (ptr, argv[1]);
- return concat (value, argv[1], NULL);
+ return result;
}
/* if-exists built-in spec function.
abort ();
rresult = regexec (&r, v1, 0, NULL, 0);
if (rresult == REG_NOMATCH)
- fatal ("invalid version number `%s'", v1);
+ fatal_error ("invalid version number %qs", v1);
else if (rresult != 0)
abort ();
rresult = regexec (&r, v2, 0, NULL, 0);
if (rresult == REG_NOMATCH)
- fatal ("invalid version number `%s'", v2);
+ fatal_error ("invalid version number %qs", v2);
else if (rresult != 0)
abort ();
bool result;
if (argc < 3)
- fatal ("too few arguments to %%:version-compare");
+ fatal_error ("too few arguments to %%:version-compare");
if (argv[0][0] == '\0')
abort ();
if ((argv[0][1] == '<' || argv[0][1] == '>') && argv[0][0] != '!')
nargs = 2;
if (argc != nargs + 3)
- fatal ("too many arguments to %%:version-compare");
+ fatal_error ("too many arguments to %%:version-compare");
switch_len = strlen (argv[nargs + 1]);
for (i = 0; i < n_switches; i++)
break;
default:
- fatal ("unknown operator '%s' in %%:version-compare", argv[0]);
+ fatal_error ("unknown operator %qs in %%:version-compare", argv[0]);
}
if (! result)
return NULL;
if (argc != 1)
abort ();
- file = find_a_file (&startfile_prefixes, argv[0], R_OK, 0);
+ file = find_a_file (&startfile_prefixes, argv[0], R_OK, true);
read_specs (file ? file : argv[0], FALSE);
return NULL;
}
+/* %:find-file spec function. This function replaces its argument by
+ the file found thru find_file, that is the -print-file-name gcc
+ program option. */
+static const char *
+find_file_spec_function (int argc, const char **argv)
+{
+ const char *file;
+
+ if (argc != 1)
+ abort ();
+
+ file = find_file (argv[0]);
+ return file;
+}
+
+
+/* %:find-plugindir spec function. This function replaces its argument
+ by the -iplugindir=<dir> option. `dir' is found thru find_file, that
+ is the -print-file-name gcc program option. */
+static const char *
+find_plugindir_spec_function (int argc, const char **argv ATTRIBUTE_UNUSED)
+{
+ const char *option;
+
+ if (argc != 0)
+ abort ();
+
+ option = concat ("-iplugindir=", find_file ("plugin"), NULL);
+ return option;
+}
+
+
/* %:print-asm-header spec function. Print a banner to say that the
following output is from the assembler. */
fflush (stdout);
return NULL;
}
+
+/* Compute a timestamp to initialize flag_random_seed. */
+
+static unsigned
+get_local_tick (void)
+{
+ unsigned ret = 0;
+
+ /* Get some more or less random data. */
+#ifdef HAVE_GETTIMEOFDAY
+ {
+ struct timeval tv;
+
+ gettimeofday (&tv, NULL);
+ ret = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+ }
+#else
+ {
+ time_t now = time (NULL);
+
+ if (now != (time_t)-1)
+ ret = (unsigned) now;
+ }
+#endif
+
+ return ret;
+}
+
+/* %:compare-debug-dump-opt spec function. Save the last argument,
+ expected to be the last -fdump-final-insns option, or generate a
+ temporary. */
+
+static const char *
+compare_debug_dump_opt_spec_function (int arg,
+ const char **argv ATTRIBUTE_UNUSED)
+{
+ const char *ret;
+ char *name;
+ int which;
+ static char random_seed[HOST_BITS_PER_WIDE_INT / 4 + 3];
+
+ if (arg != 0)
+ fatal_error ("too many arguments to %%:compare-debug-dump-opt");
+
+ do_spec_2 ("%{fdump-final-insns=*:%*}");
+ do_spec_1 (" ", 0, NULL);
+
+ if (argbuf_index > 0 && strcmp (argv[argbuf_index - 1], "."))
+ {
+ if (!compare_debug)
+ return NULL;
+
+ name = xstrdup (argv[argbuf_index - 1]);
+ ret = NULL;
+ }
+ else
+ {
+ const char *ext = NULL;
+
+ if (argbuf_index > 0)
+ {
+ do_spec_2 ("%{o*:%*}%{!o:%{!S:%b%O}%{S:%b.s}}");
+ ext = ".gkd";
+ }
+ else if (!compare_debug)
+ return NULL;
+ else
+ do_spec_2 ("%g.gkd");
+
+ do_spec_1 (" ", 0, NULL);
+
+ gcc_assert (argbuf_index > 0);
+
+ name = concat (argbuf[argbuf_index - 1], ext, NULL);
+
+ ret = concat ("-fdump-final-insns=", name, NULL);
+ }
+
+ which = compare_debug < 0;
+ debug_check_temp_file[which] = name;
+
+ if (!which)
+ {
+ unsigned HOST_WIDE_INT value = get_local_tick () ^ getpid ();
+
+ sprintf (random_seed, HOST_WIDE_INT_PRINT_HEX, value);
+ }
+
+ if (*random_seed)
+ ret = concat ("%{!frandom-seed=*:-frandom-seed=", random_seed, "} ",
+ ret, NULL);
+
+ if (which)
+ *random_seed = 0;
+
+ return ret;
+}
+
+static const char *debug_auxbase_opt;
+
+/* %:compare-debug-self-opt spec function. Expands to the options
+ that are to be passed in the second compilation of
+ compare-debug. */
+
+static const char *
+compare_debug_self_opt_spec_function (int arg,
+ const char **argv ATTRIBUTE_UNUSED)
+{
+ if (arg != 0)
+ fatal_error ("too many arguments to %%:compare-debug-self-opt");
+
+ if (compare_debug >= 0)
+ return NULL;
+
+ do_spec_2 ("%{c|S:%{o*:%*}}");
+ do_spec_1 (" ", 0, NULL);
+
+ if (argbuf_index > 0)
+ debug_auxbase_opt = concat ("-auxbase-strip ",
+ argbuf[argbuf_index - 1],
+ NULL);
+ else
+ debug_auxbase_opt = NULL;
+
+ return concat ("\
+%<o %<MD %<MMD %<MF* %<MG %<MP %<MQ* %<MT* \
+%<fdump-final-insns=* -w -S -o %j \
+%{!fcompare-debug-second:-fcompare-debug-second} \
+", compare_debug_opt, NULL);
+}
+
+/* %:compare-debug-auxbase-opt spec function. Expands to the auxbase
+ options that are to be passed in the second compilation of
+ compare-debug. It expects, as an argument, the basename of the
+ current input file name, with the .gk suffix appended to it. */
+
+static const char *
+compare_debug_auxbase_opt_spec_function (int arg,
+ const char **argv)
+{
+ char *name;
+ int len;
+
+ if (arg == 0)
+ fatal_error ("too few arguments to %%:compare-debug-auxbase-opt");
+
+ if (arg != 1)
+ fatal_error ("too many arguments to %%:compare-debug-auxbase-opt");
+
+ if (compare_debug >= 0)
+ return NULL;
+
+ len = strlen (argv[0]);
+ if (len < 3 || strcmp (argv[0] + len - 3, ".gk") != 0)
+ fatal_error ("argument to %%:compare-debug-auxbase-opt "
+ "does not end in .gk");
+
+ if (debug_auxbase_opt)
+ return debug_auxbase_opt;
+
+#define OPT "-auxbase "
+
+ len -= 3;
+ name = (char*) xmalloc (sizeof (OPT) + len);
+ memcpy (name, OPT, sizeof (OPT) - 1);
+ memcpy (name + sizeof (OPT) - 1, argv[0], len);
+ name[sizeof (OPT) - 1 + len] = '\0';
+
+#undef OPT
+
+ return name;
+}