X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fgcc.c;h=75dc67d0e8ee9c87c719c1e7ffd673c78dba82b7;hb=d29a1ab5c0f85e613d581a091a251e57c6f3f8cf;hp=7e5733cc75aabb53f192198a2e22dbe05a52b3e0;hpb=4009b53fc59b4defcbfd3aae56fa616b749d3379;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/gcc.c b/gcc/gcc.c index 7e5733cc75a..75dc67d0e8e 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -1,13 +1,13 @@ /* 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 Free Software Foundation, - Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 + 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 @@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 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. +along with GCC; see the file COPYING3. If not see +. This paragraph is here to try to keep Sun CC from dying. The number of chars here seems crucial!!!! */ @@ -86,6 +85,7 @@ compilation is specified by a string called a "spec". */ #include "prefix.h" #include "gcc.h" #include "flags.h" +#include "opts.h" /* By default there is no special suffix for target executables. */ /* FIXME: when autoconf is fixed, remove the host check - dj */ @@ -126,6 +126,9 @@ static const char dir_separator_str[] = { DIR_SEPARATOR, 0 }; /* Flag set by cppspec.c to 1. */ int is_cpp_driver; +/* Flag set to nonzero if an @file argument has been supplied to gcc. */ +static bool at_file_supplied; + /* Flag saying to pass the greatest exit code returned by a sub-process to the calling program. */ static int pass_exit_codes; @@ -152,6 +155,8 @@ static const char *print_prog_name = NULL; 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. */ @@ -167,6 +172,11 @@ static int print_multi_lib; static int print_help_list; +/* Flag saying to print the sysroot suffix used for searching for + headers. */ + +static int print_sysroot_headers_suffix; + /* Flag indicating whether we should print the command and arguments */ static int verbose_flag; @@ -178,9 +188,9 @@ static int verbose_flag; shell scripts to capture the driver-generated command line. */ static int verbose_only_flag; -/* Flag indicating to print target specific command line options. */ +/* Flag indicating how to print command line options of sub-processes. */ -static int target_help_flag; +static int print_subprocess_help; /* Flag indicating whether we should report subprocess execution times (if this is supported by the system - see pexecute.c). */ @@ -237,7 +247,7 @@ static const char *spec_machine = DEFAULT_TARGET_MACHINE; /* Nonzero if cross-compiling. When -b is used, the value comes from the `specs' file. */ -#ifdef CROSS_COMPILE +#ifdef CROSS_DIRECTORY_STRUCTURE static const char *cross_compile = "1"; #else static const char *cross_compile = "0"; @@ -277,18 +287,28 @@ static struct obstack obstack; 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); @@ -349,11 +369,13 @@ static void init_gcc_specs (struct obstack *, const char *, const char *, static const char *convert_filename (const char *, int, int); #endif +static const char *getenv_spec_function (int, const char **); static const char *if_exists_spec_function (int, const char **); static const char *if_exists_else_spec_function (int, 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 *print_asm_header_spec_function (int, const char **); /* The Specs Language @@ -509,15 +531,18 @@ or with constant text in a single argument. part of that switch that matched the '*'. %{.S:X} substitutes X, if processing a file with suffix S. %{!.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 - combined with !, ., and * as above binding stronger than the OR. + 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; :D} else substitutes D. There can be as many clauses as you need. - This may be combined with ., !, |, and * as above. + This may be combined with '.', '!', ',', '|', and '*' as above. %(Spec) processes a specification defined in a specs file as *Spec: %[Spec] as above, but put __ around -D arguments @@ -642,21 +667,27 @@ proper position among the other output files. */ #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 \ + ? "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}" ASM_MAP \ + : "%{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*:--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*:--gdwarf2}" ASM_MAP # endif # endif #endif @@ -681,10 +712,6 @@ proper position among the other output files. */ #endif #endif -#ifndef LINK_GCC_MATH_SPEC -#define LINK_GCC_MATH_SPEC "" -#endif - #ifndef LINK_PIE_SPEC #ifdef HAVE_LD_PIE #define LINK_PIE_SPEC "%{pie:-pie} " @@ -705,9 +732,9 @@ proper position among the other output files. */ %(linker) %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)\ + %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)} %(mflib)\ %{fprofile-arcs|fprofile-generate|coverage:-lgcov}\ - %{!nostdlib:%{!nodefaultlibs:%(link_gcc_math) %(link_ssp) %(link_gcc_c_sequence)}}\ + %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\ %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}" #endif @@ -738,7 +765,6 @@ static const char *cc1_spec = CC1_SPEC; static const char *cc1plus_spec = CC1PLUS_SPEC; static const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC; static const char *link_ssp_spec = LINK_SSP_SPEC; -static const char *link_gcc_math_spec = LINK_GCC_MATH_SPEC; static const char *asm_spec = ASM_SPEC; static const char *asm_final_spec = ASM_FINAL_SPEC; static const char *link_spec = LINK_SPEC; @@ -779,8 +805,9 @@ static const char *cpp_unique_options = %{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\ %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\ %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\ - %{!E:%{!M:%{!MM:%{MD|MMD:%{o*:-MQ %*}}}}}\ - %{remap} %{g3:-dD} %{H} %C %{D*&U*&A*} %{i*} %Z %i\ + %{!E:%{!M:%{!MM:%{!MT:%{!MQ:%{MD|MMD:%{o*:-MQ %*}}}}}}}\ + %{remap} %{g3|ggdb3|gstabs3|gcoff3|gxcoff3|gvms3:-dD}\ + %{H} %C %{D*&U*&A*} %{i*} %Z %i\ %{fmudflap:-D_MUDFLAP -include mf-runtime.h}\ %{fmudflapth:-D_MUDFLAP -D_MUDFLAPTH -include mf-runtime.h}\ %{E|M|MM:%W{o*}}"; @@ -792,7 +819,7 @@ static const char *cpp_unique_options = 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*}\ + %{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 @@ -808,12 +835,19 @@ static const char *cc1_options = %{v:-version} %{pg:-p} %{p} %{f*} %{undef}\ %{Qn:-fno-ident} %{--help:--help}\ %{--target-help:--target-help}\ + %{--help=*:--help=%(VALUE)}\ %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\ %{fsyntax-only:-o %j} %{-param*}\ %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants}\ %{coverage:-fprofile-arcs -ftest-coverage}"; static const char *asm_options = +"%{--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 = @@ -847,7 +881,7 @@ static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS; /* 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[] = { @@ -943,11 +977,14 @@ static const struct compiler default_compilers[] = {".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}, @@ -1000,15 +1037,16 @@ static const struct compiler default_compilers[] = {".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 }}}}" @@ -1126,6 +1164,8 @@ static const struct option_map option_map[] = {"--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}, {"--quiet", "-q", 0}, @@ -1166,7 +1206,7 @@ static const struct { /* 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) @@ -1175,7 +1215,7 @@ 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; @@ -1205,7 +1245,7 @@ translate_options (int *argcp, const char *const **argvp) } 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); @@ -1459,7 +1499,7 @@ static const char *gcc_libexec_prefix; #define STANDARD_STARTFILE_PREFIX_2 "/usr/lib/" #endif -#ifdef CROSS_COMPILE /* Don't use these prefixes for a cross compiler. */ +#ifdef CROSS_DIRECTORY_STRUCTURE /* Don't use these prefixes for a cross compiler. */ #undef MD_EXEC_PREFIX #undef MD_STARTFILE_PREFIX #undef MD_STARTFILE_PREFIX_1 @@ -1476,25 +1516,33 @@ static const char *gcc_libexec_prefix; #define MD_STARTFILE_PREFIX_1 "" #endif +/* These directories are locations set at configure-time based on the + --prefix option provided to configure. Their initializers are + defined in Makefile.in. These paths are not *directly* used when + gcc_exec_prefix is set because, in that case, we know where the + compiler has been installed, and use paths relative to that + location instead. */ static const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX; +static const char *const standard_libexec_prefix = STANDARD_LIBEXEC_PREFIX; +static const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX; +static const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX; + +/* 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; -static const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX; static const char *const standard_startfile_prefix_1 = STANDARD_STARTFILE_PREFIX_1; static const char *const standard_startfile_prefix_2 = STANDARD_STARTFILE_PREFIX_2; +/* A relative path to be used in finding the location of tools + relative to the driver. */ static const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX; -static const char *tooldir_prefix; - -static const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX; - -static const char *standard_libexec_prefix = STANDARD_LIBEXEC_PREFIX; /* Subdirectory to use for locating libraries. Set by set_multilib_dir based on the compilation options. */ @@ -1546,7 +1594,6 @@ static struct spec_list static_specs[] = INIT_STATIC_SPEC ("cc1plus", &cc1plus_spec), INIT_STATIC_SPEC ("link_gcc_c_sequence", &link_gcc_c_sequence_spec), INIT_STATIC_SPEC ("link_ssp", &link_ssp_spec), - INIT_STATIC_SPEC ("link_gcc_math", &link_gcc_math_spec), INIT_STATIC_SPEC ("endfile", &endfile_spec), INIT_STATIC_SPEC ("link", &link_spec), INIT_STATIC_SPEC ("lib", &lib_spec), @@ -1596,11 +1643,13 @@ static struct spec_list *specs = (struct spec_list *) 0; static const struct spec_function static_spec_functions[] = { + { "getenv", getenv_spec_function }, { "if-exists", if_exists_spec_function }, { "if-exists-else", if_exists_else_spec_function }, { "replace-outfile", replace_outfile_spec_function }, { "version-compare", version_compare_spec_function }, { "include", include_spec_function }, + { "print-asm-header", print_asm_header_spec_function }, #ifdef EXTRA_SPEC_FUNCTIONS EXTRA_SPEC_FUNCTIONS #endif @@ -1670,8 +1719,7 @@ init_spec (void) notice ("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--) { @@ -1685,10 +1733,6 @@ init_spec (void) } #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]; @@ -1855,7 +1899,7 @@ set_spec (const char *name, const char *spec) /* Free the old spec. */ if (old_spec && sl->alloc_p) - free ((void *) old_spec); + free (CONST_CAST(char *, old_spec)); sl->alloc_p = 1; } @@ -1938,7 +1982,7 @@ static void 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; @@ -2160,7 +2204,7 @@ read_specs (const char *filename, int main_p) 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; @@ -2230,8 +2274,7 @@ read_specs (const char *filename, int main_p) { /* 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; @@ -2510,18 +2553,18 @@ for_each_path (const struct path_prefix *paths, 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 @@ -2530,12 +2573,12 @@ for_each_path (const struct path_prefix *paths, 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; @@ -2552,7 +2595,7 @@ struct add_to_obstack_info { 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; @@ -2566,6 +2609,16 @@ add_to_obstack (char *path, void *data) 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) + notice ("%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. @@ -2600,7 +2653,7 @@ static void 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)); } /* Check whether NAME can be accessed in MODE. This is like access, @@ -2636,7 +2689,7 @@ struct file_at_path_info { 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); @@ -2695,8 +2748,9 @@ find_a_file (const struct path_prefix *pprefix, const char *name, int mode, 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 @@ -2754,6 +2808,7 @@ add_prefix (struct path_prefix *pprefix, const char *prefix, } /* Same as add_prefix, but prepending target_system_root to prefix. */ +/* The target_system_root prefix has been relocated by gcc_exec_prefix. */ static void add_sysrooted_prefix (struct path_prefix *pprefix, const char *prefix, const char *component, @@ -2801,13 +2856,20 @@ execute (void) 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. @@ -2815,10 +2877,12 @@ execute (void) 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) @@ -2912,7 +2976,7 @@ execute (void) 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"; @@ -2941,7 +3005,7 @@ execute (void) 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) { @@ -2955,7 +3019,7 @@ execute (void) } if (string != commands[i].prog) - free ((void *) string); + free (CONST_CAST (char *, string)); } execution_count++; @@ -2967,13 +3031,13 @@ execute (void) 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")); if (report_times) { - 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")); } @@ -3041,24 +3105,22 @@ See %s for instructions.", 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 % Pass comma-separated on to the assembler\n"), stdout); fputs (_(" -Wp, Pass comma-separated on to the preprocessor\n"), stdout); fputs (_(" -Wl, Pass comma-separated on to the linker\n"), stdout); @@ -3197,7 +3263,7 @@ display_help (void) fputs (_(" -std= Assume that the input sources are for \n"), stdout); fputs (_("\ --sysroot= Use as the root directory for headers\n\ - for headers and libraries\n"), stdout); + and libraries\n"), stdout); fputs (_(" -B Add to the compiler's search paths\n"), stdout); fputs (_(" -b Run gcc for target , if installed\n"), stdout); fputs (_(" -V Run gcc version number , if installed\n"), stdout); @@ -3232,8 +3298,8 @@ add_preprocessor_option (const char *option, int len) 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); @@ -3247,8 +3313,8 @@ add_assembler_option (const char *option, int 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); } @@ -3261,8 +3327,7 @@ add_linker_option (const char *option, int 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); } @@ -3283,6 +3348,7 @@ process_command (int argc, const char **argv) int is_modify_target_name; unsigned int j; #endif + const char *tooldir_prefix; GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX"); @@ -3347,15 +3413,14 @@ process_command (int argc, const char **argv) for (baselen = strlen (progname); baselen > 0; baselen--) if (IS_DIR_SEPARATOR (progname[baselen-1])) break; - new_argv0 = xmemdup (progname, baselen, + new_argv0 = XDUPVAR (char, 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 = XDUPVEC (char *, argv, argc + 1); new_argv[0] = new_argv0; execvp (new_argv0, new_argv); @@ -3376,7 +3441,7 @@ process_command (int argc, const char **argv) 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 { @@ -3388,10 +3453,18 @@ process_command (int argc, const char **argv) gcc_libexec_prefix = make_relative_prefix (tmp_prefix, standard_exec_prefix, standard_libexec_prefix); + + /* The path is unrelocated, so fallback to the original setting. */ + if (!gcc_libexec_prefix) + gcc_libexec_prefix = standard_libexec_prefix; + free (tmp_prefix); } #else #endif + /* From this point onward, gcc_exec_prefix is non-null if the toolchain + is relocated. The toolchain was either relocated using GCC_EXEC_PREFIX + or an automatically created GCC_EXEC_PREFIX from argv[0]. */ if (gcc_exec_prefix) { @@ -3422,7 +3495,7 @@ process_command (int argc, const char **argv) if (temp) { const char *startp, *endp; - char *nstore = alloca (strlen (temp) + 3); + char *nstore = (char *) alloca (strlen (temp) + 3); startp = endp = temp; while (1) @@ -3456,7 +3529,7 @@ process_command (int argc, const char **argv) 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) @@ -3489,7 +3562,7 @@ process_command (int argc, const char **argv) 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) @@ -3552,8 +3625,9 @@ process_command (int argc, const char **argv) 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 2006 Free Software Foundation, Inc.\n", + printf (_("%s %s%s\n"), programname, pkgversion_string, + version_string); + printf ("Copyright %s 2008 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"), @@ -3575,10 +3649,19 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" add_assembler_option ("--help", 6); add_linker_option ("--help", 6); } + 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++; + } else if (strcmp (argv[i], "-ftarget-help") == 0) { /* translate_options() has turned --target-help into -ftarget-help. */ - target_help_flag = 1; + print_subprocess_help = 1; /* We will be passing a dummy file on to the sub-processes. */ n_infiles++; @@ -3607,8 +3690,12 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" 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 (! strncmp (argv[i], "-Wa,", 4)) { int prev, j; @@ -3732,6 +3819,15 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" use_pipes = 1; n_switches++; } + else if (strcmp (argv[i], "-wrapper") == 0) + { + if (++i >= argc) + fatal ("argument to '-wrapper' is missing"); + + wrapper_string = argv[i]; + n_switches++; + n_switches++; + } else if (strcmp (argv[i], "-###") == 0) { /* This is similar to -v except that there is no execution @@ -3749,7 +3845,10 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" switch (c) { case 'b': - if (NULL == strchr(argv[i] + 2, '-')) break; + 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; @@ -3785,28 +3884,6 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" value = tmp; } - /* As a kludge, if the arg is "[foo/]stageN/", just - add "[foo/]include" to the include prefix. */ - if ((len == 7 - || (len > 7 - && (IS_DIR_SEPARATOR (value[len - 8])))) - && strncmp (value + len - 7, "stage", 5) == 0 - && ISDIGIT (value[len - 2]) - && (IS_DIR_SEPARATOR (value[len - 1]))) - { - if (len == 7) - add_prefix (&include_prefixes, "./", NULL, - PREFIX_PRIORITY_B_OPT, 0, 0); - else - { - char *string = xmalloc (len - 6); - memcpy (string, value, len - 7); - string[len - 7] = 0; - add_prefix (&include_prefixes, string, NULL, - PREFIX_PRIORITY_B_OPT, 0, 0); - } - } - add_prefix (&exec_prefixes, value, NULL, PREFIX_PRIORITY_B_OPT, 0, 0); add_prefix (&startfile_prefixes, value, NULL, @@ -3884,7 +3961,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" 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) + char *new_name = XNEWVEC (char, strlen (modify_target[j].str) + strlen (spec_machine)); const char *p, *r; char *q; @@ -3938,62 +4015,50 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" use_pipes = 0; } - /* Set up the search paths before we go looking for config files. */ + /* 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. */ - /* These come before the md prefixes so that we will find gcc's subcommands - (such as cpp) rather than those of the host system. */ - /* Use 2 as fourth arg meaning try just the machine as a suffix, - as well as trying the machine and the version. */ + /* If we don't know where the toolchain has been installed, use the + configured-in locations. */ + if (!gcc_exec_prefix) + { #ifndef OS2 - add_prefix (&exec_prefixes, standard_libexec_prefix, "GCC", - PREFIX_PRIORITY_LAST, 1, 0); - add_prefix (&exec_prefixes, standard_libexec_prefix, "BINUTILS", - PREFIX_PRIORITY_LAST, 2, 0); - add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS", - PREFIX_PRIORITY_LAST, 2, 0); - 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); + add_prefix (&exec_prefixes, standard_libexec_prefix, "GCC", + PREFIX_PRIORITY_LAST, 1, 0); + add_prefix (&exec_prefixes, standard_libexec_prefix, "BINUTILS", + PREFIX_PRIORITY_LAST, 2, 0); + add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS", + PREFIX_PRIORITY_LAST, 2, 0); #endif + add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS", + PREFIX_PRIORITY_LAST, 1, 0); + } - add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS", - PREFIX_PRIORITY_LAST, 1, 0); - add_prefix (&startfile_prefixes, standard_exec_prefix_2, "BINUTILS", - 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); - /* If tooldir is relative, base it on exec_prefixes. A relative - tooldir lets us move the installed tree as a unit. - - If GCC_EXEC_PREFIX is defined, then we want to add two relative - directories, so that we can search both the user specified directory - and the standard place. */ - - if (!IS_ABSOLUTE_PATH (tooldir_prefix)) - { - if (gcc_exec_prefix) - { - char *gcc_exec_tooldir_prefix - = concat (gcc_exec_prefix, spec_machine, dir_separator_str, - spec_version, dir_separator_str, tooldir_prefix, NULL); - - add_prefix (&exec_prefixes, - concat (gcc_exec_tooldir_prefix, "bin", - dir_separator_str, NULL), - NULL, PREFIX_PRIORITY_LAST, 0, 0); - add_prefix (&startfile_prefixes, - concat (gcc_exec_tooldir_prefix, "lib", - dir_separator_str, NULL), - NULL, PREFIX_PRIORITY_LAST, 0, 1); - } - - tooldir_prefix = concat (standard_exec_prefix, spec_machine, - dir_separator_str, spec_version, - dir_separator_str, tooldir_prefix, NULL); - } + /* Look for tools relative to the location from which the driver is + running, or, if that is not available, the configured prefix. */ + tooldir_prefix + = concat (gcc_exec_prefix ? gcc_exec_prefix : standard_exec_prefix, + spec_machine, dir_separator_str, + spec_version, dir_separator_str, tooldir_prefix, NULL); add_prefix (&exec_prefixes, concat (tooldir_prefix, "bin", dir_separator_str, NULL), @@ -4067,11 +4132,11 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" ; else if (! strcmp (argv[i], "-print-multi-directory")) ; - else if (! strcmp (argv[i], "-print-multi-os-directory")) + else if (! strcmp (argv[i], "-print-sysroot")) ; - else if (! strcmp (argv[i], "-ftarget-help")) + else if (! strcmp (argv[i], "-print-multi-os-directory")) ; - else if (! strcmp (argv[i], "-fhelp")) + else if (! strcmp (argv[i], "-print-sysroot-headers-suffix")) ; else if (! strncmp (argv[i], "--sysroot=", strlen ("--sysroot="))) { @@ -4087,7 +4152,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" -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].live_cond = 0; switches[n_switches].validated = 0; n_switches++; } @@ -4130,6 +4195,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" infiles[n_infiles].language = "*"; infiles[n_infiles++].name = argv[i]; } + else if (strcmp (argv[i], "-wrapper") == 0) + i++; else if (strcmp (argv[i], "-specs") == 0) i++; else if (strncmp (argv[i], "-specs=", 7) == 0) @@ -4198,14 +4265,16 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" else switches[n_switches].args = 0; - switches[n_switches].live_cond = SWITCH_OK; + 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 them. */ + /* These are always valid, since gcc.c itself understands the + first four and gfortranspec.c understands -static-libgfortran. */ if (!strcmp (p, "save-temps") || !strcmp (p, "static-libgcc") || !strcmp (p, "shared-libgcc") - || !strcmp (p, "pipe")) + || !strcmp (p, "pipe") + || !strcmp (p, "static-libgfortran")) switches[n_switches].validated = 1; else { @@ -4238,34 +4307,14 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" error ("warning: '-x %s' after last input file has no effect", spec_lang); /* Ensure we only invoke each subprocess once. */ - if (target_help_flag || print_help_list) + if (print_subprocess_help || print_help_list) { n_infiles = 1; - /* Create a dummy input file, so that we can pass --target-help on to - the various sub-processes. */ + /* 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"; - - if (target_help_flag) - { - switches[n_switches].part1 = "--target-help"; - switches[n_switches].args = 0; - switches[n_switches].live_cond = SWITCH_OK; - switches[n_switches].validated = 0; - - n_switches++; - } - - if (print_help_list) - { - switches[n_switches].part1 = "--help"; - switches[n_switches].args = 0; - switches[n_switches].live_cond = SWITCH_OK; - switches[n_switches].validated = 0; - - n_switches++; - } } switches[n_switches].part1 = 0; @@ -4297,7 +4346,7 @@ set_collect_gcc_options (void) 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); @@ -4326,7 +4375,7 @@ set_collect_gcc_options (void) } } obstack_grow (&collect_obstack, "\0", 1); - putenv (XOBFINISH (&collect_obstack, char *)); + xputenv (XOBFINISH (&collect_obstack, char *)); } /* Process a spec string, accumulating and running commands. */ @@ -4379,6 +4428,72 @@ 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); + 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. */ @@ -4408,7 +4523,6 @@ do_spec (const char *spec) static int do_spec_2 (const char *spec) { - const char *string; int result; clear_args (); @@ -4421,18 +4535,7 @@ do_spec_2 (const char *spec) 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; } @@ -4470,7 +4573,7 @@ do_option_spec (const char *name, const char *spec) } /* 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; @@ -4502,8 +4605,7 @@ do_self_spec (const char *spec) first = n_switches; n_switches += argbuf_index; - switches = xrealloc (switches, - sizeof (struct switchstr) * (n_switches + 1)); + switches = XRESIZEVEC (struct switchstr, switches, n_switches + 1); switches[n_switches] = switches[first]; for (i = 0; i < argbuf_index; i++) @@ -4517,7 +4619,7 @@ do_self_spec (const char *spec) sw = &switches[i + first]; sw->part1 = &argbuf[i][1]; sw->args = 0; - sw->live_cond = SWITCH_OK; + sw->live_cond = 0; sw->validated = 0; sw->ordering = 0; } @@ -4537,7 +4639,7 @@ struct spec_path_info { 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; @@ -4593,7 +4695,6 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) const char *p = spec; int c; int i; - const char *string; int value; while ((c = *p++)) @@ -4602,19 +4703,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) 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], "|")) { @@ -4648,17 +4737,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) 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); @@ -4667,19 +4746,9 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) 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; @@ -4738,7 +4807,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) 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); @@ -4752,7 +4821,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) 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); @@ -4853,12 +4922,14 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) if (save_temps_flag) { + char *tmp; + 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'; + tmp = (char *) alloca (temp_filename_length + 1); + strncpy (tmp, input_basename, basename_length); + strncpy (tmp + basename_length, suffix, suffix_length); + tmp[temp_filename_length] = '\0'; + temp_filename = tmp; if (strcmp (temp_filename, input_filename) != 0) { #ifndef HOST_LACKS_INODE_NUMBERS @@ -4915,7 +4986,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) { if (t == 0) { - t = xmalloc (sizeof (struct temp_name)); + t = XNEW (struct temp_name); t->next = temp_names; temp_names = t; } @@ -5003,6 +5074,14 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) for_each_path (&include_prefixes, false, info.append_len, spec_path, &info); + + info.append = "include-fixed"; + if (*sysroot_hdrs_suffix_spec) + info.append = concat (info.append, dir_separator_str, + multilib_dir, NULL); + info.append_len = strlen (info.append); + for_each_path (&include_prefixes, false, info.append_len, + spec_path, &info); } break; @@ -5011,9 +5090,63 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) int max = n_infiles; max += lang_specific_extra_outfiles; - for (i = 0; i < max; i++) - if (outfiles[i]) - store_arg (outfiles[i], 0, 0); + if (HAVE_GNU_LD && at_file_supplied) + { + /* We are going to expand `%o' 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 *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); + + /* Convert OUTFILES into a form suitable for writeargv. */ + + /* Determine how many are non-NULL. */ + for (n_files = 0, i = 0; i < max; i++) + n_files += outfiles[i] != NULL; + + 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] = 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); + } + else + for (i = 0; i < max; i++) + if (outfiles[i]) + store_arg (outfiles[i], 0, 0); break; } @@ -5043,18 +5176,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) 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) @@ -5247,7 +5369,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) 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; } @@ -5308,7 +5430,7 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) } 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; @@ -5373,17 +5495,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) /* 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; } @@ -5537,27 +5650,24 @@ handle_spec_function (const char *p) static inline bool input_suffix_matches (const char *atom, const char *end_atom) { - /* We special case the semantics of {.s:...} and {.S:...} and their - negative variants. Instead of testing the input filename suffix, - we test whether the input source file is an assembler file or an - assembler-with-cpp file respectively. This allows us to correctly - handle the -x command line option. */ - - if (atom + 1 == end_atom - && input_file_compiler - && input_file_compiler->suffix) - { - if (*atom == 's') - return !strcmp (input_file_compiler->suffix, "@assembler"); - if (*atom == 'S') - return !strcmp (input_file_compiler->suffix, "@assembler-with-cpp"); - } - return (input_suffix && !strncmp (input_suffix, atom, end_atom - atom) && input_suffix[end_atom - atom] == '\0'); } +/* Subroutine of handle_braces. Returns true if the current + input file's spec name matches the atom bracketed by ATOM and END_ATOM. */ +static bool +input_spec_matches (const char *atom, const char *end_atom) +{ + return (input_file_compiler + && input_file_compiler->suffix + && input_file_compiler->suffix[0] != '\0' + && !strncmp (input_file_compiler->suffix + 1, atom, + end_atom - atom) + && input_file_compiler->suffix[end_atom - atom + 1] == '\0'); +} + /* Subroutine of handle_braces. Returns true if a switch matching the atom bracketed by ATOM and END_ATOM appeared on the command line. */ @@ -5621,6 +5731,7 @@ handle_braces (const char *p) const char *orig = p; bool a_is_suffix; + bool a_is_spectype; bool a_is_starred; bool a_is_negated; bool a_matched; @@ -5641,8 +5752,12 @@ handle_braces (const char *p) goto invalid; /* Scan one "atom" (S in the description above of %{}, possibly - with !, ., or * modifiers). */ - a_matched = a_is_suffix = a_is_starred = a_is_negated = false; + with '!', '.', '@', ',', or '*' modifiers). */ + a_matched = false; + a_is_suffix = false; + a_is_starred = false; + a_is_negated = false; + a_is_spectype = false; SKIP_WHITE(); if (*p == '!') @@ -5651,6 +5766,8 @@ handle_braces (const char *p) SKIP_WHITE(); if (*p == '.') p++, a_is_suffix = true; + else if (*p == ',') + p++, a_is_spectype = true; atom = p; while (ISIDNUM(*p) || *p == '-' || *p == '+' || *p == '=' @@ -5668,7 +5785,7 @@ handle_braces (const char *p) /* Substitute the switch(es) indicated by the current atom. */ ordered_set = true; if (disjunct_set || n_way_choice || a_is_negated || a_is_suffix - || atom == end_atom) + || a_is_spectype || atom == end_atom) goto invalid; mark_matching_switches (atom, end_atom, a_is_starred); @@ -5687,7 +5804,8 @@ handle_braces (const char *p) if (atom == end_atom) { if (!n_way_choice || disj_matched || *p == '|' - || a_is_negated || a_is_suffix || a_is_starred) + || a_is_negated || a_is_suffix || a_is_spectype + || a_is_starred) goto invalid; /* An empty term may appear as the last choice of an @@ -5698,28 +5816,30 @@ handle_braces (const char *p) } else { - if (a_is_suffix && a_is_starred) - goto invalid; - - if (!a_is_starred) - disj_starred = false; - - /* Don't bother testing this atom if we already have a - match. */ - if (!disj_matched && !n_way_matched) - { - if (a_is_suffix) - a_matched = input_suffix_matches (atom, end_atom); - else - a_matched = switch_matches (atom, end_atom, a_is_starred); - - if (a_matched != a_is_negated) - { - disj_matched = true; - d_atom = atom; - d_end_atom = end_atom; - } - } + if ((a_is_suffix || a_is_spectype) && a_is_starred) + goto invalid; + + if (!a_is_starred) + disj_starred = false; + + /* Don't bother testing this atom if we already have a + match. */ + if (!disj_matched && !n_way_matched) + { + if (a_is_suffix) + a_matched = input_suffix_matches (atom, end_atom); + else if (a_is_spectype) + 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; + d_atom = atom; + d_end_atom = end_atom; + } + } } if (*p == ':') @@ -5867,7 +5987,8 @@ check_live_switch (int switchnum, int prefix_length) /* 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; + return ((switches[switchnum].live_cond & SWITCH_LIVE) != 0 + && (switches[switchnum].live_cond & SWITCH_FALSE) == 0); /* Now search for duplicate in a manner that depends on the name. */ switch (*name) @@ -5914,7 +6035,7 @@ check_live_switch (int switchnum, int prefix_length) } /* Otherwise the switch is live. */ - switches[switchnum].live_cond = SWITCH_LIVE; + switches[switchnum].live_cond |= SWITCH_LIVE; return 1; } @@ -5929,7 +6050,7 @@ check_live_switch (int switchnum, int prefix_length) 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) @@ -5954,13 +6075,13 @@ give_switch (int switchnum, int 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 @@ -5997,7 +6118,7 @@ is_directory (const char *path1, bool linker) /* 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])) @@ -6088,6 +6209,11 @@ main (int argc, char **argv) char *specs_file; const char *p; 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])) @@ -6098,6 +6224,12 @@ main (int argc, char **argv) expandargv (&argc, &argv); + /* Determine if any expansions were made. */ + if (argv != old_argv) + at_file_supplied = true; + + prune_options (&argc, &argv); + #ifdef GCC_DRIVER_HOST_INITIALIZATION /* Perform host dependent initialization when needed. */ GCC_DRIVER_HOST_INITIALIZATION; @@ -6179,11 +6311,11 @@ main (int argc, char **argv) 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 *)); + xputenv (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). @@ -6195,7 +6327,7 @@ main (int argc, 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; @@ -6214,7 +6346,7 @@ main (int argc, char **argv) /* 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); @@ -6314,18 +6446,16 @@ main (int argc, char **argv) PREFIX_PRIORITY_LAST, 0, 1); else if (*cross_compile == '0') { - if (gcc_exec_prefix) - add_prefix (&startfile_prefixes, - concat (gcc_exec_prefix, machine_suffix, - standard_startfile_prefix, NULL), - NULL, PREFIX_PRIORITY_LAST, 0, 1); add_prefix (&startfile_prefixes, - concat (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); } + /* Sysrooted prefixes are relocated because target_system_root is + also relocated by gcc_exec_prefix. */ if (*standard_startfile_prefix_1) add_sysrooted_prefix (&startfile_prefixes, standard_startfile_prefix_1, "BINUTILS", @@ -6369,7 +6499,9 @@ main (int argc, char **argv) if (print_search_dirs) { - printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix); + printf (_("install: %s%s\n"), + gcc_exec_prefix ? gcc_exec_prefix : standard_exec_prefix, + gcc_exec_prefix ? "" : machine_suffix); printf (_("programs: %s\n"), build_search_list (&exec_prefixes, "", false, false)); printf (_("libraries: %s\n"), @@ -6405,6 +6537,18 @@ main (int argc, char **argv) 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) @@ -6414,14 +6558,19 @@ main (int argc, char **argv) return (0); } - if (target_help_flag) - { - /* Print if any target specific options. */ - - /* We do not exit here. Instead we have created a fake input file - called 'target-dummy' which needs to be compiled, and we pass this - on to the various sub-processes, along with the --target-help - switch. */ + if (print_sysroot_headers_suffix) + { + if (*sysroot_hdrs_suffix_spec) + { + printf("%s\n", (target_sysroot_hdrs_suffix + ? target_sysroot_hdrs_suffix + : "")); + return (0); + } + else + /* The error status indicates that only one set of fixed + headers should be built. */ + fatal ("not configured with sysroot headers suffix"); } if (print_help_list) @@ -6472,10 +6621,10 @@ main (int argc, char **argv) if (! strncmp (version_string, compiler_version, n) && compiler_version[n] == 0) - notice ("gcc version %s\n", version_string); + notice ("gcc version %s %s\n", version_string, pkgversion_string); else - notice ("gcc driver version %s executing gcc version %s\n", - version_string, compiler_version); + notice ("gcc driver version %s %sexecuting gcc version %s\n", + version_string, pkgversion_string, compiler_version); if (n_infiles == 0) return (0); @@ -6683,7 +6832,7 @@ main (int argc, char **argv) /* Run ld to link all the compiler output files. */ - if (num_linker_inputs > 0 && error_count == 0) + if (num_linker_inputs > 0 && error_count == 0 && print_subprocess_help < 2) { int tmp = execution_count; @@ -6699,6 +6848,13 @@ main (int argc, char **argv) putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH", false); putenv_from_prefixes (&startfile_prefixes, LIBRARY_PATH_ENV, true); + if (print_subprocess_help == 1) + { + printf (_("\nLinker options\n==============\n\n")); + printf (_("Use \"-Wl,OPTION\" to pass \"OPTION\"" + " to the linker.\n\n")); + fflush (stdout); + } value = do_spec (link_command_spec); if (value < 0) error_count = 1; @@ -6710,7 +6866,8 @@ main (int argc, char **argv) if (! linker_was_run && error_count == 0) for (i = 0; (int) i < n_infiles; i++) - if (explicit_link_files[i]) + if (explicit_link_files[i] + && !(infiles[i].language && infiles[i].language[0] == '*')) error ("%s: linker input file unused because linking not done", outfiles[i]); @@ -6943,7 +7100,7 @@ next_member: p++; SKIP_WHITE (); - if (*p == '.') + if (*p == '.' || *p == ',') suffix = true, p++; atom = p; @@ -7034,7 +7191,8 @@ used_arg (const char *p, int len) 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') @@ -7071,7 +7229,7 @@ used_arg (const char *p, int len) 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++) @@ -7393,7 +7551,7 @@ set_multilib_dir (void) 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) @@ -7660,6 +7818,44 @@ print_multilib_info (void) } } +/* getenv built-in spec function. + + Returns the value of the environment variable given by its first + argument, concatenated with the second argument. If the + environment variable is not defined, a fatal error is issued. */ + +static const char * +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]); + + /* 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 result; +} + /* if-exists built-in spec function. Checks to see if the file specified by the absolute pathname in @@ -7848,8 +8044,21 @@ include_spec_function (int argc, const char **argv) 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; } + +/* %:print-asm-header spec function. Print a banner to say that the + following output is from the assembler. */ + +static const char * +print_asm_header_spec_function (int arg ATTRIBUTE_UNUSED, + const char **argv ATTRIBUTE_UNUSED) +{ + printf (_("Assembler options\n=================\n\n")); + printf (_("Use \"-Wa,OPTION\" to pass \"OPTION\" to the assembler.\n\n")); + fflush (stdout); + return NULL; +}