X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fgcc.c;h=0636579644ff545c63e7d3aff3f060c31f88cbc4;hb=ff84f6db4f5156191531c8d5226bd0ccfc12cf2a;hp=7a5056a5ba02f9295434971fbb00c81c6bb7297d;hpb=6ea4242fb368994f583943b9cffdd14675cb6ad8;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/gcc.c b/gcc/gcc.c index 7a5056a5ba0..0636579644f 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, 2007 + 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!!!! */ @@ -127,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; @@ -295,6 +297,7 @@ 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); @@ -361,6 +364,7 @@ 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 @@ -516,15 +520,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 @@ -649,21 +656,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 @@ -708,7 +721,7 @@ 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_ssp) %(link_gcc_c_sequence)}}\ %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}" @@ -781,7 +794,7 @@ 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 %*}}}}}\ + %{!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}\ @@ -818,6 +831,12 @@ static const char *cc1_options = %{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 = @@ -851,7 +870,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[] = { @@ -947,11 +966,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}, @@ -1004,15 +1026,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 }}}}" @@ -1614,6 +1637,7 @@ static const struct spec_function static_spec_functions[] = { "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 @@ -1698,10 +1722,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]; @@ -1868,7 +1888,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; } @@ -2173,7 +2193,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; @@ -2523,18 +2543,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 @@ -2543,12 +2563,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; @@ -2579,6 +2599,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. @@ -2613,7 +2643,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, @@ -2955,7 +2985,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) { @@ -2969,7 +2999,7 @@ execute (void) } if (string != commands[i].prog) - free ((void *) string); + free (CONST_CAST (char *, string)); } execution_count++; @@ -3055,24 +3085,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 %part1 = &argbuf[i][1]; sw->args = 0; - sw->live_cond = SWITCH_OK; + sw->live_cond = 0; sw->validated = 0; sw->ordering = 0; } @@ -4577,7 +4616,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++)) @@ -4586,19 +4624,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], "|")) { @@ -4632,17 +4658,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); @@ -4651,19 +4667,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; @@ -4837,12 +4843,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 = 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 @@ -5003,9 +5011,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 = 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; } @@ -5035,18 +5097,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) @@ -5239,7 +5290,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; } @@ -5365,17 +5416,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; } @@ -5529,27 +5571,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. */ @@ -5613,6 +5652,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; @@ -5633,8 +5673,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 == '!') @@ -5643,6 +5687,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 == '=' @@ -5660,7 +5706,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); @@ -5679,7 +5725,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 @@ -5690,28 +5737,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 == ':') @@ -5859,7 +5908,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) @@ -5906,7 +5956,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; } @@ -5921,7 +5971,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) @@ -5946,13 +5996,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 @@ -6080,6 +6130,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])) @@ -6090,6 +6145,10 @@ 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 @@ -6173,11 +6232,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). @@ -6412,7 +6471,9 @@ main (int argc, char **argv) { if (*sysroot_hdrs_suffix_spec) { - printf("%s\n", target_sysroot_hdrs_suffix); + printf("%s\n", (target_sysroot_hdrs_suffix + ? target_sysroot_hdrs_suffix + : "")); return (0); } else @@ -6469,10 +6530,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); @@ -6680,7 +6741,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; @@ -6696,6 +6757,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; @@ -6707,7 +6775,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]); @@ -6940,7 +7009,7 @@ next_member: p++; SKIP_WHITE (); - if (*p == '.') + if (*p == '.' || *p == ',') suffix = true, p++; atom = p; @@ -7068,7 +7137,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++) @@ -7390,7 +7459,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) @@ -7667,6 +7736,9 @@ 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; @@ -7675,7 +7747,21 @@ getenv_spec_function (int argc, const char **argv) if (!value) fatal ("environment variable \"%s\" not defined", argv[0]); - return concat (value, argv[1], NULL); + /* We have to escape every character of the environment variable so + they are not interpretted as active spec characters. A + particulaly 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 = xmalloc (len); + for (ptr = result; *value; ptr += 2) + { + ptr[0] = '\\'; + ptr[1] = *value++; + } + + strcpy (ptr, argv[1]); + + return result; } /* if-exists built-in spec function. @@ -7871,3 +7957,16 @@ include_spec_function (int argc, const char **argv) 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; +}