gcc.c revision 122197
118334Speter/* Compiler driver program that can handle many languages.
290277Sobrien   Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
390277Sobrien   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
418334Speter
590277SobrienThis file is part of GCC.
618334Speter
790277SobrienGCC is free software; you can redistribute it and/or modify it under
890277Sobrienthe terms of the GNU General Public License as published by the Free
990277SobrienSoftware Foundation; either version 2, or (at your option) any later
1090277Sobrienversion.
1118334Speter
1290277SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1390277SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1490277SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1590277Sobrienfor more details.
1618334Speter
1718334SpeterYou should have received a copy of the GNU General Public License
1890277Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
1990277SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
2090277Sobrien02111-1307, USA.
2118334Speter
2218334SpeterThis paragraph is here to try to keep Sun CC from dying.
2318334SpeterThe number of chars here seems crucial!!!!  */
2418334Speter
2551232Sbde/* $FreeBSD: head/contrib/gcc/gcc.c 122197 2003-11-07 03:23:43Z kan $ */
2651232Sbde
2718334Speter/* This program is the user interface to the C compiler and possibly to
2818334Speterother compilers.  It is used because compilation is a complicated procedure
2918334Speterwhich involves running several programs and passing temporary files between
3018334Speterthem, forwarding the users switches to those programs selectively,
3118334Speterand deleting the temporary files at the end.
3218334Speter
3318334SpeterCC recognizes how to compile each input file by suffixes in the file names.
3418334SpeterOnce it knows which kind of compilation to perform, the procedure for
3518334Spetercompilation is specified by a string called a "spec".  */
3690277Sobrien
3790277Sobrien/* A Short Introduction to Adding a Command-Line Option.
3890277Sobrien
3990277Sobrien   Before adding a command-line option, consider if it is really
4090277Sobrien   necessary.  Each additional command-line option adds complexity and
4190277Sobrien   is difficult to remove in subsequent versions.
4290277Sobrien
4390277Sobrien   In the following, consider adding the command-line argument
4490277Sobrien   `--bar'.
4590277Sobrien
4690277Sobrien   1. Each command-line option is specified in the specs file.  The
4790277Sobrien   notation is described below in the comment entitled "The Specs
4890277Sobrien   Language".  Read it.
4990277Sobrien
5090277Sobrien   2. In this file, add an entry to "option_map" equating the long
5190277Sobrien   `--' argument version and any shorter, single letter version.  Read
5290277Sobrien   the comments in the declaration of "struct option_map" for an
5390277Sobrien   explanation.  Do not omit the first `-'.
5490277Sobrien
5590277Sobrien   3. Look in the "specs" file to determine which program or option
5690277Sobrien   list should be given the argument, e.g., "cc1_options".  Add the
5790277Sobrien   appropriate syntax for the shorter option version to the
5890277Sobrien   corresponding "const char *" entry in this file.  Omit the first
5990277Sobrien   `-' from the option.  For example, use `-bar', rather than `--bar'.
6090277Sobrien
6190277Sobrien   4. If the argument takes an argument, e.g., `--baz argument1',
6290277Sobrien   modify either DEFAULT_SWITCH_TAKES_ARG or
6390277Sobrien   DEFAULT_WORD_SWITCH_TAKES_ARG in this file.  Omit the first `-'
6490277Sobrien   from `--baz'.
6590277Sobrien
6690277Sobrien   5. Document the option in this file's display_help().  If the
6790277Sobrien   option is passed to a subprogram, modify its corresponding
6890277Sobrien   function, e.g., cppinit.c:print_help() or toplev.c:display_help(),
6990277Sobrien   instead.
7090277Sobrien
7190277Sobrien   6. Compile and test.  Make sure that your new specs file is being
7290277Sobrien   read.  For example, use a debugger to investigate the value of
7390277Sobrien   "specs_file" in main().  */
7490277Sobrien
7550599Sobrien#include "config.h"
7650599Sobrien#include "system.h"
7750599Sobrien#include <signal.h>
7890277Sobrien#if ! defined( SIGCHLD ) && defined( SIGCLD )
7990277Sobrien#  define SIGCHLD SIGCLD
8090277Sobrien#endif
8150599Sobrien#include "obstack.h"
8252520Sobrien#include "intl.h"
8352520Sobrien#include "prefix.h"
8490277Sobrien#include "gcc.h"
8590277Sobrien#include "flags.h"
8618334Speter
8790277Sobrien#ifdef HAVE_SYS_RESOURCE_H
8890277Sobrien#include <sys/resource.h>
8918334Speter#endif
9090277Sobrien#if defined (HAVE_DECL_GETRUSAGE) && !HAVE_DECL_GETRUSAGE
9190277Sobrienextern int getrusage PARAMS ((int, struct rusage *));
9290277Sobrien#endif
9318334Speter
9490277Sobrien/* By default there is no special suffix for target executables.  */
9590277Sobrien/* FIXME: when autoconf is fixed, remove the host check - dj */
9690277Sobrien#if defined(TARGET_EXECUTABLE_SUFFIX) && defined(HOST_EXECUTABLE_SUFFIX)
9790277Sobrien#define HAVE_TARGET_EXECUTABLE_SUFFIX
9818334Speter#endif
9918334Speter
10090277Sobrien/* By default there is no special suffix for host executables.  */
10190277Sobrien#ifdef HOST_EXECUTABLE_SUFFIX
10290277Sobrien#define HAVE_HOST_EXECUTABLE_SUFFIX
10318334Speter#else
10490277Sobrien#define HOST_EXECUTABLE_SUFFIX ""
10518334Speter#endif
10618334Speter
10790277Sobrien/* By default, the suffix for target object files is ".o".  */
10890277Sobrien#ifdef TARGET_OBJECT_SUFFIX
10990277Sobrien#define HAVE_TARGET_OBJECT_SUFFIX
11090277Sobrien#else
11190277Sobrien#define TARGET_OBJECT_SUFFIX ".o"
11218334Speter#endif
11318334Speter
11490277Sobrien#ifndef VMS
11590277Sobrien/* FIXME: the location independence code for VMS is hairier than this,
11690277Sobrien   and hasn't been written.  */
11790277Sobrien#ifndef DIR_UP
11890277Sobrien#define DIR_UP ".."
11990277Sobrien#endif /* DIR_UP */
12090277Sobrien#endif /* VMS */
12118334Speter
12290277Sobrienstatic const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
12352520Sobrien
12490277Sobrien/* Most every one is fine with LIBRARY_PATH.  For some, it conflicts.  */
12590277Sobrien#ifndef LIBRARY_PATH_ENV
12690277Sobrien#define LIBRARY_PATH_ENV "LIBRARY_PATH"
12790277Sobrien#endif
12890277Sobrien
12950599Sobrien#ifndef HAVE_KILL
13050599Sobrien#define kill(p,s) raise(s)
13118334Speter#endif
13218334Speter
13318334Speter/* If a stage of compilation returns an exit status >= 1,
13418334Speter   compilation of that file ceases.  */
13518334Speter
13618334Speter#define MIN_FATAL_STATUS 1
13718334Speter
13890277Sobrien/* Flag set by cppspec.c to 1.  */
13990277Sobrienint is_cpp_driver;
14090277Sobrien
14190277Sobrien/* Flag saying to pass the greatest exit code returned by a sub-process
14290277Sobrien   to the calling program.  */
14390277Sobrienstatic int pass_exit_codes;
14490277Sobrien
14590277Sobrien/* Definition of string containing the arguments given to configure.  */
14690277Sobrien#include "configargs.h"
14790277Sobrien
14818334Speter/* Flag saying to print the directories gcc will search through looking for
14918334Speter   programs, libraries, etc.  */
15018334Speter
15118334Speterstatic int print_search_dirs;
15218334Speter
15318334Speter/* Flag saying to print the full filename of this file
15418334Speter   as found through our usual search mechanism.  */
15518334Speter
15652520Sobrienstatic const char *print_file_name = NULL;
15718334Speter
15850599Sobrien/* As print_file_name, but search for executable file.  */
15918334Speter
16052520Sobrienstatic const char *print_prog_name = NULL;
16118334Speter
16218334Speter/* Flag saying to print the relative path we'd use to
16318334Speter   find libgcc.a given the current compiler flags.  */
16418334Speter
16518334Speterstatic int print_multi_directory;
16618334Speter
167104763Skan/* Flag saying to print the relative path we'd use to
168104763Skan   find OS libraries given the current compiler flags.  */
169104763Skan
170104763Skanstatic int print_multi_os_directory;
171104763Skan
17218334Speter/* Flag saying to print the list of subdirectories and
17318334Speter   compiler flags used to select them in a standard form.  */
17418334Speter
17518334Speterstatic int print_multi_lib;
17618334Speter
17750599Sobrien/* Flag saying to print the command line options understood by gcc and its
17850599Sobrien   sub-processes.  */
17950599Sobrien
18050599Sobrienstatic int print_help_list;
18150599Sobrien
18218334Speter/* Flag indicating whether we should print the command and arguments */
18318334Speter
18418334Speterstatic int verbose_flag;
18518334Speter
18690277Sobrien/* Flag indicating whether we should ONLY print the command and
18790277Sobrien   arguments (like verbose_flag) without executing the command.
18890277Sobrien   Displayed arguments are quoted so that the generated command
18990277Sobrien   line is suitable for execution.  This is intended for use in
19090277Sobrien   shell scripts to capture the driver-generated command line.  */
19190277Sobrienstatic int verbose_only_flag;
19290277Sobrien
19390277Sobrien/* Flag indicating to print target specific command line options.  */
19490277Sobrien
19590277Sobrienstatic int target_help_flag;
19690277Sobrien
19790277Sobrien/* Flag indicating whether we should report subprocess execution times
19890277Sobrien   (if this is supported by the system - see pexecute.c).  */
19990277Sobrien
20090277Sobrienstatic int report_times;
20190277Sobrien
20218334Speter/* Nonzero means write "temp" files in source directory
20318334Speter   and use the source file's name in them, and don't delete them.  */
20418334Speter
20518334Speterstatic int save_temps_flag;
20618334Speter
20718334Speter/* The compiler version.  */
20818334Speter
20990277Sobrienstatic const char *compiler_version;
21018334Speter
21118334Speter/* The target version specified with -V */
21218334Speter
213117413Skanstatic const char *const spec_version = DEFAULT_TARGET_VERSION;
21418334Speter
21518334Speter/* The target machine specified with -b.  */
21618334Speter
21752520Sobrienstatic const char *spec_machine = DEFAULT_TARGET_MACHINE;
21818334Speter
21918334Speter/* Nonzero if cross-compiling.
22018334Speter   When -b is used, the value comes from the `specs' file.  */
22118334Speter
22218334Speter#ifdef CROSS_COMPILE
22390277Sobrienstatic const char *cross_compile = "1";
22418334Speter#else
22590277Sobrienstatic const char *cross_compile = "0";
22618334Speter#endif
22718334Speter
22890277Sobrien#ifdef MODIFY_TARGET_NAME
22990277Sobrien
23090277Sobrien/* Information on how to alter the target name based on a command-line
23190277Sobrien   switch.  The only case we support now is simply appending or deleting a
23290277Sobrien   string to or from the end of the first part of the configuration name.  */
23390277Sobrien
23490277Sobrienstatic const struct modify_target
23590277Sobrien{
23690277Sobrien  const char *const sw;
23790277Sobrien  const enum add_del {ADD, DELETE} add_del;
23890277Sobrien  const char *const str;
23990277Sobrien}
24090277Sobrienmodify_target[] = MODIFY_TARGET_NAME;
24190277Sobrien#endif
242117413Skan
24318334Speter/* The number of errors that have occurred; the link phase will not be
244117413Skan   run if this is nonzero.  */
24518334Speterstatic int error_count = 0;
24618334Speter
24790277Sobrien/* Greatest exit code of sub-processes that has been encountered up to
24890277Sobrien   now.  */
24990277Sobrienstatic int greatest_status = 1;
25090277Sobrien
25118334Speter/* This is the obstack which we use to allocate many strings.  */
25218334Speter
25318334Speterstatic struct obstack obstack;
25418334Speter
25518334Speter/* This is the obstack to build an environment variable to pass to
25618334Speter   collect2 that describes all of the relevant switches of what to
25718334Speter   pass the compiler in building the list of pointers to constructors
25818334Speter   and destructors.  */
25918334Speter
26018334Speterstatic struct obstack collect_obstack;
26118334Speter
26290277Sobrien/* These structs are used to collect resource usage information for
26390277Sobrien   subprocesses.  */
26490277Sobrien#ifdef HAVE_GETRUSAGE
26590277Sobrienstatic struct rusage rus, prus;
26690277Sobrien#endif
26718334Speter
26818334Speter/* Forward declaration for prototypes.  */
26918334Speterstruct path_prefix;
27018334Speter
27190277Sobrienstatic void init_spec		PARAMS ((void));
27290277Sobrienstatic void store_arg		PARAMS ((const char *, int, int));
27390277Sobrienstatic char *load_specs		PARAMS ((const char *));
27490277Sobrienstatic void read_specs		PARAMS ((const char *, int));
27590277Sobrienstatic void set_spec		PARAMS ((const char *, const char *));
27690277Sobrienstatic struct compiler *lookup_compiler PARAMS ((const char *, size_t, const char *));
27790277Sobrienstatic char *build_search_list	PARAMS ((struct path_prefix *, const char *, int));
27890277Sobrienstatic void putenv_from_prefixes PARAMS ((struct path_prefix *, const char *));
27990277Sobrienstatic int access_check		PARAMS ((const char *, int));
280104763Skanstatic char *find_a_file	PARAMS ((struct path_prefix *, const char *,
281104763Skan					 int, int));
28290277Sobrienstatic void add_prefix		PARAMS ((struct path_prefix *, const char *,
283104763Skan					 const char *, int, int, int *, int));
28490277Sobrienstatic void translate_options	PARAMS ((int *, const char *const **));
28590277Sobrienstatic char *skip_whitespace	PARAMS ((char *));
28690277Sobrienstatic void delete_if_ordinary	PARAMS ((const char *));
28790277Sobrienstatic void delete_temp_files	PARAMS ((void));
28890277Sobrienstatic void delete_failure_queue PARAMS ((void));
28990277Sobrienstatic void clear_failure_queue PARAMS ((void));
29090277Sobrienstatic int check_live_switch	PARAMS ((int, int));
29190277Sobrienstatic const char *handle_braces PARAMS ((const char *));
292117413Skanstatic const struct spec_function *lookup_spec_function PARAMS ((const char *));
293117413Skanstatic const char *eval_spec_function	PARAMS ((const char *, const char *));
294117413Skanstatic const char *handle_spec_function PARAMS ((const char *));
29590277Sobrienstatic char *save_string	PARAMS ((const char *, int));
29690277Sobrienstatic void set_collect_gcc_options PARAMS ((void));
29790277Sobrienstatic int do_spec_1		PARAMS ((const char *, int, const char *));
298117413Skanstatic int do_spec_2		PARAMS ((const char *));
299117413Skanstatic void do_self_spec	PARAMS ((const char *));
30090277Sobrienstatic const char *find_file	PARAMS ((const char *));
30190277Sobrienstatic int is_directory		PARAMS ((const char *, const char *, int));
30290277Sobrienstatic void validate_switches	PARAMS ((const char *));
30390277Sobrienstatic void validate_all_switches PARAMS ((void));
30490277Sobrienstatic void give_switch		PARAMS ((int, int, int));
30590277Sobrienstatic int used_arg		PARAMS ((const char *, int));
30690277Sobrienstatic int default_arg		PARAMS ((const char *, int));
30790277Sobrienstatic void set_multilib_dir	PARAMS ((void));
30890277Sobrienstatic void print_multilib_info	PARAMS ((void));
30990277Sobrienstatic void perror_with_name	PARAMS ((const char *));
31090277Sobrienstatic void pfatal_pexecute	PARAMS ((const char *, const char *))
31152520Sobrien  ATTRIBUTE_NORETURN;
31290277Sobrienstatic void notice		PARAMS ((const char *, ...))
31352520Sobrien  ATTRIBUTE_PRINTF_1;
31490277Sobrienstatic void display_help 	PARAMS ((void));
31590277Sobrienstatic void add_preprocessor_option	PARAMS ((const char *, int));
31690277Sobrienstatic void add_assembler_option	PARAMS ((const char *, int));
31790277Sobrienstatic void add_linker_option		PARAMS ((const char *, int));
31890277Sobrienstatic void process_command		PARAMS ((int, const char *const *));
31990277Sobrienstatic int execute			PARAMS ((void));
320117413Skanstatic void alloc_args			PARAMS ((void));
32190277Sobrienstatic void clear_args			PARAMS ((void));
32290277Sobrienstatic void fatal_error			PARAMS ((int));
32390277Sobrien#ifdef ENABLE_SHARED_LIBGCC
32490277Sobrienstatic void init_gcc_specs              PARAMS ((struct obstack *,
32590277Sobrien						 const char *, const char *,
32690277Sobrien						 const char *));
32790277Sobrien#endif
32890277Sobrien#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
32990277Sobrienstatic const char *convert_filename	PARAMS ((const char *, int, int));
33090277Sobrien#endif
331117413Skan
332117413Skanstatic const char *if_exists_spec_function PARAMS ((int, const char **));
333117413Skanstatic const char *if_exists_else_spec_function PARAMS ((int, const char **));
33490277Sobrien
33590277Sobrien/* The Specs Language
33618334Speter
33790277SobrienSpecs are strings containing lines, each of which (if not blank)
33818334Speteris made up of a program name, and arguments separated by spaces.
33918334SpeterThe program name must be exact and start from root, since no path
34018334Speteris searched and it is unreliable to depend on the current working directory.
34118334SpeterRedirection of input or output is not supported; the subprograms must
34218334Speteraccept filenames saying what files to read and write.
34318334Speter
34418334SpeterIn addition, the specs can contain %-sequences to substitute variable text
34518334Speteror for conditional text.  Here is a table of all defined %-sequences.
34618334SpeterNote that spaces are not generated automatically around the results of
34718334Speterexpanding these sequences; therefore, you can concatenate them together
34818334Speteror with constant text in a single argument.
34918334Speter
35018334Speter %%	substitute one % into the program name or argument.
35118334Speter %i     substitute the name of the input file being processed.
35218334Speter %b     substitute the basename of the input file being processed.
35318334Speter	This is the substring up to (and not including) the last period
35418334Speter	and not including the directory.
35590277Sobrien %B	same as %b, but include the file suffix (text after the last period).
35650599Sobrien %gSUFFIX
35750599Sobrien	substitute a file name that has suffix SUFFIX and is chosen
35850599Sobrien	once per compilation, and mark the argument a la %d.  To reduce
35950599Sobrien	exposure to denial-of-service attacks, the file name is now
36050599Sobrien	chosen in a way that is hard to predict even when previously
36150599Sobrien	chosen file names are known.  For example, `%g.s ... %g.o ... %g.s'
36250599Sobrien	might turn into `ccUVUUAU.s ccXYAXZ12.o ccUVUUAU.s'.  SUFFIX matches
36390277Sobrien	the regexp "[.A-Za-z]*%O"; "%O" is treated exactly as if it
36490277Sobrien	had been pre-processed.  Previously, %g was simply substituted
36590277Sobrien	with a file name chosen once per compilation, without regard
36690277Sobrien	to any appended suffix (which was therefore treated just like
36790277Sobrien	ordinary text), making such attacks more likely to succeed.
36850599Sobrien %uSUFFIX
36950599Sobrien	like %g, but generates a new temporary file name even if %uSUFFIX
37050599Sobrien	was already seen.
37150599Sobrien %USUFFIX
37250599Sobrien	substitutes the last file name generated with %uSUFFIX, generating a
37350599Sobrien	new one if there is no such last file name.  In the absence of any
37450599Sobrien	%uSUFFIX, this is just like %gSUFFIX, except they don't share
37550599Sobrien	the same suffix "space", so `%g.s ... %U.s ... %g.s ... %U.s'
37650599Sobrien	would involve the generation of two distinct file names, one
37750599Sobrien	for each `%g.s' and another for each `%U.s'.  Previously, %U was
37850599Sobrien	simply substituted with a file name chosen for the previous %u,
37950599Sobrien	without regard to any appended suffix.
38090277Sobrien %jSUFFIX
38190277Sobrien        substitutes the name of the HOST_BIT_BUCKET, if any, and if it is
38290277Sobrien        writable, and if save-temps is off; otherwise, substitute the name
38390277Sobrien        of a temporary file, just like %u.  This temporary file is not
38490277Sobrien        meant for communication between processes, but rather as a junk
38590277Sobrien        disposal mechanism.
38690277Sobrien %.SUFFIX
38790277Sobrien        substitutes .SUFFIX for the suffixes of a matched switch's args when
38890277Sobrien        it is subsequently output with %*. SUFFIX is terminated by the next
38990277Sobrien        space or %.
39018334Speter %d	marks the argument containing or following the %d as a
39118334Speter	temporary file name, so that that file will be deleted if CC exits
39218334Speter	successfully.  Unlike %g, this contributes no text to the argument.
39318334Speter %w	marks the argument containing or following the %w as the
39418334Speter	"output file" of this compilation.  This puts the argument
39518334Speter	into the sequence of arguments that %o will substitute later.
39618334Speter %W{...}
39718334Speter	like %{...} but mark last argument supplied within
39818334Speter	as a file to be deleted on failure.
39918334Speter %o	substitutes the names of all the output files, with spaces
40018334Speter	automatically placed around them.  You should write spaces
40118334Speter	around the %o as well or the results are undefined.
40218334Speter	%o is for use in the specs for running the linker.
40318334Speter	Input files whose names have no recognized suffix are not compiled
40418334Speter	at all, but they are included among the output files, so they will
40518334Speter	be linked.
40650599Sobrien %O	substitutes the suffix for object files.  Note that this is
40790277Sobrien        handled specially when it immediately follows %g, %u, or %U
40890277Sobrien	(with or without a suffix argument) because of the need for
40990277Sobrien	those to form complete file names.  The handling is such that
41090277Sobrien	%O is treated exactly as if it had already been substituted,
41190277Sobrien	except that %g, %u, and %U do not currently support additional
41290277Sobrien	SUFFIX characters following %O as they would following, for
41390277Sobrien	example, `.o'.
41418334Speter %p	substitutes the standard macro predefinitions for the
41518334Speter	current target machine.  Use this when running cpp.
41618334Speter %P	like %p, but puts `__' before and after the name of each macro.
41718334Speter	(Except macros that already have __.)
41818334Speter	This is for ANSI C.
41918334Speter %I	Substitute a -iprefix option made from GCC_EXEC_PREFIX.
42018334Speter %s     current argument is the name of a library or startup file of some sort.
42118334Speter        Search for that file in a standard list of directories
42218334Speter	and substitute the full name found.
42318334Speter %eSTR  Print STR as an error message.  STR is terminated by a newline.
42418334Speter        Use this when inconsistent options are detected.
425117413Skan %nSTR  Print STR as a notice.  STR is terminated by a newline.
42618334Speter %x{OPTION}	Accumulate an option for %X.
42718334Speter %X	Output the accumulated linker options specified by compilations.
42818334Speter %Y	Output the accumulated assembler options specified by compilations.
42918334Speter %Z	Output the accumulated preprocessor options specified by compilations.
43018334Speter %v1	Substitute the major version number of GCC.
43190277Sobrien	(For version 2.5.3, this is 2.)
43218334Speter %v2	Substitute the minor version number of GCC.
43390277Sobrien	(For version 2.5.3, this is 5.)
43490277Sobrien %v3	Substitute the patch level number of GCC.
43590277Sobrien	(For version 2.5.3, this is 3.)
43618334Speter %a     process ASM_SPEC as a spec.
43718334Speter        This allows config.h to specify part of the spec for running as.
43818334Speter %A	process ASM_FINAL_SPEC as a spec.  A capital A is actually
43918334Speter	used here.  This can be used to run a post-processor after the
44050599Sobrien	assembler has done its job.
44118334Speter %D	Dump out a -L option for each directory in startfile_prefixes.
44218334Speter	If multilib_dir is set, extra entries are generated with it affixed.
44318334Speter %l     process LINK_SPEC as a spec.
44418334Speter %L     process LIB_SPEC as a spec.
44518334Speter %G     process LIBGCC_SPEC as a spec.
44690277Sobrien %M     output multilib_dir with directory separators replaced with "_";
44790277Sobrien	if multilib_dir is not set or is ".", output "".
44818334Speter %S     process STARTFILE_SPEC as a spec.  A capital S is actually used here.
44918334Speter %E     process ENDFILE_SPEC as a spec.  A capital E is actually used here.
45090277Sobrien %C     process CPP_SPEC as a spec.
45118334Speter %1	process CC1_SPEC as a spec.
45218334Speter %2	process CC1PLUS_SPEC as a spec.
45318334Speter %|	output "-" if the input for the current command is coming from a pipe.
45418334Speter %*	substitute the variable part of a matched option.  (See below.)
45518334Speter	Note that each comma in the substituted string is replaced by
45618334Speter	a single space.
457117413Skan %:function(args)
458117413Skan	Call the named function FUNCTION, passing it ARGS.  ARGS is
459117413Skan	first processed as a nested spec string, then split into an
460117413Skan	argument vector in the usual fashion.  The function returns
461117413Skan	a string which is processed as if it had appeared literally
462117413Skan	as part of the current spec.
46318334Speter %{S}   substitutes the -S switch, if that switch was given to CC.
46418334Speter	If that switch was not specified, this substitutes nothing.
46518334Speter	Here S is a metasyntactic variable.
46618334Speter %{S*}  substitutes all the switches specified to CC whose names start
46790277Sobrien	with -S.  This is used for -o, -I, etc; switches that take
46818334Speter	arguments.  CC considers `-o foo' as being one switch whose
46918334Speter	name starts with `o'.  %{o*} would substitute this text,
47018334Speter	including the space; thus, two arguments would be generated.
47150599Sobrien %{^S*} likewise, but don't put a blank between a switch and any args.
47290277Sobrien %{S*&T*} likewise, but preserve order of S and T options (the order
47390277Sobrien 	of S and T in the spec is not significant).  Can be any number
47490277Sobrien 	of ampersand-separated variables; for each the wild card is
47590277Sobrien 	optional.  Useful for CPP as %{D*&U*&A*}.
47618334Speter %{S*:X} substitutes X if one or more switches whose names start with -S are
47718334Speter	specified to CC.  Note that the tail part of the -S option
47818334Speter	(i.e. the part matched by the `*') will be substituted for each
47918334Speter	occurrence of %* within X.
48090277Sobrien %{<S}  remove all occurrences of -S from the command line.
48190277Sobrien        Note - this option is position dependent.  % commands in the
48290277Sobrien        spec string before this option will see -S, % commands in the
48390277Sobrien        spec string after this option will not.
48418334Speter %{S:X} substitutes X, but only if the -S switch was given to CC.
48518334Speter %{!S:X} substitutes X, but only if the -S switch was NOT given to CC.
48618334Speter %{|S:X} like %{S:X}, but if no S switch, substitute `-'.
48718334Speter %{|!S:X} like %{!S:X}, but if there is an S switch, substitute `-'.
48818334Speter %{.S:X} substitutes X, but only if processing a file with suffix S.
48918334Speter %{!.S:X} substitutes X, but only if NOT processing a file with suffix S.
49050599Sobrien %{S|P:X} substitutes X if either -S or -P was given to CC.  This may be
49150599Sobrien	  combined with ! and . as above binding stronger than the OR.
49218334Speter %(Spec) processes a specification defined in a specs file as *Spec:
49318334Speter %[Spec] as above, but put __ around -D arguments
49418334Speter
49518334SpeterThe conditional text X in a %{S:X} or %{!S:X} construct may contain
49618334Speterother nested % constructs or spaces, or even newlines.  They are
49718334Speterprocessed as usual, as described above.
49818334Speter
49918334SpeterThe -O, -f, -m, and -W switches are handled specifically in these
50018334Speterconstructs.  If another value of -O or the negated form of a -f, -m, or
50118334Speter-W switch is found later in the command line, the earlier switch
50218334Spetervalue is ignored, except with {S*} where S is just one letter; this
50318334Speterpasses all matching options.
50418334Speter
50550599SobrienThe character | at the beginning of the predicate text is used to indicate
50650599Sobrienthat a command should be piped to the following command, but only if -pipe
50750599Sobrienis specified.
50818334Speter
50918334SpeterNote that it is built into CC which switches take arguments and which
51018334Speterdo not.  You might think it would be useful to generalize this to
51118334Speterallow each compiler's spec to say which switches take arguments.  But
51218334Speterthis cannot be done in a consistent fashion.  CC cannot even decide
51318334Speterwhich input files have been specified without knowing which switches
51418334Spetertake arguments, and it must know which input files to compile in order
51518334Speterto tell which compilers to run.
51618334Speter
51718334SpeterCC also knows implicitly that arguments starting in `-l' are to be
51818334Spetertreated as compiler output files, and passed to the linker in their
51918334Speterproper position among the other output files.  */
52018334Speter
52196285Sobrien/* Define the macros used for specs %a, %l, %L, %S, %C, %1.  */
52218334Speter
52318334Speter/* config.h can define ASM_SPEC to provide extra args to the assembler
52418334Speter   or extra switch-translations.  */
52518334Speter#ifndef ASM_SPEC
52618334Speter#define ASM_SPEC ""
52718334Speter#endif
52818334Speter
52918334Speter/* config.h can define ASM_FINAL_SPEC to run a post processor after
53018334Speter   the assembler has run.  */
53118334Speter#ifndef ASM_FINAL_SPEC
53218334Speter#define ASM_FINAL_SPEC ""
53318334Speter#endif
53418334Speter
53518334Speter/* config.h can define CPP_SPEC to provide extra args to the C preprocessor
53618334Speter   or extra switch-translations.  */
53718334Speter#ifndef CPP_SPEC
53818334Speter#define CPP_SPEC ""
53918334Speter#endif
54018334Speter
54118334Speter/* config.h can define CC1_SPEC to provide extra args to cc1 and cc1plus
54218334Speter   or extra switch-translations.  */
54318334Speter#ifndef CC1_SPEC
54418334Speter#define CC1_SPEC ""
54518334Speter#endif
54618334Speter
54718334Speter/* config.h can define CC1PLUS_SPEC to provide extra args to cc1plus
54818334Speter   or extra switch-translations.  */
54918334Speter#ifndef CC1PLUS_SPEC
55018334Speter#define CC1PLUS_SPEC ""
55118334Speter#endif
55218334Speter
55318334Speter/* config.h can define LINK_SPEC to provide extra args to the linker
55418334Speter   or extra switch-translations.  */
55518334Speter#ifndef LINK_SPEC
55618334Speter#define LINK_SPEC ""
55718334Speter#endif
55818334Speter
55918334Speter/* config.h can define LIB_SPEC to override the default libraries.  */
56018334Speter#ifndef LIB_SPEC
56118334Speter#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
56218334Speter#endif
56318334Speter
56418334Speter/* config.h can define LIBGCC_SPEC to override how and when libgcc.a is
56518334Speter   included.  */
56618334Speter#ifndef LIBGCC_SPEC
56718334Speter#if defined(LINK_LIBGCC_SPECIAL) || defined(LINK_LIBGCC_SPECIAL_1)
56818334Speter/* Have gcc do the search for libgcc.a.  */
56950599Sobrien#define LIBGCC_SPEC "libgcc.a%s"
57018334Speter#else
57150599Sobrien#define LIBGCC_SPEC "-lgcc"
57218334Speter#endif
57318334Speter#endif
57418334Speter
57518334Speter/* config.h can define STARTFILE_SPEC to override the default crt0 files.  */
57618334Speter#ifndef STARTFILE_SPEC
57718334Speter#define STARTFILE_SPEC  \
57818334Speter  "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}"
57918334Speter#endif
58018334Speter
58150599Sobrien/* config.h can define SWITCHES_NEED_SPACES to control which options
58250599Sobrien   require spaces between the option and the argument.  */
58318334Speter#ifndef SWITCHES_NEED_SPACES
58418334Speter#define SWITCHES_NEED_SPACES ""
58518334Speter#endif
58618334Speter
58718334Speter/* config.h can define ENDFILE_SPEC to override the default crtn files.  */
58818334Speter#ifndef ENDFILE_SPEC
58918334Speter#define ENDFILE_SPEC ""
59018334Speter#endif
59118334Speter
59250599Sobrien#ifndef LINKER_NAME
59350599Sobrien#define LINKER_NAME "collect2"
59418334Speter#endif
59518334Speter
59690277Sobrien/* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g'
59790277Sobrien   to the assembler.  */
59890277Sobrien#ifndef ASM_DEBUG_SPEC
59990277Sobrien# if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \
60090277Sobrien     && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
60190277Sobrien#  define ASM_DEBUG_SPEC					\
60290277Sobrien      (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG			\
60390277Sobrien       ? "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}"	\
60490277Sobrien       : "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}")
60590277Sobrien# else
60690277Sobrien#  if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
60790277Sobrien#   define ASM_DEBUG_SPEC "%{g*:--gstabs}"
60890277Sobrien#  endif
60990277Sobrien#  if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG)
61090277Sobrien#   define ASM_DEBUG_SPEC "%{g*:--gdwarf2}"
61190277Sobrien#  endif
61290277Sobrien# endif
61390277Sobrien#endif
61490277Sobrien#ifndef ASM_DEBUG_SPEC
61590277Sobrien# define ASM_DEBUG_SPEC ""
61690277Sobrien#endif
61718334Speter
61890277Sobrien/* Here is the spec for running the linker, after compiling all files.  */
61990277Sobrien
62096285Sobrien/* This is overridable by the target in case they need to specify the
62196285Sobrien   -lgcc and -lc order specially, yet not require them to override all
62296285Sobrien   of LINK_COMMAND_SPEC.  */
62396285Sobrien#ifndef LINK_GCC_C_SEQUENCE_SPEC
62496285Sobrien#define LINK_GCC_C_SEQUENCE_SPEC "%G %L %G"
62596285Sobrien#endif
62696285Sobrien
62790277Sobrien/* -u* was put back because both BSD and SysV seem to support it.  */
62890277Sobrien/* %{static:} simply prevents an error message if the target machine
62990277Sobrien   doesn't handle -static.  */
63090277Sobrien/* We want %{T*} after %{L*} and %D so that it can be used to specify linker
63190277Sobrien   scripts which exist in user specified directories, or in standard
63290277Sobrien   directories.  */
63390277Sobrien#ifndef LINK_COMMAND_SPEC
63490277Sobrien#define LINK_COMMAND_SPEC "\
63590277Sobrien%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
63690277Sobrien    %(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r} %{s} %{t}\
63790277Sobrien    %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
63896285Sobrien    %{static:} %{L*} %(link_libgcc) %o %{!nostdlib:%{!nodefaultlibs:%(link_gcc_c_sequence)}}\
63990277Sobrien    %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
64090277Sobrien#endif
64190277Sobrien
64290277Sobrien#ifndef LINK_LIBGCC_SPEC
64390277Sobrien# ifdef LINK_LIBGCC_SPECIAL
64490277Sobrien/* Don't generate -L options for startfile prefix list.  */
64590277Sobrien#  define LINK_LIBGCC_SPEC ""
64690277Sobrien# else
64790277Sobrien/* Do generate them.  */
64890277Sobrien#  define LINK_LIBGCC_SPEC "%D"
64990277Sobrien# endif
65090277Sobrien#endif
65190277Sobrien
652117413Skan#ifndef STARTFILE_PREFIX_SPEC
653117413Skan# define STARTFILE_PREFIX_SPEC ""
654117413Skan#endif
655117413Skan
656117413Skanstatic const char *asm_debug;
65790277Sobrienstatic const char *cpp_spec = CPP_SPEC;
65890277Sobrienstatic const char *cpp_predefines = CPP_PREDEFINES;
65990277Sobrienstatic const char *cc1_spec = CC1_SPEC;
66090277Sobrienstatic const char *cc1plus_spec = CC1PLUS_SPEC;
66196285Sobrienstatic const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC;
66290277Sobrienstatic const char *asm_spec = ASM_SPEC;
66390277Sobrienstatic const char *asm_final_spec = ASM_FINAL_SPEC;
66490277Sobrienstatic const char *link_spec = LINK_SPEC;
66590277Sobrienstatic const char *lib_spec = LIB_SPEC;
66690277Sobrienstatic const char *libgcc_spec = LIBGCC_SPEC;
66790277Sobrienstatic const char *endfile_spec = ENDFILE_SPEC;
66890277Sobrienstatic const char *startfile_spec = STARTFILE_SPEC;
66990277Sobrienstatic const char *switches_need_spaces = SWITCHES_NEED_SPACES;
67090277Sobrienstatic const char *linker_name_spec = LINKER_NAME;
67190277Sobrienstatic const char *link_command_spec = LINK_COMMAND_SPEC;
67290277Sobrienstatic const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
673117413Skanstatic const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC;
67490277Sobrien
67590277Sobrien/* Standard options to cpp, cc1, and as, to reduce duplication in specs.
67690277Sobrien   There should be no need to override these in target dependent files,
67790277Sobrien   but we need to copy them to the specs file so that newer versions
67890277Sobrien   of the GCC driver can correctly drive older tool chains with the
67990277Sobrien   appropriate -B options.  */
68090277Sobrien
681117413Skan/* When cpplib handles traditional preprocessing, get rid of this, and
682117413Skan   call cc1 (or cc1obj in objc/lang-specs.h) from the main specs so
683117413Skan   that we default the front end language better.  */
68490277Sobrienstatic const char *trad_capable_cpp =
685117413Skan"cc1 -E %{traditional|ftraditional|traditional-cpp:-traditional-cpp}";
68690277Sobrien
687107594Sobrien/* We don't wrap .d files in %W{} since a missing .d file, and
688107594Sobrien   therefore no dependency entry, confuses make into thinking a .o
689107594Sobrien   file that happens to exist is up-to-date.  */
69090277Sobrienstatic const char *cpp_unique_options =
69190277Sobrien"%{C:%{!E:%eGNU C does not support -C without using -E}}\
692117413Skan %{CC:%{!E:%eGNU C does not support -CC without using -E}}\
693117413Skan %{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*} %{P} %I\
694107594Sobrien %{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\
695107594Sobrien %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\
696107594Sobrien %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\
69796285Sobrien %{!E:%{!M:%{!MM:%{MD|MMD:%{o*:-MQ %*}}}}}\
698117413Skan %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
69990277Sobrien %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
700117413Skan %{remap} %{g3:-dD} %{H} %C %{D*&U*&A*} %{i*} %Z %i\
70196285Sobrien %{E|M|MM:%W{o*}}";
70290277Sobrien
70390277Sobrien/* This contains cpp options which are common with cc1_options and are passed
704117413Skan   only when preprocessing only to avoid duplication.  We pass the cc1 spec
705117413Skan   options to the preprocessor so that it the cc1 spec may manipulate
706117413Skan   options used to set target flags.  Those special target flags settings may
707117413Skan   in turn cause preprocessor symbols to be defined specially.  */
70890277Sobrienstatic const char *cpp_options =
709117413Skan"%(cpp_unique_options) %1 %{m*} %{std*} %{ansi} %{W*&pedantic*} %{w} %{f*}\
710117413Skan %{O*} %{undef}";
71190277Sobrien
712117413Skan/* This contains cpp options which are not passed when the preprocessor
713117413Skan   output will be used by another program.  */
714117413Skanstatic const char *cpp_debug_options = "%{d*}";
715117413Skan
71690277Sobrien/* NB: This is shared amongst all front-ends.  */
71790277Sobrienstatic const char *cc1_options =
71890277Sobrien"%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
71990277Sobrien %1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\
720117413Skan -auxbase%{c|S:%{o*:-strip %*}%{!o*: %b}}%{!c:%{!S: %b}}\
721117413Skan %{g*} %{O*} %{W*&pedantic*} %{w} %{std*} %{ansi}\
722117413Skan %{v:-version} %{pg:-p} %{p} %{f*} %{undef}\
72390277Sobrien %{Qn:-fno-ident} %{--help:--help}\
72490277Sobrien %{--target-help:--target-help}\
72590277Sobrien %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\
72690277Sobrien %{fsyntax-only:-o %j} %{-param*}";
72790277Sobrien
72890277Sobrienstatic const char *asm_options =
72990277Sobrien"%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
73090277Sobrien
73190277Sobrienstatic const char *invoke_as =
73290277Sobrien"%{!S:-o %{|!pipe:%g.s} |\n as %(asm_options) %{!pipe:%g.s} %A }";
73390277Sobrien
73450599Sobrien/* Some compilers have limits on line lengths, and the multilib_select
73550599Sobrien   and/or multilib_matches strings can be very long, so we build them at
73650599Sobrien   run time.  */
73750599Sobrienstatic struct obstack multilib_obstack;
73890277Sobrienstatic const char *multilib_select;
73990277Sobrienstatic const char *multilib_matches;
74090277Sobrienstatic const char *multilib_defaults;
74190277Sobrienstatic const char *multilib_exclusions;
74250599Sobrien#include "multilib.h"
74350599Sobrien
74450599Sobrien/* Check whether a particular argument is a default argument.  */
74550599Sobrien
74650599Sobrien#ifndef MULTILIB_DEFAULTS
74750599Sobrien#define MULTILIB_DEFAULTS { "" }
74850599Sobrien#endif
74950599Sobrien
75090277Sobrienstatic const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
75150599Sobrien
752117413Skan#ifndef DRIVER_SELF_SPECS
753117413Skan#define DRIVER_SELF_SPECS ""
754117413Skan#endif
755117413Skan
756117413Skanstatic const char *const driver_self_specs[] = { DRIVER_SELF_SPECS };
757117413Skan
75890277Sobrienstruct user_specs
75990277Sobrien{
76050599Sobrien  struct user_specs *next;
76152520Sobrien  const char *filename;
76250599Sobrien};
76350599Sobrien
76450599Sobrienstatic struct user_specs *user_specs_head, *user_specs_tail;
76550599Sobrien
76650599Sobrien#ifndef SWITCH_TAKES_ARG
76750599Sobrien#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
76818334Speter#endif
76918334Speter
77018334Speter#ifndef WORD_SWITCH_TAKES_ARG
77118334Speter#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
77218334Speter#endif
77318334Speter
77490277Sobrien#ifdef HAVE_TARGET_EXECUTABLE_SUFFIX
77550599Sobrien/* This defines which switches stop a full compilation.  */
77650599Sobrien#define DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) \
77750599Sobrien  ((CHAR) == 'c' || (CHAR) == 'S')
77850599Sobrien
77950599Sobrien#ifndef SWITCH_CURTAILS_COMPILATION
78050599Sobrien#define SWITCH_CURTAILS_COMPILATION(CHAR) \
78150599Sobrien  DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR)
78250599Sobrien#endif
78350599Sobrien#endif
78450599Sobrien
78518334Speter/* Record the mapping from file suffixes for compilation specs.  */
78618334Speter
78718334Speterstruct compiler
78818334Speter{
78952520Sobrien  const char *suffix;		/* Use this compiler for input files
79018334Speter				   whose names end in this suffix.  */
79118334Speter
79290277Sobrien  const char *spec;		/* To use this compiler, run this spec.  */
79390277Sobrien
79490277Sobrien  const char *cpp_spec;         /* If non-NULL, substitute this spec
79590277Sobrien				   for `%C', rather than the usual
79690277Sobrien				   cpp_spec.  */
79718334Speter};
79818334Speter
79918334Speter/* Pointer to a vector of `struct compiler' that gives the spec for
80018334Speter   compiling a file, based on its suffix.
80118334Speter   A file that does not end in any of these suffixes will be passed
80218334Speter   unchanged to the loader and nothing else will be done to it.
80318334Speter
80418334Speter   An entry containing two 0s is used to terminate the vector.
80518334Speter
80618334Speter   If multiple entries match a file, the last matching one is used.  */
80718334Speter
80818334Speterstatic struct compiler *compilers;
80918334Speter
81018334Speter/* Number of entries in `compilers', not counting the null terminator.  */
81118334Speter
81218334Speterstatic int n_compilers;
81318334Speter
81418334Speter/* The default list of file name suffixes and their compilation specs.  */
81518334Speter
81690277Sobrienstatic const struct compiler default_compilers[] =
81718334Speter{
81850599Sobrien  /* Add lists of suffixes of known languages here.  If those languages
81950599Sobrien     were not present when we built the driver, we will hit these copies
82050599Sobrien     and be given a more meaningful error than "file not used since
82150599Sobrien     linking is not done".  */
82290277Sobrien  {".m",  "#Objective-C", 0}, {".mi",  "#Objective-C", 0},
82390277Sobrien  {".cc", "#C++", 0}, {".cxx", "#C++", 0}, {".cpp", "#C++", 0},
82490277Sobrien  {".cp", "#C++", 0}, {".c++", "#C++", 0}, {".C", "#C++", 0},
82590277Sobrien  {".ii", "#C++", 0},
82690277Sobrien  {".ads", "#Ada", 0}, {".adb", "#Ada", 0},
82790277Sobrien  {".f", "#Fortran", 0}, {".for", "#Fortran", 0}, {".fpp", "#Fortran", 0},
82890277Sobrien  {".F", "#Fortran", 0}, {".FOR", "#Fortran", 0}, {".FPP", "#Fortran", 0},
82990277Sobrien  {".r", "#Ratfor", 0},
83090277Sobrien  {".p", "#Pascal", 0}, {".pas", "#Pascal", 0},
83190277Sobrien  {".java", "#Java", 0}, {".class", "#Java", 0},
83290277Sobrien  {".zip", "#Java", 0}, {".jar", "#Java", 0},
83350599Sobrien  /* Next come the entries for C.  */
83490277Sobrien  {".c", "@c", 0},
83518334Speter  {"@c",
83690277Sobrien   /* cc1 has an integrated ISO C preprocessor.  We should invoke the
837117413Skan      external preprocessor if -save-temps is given.  */
838117413Skan     "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
83990277Sobrien      %{!E:%{!M:%{!MM:\
840117413Skan          %{traditional|ftraditional:\
841117413Skan%eGNU C no longer supports -traditional without -E}\
842117413Skan	  %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
84396285Sobrien		%(cpp_options) %{save-temps:%b.i} %{!save-temps:%g.i} \n\
84496285Sobrien		    cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} %(cc1_options)}\
845117413Skan	  %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
846117413Skan		cc1 %(cpp_unique_options) %(cc1_options)}}}\
84790277Sobrien        %{!fsyntax-only:%(invoke_as)}}}}", 0},
84818334Speter  {"-",
84990277Sobrien   "%{!E:%e-E required when input is from standard input}\
850117413Skan    %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 0},
85190277Sobrien  {".h", "@c-header", 0},
85218334Speter  {"@c-header",
85390277Sobrien   "%{!E:%ecompilation of header file requested} \
854117413Skan    %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)",
855117413Skan   0},
85690277Sobrien  {".i", "@cpp-output", 0},
85718334Speter  {"@cpp-output",
85890277Sobrien   "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0},
85990277Sobrien  {".s", "@assembler", 0},
86018334Speter  {"@assembler",
86190277Sobrien   "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0},
86290277Sobrien  {".S", "@assembler-with-cpp", 0},
86318334Speter  {"@assembler-with-cpp",
86490277Sobrien   "%(trad_capable_cpp) -lang-asm %(cpp_options)\
865117413Skan      %{E|M|MM:%(cpp_debug_options)}\
86690277Sobrien      %{!M:%{!MM:%{!E:%{!S:-o %{|!pipe:%g.s} |\n\
86790277Sobrien       as %(asm_debug) %(asm_options) %{!pipe:%g.s} %A }}}}", 0},
86818334Speter#include "specs.h"
86918334Speter  /* Mark end of table */
87090277Sobrien  {0, 0, 0}
87118334Speter};
87218334Speter
87318334Speter/* Number of elements in default_compilers, not counting the terminator.  */
87418334Speter
875117413Skanstatic const int n_default_compilers = ARRAY_SIZE (default_compilers) - 1;
87618334Speter
87718334Speter/* A vector of options to give to the linker.
87818334Speter   These options are accumulated by %x,
87918334Speter   and substituted into the linker command with %X.  */
88018334Speterstatic int n_linker_options;
88118334Speterstatic char **linker_options;
88218334Speter
88318334Speter/* A vector of options to give to the assembler.
88418334Speter   These options are accumulated by -Wa,
88518334Speter   and substituted into the assembler command with %Y.  */
88618334Speterstatic int n_assembler_options;
88718334Speterstatic char **assembler_options;
88818334Speter
88918334Speter/* A vector of options to give to the preprocessor.
89018334Speter   These options are accumulated by -Wp,
89118334Speter   and substituted into the preprocessor command with %Z.  */
89218334Speterstatic int n_preprocessor_options;
89318334Speterstatic char **preprocessor_options;
89418334Speter
89518334Speter/* Define how to map long options into short ones.  */
89618334Speter
89718334Speter/* This structure describes one mapping.  */
89818334Speterstruct option_map
89918334Speter{
90018334Speter  /* The long option's name.  */
90190277Sobrien  const char *const name;
90218334Speter  /* The equivalent short option.  */
90390277Sobrien  const char *const equivalent;
90418334Speter  /* Argument info.  A string of flag chars; NULL equals no options.
90518334Speter     a => argument required.
90618334Speter     o => argument optional.
90718334Speter     j => join argument to equivalent, making one word.
90818334Speter     * => require other text after NAME as an argument.  */
90990277Sobrien  const char *const arg_info;
91018334Speter};
91118334Speter
91218334Speter/* This is the table of mappings.  Mappings are tried sequentially
91318334Speter   for each option encountered; the first one that matches, wins.  */
91418334Speter
91590277Sobrienstatic const struct option_map option_map[] =
91618334Speter {
91718334Speter   {"--all-warnings", "-Wall", 0},
91818334Speter   {"--ansi", "-ansi", 0},
91918334Speter   {"--assemble", "-S", 0},
92018334Speter   {"--assert", "-A", "a"},
92152520Sobrien   {"--classpath", "-fclasspath=", "aj"},
92296285Sobrien   {"--bootclasspath", "-fbootclasspath=", "aj"},
92396285Sobrien   {"--CLASSPATH", "-fclasspath=", "aj"},
92418334Speter   {"--comments", "-C", 0},
925117413Skan   {"--comments-in-macros", "-CC", 0},
92618334Speter   {"--compile", "-c", 0},
92718334Speter   {"--debug", "-g", "oj"},
92850599Sobrien   {"--define-macro", "-D", "aj"},
92918334Speter   {"--dependencies", "-M", 0},
93018334Speter   {"--dump", "-d", "a"},
93118334Speter   {"--dumpbase", "-dumpbase", "a"},
93218334Speter   {"--entry", "-e", 0},
93318334Speter   {"--extra-warnings", "-W", 0},
93418334Speter   {"--for-assembler", "-Wa", "a"},
93518334Speter   {"--for-linker", "-Xlinker", "a"},
93618334Speter   {"--force-link", "-u", "a"},
93718334Speter   {"--imacros", "-imacros", "a"},
93818334Speter   {"--include", "-include", "a"},
93918334Speter   {"--include-barrier", "-I-", 0},
94050599Sobrien   {"--include-directory", "-I", "aj"},
94118334Speter   {"--include-directory-after", "-idirafter", "a"},
94218334Speter   {"--include-prefix", "-iprefix", "a"},
94318334Speter   {"--include-with-prefix", "-iwithprefix", "a"},
94418334Speter   {"--include-with-prefix-before", "-iwithprefixbefore", "a"},
94518334Speter   {"--include-with-prefix-after", "-iwithprefix", "a"},
94618334Speter   {"--language", "-x", "a"},
94718334Speter   {"--library-directory", "-L", "a"},
94818334Speter   {"--machine", "-m", "aj"},
94918334Speter   {"--machine-", "-m", "*j"},
95096285Sobrien   {"--no-integrated-cpp", "-no-integrated-cpp", 0},
95118334Speter   {"--no-line-commands", "-P", 0},
95218334Speter   {"--no-precompiled-includes", "-noprecomp", 0},
95318334Speter   {"--no-standard-includes", "-nostdinc", 0},
95418334Speter   {"--no-standard-libraries", "-nostdlib", 0},
95518334Speter   {"--no-warnings", "-w", 0},
95618334Speter   {"--optimize", "-O", "oj"},
95718334Speter   {"--output", "-o", "a"},
95852520Sobrien   {"--output-class-directory", "-foutput-class-dir=", "ja"},
95990277Sobrien   {"--param", "--param", "a"},
96018334Speter   {"--pedantic", "-pedantic", 0},
96118334Speter   {"--pedantic-errors", "-pedantic-errors", 0},
96218334Speter   {"--pipe", "-pipe", 0},
96318334Speter   {"--prefix", "-B", "a"},
96418334Speter   {"--preprocess", "-E", 0},
96518334Speter   {"--print-search-dirs", "-print-search-dirs", 0},
96618334Speter   {"--print-file-name", "-print-file-name=", "aj"},
96718334Speter   {"--print-libgcc-file-name", "-print-libgcc-file-name", 0},
96818334Speter   {"--print-missing-file-dependencies", "-MG", 0},
96918334Speter   {"--print-multi-lib", "-print-multi-lib", 0},
97018334Speter   {"--print-multi-directory", "-print-multi-directory", 0},
971104763Skan   {"--print-multi-os-directory", "-print-multi-os-directory", 0},
97218334Speter   {"--print-prog-name", "-print-prog-name=", "aj"},
97318334Speter   {"--profile", "-p", 0},
97418334Speter   {"--profile-blocks", "-a", 0},
97518334Speter   {"--quiet", "-q", 0},
97696285Sobrien   {"--resource", "-fcompile-resource=", "aj"},
97718334Speter   {"--save-temps", "-save-temps", 0},
97818334Speter   {"--shared", "-shared", 0},
97918334Speter   {"--silent", "-q", 0},
98050599Sobrien   {"--specs", "-specs=", "aj"},
98118334Speter   {"--static", "-static", 0},
98252520Sobrien   {"--std", "-std=", "aj"},
98318334Speter   {"--symbolic", "-symbolic", 0},
98418334Speter   {"--target", "-b", "a"},
98590277Sobrien   {"--time", "-time", 0},
98618334Speter   {"--trace-includes", "-H", 0},
98718334Speter   {"--traditional", "-traditional", 0},
98818334Speter   {"--traditional-cpp", "-traditional-cpp", 0},
98918334Speter   {"--trigraphs", "-trigraphs", 0},
99050599Sobrien   {"--undefine-macro", "-U", "aj"},
99118334Speter   {"--use-version", "-V", "a"},
99218334Speter   {"--user-dependencies", "-MM", 0},
99318334Speter   {"--verbose", "-v", 0},
99418334Speter   {"--warn-", "-W", "*j"},
99518334Speter   {"--write-dependencies", "-MD", 0},
99618334Speter   {"--write-user-dependencies", "-MMD", 0},
99718334Speter   {"--", "-f", "*j"}
99818334Speter };
99918334Speter
100090277Sobrien
100190277Sobrien#ifdef TARGET_OPTION_TRANSLATE_TABLE
100290277Sobrienstatic const struct {
100390277Sobrien  const char *const option_found;
100490277Sobrien  const char *const replacements;
100590277Sobrien} target_option_translations[] =
100690277Sobrien{
100790277Sobrien  TARGET_OPTION_TRANSLATE_TABLE,
100890277Sobrien  { 0, 0 }
100990277Sobrien};
101090277Sobrien#endif
101190277Sobrien
101218334Speter/* Translate the options described by *ARGCP and *ARGVP.
101318334Speter   Make a new vector and store it back in *ARGVP,
101418334Speter   and store its length in *ARGVC.  */
101518334Speter
101618334Speterstatic void
101718334Spetertranslate_options (argcp, argvp)
101818334Speter     int *argcp;
101990277Sobrien     const char *const **argvp;
102018334Speter{
102152520Sobrien  int i;
102218334Speter  int argc = *argcp;
102390277Sobrien  const char *const *argv = *argvp;
102490277Sobrien  int newvsize = (argc + 2) * 2 * sizeof (const char *);
102552520Sobrien  const char **newv =
102690277Sobrien    (const char **) xmalloc (newvsize);
102718334Speter  int newindex = 0;
102818334Speter
102918334Speter  i = 0;
103018334Speter  newv[newindex++] = argv[i++];
103118334Speter
103218334Speter  while (i < argc)
103318334Speter    {
103490277Sobrien#ifdef TARGET_OPTION_TRANSLATE_TABLE
103590277Sobrien      int tott_idx;
103690277Sobrien
103790277Sobrien      for (tott_idx = 0;
103890277Sobrien	   target_option_translations[tott_idx].option_found;
103990277Sobrien	   tott_idx++)
104090277Sobrien	{
104190277Sobrien	  if (strcmp (target_option_translations[tott_idx].option_found,
104290277Sobrien		      argv[i]) == 0)
104390277Sobrien	    {
104490277Sobrien	      int spaces = 1;
104590277Sobrien	      const char *sp;
104690277Sobrien	      char *np;
104790277Sobrien
104890277Sobrien	      for (sp = target_option_translations[tott_idx].replacements;
104990277Sobrien		   *sp; sp++)
105090277Sobrien		{
105190277Sobrien		  if (*sp == ' ')
105290277Sobrien		    spaces ++;
105390277Sobrien		}
105490277Sobrien
105590277Sobrien	      newvsize += spaces * sizeof (const char *);
105690277Sobrien	      newv = (const char **) xrealloc (newv, newvsize);
105790277Sobrien
105890277Sobrien	      sp = target_option_translations[tott_idx].replacements;
105990277Sobrien	      np = xstrdup (sp);
106090277Sobrien
106190277Sobrien	      while (1)
106290277Sobrien		{
106390277Sobrien		  while (*np == ' ')
106490277Sobrien		    np++;
106590277Sobrien		  if (*np == 0)
106690277Sobrien		    break;
106790277Sobrien		  newv[newindex++] = np;
106890277Sobrien		  while (*np != ' ' && *np)
106990277Sobrien		    np++;
107090277Sobrien		  if (*np == 0)
107190277Sobrien		    break;
107290277Sobrien		  *np++ = 0;
107390277Sobrien		}
107490277Sobrien
107590277Sobrien	      i ++;
107690277Sobrien	      break;
107790277Sobrien	    }
107890277Sobrien	}
107990277Sobrien      if (target_option_translations[tott_idx].option_found)
108090277Sobrien	continue;
108190277Sobrien#endif
108290277Sobrien
108318334Speter      /* Translate -- options.  */
108418334Speter      if (argv[i][0] == '-' && argv[i][1] == '-')
108518334Speter	{
108652520Sobrien	  size_t j;
108718334Speter	  /* Find a mapping that applies to this option.  */
108890277Sobrien	  for (j = 0; j < ARRAY_SIZE (option_map); j++)
108918334Speter	    {
109050599Sobrien	      size_t optlen = strlen (option_map[j].name);
109150599Sobrien	      size_t arglen = strlen (argv[i]);
109250599Sobrien	      size_t complen = arglen > optlen ? optlen : arglen;
109352520Sobrien	      const char *arginfo = option_map[j].arg_info;
109418334Speter
109518334Speter	      if (arginfo == 0)
109618334Speter		arginfo = "";
109718334Speter
109818334Speter	      if (!strncmp (argv[i], option_map[j].name, complen))
109918334Speter		{
110052520Sobrien		  const char *arg = 0;
110118334Speter
110218334Speter		  if (arglen < optlen)
110318334Speter		    {
110452520Sobrien		      size_t k;
110590277Sobrien		      for (k = j + 1; k < ARRAY_SIZE (option_map); k++)
110618334Speter			if (strlen (option_map[k].name) >= arglen
110718334Speter			    && !strncmp (argv[i], option_map[k].name, arglen))
110818334Speter			  {
110990277Sobrien			    error ("ambiguous abbreviation %s", argv[i]);
111018334Speter			    break;
111118334Speter			  }
111218334Speter
111390277Sobrien		      if (k != ARRAY_SIZE (option_map))
111418334Speter			break;
111518334Speter		    }
111618334Speter
111718334Speter		  if (arglen > optlen)
111818334Speter		    {
111918334Speter		      /* If the option has an argument, accept that.  */
112018334Speter		      if (argv[i][optlen] == '=')
112118334Speter			arg = argv[i] + optlen + 1;
112218334Speter
112318334Speter		      /* If this mapping requires extra text at end of name,
112418334Speter			 accept that as "argument".  */
112590277Sobrien		      else if (strchr (arginfo, '*') != 0)
112618334Speter			arg = argv[i] + optlen;
112718334Speter
112818334Speter		      /* Otherwise, extra text at end means mismatch.
112918334Speter			 Try other mappings.  */
113018334Speter		      else
113118334Speter			continue;
113218334Speter		    }
113318334Speter
113490277Sobrien		  else if (strchr (arginfo, '*') != 0)
113518334Speter		    {
113690277Sobrien		      error ("incomplete `%s' option", option_map[j].name);
113718334Speter		      break;
113818334Speter		    }
113918334Speter
114018334Speter		  /* Handle arguments.  */
114190277Sobrien		  if (strchr (arginfo, 'a') != 0)
114218334Speter		    {
114318334Speter		      if (arg == 0)
114418334Speter			{
114518334Speter			  if (i + 1 == argc)
114618334Speter			    {
114790277Sobrien			      error ("missing argument to `%s' option",
114818334Speter				     option_map[j].name);
114918334Speter			      break;
115018334Speter			    }
115118334Speter
115218334Speter			  arg = argv[++i];
115318334Speter			}
115418334Speter		    }
115590277Sobrien		  else if (strchr (arginfo, '*') != 0)
115618334Speter		    ;
115790277Sobrien		  else if (strchr (arginfo, 'o') == 0)
115818334Speter		    {
115918334Speter		      if (arg != 0)
116090277Sobrien			error ("extraneous argument to `%s' option",
116118334Speter			       option_map[j].name);
116218334Speter		      arg = 0;
116318334Speter		    }
116418334Speter
116518334Speter		  /* Store the translation as one argv elt or as two.  */
116690277Sobrien		  if (arg != 0 && strchr (arginfo, 'j') != 0)
116750599Sobrien		    newv[newindex++] = concat (option_map[j].equivalent, arg,
116890277Sobrien					       NULL);
116918334Speter		  else if (arg != 0)
117018334Speter		    {
117118334Speter		      newv[newindex++] = option_map[j].equivalent;
117218334Speter		      newv[newindex++] = arg;
117318334Speter		    }
117418334Speter		  else
117518334Speter		    newv[newindex++] = option_map[j].equivalent;
117618334Speter
117718334Speter		  break;
117818334Speter		}
117918334Speter	    }
118018334Speter	  i++;
118118334Speter	}
118218334Speter
118318334Speter      /* Handle old-fashioned options--just copy them through,
118418334Speter	 with their arguments.  */
118518334Speter      else if (argv[i][0] == '-')
118618334Speter	{
118752520Sobrien	  const char *p = argv[i] + 1;
118818334Speter	  int c = *p;
118918334Speter	  int nskip = 1;
119018334Speter
119118334Speter	  if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
119218334Speter	    nskip += SWITCH_TAKES_ARG (c) - (p[1] != 0);
119318334Speter	  else if (WORD_SWITCH_TAKES_ARG (p))
119418334Speter	    nskip += WORD_SWITCH_TAKES_ARG (p);
1195117413Skan	  else if ((c == 'B' || c == 'b' || c == 'x')
119618334Speter		   && p[1] == 0)
119718334Speter	    nskip += 1;
119818334Speter	  else if (! strcmp (p, "Xlinker"))
119918334Speter	    nskip += 1;
120018334Speter
120118334Speter	  /* Watch out for an option at the end of the command line that
120218334Speter	     is missing arguments, and avoid skipping past the end of the
120318334Speter	     command line.  */
120418334Speter	  if (nskip + i > argc)
120518334Speter	    nskip = argc - i;
120618334Speter
120718334Speter	  while (nskip > 0)
120818334Speter	    {
120918334Speter	      newv[newindex++] = argv[i++];
121018334Speter	      nskip--;
121118334Speter	    }
121218334Speter	}
121318334Speter      else
121418334Speter	/* Ordinary operands, or +e options.  */
121518334Speter	newv[newindex++] = argv[i++];
121618334Speter    }
121718334Speter
121818334Speter  newv[newindex] = 0;
121918334Speter
122018334Speter  *argvp = newv;
122118334Speter  *argcp = newindex;
122218334Speter}
122318334Speter
122418334Speterstatic char *
122518334Speterskip_whitespace (p)
122618334Speter     char *p;
122718334Speter{
122818334Speter  while (1)
122918334Speter    {
123018334Speter      /* A fully-blank line is a delimiter in the SPEC file and shouldn't
123118334Speter	 be considered whitespace.  */
123218334Speter      if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n')
123318334Speter	return p + 1;
123418334Speter      else if (*p == '\n' || *p == ' ' || *p == '\t')
123518334Speter	p++;
123618334Speter      else if (*p == '#')
123718334Speter	{
123890277Sobrien	  while (*p != '\n')
123990277Sobrien	    p++;
124018334Speter	  p++;
124118334Speter	}
124218334Speter      else
124318334Speter	break;
124418334Speter    }
124518334Speter
124618334Speter  return p;
124718334Speter}
124890277Sobrien/* Structures to keep track of prefixes to try when looking for files.  */
124990277Sobrien
125090277Sobrienstruct prefix_list
125190277Sobrien{
125290277Sobrien  const char *prefix;	      /* String to prepend to the path.  */
125390277Sobrien  struct prefix_list *next;   /* Next in linked list.  */
125490277Sobrien  int require_machine_suffix; /* Don't use without machine_suffix.  */
125590277Sobrien  /* 2 means try both machine_suffix and just_machine_suffix.  */
125690277Sobrien  int *used_flag_ptr;	      /* 1 if a file was found with this prefix.  */
1257104763Skan  int priority;		      /* Sort key - priority within list.  */
1258104763Skan  int os_multilib;	      /* 1 if OS multilib scheme should be used,
1259104763Skan				 0 for GCC multilib scheme.  */
126090277Sobrien};
126190277Sobrien
126290277Sobrienstruct path_prefix
126390277Sobrien{
126490277Sobrien  struct prefix_list *plist;  /* List of prefixes to try */
126590277Sobrien  int max_len;                /* Max length of a prefix in PLIST */
126690277Sobrien  const char *name;           /* Name of this list (used in config stuff) */
126790277Sobrien};
126890277Sobrien
126990277Sobrien/* List of prefixes to try when looking for executables.  */
127090277Sobrien
127190277Sobrienstatic struct path_prefix exec_prefixes = { 0, 0, "exec" };
127290277Sobrien
127390277Sobrien/* List of prefixes to try when looking for startup (crt0) files.  */
127490277Sobrien
127590277Sobrienstatic struct path_prefix startfile_prefixes = { 0, 0, "startfile" };
127690277Sobrien
127790277Sobrien/* List of prefixes to try when looking for include files.  */
127890277Sobrien
127990277Sobrienstatic struct path_prefix include_prefixes = { 0, 0, "include" };
128090277Sobrien
128190277Sobrien/* Suffix to attach to directories searched for commands.
128290277Sobrien   This looks like `MACHINE/VERSION/'.  */
128390277Sobrien
128490277Sobrienstatic const char *machine_suffix = 0;
128590277Sobrien
128690277Sobrien/* Suffix to attach to directories searched for commands.
128790277Sobrien   This is just `MACHINE/'.  */
128890277Sobrien
128990277Sobrienstatic const char *just_machine_suffix = 0;
129090277Sobrien
129190277Sobrien/* Adjusted value of GCC_EXEC_PREFIX envvar.  */
129290277Sobrien
129390277Sobrienstatic const char *gcc_exec_prefix;
129490277Sobrien
129590277Sobrien/* Default prefixes to attach to command names.  */
129690277Sobrien
129790277Sobrien#ifdef CROSS_COMPILE  /* Don't use these prefixes for a cross compiler.  */
129890277Sobrien#undef MD_EXEC_PREFIX
129990277Sobrien#undef MD_STARTFILE_PREFIX
130090277Sobrien#undef MD_STARTFILE_PREFIX_1
130190277Sobrien#endif
130290277Sobrien
130390277Sobrien/* If no prefixes defined, use the null string, which will disable them.  */
130490277Sobrien#ifndef MD_EXEC_PREFIX
130590277Sobrien#define MD_EXEC_PREFIX ""
130690277Sobrien#endif
130790277Sobrien#ifndef MD_STARTFILE_PREFIX
130890277Sobrien#define MD_STARTFILE_PREFIX ""
130990277Sobrien#endif
131090277Sobrien#ifndef MD_STARTFILE_PREFIX_1
131190277Sobrien#define MD_STARTFILE_PREFIX_1 ""
131290277Sobrien#endif
131390277Sobrien
131490277Sobrien/* Supply defaults for the standard prefixes.  */
131590277Sobrien
131690277Sobrien#ifndef STANDARD_EXEC_PREFIX
131790277Sobrien#define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/"
131890277Sobrien#endif
131990277Sobrien#ifndef STANDARD_STARTFILE_PREFIX
132090277Sobrien#define STANDARD_STARTFILE_PREFIX "/usr/local/lib/"
132190277Sobrien#endif
132290277Sobrien#ifndef TOOLDIR_BASE_PREFIX
132390277Sobrien#define TOOLDIR_BASE_PREFIX "/usr/local/"
132490277Sobrien#endif
132596736Sru#ifndef FREEBSD_NATIVE
132690277Sobrien#ifndef STANDARD_BINDIR_PREFIX
132790277Sobrien#define STANDARD_BINDIR_PREFIX "/usr/local/bin"
132890277Sobrien#endif
132996736Sru#endif	/* not FREEBSD_NATIVE */
133090277Sobrien
133190277Sobrienstatic const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX;
133290277Sobrienstatic const char *const standard_exec_prefix_1 = "/usr/lib/gcc/";
133390277Sobrienstatic const char *md_exec_prefix = MD_EXEC_PREFIX;
133490277Sobrien
133590277Sobrienstatic const char *md_startfile_prefix = MD_STARTFILE_PREFIX;
133690277Sobrienstatic const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
133790277Sobrienstatic const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
133890277Sobrienstatic const char *const standard_startfile_prefix_1 = "/lib/";
133990277Sobrienstatic const char *const standard_startfile_prefix_2 = "/usr/lib/";
134090277Sobrien
134190277Sobrienstatic const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
134290277Sobrienstatic const char *tooldir_prefix;
134390277Sobrien
134496736Sru#ifndef FREEBSD_NATIVE
134590277Sobrienstatic const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
134696736Sru#endif	/* not FREEBSD_NATIVE */
134790277Sobrien
134890277Sobrien/* Subdirectory to use for locating libraries.  Set by
134990277Sobrien   set_multilib_dir based on the compilation options.  */
135090277Sobrien
135190277Sobrienstatic const char *multilib_dir;
1352104763Skan
1353104763Skan/* Subdirectory to use for locating libraries in OS conventions.  Set by
1354104763Skan   set_multilib_dir based on the compilation options.  */
1355104763Skan
1356104763Skanstatic const char *multilib_os_dir;
135718334Speter
135850599Sobrien/* Structure to keep track of the specs that have been defined so far.
135950599Sobrien   These are accessed using %(specname) or %[specname] in a compiler
136050599Sobrien   or link spec.  */
136118334Speter
136218334Speterstruct spec_list
136318334Speter{
136450599Sobrien				/* The following 2 fields must be first */
136550599Sobrien				/* to allow EXTRA_SPECS to be initialized */
136690277Sobrien  const char *name;		/* name of the spec.  */
136790277Sobrien  const char *ptr;		/* available ptr if no static pointer */
136850599Sobrien
136950599Sobrien				/* The following fields are not initialized */
137050599Sobrien				/* by EXTRA_SPECS */
137190277Sobrien  const char **ptr_spec;	/* pointer to the spec itself.  */
137250599Sobrien  struct spec_list *next;	/* Next spec in linked list.  */
137350599Sobrien  int name_len;			/* length of the name */
137450599Sobrien  int alloc_p;			/* whether string was allocated */
137518334Speter};
137618334Speter
137750599Sobrien#define INIT_STATIC_SPEC(NAME,PTR) \
137890277Sobrien{ NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, 0 }
137918334Speter
138090277Sobrien/* List of statically defined specs.  */
138190277Sobrienstatic struct spec_list static_specs[] =
138290277Sobrien{
138350599Sobrien  INIT_STATIC_SPEC ("asm",			&asm_spec),
138490277Sobrien  INIT_STATIC_SPEC ("asm_debug",		&asm_debug),
138550599Sobrien  INIT_STATIC_SPEC ("asm_final",		&asm_final_spec),
138690277Sobrien  INIT_STATIC_SPEC ("asm_options",		&asm_options),
138790277Sobrien  INIT_STATIC_SPEC ("invoke_as",		&invoke_as),
138850599Sobrien  INIT_STATIC_SPEC ("cpp",			&cpp_spec),
138990277Sobrien  INIT_STATIC_SPEC ("cpp_options",		&cpp_options),
1390117413Skan  INIT_STATIC_SPEC ("cpp_debug_options",	&cpp_debug_options),
139190277Sobrien  INIT_STATIC_SPEC ("cpp_unique_options",	&cpp_unique_options),
139290277Sobrien  INIT_STATIC_SPEC ("trad_capable_cpp",		&trad_capable_cpp),
139350599Sobrien  INIT_STATIC_SPEC ("cc1",			&cc1_spec),
139490277Sobrien  INIT_STATIC_SPEC ("cc1_options",		&cc1_options),
139550599Sobrien  INIT_STATIC_SPEC ("cc1plus",			&cc1plus_spec),
139696285Sobrien  INIT_STATIC_SPEC ("link_gcc_c_sequence",	&link_gcc_c_sequence_spec),
139750599Sobrien  INIT_STATIC_SPEC ("endfile",			&endfile_spec),
139850599Sobrien  INIT_STATIC_SPEC ("link",			&link_spec),
139950599Sobrien  INIT_STATIC_SPEC ("lib",			&lib_spec),
140050599Sobrien  INIT_STATIC_SPEC ("libgcc",			&libgcc_spec),
140150599Sobrien  INIT_STATIC_SPEC ("startfile",		&startfile_spec),
140250599Sobrien  INIT_STATIC_SPEC ("switches_need_spaces",	&switches_need_spaces),
140350599Sobrien  INIT_STATIC_SPEC ("predefines",		&cpp_predefines),
140450599Sobrien  INIT_STATIC_SPEC ("cross_compile",		&cross_compile),
140550599Sobrien  INIT_STATIC_SPEC ("version",			&compiler_version),
140650599Sobrien  INIT_STATIC_SPEC ("multilib",			&multilib_select),
140750599Sobrien  INIT_STATIC_SPEC ("multilib_defaults",	&multilib_defaults),
140850599Sobrien  INIT_STATIC_SPEC ("multilib_extra",		&multilib_extra),
140950599Sobrien  INIT_STATIC_SPEC ("multilib_matches",		&multilib_matches),
141090277Sobrien  INIT_STATIC_SPEC ("multilib_exclusions",	&multilib_exclusions),
1411104763Skan  INIT_STATIC_SPEC ("multilib_options",		&multilib_options),
141250599Sobrien  INIT_STATIC_SPEC ("linker",			&linker_name_spec),
141390277Sobrien  INIT_STATIC_SPEC ("link_libgcc",		&link_libgcc_spec),
141490277Sobrien  INIT_STATIC_SPEC ("md_exec_prefix",		&md_exec_prefix),
141590277Sobrien  INIT_STATIC_SPEC ("md_startfile_prefix",	&md_startfile_prefix),
141690277Sobrien  INIT_STATIC_SPEC ("md_startfile_prefix_1",	&md_startfile_prefix_1),
1417117413Skan  INIT_STATIC_SPEC ("startfile_prefix_spec",	&startfile_prefix_spec),
141850599Sobrien};
141950599Sobrien
142050599Sobrien#ifdef EXTRA_SPECS		/* additional specs needed */
142152520Sobrien/* Structure to keep track of just the first two args of a spec_list.
142290277Sobrien   That is all that the EXTRA_SPECS macro gives us.  */
142352520Sobrienstruct spec_list_1
142452520Sobrien{
142590277Sobrien  const char *const name;
142690277Sobrien  const char *const ptr;
142752520Sobrien};
142852520Sobrien
142990277Sobrienstatic const struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
143090277Sobrienstatic struct spec_list *extra_specs = (struct spec_list *) 0;
143150599Sobrien#endif
143250599Sobrien
143350599Sobrien/* List of dynamically allocates specs that have been defined so far.  */
143450599Sobrien
143590277Sobrienstatic struct spec_list *specs = (struct spec_list *) 0;
143690277Sobrien
1437117413Skan/* List of static spec functions.  */
1438117413Skan
1439117413Skanstatic const struct spec_function static_spec_functions[] =
1440117413Skan{
1441117413Skan  { "if-exists",		if_exists_spec_function },
1442117413Skan  { "if-exists-else",		if_exists_else_spec_function },
1443117413Skan  { 0, 0 }
1444117413Skan};
1445117413Skan
1446117413Skanstatic int processing_spec_function;
1447117413Skan
144890277Sobrien/* Add appropriate libgcc specs to OBSTACK, taking into account
144990277Sobrien   various permutations of -shared-libgcc, -shared, and such.  */
145050599Sobrien
145190277Sobrien#ifdef ENABLE_SHARED_LIBGCC
145290277Sobrienstatic void
145390277Sobrieninit_gcc_specs (obstack, shared_name, static_name, eh_name)
145490277Sobrien     struct obstack *obstack;
145590277Sobrien     const char *shared_name;
145690277Sobrien     const char *static_name;
145790277Sobrien     const char *eh_name;
145890277Sobrien{
145996285Sobrien  char *buf;
146090277Sobrien
146196285Sobrien  buf = concat ("%{static|static-libgcc:", static_name, " ", eh_name,
146296285Sobrien		"}%{!static:%{!static-libgcc:",
146396285Sobrien		"%{!shared:%{!shared-libgcc:", static_name, " ",
146496285Sobrien		eh_name, "}%{shared-libgcc:", shared_name, " ",
146596285Sobrien		static_name, "}}%{shared:",
146690277Sobrien#ifdef LINK_EH_SPEC
146796285Sobrien		"%{shared-libgcc:", shared_name,
146896285Sobrien		"}%{!shared-libgcc:", static_name, "}",
146990277Sobrien#else
147096285Sobrien		shared_name,
147190277Sobrien#endif
147296285Sobrien		"}}}", NULL);
147396285Sobrien
147496285Sobrien  obstack_grow (obstack, buf, strlen (buf));
147596285Sobrien  free (buf);
147690277Sobrien}
147790277Sobrien#endif /* ENABLE_SHARED_LIBGCC */
147890277Sobrien
147950599Sobrien/* Initialize the specs lookup routines.  */
148050599Sobrien
148150599Sobrienstatic void
148250599Sobrieninit_spec ()
148350599Sobrien{
148490277Sobrien  struct spec_list *next = (struct spec_list *) 0;
148590277Sobrien  struct spec_list *sl   = (struct spec_list *) 0;
148650599Sobrien  int i;
148750599Sobrien
148850599Sobrien  if (specs)
148990277Sobrien    return;			/* Already initialized.  */
149050599Sobrien
149150599Sobrien  if (verbose_flag)
149290277Sobrien    notice ("Using built-in specs.\n");
149350599Sobrien
149450599Sobrien#ifdef EXTRA_SPECS
149552520Sobrien  extra_specs = (struct spec_list *)
149690277Sobrien    xcalloc (sizeof (struct spec_list), ARRAY_SIZE (extra_specs_1));
149790277Sobrien
149890277Sobrien  for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--)
149950599Sobrien    {
150050599Sobrien      sl = &extra_specs[i];
150152520Sobrien      sl->name = extra_specs_1[i].name;
150252520Sobrien      sl->ptr = extra_specs_1[i].ptr;
150350599Sobrien      sl->next = next;
150450599Sobrien      sl->name_len = strlen (sl->name);
150550599Sobrien      sl->ptr_spec = &sl->ptr;
150650599Sobrien      next = sl;
150750599Sobrien    }
150850599Sobrien#endif
150950599Sobrien
1510117413Skan  /* Initialize here, not in definition.  The IRIX 6 O32 cc sometimes chokes
1511117413Skan     on ?: in file-scope variable initializations.  */
1512117413Skan  asm_debug = ASM_DEBUG_SPEC;
1513117413Skan
151490277Sobrien  for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
151550599Sobrien    {
151650599Sobrien      sl = &static_specs[i];
151750599Sobrien      sl->next = next;
151850599Sobrien      next = sl;
151950599Sobrien    }
152050599Sobrien
152190277Sobrien#ifdef ENABLE_SHARED_LIBGCC
152290277Sobrien  /* ??? If neither -shared-libgcc nor --static-libgcc was
152390277Sobrien     seen, then we should be making an educated guess.  Some proposed
152490277Sobrien     heuristics for ELF include:
152590277Sobrien
152690277Sobrien	(1) If "-Wl,--export-dynamic", then it's a fair bet that the
152790277Sobrien	    program will be doing dynamic loading, which will likely
152890277Sobrien	    need the shared libgcc.
152990277Sobrien
153090277Sobrien	(2) If "-ldl", then it's also a fair bet that we're doing
153190277Sobrien	    dynamic loading.
153290277Sobrien
153390277Sobrien	(3) For each ET_DYN we're linking against (either through -lfoo
153490277Sobrien	    or /some/path/foo.so), check to see whether it or one of
153590277Sobrien	    its dependencies depends on a shared libgcc.
153690277Sobrien
153790277Sobrien	(4) If "-shared"
153890277Sobrien
153990277Sobrien	    If the runtime is fixed to look for program headers instead
154090277Sobrien	    of calling __register_frame_info at all, for each object,
154190277Sobrien	    use the shared libgcc if any EH symbol referenced.
154290277Sobrien
154390277Sobrien	    If crtstuff is fixed to not invoke __register_frame_info
154490277Sobrien	    automatically, for each object, use the shared libgcc if
154590277Sobrien	    any non-empty unwind section found.
154690277Sobrien
154790277Sobrien     Doing any of this probably requires invoking an external program to
154890277Sobrien     do the actual object file scanning.  */
154990277Sobrien  {
155090277Sobrien    const char *p = libgcc_spec;
155190277Sobrien    int in_sep = 1;
1552117413Skan
155390277Sobrien    /* Transform the extant libgcc_spec into one that uses the shared libgcc
155490277Sobrien       when given the proper command line arguments.  */
155590277Sobrien    while (*p)
155690277Sobrien      {
1557117413Skan	if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0)
155890277Sobrien	  {
155990277Sobrien	    init_gcc_specs (&obstack,
156090277Sobrien#ifdef NO_SHARED_LIBGCC_MULTILIB
156190277Sobrien			    "-lgcc_s"
156290277Sobrien#else
156390277Sobrien			    "-lgcc_s%M"
156490277Sobrien#endif
1565122197Skan#ifdef USE_LIBUNWIND_EXCEPTIONS
1566122197Skan			    " -lunwind"
1567122197Skan#endif
156890277Sobrien			    ,
156990277Sobrien			    "-lgcc",
157090277Sobrien			    "-lgcc_eh");
157190277Sobrien	    p += 5;
157290277Sobrien	    in_sep = 0;
157390277Sobrien	  }
157490277Sobrien	else if (in_sep && *p == 'l' && strncmp (p, "libgcc.a%s", 10) == 0)
157590277Sobrien	  {
157690277Sobrien	    /* Ug.  We don't know shared library extensions.  Hope that
157790277Sobrien	       systems that use this form don't do shared libraries.  */
157890277Sobrien	    init_gcc_specs (&obstack,
157990277Sobrien#ifdef NO_SHARED_LIBGCC_MULTILIB
158090277Sobrien			    "-lgcc_s"
158190277Sobrien#else
158290277Sobrien			    "-lgcc_s%M"
158390277Sobrien#endif
158490277Sobrien			    ,
158590277Sobrien			    "libgcc.a%s",
158690277Sobrien			    "libgcc_eh.a%s");
158790277Sobrien	    p += 10;
158890277Sobrien	    in_sep = 0;
158990277Sobrien	  }
159090277Sobrien	else
159190277Sobrien	  {
159290277Sobrien	    obstack_1grow (&obstack, *p);
159390277Sobrien	    in_sep = (*p == ' ');
159490277Sobrien	    p += 1;
159590277Sobrien	  }
159690277Sobrien      }
159790277Sobrien
159890277Sobrien    obstack_1grow (&obstack, '\0');
159990277Sobrien    libgcc_spec = obstack_finish (&obstack);
160090277Sobrien  }
160190277Sobrien#endif
160290277Sobrien#ifdef USE_AS_TRADITIONAL_FORMAT
160390277Sobrien  /* Prepend "--traditional-format" to whatever asm_spec we had before.  */
160490277Sobrien  {
160590277Sobrien    static const char tf[] = "--traditional-format ";
160690277Sobrien    obstack_grow (&obstack, tf, sizeof(tf) - 1);
160790277Sobrien    obstack_grow0 (&obstack, asm_spec, strlen (asm_spec));
160890277Sobrien    asm_spec = obstack_finish (&obstack);
160990277Sobrien  }
161090277Sobrien#endif
161190277Sobrien#ifdef LINK_EH_SPEC
161290277Sobrien  /* Prepend LINK_EH_SPEC to whatever link_spec we had before.  */
161390277Sobrien  obstack_grow (&obstack, LINK_EH_SPEC, sizeof(LINK_EH_SPEC) - 1);
161490277Sobrien  obstack_grow0 (&obstack, link_spec, strlen (link_spec));
161590277Sobrien  link_spec = obstack_finish (&obstack);
161690277Sobrien#endif
161790277Sobrien
161850599Sobrien  specs = sl;
161950599Sobrien}
162050599Sobrien
162118334Speter/* Change the value of spec NAME to SPEC.  If SPEC is empty, then the spec is
162218334Speter   removed; If the spec starts with a + then SPEC is added to the end of the
162350599Sobrien   current spec.  */
162418334Speter
162518334Speterstatic void
162618334Speterset_spec (name, spec)
162752520Sobrien     const char *name;
162852520Sobrien     const char *spec;
162918334Speter{
163018334Speter  struct spec_list *sl;
163190277Sobrien  const char *old_spec;
163250599Sobrien  int name_len = strlen (name);
163350599Sobrien  int i;
163418334Speter
163590277Sobrien  /* If this is the first call, initialize the statically allocated specs.  */
163650599Sobrien  if (!specs)
163750599Sobrien    {
163890277Sobrien      struct spec_list *next = (struct spec_list *) 0;
163990277Sobrien      for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
164050599Sobrien	{
164150599Sobrien	  sl = &static_specs[i];
164250599Sobrien	  sl->next = next;
164350599Sobrien	  next = sl;
164450599Sobrien	}
164550599Sobrien      specs = sl;
164650599Sobrien    }
164750599Sobrien
164890277Sobrien  /* See if the spec already exists.  */
164918334Speter  for (sl = specs; sl; sl = sl->next)
165050599Sobrien    if (name_len == sl->name_len && !strcmp (sl->name, name))
165118334Speter      break;
165218334Speter
165318334Speter  if (!sl)
165418334Speter    {
165590277Sobrien      /* Not found - make it.  */
165618334Speter      sl = (struct spec_list *) xmalloc (sizeof (struct spec_list));
165790277Sobrien      sl->name = xstrdup (name);
165850599Sobrien      sl->name_len = name_len;
165950599Sobrien      sl->ptr_spec = &sl->ptr;
166050599Sobrien      sl->alloc_p = 0;
166150599Sobrien      *(sl->ptr_spec) = "";
166218334Speter      sl->next = specs;
166318334Speter      specs = sl;
166418334Speter    }
166518334Speter
166650599Sobrien  old_spec = *(sl->ptr_spec);
166752520Sobrien  *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1]))
166890277Sobrien		     ? concat (old_spec, spec + 1, NULL)
166990277Sobrien		     : xstrdup (spec));
167018334Speter
167150599Sobrien#ifdef DEBUG_SPECS
167250599Sobrien  if (verbose_flag)
167352520Sobrien    notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
167450599Sobrien#endif
167550599Sobrien
167690277Sobrien  /* Free the old spec.  */
167750599Sobrien  if (old_spec && sl->alloc_p)
167890277Sobrien    free ((PTR) old_spec);
167950599Sobrien
168050599Sobrien  sl->alloc_p = 1;
168118334Speter}
168218334Speter
168318334Speter/* Accumulate a command (program name and args), and run it.  */
168418334Speter
168518334Speter/* Vector of pointers to arguments in the current line of specifications.  */
168618334Speter
168790277Sobrienstatic const char **argbuf;
168818334Speter
168918334Speter/* Number of elements allocated in argbuf.  */
169018334Speter
169118334Speterstatic int argbuf_length;
169218334Speter
169318334Speter/* Number of elements in argbuf currently in use (containing args).  */
169418334Speter
169518334Speterstatic int argbuf_index;
169618334Speter
169790277Sobrien/* This is the list of suffixes and codes (%g/%u/%U/%j) and the associated
169890277Sobrien   temp file.  If the HOST_BIT_BUCKET is used for %j, no entry is made for
169990277Sobrien   it here.  */
170050599Sobrien
170118334Speterstatic struct temp_name {
170252520Sobrien  const char *suffix;	/* suffix associated with the code.  */
170318334Speter  int length;		/* strlen (suffix).  */
170418334Speter  int unique;		/* Indicates whether %g or %u/%U was used.  */
170552520Sobrien  const char *filename;	/* associated filename.  */
170618334Speter  int filename_length;	/* strlen (filename).  */
170718334Speter  struct temp_name *next;
170818334Speter} *temp_names;
170918334Speter
171018334Speter/* Number of commands executed so far.  */
171118334Speter
171218334Speterstatic int execution_count;
171318334Speter
171418334Speter/* Number of commands that exited with a signal.  */
171518334Speter
171618334Speterstatic int signal_count;
171718334Speter
171818334Speter/* Name with which this program was invoked.  */
171918334Speter
172052520Sobrienstatic const char *programname;
172118334Speter
1722117413Skan/* Allocate the argument vector.  */
1723117413Skan
1724117413Skanstatic void
1725117413Skanalloc_args ()
1726117413Skan{
1727117413Skan  argbuf_length = 10;
1728117413Skan  argbuf = (const char **) xmalloc (argbuf_length * sizeof (const char *));
1729117413Skan}
1730117413Skan
173118334Speter/* Clear out the vector of arguments (after a command is executed).  */
173218334Speter
173318334Speterstatic void
173418334Speterclear_args ()
173518334Speter{
173618334Speter  argbuf_index = 0;
173718334Speter}
173818334Speter
173918334Speter/* Add one argument to the vector at the end.
174018334Speter   This is done when a space is seen or at the end of the line.
174118334Speter   If DELETE_ALWAYS is nonzero, the arg is a filename
174218334Speter    and the file should be deleted eventually.
174318334Speter   If DELETE_FAILURE is nonzero, the arg is a filename
174418334Speter    and the file should be deleted if this compilation fails.  */
174518334Speter
174618334Speterstatic void
174718334Speterstore_arg (arg, delete_always, delete_failure)
174890277Sobrien     const char *arg;
174918334Speter     int delete_always, delete_failure;
175018334Speter{
175118334Speter  if (argbuf_index + 1 == argbuf_length)
175250599Sobrien    argbuf
175390277Sobrien      = (const char **) xrealloc (argbuf,
175490277Sobrien				  (argbuf_length *= 2) * sizeof (const char *));
175518334Speter
175618334Speter  argbuf[argbuf_index++] = arg;
175718334Speter  argbuf[argbuf_index] = 0;
175818334Speter
175918334Speter  if (delete_always || delete_failure)
176018334Speter    record_temp_file (arg, delete_always, delete_failure);
176118334Speter}
176218334Speter
176390277Sobrien/* Load specs from a file name named FILENAME, replacing occurrences of
176490277Sobrien   various different types of line-endings, \r\n, \n\r and just \r, with
176590277Sobrien   a single \n.  */
176650599Sobrien
176790277Sobrienstatic char *
176890277Sobrienload_specs (filename)
176952520Sobrien     const char *filename;
177050599Sobrien{
177150599Sobrien  int desc;
177250599Sobrien  int readlen;
177350599Sobrien  struct stat statbuf;
177450599Sobrien  char *buffer;
177590277Sobrien  char *buffer_p;
177690277Sobrien  char *specs;
177790277Sobrien  char *specs_p;
177850599Sobrien
177950599Sobrien  if (verbose_flag)
178052520Sobrien    notice ("Reading specs from %s\n", filename);
178150599Sobrien
178250599Sobrien  /* Open and stat the file.  */
178350599Sobrien  desc = open (filename, O_RDONLY, 0);
178450599Sobrien  if (desc < 0)
178550599Sobrien    pfatal_with_name (filename);
178650599Sobrien  if (stat (filename, &statbuf) < 0)
178750599Sobrien    pfatal_with_name (filename);
178850599Sobrien
178950599Sobrien  /* Read contents of file into BUFFER.  */
179050599Sobrien  buffer = xmalloc ((unsigned) statbuf.st_size + 1);
179150599Sobrien  readlen = read (desc, buffer, (unsigned) statbuf.st_size);
179250599Sobrien  if (readlen < 0)
179350599Sobrien    pfatal_with_name (filename);
179450599Sobrien  buffer[readlen] = 0;
179550599Sobrien  close (desc);
179650599Sobrien
179790277Sobrien  specs = xmalloc (readlen + 1);
179890277Sobrien  specs_p = specs;
179990277Sobrien  for (buffer_p = buffer; buffer_p && *buffer_p; buffer_p++)
180090277Sobrien    {
180190277Sobrien      int skip = 0;
180290277Sobrien      char c = *buffer_p;
180390277Sobrien      if (c == '\r')
180490277Sobrien	{
180590277Sobrien	  if (buffer_p > buffer && *(buffer_p - 1) == '\n')	/* \n\r */
180690277Sobrien	    skip = 1;
180790277Sobrien	  else if (*(buffer_p + 1) == '\n')			/* \r\n */
180890277Sobrien	    skip = 1;
180990277Sobrien	  else							/* \r */
181090277Sobrien	    c = '\n';
181190277Sobrien	}
181290277Sobrien      if (! skip)
181390277Sobrien	*specs_p++ = c;
181490277Sobrien    }
181590277Sobrien  *specs_p = '\0';
181690277Sobrien
181790277Sobrien  free (buffer);
181890277Sobrien  return (specs);
181990277Sobrien}
182090277Sobrien
182190277Sobrien/* Read compilation specs from a file named FILENAME,
182290277Sobrien   replacing the default ones.
182390277Sobrien
182490277Sobrien   A suffix which starts with `*' is a definition for
182590277Sobrien   one of the machine-specific sub-specs.  The "suffix" should be
182696285Sobrien   *asm, *cc1, *cpp, *link, *startfile, etc.
182790277Sobrien   The corresponding spec is stored in asm_spec, etc.,
182890277Sobrien   rather than in the `compilers' vector.
182990277Sobrien
183090277Sobrien   Anything invalid in the file is a fatal error.  */
183190277Sobrien
183290277Sobrienstatic void
183390277Sobrienread_specs (filename, main_p)
183490277Sobrien     const char *filename;
183590277Sobrien     int main_p;
183690277Sobrien{
183790277Sobrien  char *buffer;
183890277Sobrien  char *p;
183990277Sobrien
184090277Sobrien  buffer = load_specs (filename);
184190277Sobrien
184250599Sobrien  /* Scan BUFFER for specs, putting them in the vector.  */
184350599Sobrien  p = buffer;
184450599Sobrien  while (1)
184550599Sobrien    {
184650599Sobrien      char *suffix;
184750599Sobrien      char *spec;
184850599Sobrien      char *in, *out, *p1, *p2, *p3;
184950599Sobrien
185050599Sobrien      /* Advance P in BUFFER to the next nonblank nocomment line.  */
185150599Sobrien      p = skip_whitespace (p);
185250599Sobrien      if (*p == 0)
185350599Sobrien	break;
185450599Sobrien
185550599Sobrien      /* Is this a special command that starts with '%'? */
185650599Sobrien      /* Don't allow this for the main specs file, since it would
185750599Sobrien	 encourage people to overwrite it.  */
185850599Sobrien      if (*p == '%' && !main_p)
185950599Sobrien	{
186050599Sobrien	  p1 = p;
186150599Sobrien	  while (*p && *p != '\n')
186250599Sobrien	    p++;
186350599Sobrien
186490277Sobrien	  /* Skip '\n'.  */
186590277Sobrien	  p++;
186650599Sobrien
186790277Sobrien	  if (!strncmp (p1, "%include", sizeof ("%include") - 1)
186850599Sobrien	      && (p1[sizeof "%include" - 1] == ' '
186950599Sobrien		  || p1[sizeof "%include" - 1] == '\t'))
187050599Sobrien	    {
187150599Sobrien	      char *new_filename;
187250599Sobrien
187350599Sobrien	      p1 += sizeof ("%include");
187450599Sobrien	      while (*p1 == ' ' || *p1 == '\t')
187550599Sobrien		p1++;
187650599Sobrien
187750599Sobrien	      if (*p1++ != '<' || p[-2] != '>')
187852520Sobrien		fatal ("specs %%include syntax malformed after %ld characters",
187952520Sobrien		       (long) (p1 - buffer + 1));
188050599Sobrien
188150599Sobrien	      p[-2] = '\0';
1882104763Skan	      new_filename = find_a_file (&startfile_prefixes, p1, R_OK, 0);
188350599Sobrien	      read_specs (new_filename ? new_filename : p1, FALSE);
188450599Sobrien	      continue;
188550599Sobrien	    }
188650599Sobrien	  else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1)
188750599Sobrien		   && (p1[sizeof "%include_noerr" - 1] == ' '
188850599Sobrien		       || p1[sizeof "%include_noerr" - 1] == '\t'))
188950599Sobrien	    {
189050599Sobrien	      char *new_filename;
189150599Sobrien
189250599Sobrien	      p1 += sizeof "%include_noerr";
189390277Sobrien	      while (*p1 == ' ' || *p1 == '\t')
189490277Sobrien		p1++;
189550599Sobrien
189650599Sobrien	      if (*p1++ != '<' || p[-2] != '>')
189752520Sobrien		fatal ("specs %%include syntax malformed after %ld characters",
189852520Sobrien		       (long) (p1 - buffer + 1));
189950599Sobrien
190050599Sobrien	      p[-2] = '\0';
1901104763Skan	      new_filename = find_a_file (&startfile_prefixes, p1, R_OK, 0);
190250599Sobrien	      if (new_filename)
190350599Sobrien		read_specs (new_filename, FALSE);
190450599Sobrien	      else if (verbose_flag)
190590277Sobrien		notice ("could not find specs file %s\n", p1);
190650599Sobrien	      continue;
190750599Sobrien	    }
190850599Sobrien	  else if (!strncmp (p1, "%rename", sizeof "%rename" - 1)
190950599Sobrien		   && (p1[sizeof "%rename" - 1] == ' '
191050599Sobrien		       || p1[sizeof "%rename" - 1] == '\t'))
191150599Sobrien	    {
191250599Sobrien	      int name_len;
191350599Sobrien	      struct spec_list *sl;
1914117413Skan	      struct spec_list *newsl;
191550599Sobrien
1916117413Skan	      /* Get original name.  */
191750599Sobrien	      p1 += sizeof "%rename";
191850599Sobrien	      while (*p1 == ' ' || *p1 == '\t')
191950599Sobrien		p1++;
192050599Sobrien
192190277Sobrien	      if (! ISALPHA ((unsigned char) *p1))
192252520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
192352520Sobrien		       (long) (p1 - buffer));
192450599Sobrien
192550599Sobrien	      p2 = p1;
192690277Sobrien	      while (*p2 && !ISSPACE ((unsigned char) *p2))
192750599Sobrien		p2++;
192850599Sobrien
192950599Sobrien	      if (*p2 != ' ' && *p2 != '\t')
193052520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
193152520Sobrien		       (long) (p2 - buffer));
193250599Sobrien
193350599Sobrien	      name_len = p2 - p1;
193450599Sobrien	      *p2++ = '\0';
193550599Sobrien	      while (*p2 == ' ' || *p2 == '\t')
193650599Sobrien		p2++;
193750599Sobrien
193890277Sobrien	      if (! ISALPHA ((unsigned char) *p2))
193952520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
194052520Sobrien		       (long) (p2 - buffer));
194150599Sobrien
194290277Sobrien	      /* Get new spec name.  */
194350599Sobrien	      p3 = p2;
194490277Sobrien	      while (*p3 && !ISSPACE ((unsigned char) *p3))
194550599Sobrien		p3++;
194650599Sobrien
194790277Sobrien	      if (p3 != p - 1)
194852520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
194952520Sobrien		       (long) (p3 - buffer));
195050599Sobrien	      *p3 = '\0';
195150599Sobrien
195250599Sobrien	      for (sl = specs; sl; sl = sl->next)
195350599Sobrien		if (name_len == sl->name_len && !strcmp (sl->name, p1))
195450599Sobrien		  break;
195550599Sobrien
195650599Sobrien	      if (!sl)
195750599Sobrien		fatal ("specs %s spec was not found to be renamed", p1);
195850599Sobrien
195950599Sobrien	      if (strcmp (p1, p2) == 0)
196050599Sobrien		continue;
196150599Sobrien
1962117413Skan	      for (newsl = specs; newsl; newsl = newsl->next)
1963117413Skan		if (strcmp (newsl->name, p2) == 0)
1964117413Skan		  fatal ("%s: attempt to rename spec '%s' to already defined spec '%s'",
1965117413Skan		    filename, p1, p2);
1966117413Skan
196750599Sobrien	      if (verbose_flag)
196850599Sobrien		{
196952520Sobrien		  notice ("rename spec %s to %s\n", p1, p2);
197050599Sobrien#ifdef DEBUG_SPECS
197152520Sobrien		  notice ("spec is '%s'\n\n", *(sl->ptr_spec));
197250599Sobrien#endif
197350599Sobrien		}
197450599Sobrien
197550599Sobrien	      set_spec (p2, *(sl->ptr_spec));
197650599Sobrien	      if (sl->alloc_p)
197790277Sobrien		free ((PTR) *(sl->ptr_spec));
197850599Sobrien
197950599Sobrien	      *(sl->ptr_spec) = "";
198050599Sobrien	      sl->alloc_p = 0;
198150599Sobrien	      continue;
198250599Sobrien	    }
198350599Sobrien	  else
198452520Sobrien	    fatal ("specs unknown %% command after %ld characters",
198552520Sobrien		   (long) (p1 - buffer));
198650599Sobrien	}
198750599Sobrien
198850599Sobrien      /* Find the colon that should end the suffix.  */
198950599Sobrien      p1 = p;
199050599Sobrien      while (*p1 && *p1 != ':' && *p1 != '\n')
199150599Sobrien	p1++;
199250599Sobrien
199350599Sobrien      /* The colon shouldn't be missing.  */
199450599Sobrien      if (*p1 != ':')
199552520Sobrien	fatal ("specs file malformed after %ld characters",
199652520Sobrien	       (long) (p1 - buffer));
199750599Sobrien
199850599Sobrien      /* Skip back over trailing whitespace.  */
199950599Sobrien      p2 = p1;
200050599Sobrien      while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t'))
200150599Sobrien	p2--;
200250599Sobrien
200350599Sobrien      /* Copy the suffix to a string.  */
200450599Sobrien      suffix = save_string (p, p2 - p);
200550599Sobrien      /* Find the next line.  */
200650599Sobrien      p = skip_whitespace (p1 + 1);
200750599Sobrien      if (p[1] == 0)
200852520Sobrien	fatal ("specs file malformed after %ld characters",
200952520Sobrien	       (long) (p - buffer));
201050599Sobrien
201150599Sobrien      p1 = p;
201250599Sobrien      /* Find next blank line or end of string.  */
201350599Sobrien      while (*p1 && !(*p1 == '\n' && (p1[1] == '\n' || p1[1] == '\0')))
201450599Sobrien	p1++;
201550599Sobrien
201650599Sobrien      /* Specs end at the blank line and do not include the newline.  */
201750599Sobrien      spec = save_string (p, p1 - p);
201850599Sobrien      p = p1;
201950599Sobrien
202050599Sobrien      /* Delete backslash-newline sequences from the spec.  */
202150599Sobrien      in = spec;
202250599Sobrien      out = spec;
202350599Sobrien      while (*in != 0)
202450599Sobrien	{
202550599Sobrien	  if (in[0] == '\\' && in[1] == '\n')
202650599Sobrien	    in += 2;
202750599Sobrien	  else if (in[0] == '#')
202850599Sobrien	    while (*in && *in != '\n')
202950599Sobrien	      in++;
203050599Sobrien
203150599Sobrien	  else
203250599Sobrien	    *out++ = *in++;
203350599Sobrien	}
203450599Sobrien      *out = 0;
203550599Sobrien
203650599Sobrien      if (suffix[0] == '*')
203750599Sobrien	{
203850599Sobrien	  if (! strcmp (suffix, "*link_command"))
203950599Sobrien	    link_command_spec = spec;
204050599Sobrien	  else
204150599Sobrien	    set_spec (suffix + 1, spec);
204250599Sobrien	}
204350599Sobrien      else
204450599Sobrien	{
204550599Sobrien	  /* Add this pair to the vector.  */
204650599Sobrien	  compilers
204750599Sobrien	    = ((struct compiler *)
204850599Sobrien	       xrealloc (compilers,
204950599Sobrien			 (n_compilers + 2) * sizeof (struct compiler)));
205050599Sobrien
205150599Sobrien	  compilers[n_compilers].suffix = suffix;
205290277Sobrien	  compilers[n_compilers].spec = spec;
205350599Sobrien	  n_compilers++;
205490277Sobrien	  memset (&compilers[n_compilers], 0, sizeof compilers[n_compilers]);
205550599Sobrien	}
205650599Sobrien
205750599Sobrien      if (*suffix == 0)
205850599Sobrien	link_command_spec = spec;
205950599Sobrien    }
206050599Sobrien
206150599Sobrien  if (link_command_spec == 0)
206250599Sobrien    fatal ("spec file has no spec for linking");
206350599Sobrien}
206450599Sobrien
206518334Speter/* Record the names of temporary files we tell compilers to write,
206618334Speter   and delete them at the end of the run.  */
206718334Speter
206818334Speter/* This is the common prefix we use to make temp file names.
206918334Speter   It is chosen once for each run of this program.
207090277Sobrien   It is substituted into a spec by %g or %j.
207118334Speter   Thus, all temp file names contain this prefix.
207218334Speter   In practice, all temp file names start with this prefix.
207318334Speter
207418334Speter   This prefix comes from the envvar TMPDIR if it is defined;
207518334Speter   otherwise, from the P_tmpdir macro if that is defined;
207650599Sobrien   otherwise, in /usr/tmp or /tmp;
207750599Sobrien   or finally the current directory if all else fails.  */
207818334Speter
207952520Sobrienstatic const char *temp_filename;
208018334Speter
208118334Speter/* Length of the prefix.  */
208218334Speter
208318334Speterstatic int temp_filename_length;
208418334Speter
208518334Speter/* Define the list of temporary files to delete.  */
208618334Speter
208718334Speterstruct temp_file
208818334Speter{
208952520Sobrien  const char *name;
209018334Speter  struct temp_file *next;
209118334Speter};
209218334Speter
209318334Speter/* Queue of files to delete on success or failure of compilation.  */
209418334Speterstatic struct temp_file *always_delete_queue;
209518334Speter/* Queue of files to delete on failure of compilation.  */
209618334Speterstatic struct temp_file *failure_delete_queue;
209718334Speter
209818334Speter/* Record FILENAME as a file to be deleted automatically.
209918334Speter   ALWAYS_DELETE nonzero means delete it if all compilation succeeds;
210018334Speter   otherwise delete it in any case.
210118334Speter   FAIL_DELETE nonzero means delete it if a compilation step fails;
210218334Speter   otherwise delete it in any case.  */
210318334Speter
210490277Sobrienvoid
210518334Speterrecord_temp_file (filename, always_delete, fail_delete)
210652520Sobrien     const char *filename;
210718334Speter     int always_delete;
210818334Speter     int fail_delete;
210918334Speter{
211090277Sobrien  char *const name = xstrdup (filename);
211118334Speter
211218334Speter  if (always_delete)
211318334Speter    {
211490277Sobrien      struct temp_file *temp;
211518334Speter      for (temp = always_delete_queue; temp; temp = temp->next)
211618334Speter	if (! strcmp (name, temp->name))
211718334Speter	  goto already1;
211850599Sobrien
211918334Speter      temp = (struct temp_file *) xmalloc (sizeof (struct temp_file));
212018334Speter      temp->next = always_delete_queue;
212118334Speter      temp->name = name;
212218334Speter      always_delete_queue = temp;
212350599Sobrien
212418334Speter    already1:;
212518334Speter    }
212618334Speter
212718334Speter  if (fail_delete)
212818334Speter    {
212990277Sobrien      struct temp_file *temp;
213018334Speter      for (temp = failure_delete_queue; temp; temp = temp->next)
213118334Speter	if (! strcmp (name, temp->name))
213218334Speter	  goto already2;
213350599Sobrien
213418334Speter      temp = (struct temp_file *) xmalloc (sizeof (struct temp_file));
213518334Speter      temp->next = failure_delete_queue;
213618334Speter      temp->name = name;
213718334Speter      failure_delete_queue = temp;
213850599Sobrien
213918334Speter    already2:;
214018334Speter    }
214118334Speter}
214218334Speter
214318334Speter/* Delete all the temporary files whose names we previously recorded.  */
214418334Speter
214518334Speterstatic void
214618334Speterdelete_if_ordinary (name)
214752520Sobrien     const char *name;
214818334Speter{
214918334Speter  struct stat st;
215018334Speter#ifdef DEBUG
215118334Speter  int i, c;
215218334Speter
215318334Speter  printf ("Delete %s? (y or n) ", name);
215418334Speter  fflush (stdout);
215518334Speter  i = getchar ();
215618334Speter  if (i != '\n')
215750599Sobrien    while ((c = getchar ()) != '\n' && c != EOF)
215850599Sobrien      ;
215950599Sobrien
216018334Speter  if (i == 'y' || i == 'Y')
216118334Speter#endif /* DEBUG */
216218334Speter    if (stat (name, &st) >= 0 && S_ISREG (st.st_mode))
216318334Speter      if (unlink (name) < 0)
216418334Speter	if (verbose_flag)
216518334Speter	  perror_with_name (name);
216618334Speter}
216718334Speter
216818334Speterstatic void
216918334Speterdelete_temp_files ()
217018334Speter{
217190277Sobrien  struct temp_file *temp;
217218334Speter
217318334Speter  for (temp = always_delete_queue; temp; temp = temp->next)
217418334Speter    delete_if_ordinary (temp->name);
217518334Speter  always_delete_queue = 0;
217618334Speter}
217718334Speter
217818334Speter/* Delete all the files to be deleted on error.  */
217918334Speter
218018334Speterstatic void
218118334Speterdelete_failure_queue ()
218218334Speter{
218390277Sobrien  struct temp_file *temp;
218418334Speter
218518334Speter  for (temp = failure_delete_queue; temp; temp = temp->next)
218618334Speter    delete_if_ordinary (temp->name);
218718334Speter}
218818334Speter
218918334Speterstatic void
219018334Speterclear_failure_queue ()
219118334Speter{
219218334Speter  failure_delete_queue = 0;
219318334Speter}
219418334Speter
219518334Speter/* Build a list of search directories from PATHS.
219618334Speter   PREFIX is a string to prepend to the list.
2197117413Skan   If CHECK_DIR_P is nonzero we ensure the directory exists.
219818334Speter   This is used mostly by putenv_from_prefixes so we use `collect_obstack'.
219918334Speter   It is also used by the --print-search-dirs flag.  */
220018334Speter
220118334Speterstatic char *
220218334Speterbuild_search_list (paths, prefix, check_dir_p)
220318334Speter     struct path_prefix *paths;
220452520Sobrien     const char *prefix;
220518334Speter     int check_dir_p;
220618334Speter{
220718334Speter  int suffix_len = (machine_suffix) ? strlen (machine_suffix) : 0;
220818334Speter  int just_suffix_len
220918334Speter    = (just_machine_suffix) ? strlen (just_machine_suffix) : 0;
221018334Speter  int first_time = TRUE;
221118334Speter  struct prefix_list *pprefix;
221218334Speter
221318334Speter  obstack_grow (&collect_obstack, prefix, strlen (prefix));
221490277Sobrien  obstack_1grow (&collect_obstack, '=');
221518334Speter
221618334Speter  for (pprefix = paths->plist; pprefix != 0; pprefix = pprefix->next)
221718334Speter    {
221818334Speter      int len = strlen (pprefix->prefix);
221918334Speter
222018334Speter      if (machine_suffix
222150599Sobrien	  && (! check_dir_p
222218334Speter	      || is_directory (pprefix->prefix, machine_suffix, 0)))
222318334Speter	{
222418334Speter	  if (!first_time)
222518334Speter	    obstack_1grow (&collect_obstack, PATH_SEPARATOR);
222690277Sobrien
222718334Speter	  first_time = FALSE;
222818334Speter	  obstack_grow (&collect_obstack, pprefix->prefix, len);
222918334Speter	  obstack_grow (&collect_obstack, machine_suffix, suffix_len);
223018334Speter	}
223118334Speter
223218334Speter      if (just_machine_suffix
223318334Speter	  && pprefix->require_machine_suffix == 2
223450599Sobrien	  && (! check_dir_p
223518334Speter	      || is_directory (pprefix->prefix, just_machine_suffix, 0)))
223618334Speter	{
223750599Sobrien	  if (! first_time)
223818334Speter	    obstack_1grow (&collect_obstack, PATH_SEPARATOR);
223990277Sobrien
224018334Speter	  first_time = FALSE;
224118334Speter	  obstack_grow (&collect_obstack, pprefix->prefix, len);
224218334Speter	  obstack_grow (&collect_obstack, just_machine_suffix,
224318334Speter			just_suffix_len);
224418334Speter	}
224518334Speter
224650599Sobrien      if (! pprefix->require_machine_suffix)
224718334Speter	{
224850599Sobrien	  if (! first_time)
224918334Speter	    obstack_1grow (&collect_obstack, PATH_SEPARATOR);
225018334Speter
225118334Speter	  first_time = FALSE;
225218334Speter	  obstack_grow (&collect_obstack, pprefix->prefix, len);
225318334Speter	}
225418334Speter    }
225550599Sobrien
225618334Speter  obstack_1grow (&collect_obstack, '\0');
225718334Speter  return obstack_finish (&collect_obstack);
225818334Speter}
225918334Speter
226050599Sobrien/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
226150599Sobrien   for collect.  */
226218334Speter
226318334Speterstatic void
226418334Speterputenv_from_prefixes (paths, env_var)
226518334Speter     struct path_prefix *paths;
226652520Sobrien     const char *env_var;
226718334Speter{
226818334Speter  putenv (build_search_list (paths, env_var, 1));
226918334Speter}
227018334Speter
227190277Sobrien/* Check whether NAME can be accessed in MODE.  This is like access,
227290277Sobrien   except that it never considers directories to be executable.  */
227390277Sobrien
227490277Sobrienstatic int
227590277Sobrienaccess_check (name, mode)
227690277Sobrien     const char *name;
227790277Sobrien     int mode;
227890277Sobrien{
227990277Sobrien  if (mode == X_OK)
228090277Sobrien    {
228190277Sobrien      struct stat st;
228290277Sobrien
228390277Sobrien      if (stat (name, &st) < 0
228490277Sobrien	  || S_ISDIR (st.st_mode))
228590277Sobrien	return -1;
228690277Sobrien    }
228790277Sobrien
228890277Sobrien  return access (name, mode);
228990277Sobrien}
229090277Sobrien
229118334Speter/* Search for NAME using the prefix list PREFIXES.  MODE is passed to
229218334Speter   access to check permissions.
229350599Sobrien   Return 0 if not found, otherwise return its name, allocated with malloc.  */
229418334Speter
229518334Speterstatic char *
2296104763Skanfind_a_file (pprefix, name, mode, multilib)
229718334Speter     struct path_prefix *pprefix;
229852520Sobrien     const char *name;
2299104763Skan     int mode, multilib;
230018334Speter{
230118334Speter  char *temp;
230290277Sobrien  const char *const file_suffix =
230390277Sobrien    ((mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : "");
230418334Speter  struct prefix_list *pl;
230518334Speter  int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1;
2306104763Skan  const char *multilib_name, *multilib_os_name;
230718334Speter
230852520Sobrien#ifdef DEFAULT_ASSEMBLER
230990277Sobrien  if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0)
231090277Sobrien    return xstrdup (DEFAULT_ASSEMBLER);
231152520Sobrien#endif
231252520Sobrien
231352520Sobrien#ifdef DEFAULT_LINKER
231490277Sobrien  if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0)
231590277Sobrien    return xstrdup (DEFAULT_LINKER);
231652520Sobrien#endif
231752520Sobrien
231818334Speter  if (machine_suffix)
231918334Speter    len += strlen (machine_suffix);
232018334Speter
2321104763Skan  multilib_name = name;
2322104763Skan  multilib_os_name = name;
2323104763Skan  if (multilib && multilib_os_dir)
2324104763Skan    {
2325104763Skan      int len1 = multilib_dir ? strlen (multilib_dir) + 1 : 0;
2326104763Skan      int len2 = strlen (multilib_os_dir) + 1;
2327104763Skan
2328104763Skan      len += len1 > len2 ? len1 : len2;
2329104763Skan      if (multilib_dir)
2330104763Skan	multilib_name = ACONCAT ((multilib_dir, dir_separator_str, name,
2331104763Skan				  NULL));
2332104763Skan      if (strcmp (multilib_os_dir, ".") != 0)
2333104763Skan	multilib_os_name = ACONCAT ((multilib_os_dir, dir_separator_str, name,
2334104763Skan				    NULL));
2335104763Skan    }
2336104763Skan
233718334Speter  temp = xmalloc (len);
233818334Speter
233918334Speter  /* Determine the filename to execute (special case for absolute paths).  */
234018334Speter
234190277Sobrien  if (IS_ABSOLUTE_PATHNAME (name))
234218334Speter    {
234352520Sobrien      if (access (name, mode) == 0)
234418334Speter	{
234518334Speter	  strcpy (temp, name);
234618334Speter	  return temp;
234718334Speter	}
234818334Speter    }
234918334Speter  else
235018334Speter    for (pl = pprefix->plist; pl; pl = pl->next)
235118334Speter      {
2352104763Skan	const char *this_name
2353104763Skan	  = pl->os_multilib ? multilib_os_name : multilib_name;
2354104763Skan
235518334Speter	if (machine_suffix)
235618334Speter	  {
235718334Speter	    /* Some systems have a suffix for executable files.
235818334Speter	       So try appending that first.  */
235918334Speter	    if (file_suffix[0] != 0)
236018334Speter	      {
236118334Speter		strcpy (temp, pl->prefix);
236218334Speter		strcat (temp, machine_suffix);
2363104763Skan		strcat (temp, multilib_name);
236418334Speter		strcat (temp, file_suffix);
236590277Sobrien		if (access_check (temp, mode) == 0)
236618334Speter		  {
236718334Speter		    if (pl->used_flag_ptr != 0)
236818334Speter		      *pl->used_flag_ptr = 1;
236918334Speter		    return temp;
237018334Speter		  }
237118334Speter	      }
237218334Speter
2373104763Skan	    /* Now try just the multilib_name.  */
237418334Speter	    strcpy (temp, pl->prefix);
237518334Speter	    strcat (temp, machine_suffix);
2376104763Skan	    strcat (temp, multilib_name);
237790277Sobrien	    if (access_check (temp, mode) == 0)
237818334Speter	      {
237918334Speter		if (pl->used_flag_ptr != 0)
238018334Speter		  *pl->used_flag_ptr = 1;
238118334Speter		return temp;
238218334Speter	      }
238318334Speter	  }
238418334Speter
238518334Speter	/* Certain prefixes are tried with just the machine type,
238618334Speter	   not the version.  This is used for finding as, ld, etc.  */
238718334Speter	if (just_machine_suffix && pl->require_machine_suffix == 2)
238818334Speter	  {
238918334Speter	    /* Some systems have a suffix for executable files.
239018334Speter	       So try appending that first.  */
239118334Speter	    if (file_suffix[0] != 0)
239218334Speter	      {
239318334Speter		strcpy (temp, pl->prefix);
239418334Speter		strcat (temp, just_machine_suffix);
2395104763Skan		strcat (temp, multilib_name);
239618334Speter		strcat (temp, file_suffix);
239790277Sobrien		if (access_check (temp, mode) == 0)
239818334Speter		  {
239918334Speter		    if (pl->used_flag_ptr != 0)
240018334Speter		      *pl->used_flag_ptr = 1;
240118334Speter		    return temp;
240218334Speter		  }
240318334Speter	      }
240418334Speter
240518334Speter	    strcpy (temp, pl->prefix);
240618334Speter	    strcat (temp, just_machine_suffix);
2407104763Skan	    strcat (temp, multilib_name);
240890277Sobrien	    if (access_check (temp, mode) == 0)
240918334Speter	      {
241018334Speter		if (pl->used_flag_ptr != 0)
241118334Speter		  *pl->used_flag_ptr = 1;
241218334Speter		return temp;
241318334Speter	      }
241418334Speter	  }
241518334Speter
241618334Speter	/* Certain prefixes can't be used without the machine suffix
241718334Speter	   when the machine or version is explicitly specified.  */
241850599Sobrien	if (! pl->require_machine_suffix)
241918334Speter	  {
242018334Speter	    /* Some systems have a suffix for executable files.
242118334Speter	       So try appending that first.  */
242218334Speter	    if (file_suffix[0] != 0)
242318334Speter	      {
242418334Speter		strcpy (temp, pl->prefix);
2425104763Skan		strcat (temp, this_name);
242618334Speter		strcat (temp, file_suffix);
242790277Sobrien		if (access_check (temp, mode) == 0)
242818334Speter		  {
242918334Speter		    if (pl->used_flag_ptr != 0)
243018334Speter		      *pl->used_flag_ptr = 1;
243118334Speter		    return temp;
243218334Speter		  }
243318334Speter	      }
243418334Speter
243518334Speter	    strcpy (temp, pl->prefix);
2436104763Skan	    strcat (temp, this_name);
243790277Sobrien	    if (access_check (temp, mode) == 0)
243818334Speter	      {
243918334Speter		if (pl->used_flag_ptr != 0)
244018334Speter		  *pl->used_flag_ptr = 1;
244118334Speter		return temp;
244218334Speter	      }
244318334Speter	  }
244418334Speter      }
244518334Speter
244618334Speter  free (temp);
244718334Speter  return 0;
244818334Speter}
244918334Speter
245090277Sobrien/* Ranking of prefixes in the sort list. -B prefixes are put before
245190277Sobrien   all others.  */
245218334Speter
245390277Sobrienenum path_prefix_priority
245490277Sobrien{
245590277Sobrien  PREFIX_PRIORITY_B_OPT,
245690277Sobrien  PREFIX_PRIORITY_LAST
245790277Sobrien};
245890277Sobrien
245990277Sobrien/* Add an entry for PREFIX in PLIST.  The PLIST is kept in assending
246090277Sobrien   order according to PRIORITY.  Within each PRIORITY, new entries are
246190277Sobrien   appended.
246290277Sobrien
246318334Speter   If WARN is nonzero, we will warn if no file is found
246418334Speter   through this prefix.  WARN should point to an int
246518334Speter   which will be set to 1 if this entry is used.
246618334Speter
246750599Sobrien   COMPONENT is the value to be passed to update_path.
246850599Sobrien
246918334Speter   REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without
247018334Speter   the complete value of machine_suffix.
247118334Speter   2 means try both machine_suffix and just_machine_suffix.  */
247218334Speter
247318334Speterstatic void
2474104763Skanadd_prefix (pprefix, prefix, component, priority, require_machine_suffix,
2475104763Skan	    warn, os_multilib)
247618334Speter     struct path_prefix *pprefix;
247752520Sobrien     const char *prefix;
247852520Sobrien     const char *component;
247990277Sobrien     /* enum prefix_priority */ int priority;
248018334Speter     int require_machine_suffix;
248118334Speter     int *warn;
2482104763Skan     int os_multilib;
248318334Speter{
248418334Speter  struct prefix_list *pl, **prev;
248518334Speter  int len;
248618334Speter
248790277Sobrien  for (prev = &pprefix->plist;
248890277Sobrien       (*prev) != NULL && (*prev)->priority <= priority;
248990277Sobrien       prev = &(*prev)->next)
249090277Sobrien    ;
249118334Speter
249218334Speter  /* Keep track of the longest prefix */
249318334Speter
249450599Sobrien  prefix = update_path (prefix, component);
249518334Speter  len = strlen (prefix);
249618334Speter  if (len > pprefix->max_len)
249718334Speter    pprefix->max_len = len;
249818334Speter
249918334Speter  pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
250090277Sobrien  pl->prefix = prefix;
250118334Speter  pl->require_machine_suffix = require_machine_suffix;
250218334Speter  pl->used_flag_ptr = warn;
250390277Sobrien  pl->priority = priority;
2504104763Skan  pl->os_multilib = os_multilib;
250518334Speter  if (warn)
250618334Speter    *warn = 0;
250718334Speter
250890277Sobrien  /* Insert after PREV */
250990277Sobrien  pl->next = (*prev);
251090277Sobrien  (*prev) = pl;
251118334Speter}
251218334Speter
251318334Speter/* Execute the command specified by the arguments on the current line of spec.
251418334Speter   When using pipes, this includes several piped-together commands
251518334Speter   with `|' between them.
251618334Speter
251718334Speter   Return 0 if successful, -1 if failed.  */
251818334Speter
251918334Speterstatic int
252018334Speterexecute ()
252118334Speter{
252218334Speter  int i;
252318334Speter  int n_commands;		/* # of command.  */
252418334Speter  char *string;
252518334Speter  struct command
252690277Sobrien  {
252790277Sobrien    const char *prog;		/* program name.  */
252890277Sobrien    const char **argv;		/* vector of args.  */
252990277Sobrien    int pid;			/* pid of process for this command.  */
253090277Sobrien  };
253118334Speter
253218334Speter  struct command *commands;	/* each command buffer with above info.  */
253318334Speter
2534117413Skan  if (processing_spec_function)
2535117413Skan    abort ();
2536117413Skan
253718334Speter  /* Count # of piped commands.  */
253818334Speter  for (n_commands = 1, i = 0; i < argbuf_index; i++)
253918334Speter    if (strcmp (argbuf[i], "|") == 0)
254018334Speter      n_commands++;
254118334Speter
254218334Speter  /* Get storage for each command.  */
254390277Sobrien  commands = (struct command *) alloca (n_commands * sizeof (struct command));
254418334Speter
254518334Speter  /* Split argbuf into its separate piped processes,
254618334Speter     and record info about each one.
254718334Speter     Also search for the programs that are to be run.  */
254818334Speter
254918334Speter  commands[0].prog = argbuf[0]; /* first command.  */
255018334Speter  commands[0].argv = &argbuf[0];
2551104763Skan  string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, 0);
255250599Sobrien
255318334Speter  if (string)
255418334Speter    commands[0].argv[0] = string;
255518334Speter
255618334Speter  for (n_commands = 1, i = 0; i < argbuf_index; i++)
255718334Speter    if (strcmp (argbuf[i], "|") == 0)
255818334Speter      {				/* each command.  */
255952520Sobrien#if defined (__MSDOS__) || defined (OS2) || defined (VMS)
256090277Sobrien	fatal ("-pipe not supported");
256118334Speter#endif
256218334Speter	argbuf[i] = 0;	/* termination of command args.  */
256318334Speter	commands[n_commands].prog = argbuf[i + 1];
256418334Speter	commands[n_commands].argv = &argbuf[i + 1];
2565104763Skan	string = find_a_file (&exec_prefixes, commands[n_commands].prog,
2566104763Skan			      X_OK, 0);
256718334Speter	if (string)
256818334Speter	  commands[n_commands].argv[0] = string;
256918334Speter	n_commands++;
257018334Speter      }
257118334Speter
257218334Speter  argbuf[argbuf_index] = 0;
257318334Speter
257418334Speter  /* If -v, print what we are about to do, and maybe query.  */
257518334Speter
257618334Speter  if (verbose_flag)
257718334Speter    {
257850599Sobrien      /* For help listings, put a blank line between sub-processes.  */
257950599Sobrien      if (print_help_list)
258050599Sobrien	fputc ('\n', stderr);
258190277Sobrien
258218334Speter      /* Print each piped command as a separate line.  */
258390277Sobrien      for (i = 0; i < n_commands; i++)
258418334Speter	{
258590277Sobrien	  const char *const *j;
258618334Speter
2587117413Skan	  if (verbose_only_flag)
2588117413Skan	    {
258990277Sobrien	      for (j = commands[i].argv; *j; j++)
259090277Sobrien		{
259190277Sobrien		  const char *p;
259290277Sobrien		  fprintf (stderr, " \"");
259390277Sobrien		  for (p = *j; *p; ++p)
259490277Sobrien		    {
259590277Sobrien		      if (*p == '"' || *p == '\\' || *p == '$')
259690277Sobrien			fputc ('\\', stderr);
259790277Sobrien		      fputc (*p, stderr);
259890277Sobrien		    }
259990277Sobrien		  fputc ('"', stderr);
260090277Sobrien		}
2601117413Skan	    }
2602117413Skan	  else
260390277Sobrien	    for (j = commands[i].argv; *j; j++)
260490277Sobrien	      fprintf (stderr, " %s", *j);
260518334Speter
260618334Speter	  /* Print a pipe symbol after all but the last command.  */
260718334Speter	  if (i + 1 != n_commands)
260818334Speter	    fprintf (stderr, " |");
260918334Speter	  fprintf (stderr, "\n");
261018334Speter	}
261118334Speter      fflush (stderr);
261290277Sobrien      if (verbose_only_flag != 0)
2613117413Skan	return 0;
261418334Speter#ifdef DEBUG
261552520Sobrien      notice ("\nGo ahead? (y or n) ");
261618334Speter      fflush (stderr);
261718334Speter      i = getchar ();
261818334Speter      if (i != '\n')
261950599Sobrien	while (getchar () != '\n')
262050599Sobrien	  ;
262150599Sobrien
262218334Speter      if (i != 'y' && i != 'Y')
262318334Speter	return 0;
262418334Speter#endif /* DEBUG */
262518334Speter    }
262618334Speter
2627117413Skan#ifdef ENABLE_VALGRIND_CHECKING
2628117413Skan  /* Run the each command through valgrind.  To simplifiy prepending the
2629117413Skan     path to valgrind and the option "-q" (for quiet operation unless
2630117413Skan     something triggers), we allocate a separate argv array.  */
2631117413Skan
2632117413Skan  for (i = 0; i < n_commands; i++)
2633117413Skan    {
2634117413Skan      const char **argv;
2635117413Skan      int argc;
2636117413Skan      int j;
2637117413Skan
2638117413Skan      for (argc = 0; commands[i].argv[argc] != NULL; argc++)
2639117413Skan	;
2640117413Skan
2641117413Skan      argv = alloca ((argc + 3) * sizeof (char *));
2642117413Skan
2643117413Skan      argv[0] = VALGRIND_PATH;
2644117413Skan      argv[1] = "-q";
2645117413Skan      for (j = 2; j < argc + 2; j++)
2646117413Skan	argv[j] = commands[i].argv[j - 2];
2647117413Skan      argv[j] = NULL;
2648117413Skan
2649117413Skan      commands[i].argv = argv;
2650117413Skan      commands[i].prog = argv[0];
2651117413Skan    }
2652117413Skan#endif
2653117413Skan
265418334Speter  /* Run each piped subprocess.  */
265518334Speter
265618334Speter  for (i = 0; i < n_commands; i++)
265718334Speter    {
265850599Sobrien      char *errmsg_fmt, *errmsg_arg;
265990277Sobrien      const char *string = commands[i].argv[0];
266018334Speter
266190277Sobrien      /* For some bizarre reason, the second argument of execvp() is
266290277Sobrien	 char *const *, not const char *const *.  */
266390277Sobrien      commands[i].pid = pexecute (string, (char *const *) commands[i].argv,
266450599Sobrien				  programname, temp_filename,
266550599Sobrien				  &errmsg_fmt, &errmsg_arg,
266650599Sobrien				  ((i == 0 ? PEXECUTE_FIRST : 0)
266750599Sobrien				   | (i + 1 == n_commands ? PEXECUTE_LAST : 0)
266850599Sobrien				   | (string == commands[i].prog
266950599Sobrien				      ? PEXECUTE_SEARCH : 0)
267050599Sobrien				   | (verbose_flag ? PEXECUTE_VERBOSE : 0)));
267118334Speter
267250599Sobrien      if (commands[i].pid == -1)
267350599Sobrien	pfatal_pexecute (errmsg_fmt, errmsg_arg);
267450599Sobrien
267518334Speter      if (string != commands[i].prog)
267690277Sobrien	free ((PTR) string);
267718334Speter    }
267818334Speter
267918334Speter  execution_count++;
268018334Speter
268118334Speter  /* Wait for all the subprocesses to finish.
268218334Speter     We don't care what order they finish in;
268318334Speter     we know that N_COMMANDS waits will get them all.
268418334Speter     Ignore subprocesses that we don't know about,
268518334Speter     since they can be spawned by the process that exec'ed us.  */
268618334Speter
268718334Speter  {
268818334Speter    int ret_code = 0;
268990277Sobrien#ifdef HAVE_GETRUSAGE
269090277Sobrien    struct timeval d;
269190277Sobrien    double ut = 0.0, st = 0.0;
269290277Sobrien#endif
269318334Speter
269490277Sobrien    for (i = 0; i < n_commands;)
269518334Speter      {
269618334Speter	int j;
269718334Speter	int status;
269818334Speter	int pid;
269918334Speter
270050599Sobrien	pid = pwait (commands[i].pid, &status, 0);
270118334Speter	if (pid < 0)
270218334Speter	  abort ();
270318334Speter
270490277Sobrien#ifdef HAVE_GETRUSAGE
270590277Sobrien	if (report_times)
270690277Sobrien	  {
270790277Sobrien	    /* getrusage returns the total resource usage of all children
270890277Sobrien	       up to now.  Copy the previous values into prus, get the
270990277Sobrien	       current statistics, then take the difference.  */
271090277Sobrien
271190277Sobrien	    prus = rus;
271290277Sobrien	    getrusage (RUSAGE_CHILDREN, &rus);
271390277Sobrien	    d.tv_sec = rus.ru_utime.tv_sec - prus.ru_utime.tv_sec;
271490277Sobrien	    d.tv_usec = rus.ru_utime.tv_usec - prus.ru_utime.tv_usec;
271590277Sobrien	    ut = (double) d.tv_sec + (double) d.tv_usec / 1.0e6;
271690277Sobrien
271790277Sobrien	    d.tv_sec = rus.ru_stime.tv_sec - prus.ru_stime.tv_sec;
271890277Sobrien	    d.tv_usec = rus.ru_stime.tv_usec - prus.ru_stime.tv_usec;
271990277Sobrien	    st = (double) d.tv_sec + (double) d.tv_usec / 1.0e6;
272090277Sobrien	  }
272190277Sobrien#endif
272290277Sobrien
272318334Speter	for (j = 0; j < n_commands; j++)
272418334Speter	  if (commands[j].pid == pid)
272518334Speter	    {
272618334Speter	      i++;
272790277Sobrien	      if (WIFSIGNALED (status))
272818334Speter		{
272990277Sobrien#ifdef SIGPIPE
273090277Sobrien		  /* SIGPIPE is a special case.  It happens in -pipe mode
273190277Sobrien		     when the compiler dies before the preprocessor is
273290277Sobrien		     done, or the assembler dies before the compiler is
273390277Sobrien		     done.  There's generally been an error already, and
273490277Sobrien		     this is just fallout.  So don't generate another error
273590277Sobrien		     unless we would otherwise have succeeded.  */
273690277Sobrien		  if (WTERMSIG (status) == SIGPIPE
273790277Sobrien		      && (signal_count || greatest_status >= MIN_FATAL_STATUS))
273890277Sobrien		    ;
273990277Sobrien		  else
274090277Sobrien#endif
274190277Sobrien		    fatal ("\
274290277SobrienInternal error: %s (program %s)\n\
274390277SobrienPlease submit a full bug report.\n\
274490277SobrienSee %s for instructions.",
274590277Sobrien			   strsignal (WTERMSIG (status)), commands[j].prog,
2746117413Skan			   bug_report_url);
274790277Sobrien		  signal_count++;
274890277Sobrien		  ret_code = -1;
274918334Speter		}
275090277Sobrien	      else if (WIFEXITED (status)
275190277Sobrien		       && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
275290277Sobrien		{
275390277Sobrien		  if (WEXITSTATUS (status) > greatest_status)
275490277Sobrien		    greatest_status = WEXITSTATUS (status);
275590277Sobrien		  ret_code = -1;
275690277Sobrien		}
275790277Sobrien#ifdef HAVE_GETRUSAGE
275890277Sobrien	      if (report_times && ut + st != 0)
275990277Sobrien		notice ("# %s %.2f %.2f\n", commands[j].prog, ut, st);
276090277Sobrien#endif
276118334Speter	      break;
276218334Speter	    }
276318334Speter      }
276418334Speter    return ret_code;
276518334Speter  }
276618334Speter}
276718334Speter
276818334Speter/* Find all the switches given to us
276918334Speter   and make a vector describing them.
277018334Speter   The elements of the vector are strings, one per switch given.
277118334Speter   If a switch uses following arguments, then the `part1' field
277218334Speter   is the switch itself and the `args' field
277318334Speter   is a null-terminated vector containing the following arguments.
277490277Sobrien   The `live_cond' field is:
277590277Sobrien   0 when initialized
277690277Sobrien   1 if the switch is true in a conditional spec,
277790277Sobrien   -1 if false (overridden by a later switch)
277890277Sobrien   -2 if this switch should be ignored (used in %{<S})
277952520Sobrien   The `validated' field is nonzero if any spec has looked at this switch;
278018334Speter   if it remains zero at the end of the run, it must be meaningless.  */
278118334Speter
278290277Sobrien#define SWITCH_OK       0
278390277Sobrien#define SWITCH_FALSE   -1
278490277Sobrien#define SWITCH_IGNORE  -2
278590277Sobrien#define SWITCH_LIVE     1
278690277Sobrien
278718334Speterstruct switchstr
278818334Speter{
278952520Sobrien  const char *part1;
279090277Sobrien  const char **args;
279118334Speter  int live_cond;
279290277Sobrien  unsigned char validated;
279390277Sobrien  unsigned char ordering;
279418334Speter};
279518334Speter
279618334Speterstatic struct switchstr *switches;
279718334Speter
279818334Speterstatic int n_switches;
279918334Speter
280018334Speterstruct infile
280118334Speter{
280252520Sobrien  const char *name;
280352520Sobrien  const char *language;
280418334Speter};
280518334Speter
280618334Speter/* Also a vector of input files specified.  */
280718334Speter
280818334Speterstatic struct infile *infiles;
280918334Speter
281090277Sobrienint n_infiles;
281118334Speter
281252520Sobrien/* This counts the number of libraries added by lang_specific_driver, so that
281350599Sobrien   we can tell if there were any user supplied any files or libraries.  */
281450599Sobrien
281550599Sobrienstatic int added_libraries;
281650599Sobrien
281718334Speter/* And a vector of corresponding output files is made up later.  */
281818334Speter
281990277Sobrienconst char **outfiles;
282018334Speter
282150599Sobrien/* Used to track if none of the -B paths are used.  */
282250599Sobrienstatic int warn_B;
282350599Sobrien
282450599Sobrien/* Gives value to pass as "warn" to add_prefix for standard prefixes.  */
282550599Sobrienstatic int *warn_std_ptr = 0;
282650599Sobrien
282790277Sobrien#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
282850599Sobrien
282950599Sobrien/* Convert NAME to a new name if it is the standard suffix.  DO_EXE
283090277Sobrien   is true if we should look for an executable suffix.  DO_OBJ
283190277Sobrien   is true if we should look for an object suffix.  */
283250599Sobrien
283390277Sobrienstatic const char *
283490277Sobrienconvert_filename (name, do_exe, do_obj)
283590277Sobrien     const char *name;
283690277Sobrien     int do_exe ATTRIBUTE_UNUSED;
283790277Sobrien     int do_obj ATTRIBUTE_UNUSED;
283850599Sobrien{
283990277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
284050599Sobrien  int i;
284190277Sobrien#endif
284252520Sobrien  int len;
284350599Sobrien
284452520Sobrien  if (name == NULL)
284552520Sobrien    return NULL;
284690277Sobrien
284752520Sobrien  len = strlen (name);
284852520Sobrien
284990277Sobrien#ifdef HAVE_TARGET_OBJECT_SUFFIX
285090277Sobrien  /* Convert x.o to x.obj if TARGET_OBJECT_SUFFIX is ".obj".  */
285190277Sobrien  if (do_obj && len > 2
285250599Sobrien      && name[len - 2] == '.'
285350599Sobrien      && name[len - 1] == 'o')
285450599Sobrien    {
285550599Sobrien      obstack_grow (&obstack, name, len - 2);
285690277Sobrien      obstack_grow0 (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
285750599Sobrien      name = obstack_finish (&obstack);
285850599Sobrien    }
285950599Sobrien#endif
286050599Sobrien
286190277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
286250599Sobrien  /* If there is no filetype, make it the executable suffix (which includes
286350599Sobrien     the ".").  But don't get confused if we have just "-o".  */
286490277Sobrien  if (! do_exe || TARGET_EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-'))
286550599Sobrien    return name;
286650599Sobrien
286750599Sobrien  for (i = len - 1; i >= 0; i--)
286852520Sobrien    if (IS_DIR_SEPARATOR (name[i]))
286950599Sobrien      break;
287050599Sobrien
287150599Sobrien  for (i++; i < len; i++)
287250599Sobrien    if (name[i] == '.')
287350599Sobrien      return name;
287450599Sobrien
287550599Sobrien  obstack_grow (&obstack, name, len);
287690277Sobrien  obstack_grow0 (&obstack, TARGET_EXECUTABLE_SUFFIX,
287790277Sobrien		 strlen (TARGET_EXECUTABLE_SUFFIX));
287850599Sobrien  name = obstack_finish (&obstack);
287950599Sobrien#endif
288050599Sobrien
288150599Sobrien  return name;
288250599Sobrien}
288350599Sobrien#endif
288450599Sobrien
288550599Sobrien/* Display the command line switches accepted by gcc.  */
288650599Sobrienstatic void
288750599Sobriendisplay_help ()
288850599Sobrien{
288990277Sobrien  printf (_("Usage: %s [options] file...\n"), programname);
289090277Sobrien  fputs (_("Options:\n"), stdout);
289150599Sobrien
289290277Sobrien  fputs (_("  -pass-exit-codes         Exit with highest error code from a phase\n"), stdout);
289390277Sobrien  fputs (_("  --help                   Display this information\n"), stdout);
289490277Sobrien  fputs (_("  --target-help            Display target specific command line options\n"), stdout);
289550599Sobrien  if (! verbose_flag)
289690277Sobrien    fputs (_("  (Use '-v --help' to display command line options of sub-processes)\n"), stdout);
289790277Sobrien  fputs (_("  -dumpspecs               Display all of the built in spec strings\n"), stdout);
289890277Sobrien  fputs (_("  -dumpversion             Display the version of the compiler\n"), stdout);
289990277Sobrien  fputs (_("  -dumpmachine             Display the compiler's target processor\n"), stdout);
290090277Sobrien  fputs (_("  -print-search-dirs       Display the directories in the compiler's search path\n"), stdout);
290190277Sobrien  fputs (_("  -print-libgcc-file-name  Display the name of the compiler's companion library\n"), stdout);
290290277Sobrien  fputs (_("  -print-file-name=<lib>   Display the full path to library <lib>\n"), stdout);
290390277Sobrien  fputs (_("  -print-prog-name=<prog>  Display the full path to compiler component <prog>\n"), stdout);
290490277Sobrien  fputs (_("  -print-multi-directory   Display the root directory for versions of libgcc\n"), stdout);
290590277Sobrien  fputs (_("\
290690277Sobrien  -print-multi-lib         Display the mapping between command line options and\n\
290790277Sobrien                           multiple library search directories\n"), stdout);
2908104763Skan  fputs (_("  -print-multi-os-directory Display the relative path to OS libraries\n"), stdout);
290990277Sobrien  fputs (_("  -Wa,<options>            Pass comma-separated <options> on to the assembler\n"), stdout);
291090277Sobrien  fputs (_("  -Wp,<options>            Pass comma-separated <options> on to the preprocessor\n"), stdout);
291190277Sobrien  fputs (_("  -Wl,<options>            Pass comma-separated <options> on to the linker\n"), stdout);
291290277Sobrien  fputs (_("  -Xlinker <arg>           Pass <arg> on to the linker\n"), stdout);
291390277Sobrien  fputs (_("  -save-temps              Do not delete intermediate files\n"), stdout);
291490277Sobrien  fputs (_("  -pipe                    Use pipes rather than intermediate files\n"), stdout);
291590277Sobrien  fputs (_("  -time                    Time the execution of each subprocess\n"), stdout);
291690277Sobrien  fputs (_("  -specs=<file>            Override built-in specs with the contents of <file>\n"), stdout);
291790277Sobrien  fputs (_("  -std=<standard>          Assume that the input sources are for <standard>\n"), stdout);
291890277Sobrien  fputs (_("  -B <directory>           Add <directory> to the compiler's search paths\n"), stdout);
291990277Sobrien  fputs (_("  -b <machine>             Run gcc for target <machine>, if installed\n"), stdout);
292090277Sobrien  fputs (_("  -V <version>             Run gcc version number <version>, if installed\n"), stdout);
292190277Sobrien  fputs (_("  -v                       Display the programs invoked by the compiler\n"), stdout);
292290277Sobrien  fputs (_("  -###                     Like -v but options quoted and commands not executed\n"), stdout);
292390277Sobrien  fputs (_("  -E                       Preprocess only; do not compile, assemble or link\n"), stdout);
292490277Sobrien  fputs (_("  -S                       Compile only; do not assemble or link\n"), stdout);
292590277Sobrien  fputs (_("  -c                       Compile and assemble, but do not link\n"), stdout);
292690277Sobrien  fputs (_("  -o <file>                Place the output into <file>\n"), stdout);
292790277Sobrien  fputs (_("\
292890277Sobrien  -x <language>            Specify the language of the following input files\n\
2929117413Skan                           Permissible languages include: c c++ assembler none\n\
293090277Sobrien                           'none' means revert to the default behavior of\n\
293190277Sobrien                           guessing the language based on the file's extension\n\
293290277Sobrien"), stdout);
293350599Sobrien
293490277Sobrien  printf (_("\
293590277Sobrien\nOptions starting with -g, -f, -m, -O, -W, or --param are automatically\n\
293690277Sobrien passed on to the various sub-processes invoked by %s.  In order to pass\n\
293790277Sobrien other options on to these processes the -W<letter> options must be used.\n\
293890277Sobrien"), programname);
293950599Sobrien
294050599Sobrien  /* The rest of the options are displayed by invocations of the various
294150599Sobrien     sub-processes.  */
294250599Sobrien}
294350599Sobrien
294490277Sobrienstatic void
294590277Sobrienadd_preprocessor_option (option, len)
294690277Sobrien     const char *option;
294752520Sobrien     int len;
294890277Sobrien{
294952520Sobrien  n_preprocessor_options++;
295090277Sobrien
295152520Sobrien  if (! preprocessor_options)
295252520Sobrien    preprocessor_options
295352520Sobrien      = (char **) xmalloc (n_preprocessor_options * sizeof (char *));
295452520Sobrien  else
295552520Sobrien    preprocessor_options
295652520Sobrien      = (char **) xrealloc (preprocessor_options,
295752520Sobrien			    n_preprocessor_options * sizeof (char *));
295890277Sobrien
295952520Sobrien  preprocessor_options [n_preprocessor_options - 1] =
296052520Sobrien    save_string (option, len);
296150599Sobrien}
296290277Sobrien
296390277Sobrienstatic void
296490277Sobrienadd_assembler_option (option, len)
296590277Sobrien     const char *option;
296652520Sobrien     int len;
296752520Sobrien{
296852520Sobrien  n_assembler_options++;
296952520Sobrien
297052520Sobrien  if (! assembler_options)
297152520Sobrien    assembler_options
297252520Sobrien      = (char **) xmalloc (n_assembler_options * sizeof (char *));
297352520Sobrien  else
297452520Sobrien    assembler_options
297552520Sobrien      = (char **) xrealloc (assembler_options,
297652520Sobrien			    n_assembler_options * sizeof (char *));
297752520Sobrien
297852520Sobrien  assembler_options [n_assembler_options - 1] = save_string (option, len);
297950599Sobrien}
298090277Sobrien
298190277Sobrienstatic void
298290277Sobrienadd_linker_option (option, len)
298390277Sobrien     const char *option;
298490277Sobrien     int len;
298552520Sobrien{
298652520Sobrien  n_linker_options++;
298752520Sobrien
298852520Sobrien  if (! linker_options)
298952520Sobrien    linker_options
299052520Sobrien      = (char **) xmalloc (n_linker_options * sizeof (char *));
299152520Sobrien  else
299252520Sobrien    linker_options
299352520Sobrien      = (char **) xrealloc (linker_options,
299452520Sobrien			    n_linker_options * sizeof (char *));
299552520Sobrien
299652520Sobrien  linker_options [n_linker_options - 1] = save_string (option, len);
299750599Sobrien}
299850599Sobrien
299918334Speter/* Create the vector `switches' and its contents.
300018334Speter   Store its length in `n_switches'.  */
300118334Speter
300218334Speterstatic void
300318334Speterprocess_command (argc, argv)
300418334Speter     int argc;
300590277Sobrien     const char *const *argv;
300618334Speter{
300790277Sobrien  int i;
300852520Sobrien  const char *temp;
300952520Sobrien  char *temp1;
301090277Sobrien  const char *spec_lang = 0;
301118334Speter  int last_language_n_infiles;
301250599Sobrien  int have_c = 0;
301350599Sobrien  int have_o = 0;
301450599Sobrien  int lang_n_infiles = 0;
301590277Sobrien#ifdef MODIFY_TARGET_NAME
301690277Sobrien  int is_modify_target_name;
301790277Sobrien  int j;
301890277Sobrien#endif
301918334Speter
3020117413Skan  GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
302118334Speter
302218334Speter  n_switches = 0;
302318334Speter  n_infiles = 0;
302450599Sobrien  added_libraries = 0;
302518334Speter
302618334Speter  /* Figure compiler version from version string.  */
302718334Speter
302890277Sobrien  compiler_version = temp1 = xstrdup (version_string);
302990277Sobrien
303052520Sobrien  for (; *temp1; ++temp1)
303118334Speter    {
303252520Sobrien      if (*temp1 == ' ')
303318334Speter	{
303452520Sobrien	  *temp1 = '\0';
303518334Speter	  break;
303618334Speter	}
303718334Speter    }
303818334Speter
3039117413Skan  /* If there is a -V or -b option (or both), process it now, before
3040117413Skan     trying to interpret the rest of the command line.  */
3041117413Skan  if (argc > 1 && argv[1][0] == '-'
3042117413Skan      && (argv[1][1] == 'V' || argv[1][1] == 'b'))
3043117413Skan    {
3044117413Skan      const char *new_version = DEFAULT_TARGET_VERSION;
3045117413Skan      const char *new_machine = DEFAULT_TARGET_MACHINE;
3046117413Skan      const char *progname = argv[0];
3047117413Skan      char **new_argv;
3048117413Skan      char *new_argv0;
3049117413Skan      int baselen;
3050117413Skan
3051117413Skan      while (argc > 1 && argv[1][0] == '-'
3052117413Skan	     && (argv[1][1] == 'V' || argv[1][1] == 'b'))
3053117413Skan	{
3054117413Skan	  char opt = argv[1][1];
3055117413Skan	  const char *arg;
3056117413Skan	  if (argv[1][2] != '\0')
3057117413Skan	    {
3058117413Skan	      arg = argv[1] + 2;
3059117413Skan	      argc -= 1;
3060117413Skan	      argv += 1;
3061117413Skan	    }
3062117413Skan	  else if (argc > 2)
3063117413Skan	    {
3064117413Skan	      arg = argv[2];
3065117413Skan	      argc -= 2;
3066117413Skan	      argv += 2;
3067117413Skan	    }
3068117413Skan	  else
3069117413Skan	    fatal ("`-%c' option must have argument", opt);
3070117413Skan	  if (opt == 'V')
3071117413Skan	    new_version = arg;
3072117413Skan	  else
3073117413Skan	    new_machine = arg;
3074117413Skan	}
3075117413Skan
3076117413Skan      for (baselen = strlen (progname); baselen > 0; baselen--)
3077117413Skan	if (IS_DIR_SEPARATOR (progname[baselen-1]))
3078117413Skan	  break;
3079117413Skan      new_argv0 = xmemdup (progname, baselen,
3080117413Skan			   baselen + concat_length (new_version, new_machine,
3081117413Skan						    "-gcc-", NULL) + 1);
3082117413Skan      strcpy (new_argv0 + baselen, new_machine);
3083117413Skan      strcat (new_argv0, "-gcc-");
3084117413Skan      strcat (new_argv0, new_version);
3085117413Skan
3086117413Skan      new_argv = xmemdup (argv, (argc + 1) * sizeof (argv[0]),
3087117413Skan			  (argc + 1) * sizeof (argv[0]));
3088117413Skan      new_argv[0] = new_argv0;
3089117413Skan
3090117413Skan      execvp (new_argv0, new_argv);
3091117413Skan      fatal ("couldn't run `%s': %s", new_argv0, xstrerror (errno));
3092117413Skan    }
3093117413Skan
309490277Sobrien  /* Set up the default search paths.  If there is no GCC_EXEC_PREFIX,
309590277Sobrien     see if we can create it from the pathname specified in argv[0].  */
309618334Speter
309796736Sru#ifndef FREEBSD_NATIVE
309890277Sobrien#ifndef VMS
309990277Sobrien  /* FIXME: make_relative_prefix doesn't yet work for VMS.  */
310090277Sobrien  if (!gcc_exec_prefix)
310190277Sobrien    {
310290277Sobrien      gcc_exec_prefix = make_relative_prefix (argv[0], standard_bindir_prefix,
310390277Sobrien					      standard_exec_prefix);
310490277Sobrien      if (gcc_exec_prefix)
310590277Sobrien	putenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL));
310690277Sobrien    }
310790277Sobrien#endif
310896736Sru#endif	/* not FREEBSD_NATIVE */
310990277Sobrien
311018334Speter  if (gcc_exec_prefix)
311118334Speter    {
311250599Sobrien      int len = strlen (gcc_exec_prefix);
311390277Sobrien
311490277Sobrien      if (len > (int) sizeof ("/lib/gcc-lib/") - 1
311552520Sobrien	  && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1])))
311650599Sobrien	{
311750599Sobrien	  temp = gcc_exec_prefix + len - sizeof ("/lib/gcc-lib/") + 1;
311852520Sobrien	  if (IS_DIR_SEPARATOR (*temp)
311990277Sobrien	      && strncmp (temp + 1, "lib", 3) == 0
312052520Sobrien	      && IS_DIR_SEPARATOR (temp[4])
312190277Sobrien	      && strncmp (temp + 5, "gcc-lib", 7) == 0)
312250599Sobrien	    len -= sizeof ("/lib/gcc-lib/") - 1;
312350599Sobrien	}
312450599Sobrien
312550599Sobrien      set_std_prefix (gcc_exec_prefix, len);
312690277Sobrien      add_prefix (&exec_prefixes, gcc_exec_prefix, "GCC",
3127104763Skan		  PREFIX_PRIORITY_LAST, 0, NULL, 0);
312890277Sobrien      add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC",
3129104763Skan		  PREFIX_PRIORITY_LAST, 0, NULL, 0);
313018334Speter    }
313118334Speter
313218334Speter  /* COMPILER_PATH and LIBRARY_PATH have values
313318334Speter     that are lists of directory names with colons.  */
313418334Speter
3135117413Skan  GET_ENVIRONMENT (temp, "COMPILER_PATH");
313618334Speter  if (temp)
313718334Speter    {
313852520Sobrien      const char *startp, *endp;
313918334Speter      char *nstore = (char *) alloca (strlen (temp) + 3);
314018334Speter
314118334Speter      startp = endp = temp;
314218334Speter      while (1)
314318334Speter	{
314418334Speter	  if (*endp == PATH_SEPARATOR || *endp == 0)
314518334Speter	    {
314690277Sobrien	      strncpy (nstore, startp, endp - startp);
314718334Speter	      if (endp == startp)
314890277Sobrien		strcpy (nstore, concat (".", dir_separator_str, NULL));
314952520Sobrien	      else if (!IS_DIR_SEPARATOR (endp[-1]))
315018334Speter		{
315190277Sobrien		  nstore[endp - startp] = DIR_SEPARATOR;
315290277Sobrien		  nstore[endp - startp + 1] = 0;
315318334Speter		}
315418334Speter	      else
315590277Sobrien		nstore[endp - startp] = 0;
315690277Sobrien	      add_prefix (&exec_prefixes, nstore, 0,
3157104763Skan			  PREFIX_PRIORITY_LAST, 0, NULL, 0);
315850599Sobrien	      add_prefix (&include_prefixes,
315990277Sobrien			  concat (nstore, "include", NULL),
3160104763Skan			  0, PREFIX_PRIORITY_LAST, 0, NULL, 0);
316118334Speter	      if (*endp == 0)
316218334Speter		break;
316318334Speter	      endp = startp = endp + 1;
316418334Speter	    }
316518334Speter	  else
316618334Speter	    endp++;
316718334Speter	}
316818334Speter    }
316918334Speter
3170117413Skan  GET_ENVIRONMENT (temp, LIBRARY_PATH_ENV);
317191651Sobrien  if (temp && *cross_compile == '0')
317218334Speter    {
317352520Sobrien      const char *startp, *endp;
317418334Speter      char *nstore = (char *) alloca (strlen (temp) + 3);
317518334Speter
317618334Speter      startp = endp = temp;
317718334Speter      while (1)
317818334Speter	{
317918334Speter	  if (*endp == PATH_SEPARATOR || *endp == 0)
318018334Speter	    {
318190277Sobrien	      strncpy (nstore, startp, endp - startp);
318218334Speter	      if (endp == startp)
318390277Sobrien		strcpy (nstore, concat (".", dir_separator_str, NULL));
318452520Sobrien	      else if (!IS_DIR_SEPARATOR (endp[-1]))
318518334Speter		{
318690277Sobrien		  nstore[endp - startp] = DIR_SEPARATOR;
318790277Sobrien		  nstore[endp - startp + 1] = 0;
318818334Speter		}
318918334Speter	      else
319090277Sobrien		nstore[endp - startp] = 0;
319190277Sobrien	      add_prefix (&startfile_prefixes, nstore, NULL,
3192104763Skan			  PREFIX_PRIORITY_LAST, 0, NULL, 1);
319318334Speter	      if (*endp == 0)
319418334Speter		break;
319518334Speter	      endp = startp = endp + 1;
319618334Speter	    }
319718334Speter	  else
319818334Speter	    endp++;
319918334Speter	}
320018334Speter    }
320118334Speter
320218334Speter  /* Use LPATH like LIBRARY_PATH (for the CMU build program).  */
3203117413Skan  GET_ENVIRONMENT (temp, "LPATH");
320450599Sobrien  if (temp && *cross_compile == '0')
320518334Speter    {
320652520Sobrien      const char *startp, *endp;
320718334Speter      char *nstore = (char *) alloca (strlen (temp) + 3);
320818334Speter
320918334Speter      startp = endp = temp;
321018334Speter      while (1)
321118334Speter	{
321218334Speter	  if (*endp == PATH_SEPARATOR || *endp == 0)
321318334Speter	    {
321490277Sobrien	      strncpy (nstore, startp, endp - startp);
321518334Speter	      if (endp == startp)
321690277Sobrien		strcpy (nstore, concat (".", dir_separator_str, NULL));
321752520Sobrien	      else if (!IS_DIR_SEPARATOR (endp[-1]))
321818334Speter		{
321990277Sobrien		  nstore[endp - startp] = DIR_SEPARATOR;
322090277Sobrien		  nstore[endp - startp + 1] = 0;
322118334Speter		}
322218334Speter	      else
322390277Sobrien		nstore[endp - startp] = 0;
322490277Sobrien	      add_prefix (&startfile_prefixes, nstore, NULL,
3225104763Skan			  PREFIX_PRIORITY_LAST, 0, NULL, 1);
322618334Speter	      if (*endp == 0)
322718334Speter		break;
322818334Speter	      endp = startp = endp + 1;
322918334Speter	    }
323018334Speter	  else
323118334Speter	    endp++;
323218334Speter	}
323318334Speter    }
323418334Speter
323577389Sobrien  /* Options specified as if they appeared on the command line.  */
323677389Sobrien  temp = getenv ("GCC_OPTIONS");
323777389Sobrien  if ((temp) && (strlen (temp) > 0))
323877389Sobrien    {
323977389Sobrien      int len;
324077389Sobrien      int optc = 1;
324177389Sobrien      int new_argc;
3242110024Sobrien      const char **new_argv;
324377389Sobrien      char *envopts;
324477389Sobrien
324577389Sobrien      while (isspace (*temp))
324677389Sobrien	temp++;
324777389Sobrien      len = strlen (temp);
324877389Sobrien      envopts = (char *) xmalloc (len + 1);
324977389Sobrien      strcpy (envopts, temp);
325077389Sobrien
325177389Sobrien      for (i = 0; i < (len - 1); i++)
325277389Sobrien	if ((isspace (envopts[i])) && ! (isspace (envopts[i+1])))
325377389Sobrien	  optc++;
325477389Sobrien
3255110024Sobrien      new_argv = (const char **) alloca ((optc + argc) * sizeof(char *));
325677389Sobrien
325777389Sobrien      for (i = 0, new_argc = 1; new_argc <= optc; new_argc++)
325877389Sobrien	{
325977389Sobrien	  while (isspace (envopts[i]))
326077389Sobrien	    i++;
326177389Sobrien	  new_argv[new_argc] = envopts + i;
326277389Sobrien	  while (!isspace (envopts[i]) && (envopts[i] != '\0'))
326377389Sobrien	    i++;
326477389Sobrien	  envopts[i++] = '\0';
326577389Sobrien	}
326677389Sobrien      for (i = 1; i < argc; i++)
326777389Sobrien	new_argv[new_argc++] = argv[i];
326877389Sobrien
326977389Sobrien      argv = new_argv;
327077389Sobrien      argc = new_argc;
327177389Sobrien    }
327277389Sobrien
327318334Speter  /* Convert new-style -- options to old-style.  */
327418334Speter  translate_options (&argc, &argv);
327518334Speter
327650599Sobrien  /* Do language-specific adjustment/addition of flags.  */
327790277Sobrien  lang_specific_driver (&argc, &argv, &added_libraries);
327850599Sobrien
327918334Speter  /* Scan argv twice.  Here, the first time, just count how many switches
328018334Speter     there will be in their vector, and how many input files in theirs.
328118334Speter     Here we also parse the switches that cc itself uses (e.g. -v).  */
328218334Speter
328318334Speter  for (i = 1; i < argc; i++)
328418334Speter    {
328518334Speter      if (! strcmp (argv[i], "-dumpspecs"))
328618334Speter	{
328750599Sobrien	  struct spec_list *sl;
328850599Sobrien	  init_spec ();
328950599Sobrien	  for (sl = specs; sl; sl = sl->next)
329050599Sobrien	    printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec));
329190277Sobrien	  if (link_command_spec)
329290277Sobrien	    printf ("*link_command:\n%s\n\n", link_command_spec);
329318334Speter	  exit (0);
329418334Speter	}
329518334Speter      else if (! strcmp (argv[i], "-dumpversion"))
329618334Speter	{
329750599Sobrien	  printf ("%s\n", spec_version);
329818334Speter	  exit (0);
329918334Speter	}
330018334Speter      else if (! strcmp (argv[i], "-dumpmachine"))
330118334Speter	{
330218334Speter	  printf ("%s\n", spec_machine);
330390277Sobrien	  exit (0);
330418334Speter	}
330590277Sobrien      else if (strcmp (argv[i], "-fversion") == 0)
330690277Sobrien	{
330790277Sobrien	  /* translate_options () has turned --version into -fversion.  */
330890277Sobrien	  printf (_("%s (GCC) %s\n"), programname, version_string);
3309117413Skan	  fputs (_("Copyright (C) 2003 Free Software Foundation, Inc.\n"),
331090277Sobrien		 stdout);
331190277Sobrien	  fputs (_("This is free software; see the source for copying conditions.  There is NO\n\
331290277Sobrienwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
331390277Sobrien		 stdout);
331490277Sobrien	  exit (0);
331590277Sobrien	}
331650599Sobrien      else if (strcmp (argv[i], "-fhelp") == 0)
331750599Sobrien	{
331850599Sobrien	  /* translate_options () has turned --help into -fhelp.  */
331950599Sobrien	  print_help_list = 1;
332050599Sobrien
332150599Sobrien	  /* We will be passing a dummy file on to the sub-processes.  */
332250599Sobrien	  n_infiles++;
332350599Sobrien	  n_switches++;
332490277Sobrien
332590277Sobrien	  /* CPP driver cannot obtain switch from cc1_options.  */
332690277Sobrien	  if (is_cpp_driver)
332790277Sobrien	    add_preprocessor_option ("--help", 6);
332850599Sobrien	  add_assembler_option ("--help", 6);
332950599Sobrien	  add_linker_option ("--help", 6);
333050599Sobrien	}
333190277Sobrien      else if (strcmp (argv[i], "-ftarget-help") == 0)
3332117413Skan	{
3333117413Skan	  /* translate_options() has turned --target-help into -ftarget-help.  */
3334117413Skan	  target_help_flag = 1;
333590277Sobrien
3336117413Skan	  /* We will be passing a dummy file on to the sub-processes.  */
3337117413Skan	  n_infiles++;
3338117413Skan	  n_switches++;
333990277Sobrien
334090277Sobrien	  /* CPP driver cannot obtain switch from cc1_options.  */
334190277Sobrien	  if (is_cpp_driver)
334290277Sobrien	    add_preprocessor_option ("--target-help", 13);
3343117413Skan	  add_assembler_option ("--target-help", 13);
3344117413Skan	  add_linker_option ("--target-help", 13);
3345117413Skan	}
334690277Sobrien      else if (! strcmp (argv[i], "-pass-exit-codes"))
334790277Sobrien	{
334890277Sobrien	  pass_exit_codes = 1;
334990277Sobrien	  n_switches++;
335090277Sobrien	}
335118334Speter      else if (! strcmp (argv[i], "-print-search-dirs"))
335218334Speter	print_search_dirs = 1;
335318334Speter      else if (! strcmp (argv[i], "-print-libgcc-file-name"))
335418334Speter	print_file_name = "libgcc.a";
335518334Speter      else if (! strncmp (argv[i], "-print-file-name=", 17))
335618334Speter	print_file_name = argv[i] + 17;
335718334Speter      else if (! strncmp (argv[i], "-print-prog-name=", 17))
335818334Speter	print_prog_name = argv[i] + 17;
335918334Speter      else if (! strcmp (argv[i], "-print-multi-lib"))
336018334Speter	print_multi_lib = 1;
336118334Speter      else if (! strcmp (argv[i], "-print-multi-directory"))
336218334Speter	print_multi_directory = 1;
3363104763Skan      else if (! strcmp (argv[i], "-print-multi-os-directory"))
3364104763Skan	print_multi_os_directory = 1;
336518334Speter      else if (! strncmp (argv[i], "-Wa,", 4))
336618334Speter	{
336718334Speter	  int prev, j;
336818334Speter	  /* Pass the rest of this option to the assembler.  */
336918334Speter
337018334Speter	  /* Split the argument at commas.  */
337118334Speter	  prev = 4;
337218334Speter	  for (j = 4; argv[i][j]; j++)
337318334Speter	    if (argv[i][j] == ',')
337418334Speter	      {
337550599Sobrien		add_assembler_option (argv[i] + prev, j - prev);
337618334Speter		prev = j + 1;
337718334Speter	      }
337890277Sobrien
337918334Speter	  /* Record the part after the last comma.  */
338050599Sobrien	  add_assembler_option (argv[i] + prev, j - prev);
338118334Speter	}
338218334Speter      else if (! strncmp (argv[i], "-Wp,", 4))
338318334Speter	{
338418334Speter	  int prev, j;
338518334Speter	  /* Pass the rest of this option to the preprocessor.  */
338618334Speter
338718334Speter	  /* Split the argument at commas.  */
338818334Speter	  prev = 4;
338918334Speter	  for (j = 4; argv[i][j]; j++)
339018334Speter	    if (argv[i][j] == ',')
339118334Speter	      {
339250599Sobrien		add_preprocessor_option (argv[i] + prev, j - prev);
339318334Speter		prev = j + 1;
339418334Speter	      }
339590277Sobrien
339618334Speter	  /* Record the part after the last comma.  */
339750599Sobrien	  add_preprocessor_option (argv[i] + prev, j - prev);
339818334Speter	}
339918334Speter      else if (argv[i][0] == '+' && argv[i][1] == 'e')
340018334Speter	/* The +e options to the C++ front-end.  */
340118334Speter	n_switches++;
340218334Speter      else if (strncmp (argv[i], "-Wl,", 4) == 0)
340318334Speter	{
340418334Speter	  int j;
340518334Speter	  /* Split the argument at commas.  */
340618334Speter	  for (j = 3; argv[i][j]; j++)
340718334Speter	    n_infiles += (argv[i][j] == ',');
340818334Speter	}
340918334Speter      else if (strcmp (argv[i], "-Xlinker") == 0)
341018334Speter	{
341118334Speter	  if (i + 1 == argc)
341218334Speter	    fatal ("argument to `-Xlinker' is missing");
341318334Speter
341418334Speter	  n_infiles++;
341518334Speter	  i++;
341618334Speter	}
341777389Sobrien      else if (strcmp (argv[i], "-l") == 0)
341877389Sobrien	{
341977389Sobrien	  if (i + 1 == argc)
342077389Sobrien	    fatal ("argument to `-l' is missing");
342177389Sobrien
342277389Sobrien	  n_infiles++;
342377389Sobrien	  i++;
342477389Sobrien	}
342518334Speter      else if (strncmp (argv[i], "-l", 2) == 0)
342618334Speter	n_infiles++;
342750599Sobrien      else if (strcmp (argv[i], "-save-temps") == 0)
342850599Sobrien	{
342950599Sobrien	  save_temps_flag = 1;
343050599Sobrien	  n_switches++;
343150599Sobrien	}
343250599Sobrien      else if (strcmp (argv[i], "-specs") == 0)
343350599Sobrien	{
343450599Sobrien	  struct user_specs *user = (struct user_specs *)
343550599Sobrien	    xmalloc (sizeof (struct user_specs));
343650599Sobrien	  if (++i >= argc)
343750599Sobrien	    fatal ("argument to `-specs' is missing");
343850599Sobrien
343990277Sobrien	  user->next = (struct user_specs *) 0;
344050599Sobrien	  user->filename = argv[i];
344150599Sobrien	  if (user_specs_tail)
344250599Sobrien	    user_specs_tail->next = user;
344350599Sobrien	  else
344450599Sobrien	    user_specs_head = user;
344550599Sobrien	  user_specs_tail = user;
344650599Sobrien	}
344750599Sobrien      else if (strncmp (argv[i], "-specs=", 7) == 0)
344850599Sobrien	{
344950599Sobrien	  struct user_specs *user = (struct user_specs *)
345050599Sobrien	    xmalloc (sizeof (struct user_specs));
345150599Sobrien	  if (strlen (argv[i]) == 7)
345250599Sobrien	    fatal ("argument to `-specs=' is missing");
345350599Sobrien
345490277Sobrien	  user->next = (struct user_specs *) 0;
345590277Sobrien	  user->filename = argv[i] + 7;
345650599Sobrien	  if (user_specs_tail)
345750599Sobrien	    user_specs_tail->next = user;
345850599Sobrien	  else
345950599Sobrien	    user_specs_head = user;
346050599Sobrien	  user_specs_tail = user;
346150599Sobrien	}
346290277Sobrien      else if (strcmp (argv[i], "-time") == 0)
346390277Sobrien	report_times = 1;
346490277Sobrien      else if (strcmp (argv[i], "-###") == 0)
346590277Sobrien	{
346690277Sobrien	  /* This is similar to -v except that there is no execution
346790277Sobrien	     of the commands and the echoed arguments are quoted.  It
346890277Sobrien	     is intended for use in shell scripts to capture the
346990277Sobrien	     driver-generated command line.  */
347090277Sobrien	  verbose_only_flag++;
347190277Sobrien	  verbose_flag++;
347290277Sobrien	}
347318334Speter      else if (argv[i][0] == '-' && argv[i][1] != 0)
347418334Speter	{
347590277Sobrien	  const char *p = &argv[i][1];
347690277Sobrien	  int c = *p;
347718334Speter
347818334Speter	  switch (c)
347918334Speter	    {
348018334Speter	    case 'b':
3481117413Skan	    case 'V':
3482117413Skan	      fatal ("`-%c' must come at the start of the command line", c);
348318334Speter	      break;
348418334Speter
348518334Speter	    case 'B':
348618334Speter	      {
348790277Sobrien		const char *value;
348890277Sobrien		int len;
348990277Sobrien
349018334Speter		if (p[1] == 0 && i + 1 == argc)
349118334Speter		  fatal ("argument to `-B' is missing");
349218334Speter		if (p[1] == 0)
349318334Speter		  value = argv[++i];
349418334Speter		else
349518334Speter		  value = p + 1;
349618334Speter
349790277Sobrien		len = strlen (value);
349890277Sobrien
349990277Sobrien		/* Catch the case where the user has forgotten to append a
350090277Sobrien		   directory separator to the path.  Note, they may be using
350190277Sobrien		   -B to add an executable name prefix, eg "i386-elf-", in
350290277Sobrien		   order to distinguish between multiple installations of
350390277Sobrien		   GCC in the same directory.  Hence we must check to see
350490277Sobrien		   if appending a directory separator actually makes a
350590277Sobrien		   valid directory name.  */
350690277Sobrien		if (! IS_DIR_SEPARATOR (value [len - 1])
350790277Sobrien		    && is_directory (value, "", 0))
350890277Sobrien		  {
350990277Sobrien		    char *tmp = xmalloc (len + 2);
351090277Sobrien		    strcpy (tmp, value);
351190277Sobrien		    tmp[len] = DIR_SEPARATOR;
351290277Sobrien		    tmp[++ len] = 0;
351390277Sobrien		    value = tmp;
351490277Sobrien		  }
3515117413Skan
351690277Sobrien		/* As a kludge, if the arg is "[foo/]stageN/", just
351790277Sobrien		   add "[foo/]include" to the include prefix.  */
351890277Sobrien		if ((len == 7
351990277Sobrien		     || (len > 7
352090277Sobrien			 && (IS_DIR_SEPARATOR (value[len - 8]))))
352190277Sobrien		    && strncmp (value + len - 7, "stage", 5) == 0
352290277Sobrien		    && ISDIGIT (value[len - 2])
352390277Sobrien		    && (IS_DIR_SEPARATOR (value[len - 1])))
352490277Sobrien		  {
352590277Sobrien		    if (len == 7)
352690277Sobrien		      add_prefix (&include_prefixes, "include", NULL,
3527104763Skan				  PREFIX_PRIORITY_B_OPT, 0, NULL, 0);
352890277Sobrien		    else
352990277Sobrien		      {
353090277Sobrien			char * string = xmalloc (len + 1);
353190277Sobrien
353290277Sobrien			strncpy (string, value, len - 7);
353390277Sobrien			strcpy (string + len - 7, "include");
353490277Sobrien			add_prefix (&include_prefixes, string, NULL,
3535104763Skan				    PREFIX_PRIORITY_B_OPT, 0, NULL, 0);
353690277Sobrien		      }
353790277Sobrien		  }
353890277Sobrien
353990277Sobrien		add_prefix (&exec_prefixes, value, NULL,
3540104763Skan			    PREFIX_PRIORITY_B_OPT, 0, &warn_B, 0);
354190277Sobrien		add_prefix (&startfile_prefixes, value, NULL,
3542104763Skan			    PREFIX_PRIORITY_B_OPT, 0, &warn_B, 0);
354390277Sobrien		add_prefix (&include_prefixes, concat (value, "include", NULL),
3544104763Skan			    NULL, PREFIX_PRIORITY_B_OPT, 0, NULL, 0);
354590277Sobrien		n_switches++;
354618334Speter	      }
354718334Speter	      break;
354818334Speter
354918334Speter	    case 'v':	/* Print our subcommands and print versions.  */
355018334Speter	      n_switches++;
355118334Speter	      /* If they do anything other than exactly `-v', don't set
355218334Speter		 verbose_flag; rather, continue on to give the error.  */
355318334Speter	      if (p[1] != 0)
355418334Speter		break;
355518334Speter	      verbose_flag++;
355618334Speter	      break;
355718334Speter
355850599Sobrien	    case 'S':
355950599Sobrien	    case 'c':
356050599Sobrien	      if (p[1] == 0)
356118334Speter		{
356250599Sobrien		  have_c = 1;
356318334Speter		  n_switches++;
356418334Speter		  break;
356518334Speter		}
356650599Sobrien	      goto normal_switch;
356750599Sobrien
356850599Sobrien	    case 'o':
356950599Sobrien	      have_o = 1;
357090277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
357150599Sobrien	      if (! have_c)
357250599Sobrien		{
357350599Sobrien		  int skip;
357490277Sobrien
357550599Sobrien		  /* Forward scan, just in case -S or -c is specified
357650599Sobrien		     after -o.  */
357750599Sobrien		  int j = i + 1;
357850599Sobrien		  if (p[1] == 0)
357950599Sobrien		    ++j;
358050599Sobrien		  while (j < argc)
358150599Sobrien		    {
358250599Sobrien		      if (argv[j][0] == '-')
358350599Sobrien			{
358450599Sobrien			  if (SWITCH_CURTAILS_COMPILATION (argv[j][1])
358550599Sobrien			      && argv[j][2] == 0)
358650599Sobrien			    {
358750599Sobrien			      have_c = 1;
358850599Sobrien			      break;
358950599Sobrien			    }
359090277Sobrien			  else if ((skip = SWITCH_TAKES_ARG (argv[j][1])))
359150599Sobrien			    j += skip - (argv[j][2] != 0);
359290277Sobrien			  else if ((skip = WORD_SWITCH_TAKES_ARG (argv[j] + 1)))
359350599Sobrien			    j += skip;
359450599Sobrien			}
359550599Sobrien		      j++;
359650599Sobrien		    }
359750599Sobrien		}
359850599Sobrien#endif
359990277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX)
360050599Sobrien	      if (p[1] == 0)
360190277Sobrien		argv[i + 1] = convert_filename (argv[i + 1], ! have_c, 0);
360250599Sobrien	      else
360390277Sobrien		argv[i] = convert_filename (argv[i], ! have_c, 0);
360450599Sobrien#endif
360550599Sobrien	      goto normal_switch;
360650599Sobrien
360718334Speter	    default:
360850599Sobrien	    normal_switch:
360990277Sobrien
361090277Sobrien#ifdef MODIFY_TARGET_NAME
361190277Sobrien	      is_modify_target_name = 0;
361290277Sobrien
3613117413Skan	      for (j = 0; j < ARRAY_SIZE (modify_target); j++)
361490277Sobrien		if (! strcmp (argv[i], modify_target[j].sw))
361590277Sobrien		  {
361690277Sobrien		    char *new_name
361790277Sobrien		      = (char *) xmalloc (strlen (modify_target[j].str)
361890277Sobrien					  + strlen (spec_machine));
361990277Sobrien		    const char *p, *r;
362090277Sobrien		    char *q;
362190277Sobrien		    int made_addition = 0;
362290277Sobrien
362390277Sobrien		    is_modify_target_name = 1;
362490277Sobrien		    for (p = spec_machine, q = new_name; *p != 0; )
362590277Sobrien		      {
362690277Sobrien			if (modify_target[j].add_del == DELETE
362790277Sobrien			    && (! strncmp (q, modify_target[j].str,
362890277Sobrien					   strlen (modify_target[j].str))))
362990277Sobrien			  p += strlen (modify_target[j].str);
363090277Sobrien			else if (modify_target[j].add_del == ADD
363190277Sobrien				 && ! made_addition && *p == '-')
363290277Sobrien			  {
363390277Sobrien			    for (r = modify_target[j].str; *r != 0; )
363490277Sobrien			      *q++ = *r++;
363590277Sobrien			    made_addition = 1;
363690277Sobrien			  }
363790277Sobrien
363890277Sobrien			*q++ = *p++;
363990277Sobrien		      }
364090277Sobrien
364190277Sobrien		    spec_machine = new_name;
364290277Sobrien		  }
364390277Sobrien
364490277Sobrien	      if (is_modify_target_name)
364590277Sobrien		break;
3646117413Skan#endif
364790277Sobrien
364818334Speter	      n_switches++;
364918334Speter
365018334Speter	      if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
365118334Speter		i += SWITCH_TAKES_ARG (c) - (p[1] != 0);
365218334Speter	      else if (WORD_SWITCH_TAKES_ARG (p))
365318334Speter		i += WORD_SWITCH_TAKES_ARG (p);
365418334Speter	    }
365518334Speter	}
365618334Speter      else
365750599Sobrien	{
365850599Sobrien	  n_infiles++;
365950599Sobrien	  lang_n_infiles++;
366050599Sobrien	}
366118334Speter    }
366218334Speter
366350599Sobrien  if (have_c && have_o && lang_n_infiles > 1)
366450599Sobrien    fatal ("cannot specify -o with -c or -S and multiple compilations");
366550599Sobrien
366618334Speter  /* Set up the search paths before we go looking for config files.  */
366718334Speter
366818334Speter  /* These come before the md prefixes so that we will find gcc's subcommands
366918334Speter     (such as cpp) rather than those of the host system.  */
367018334Speter  /* Use 2 as fourth arg meaning try just the machine as a suffix,
367118334Speter     as well as trying the machine and the version.  */
367218346Speter#ifdef FREEBSD_NATIVE
3673104953Sobrien      add_prefix (&exec_prefixes, PREFIX"/bin/", "BINUTILS",
3674104763Skan		  0, 0, warn_std_ptr, 0);
367591561Sobrien#endif	/* FREEBSD_NATIVE */
367618334Speter#ifndef OS2
367790277Sobrien  add_prefix (&exec_prefixes, standard_exec_prefix, "GCC",
3678104763Skan	      PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0);
367950599Sobrien  add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS",
3680104763Skan	      PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0);
368196736Sru#ifndef FREEBSD_NATIVE
368250599Sobrien  add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS",
3683104763Skan	      PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0);
368491578Sobrien#endif	/* not FREEBSD_NATIVE */
368518334Speter#endif
368618334Speter
368791578Sobrien#ifndef FREEBSD_NATIVE
368850599Sobrien  add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS",
3689104763Skan	      PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0);
369050599Sobrien  add_prefix (&startfile_prefixes, standard_exec_prefix_1, "BINUTILS",
3691104763Skan	      PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0);
369291561Sobrien#endif	/* not FREEBSD_NATIVE */
369318334Speter
369490277Sobrien  tooldir_prefix = concat (tooldir_base_prefix, spec_machine,
369590277Sobrien			   dir_separator_str, NULL);
369618334Speter
369718334Speter  /* If tooldir is relative, base it on exec_prefixes.  A relative
369818334Speter     tooldir lets us move the installed tree as a unit.
369918334Speter
370018334Speter     If GCC_EXEC_PREFIX is defined, then we want to add two relative
370118334Speter     directories, so that we can search both the user specified directory
370218334Speter     and the standard place.  */
370318334Speter
370490277Sobrien  if (!IS_ABSOLUTE_PATHNAME (tooldir_prefix))
370518334Speter    {
370618334Speter      if (gcc_exec_prefix)
370718334Speter	{
370818334Speter	  char *gcc_exec_tooldir_prefix
370950599Sobrien	    = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
371090277Sobrien		      spec_version, dir_separator_str, tooldir_prefix, NULL);
371118334Speter
371218334Speter	  add_prefix (&exec_prefixes,
371390277Sobrien		      concat (gcc_exec_tooldir_prefix, "bin",
371490277Sobrien			      dir_separator_str, NULL),
3715104763Skan		      NULL, PREFIX_PRIORITY_LAST, 0, NULL, 0);
371618334Speter	  add_prefix (&startfile_prefixes,
371790277Sobrien		      concat (gcc_exec_tooldir_prefix, "lib",
371890277Sobrien			      dir_separator_str, NULL),
3719104763Skan		      NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1);
372018334Speter	}
372118334Speter
372250599Sobrien      tooldir_prefix = concat (standard_exec_prefix, spec_machine,
372390277Sobrien			       dir_separator_str, spec_version,
372490277Sobrien			       dir_separator_str, tooldir_prefix, NULL);
372518334Speter    }
372618334Speter
372718346Speter#ifndef FREEBSD_NATIVE
372890277Sobrien  add_prefix (&exec_prefixes,
372990277Sobrien	      concat (tooldir_prefix, "bin", dir_separator_str, NULL),
3730104763Skan	      "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 0);
373118334Speter  add_prefix (&startfile_prefixes,
373290277Sobrien	      concat (tooldir_prefix, "lib", dir_separator_str, NULL),
3733104763Skan	      "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1);
373418346Speter#endif /* FREEBSD_NATIVE */
373518334Speter
373618334Speter  /* More prefixes are enabled in main, after we read the specs file
373718334Speter     and determine whether this is cross-compilation or not.  */
373818334Speter
373918334Speter  /* Then create the space for the vectors and scan again.  */
374018334Speter
374118334Speter  switches = ((struct switchstr *)
374218334Speter	      xmalloc ((n_switches + 1) * sizeof (struct switchstr)));
374318334Speter  infiles = (struct infile *) xmalloc ((n_infiles + 1) * sizeof (struct infile));
374418334Speter  n_switches = 0;
374518334Speter  n_infiles = 0;
374618334Speter  last_language_n_infiles = -1;
374718334Speter
374818334Speter  /* This, time, copy the text of each switch and store a pointer
374918334Speter     to the copy in the vector of switches.
375018334Speter     Store all the infiles in their vector.  */
375118334Speter
375218334Speter  for (i = 1; i < argc; i++)
375318334Speter    {
375418334Speter      /* Just skip the switches that were handled by the preceding loop.  */
375590277Sobrien#ifdef MODIFY_TARGET_NAME
375690277Sobrien      is_modify_target_name = 0;
375790277Sobrien
3758117413Skan      for (j = 0; j < ARRAY_SIZE (modify_target); j++)
375990277Sobrien	if (! strcmp (argv[i], modify_target[j].sw))
376090277Sobrien	  is_modify_target_name = 1;
376190277Sobrien
376290277Sobrien      if (is_modify_target_name)
376390277Sobrien	;
376490277Sobrien      else
376590277Sobrien#endif
376618334Speter      if (! strncmp (argv[i], "-Wa,", 4))
376718334Speter	;
376818334Speter      else if (! strncmp (argv[i], "-Wp,", 4))
376918334Speter	;
377090277Sobrien      else if (! strcmp (argv[i], "-pass-exit-codes"))
377190277Sobrien	;
377218334Speter      else if (! strcmp (argv[i], "-print-search-dirs"))
377318334Speter	;
377418334Speter      else if (! strcmp (argv[i], "-print-libgcc-file-name"))
377518334Speter	;
377618334Speter      else if (! strncmp (argv[i], "-print-file-name=", 17))
377718334Speter	;
377818334Speter      else if (! strncmp (argv[i], "-print-prog-name=", 17))
377918334Speter	;
378018334Speter      else if (! strcmp (argv[i], "-print-multi-lib"))
378118334Speter	;
378218334Speter      else if (! strcmp (argv[i], "-print-multi-directory"))
378318334Speter	;
3784104763Skan      else if (! strcmp (argv[i], "-print-multi-os-directory"))
3785104763Skan	;
378690277Sobrien      else if (! strcmp (argv[i], "-ftarget-help"))
378790277Sobrien	;
378890277Sobrien      else if (! strcmp (argv[i], "-fhelp"))
378990277Sobrien	;
379018334Speter      else if (argv[i][0] == '+' && argv[i][1] == 'e')
379118334Speter	{
379218334Speter	  /* Compensate for the +e options to the C++ front-end;
379318334Speter	     they're there simply for cfront call-compatibility.  We do
379418334Speter	     some magic in default_compilers to pass them down properly.
379518334Speter	     Note we deliberately start at the `+' here, to avoid passing
379618334Speter	     -e0 or -e1 down into the linker.  */
379718334Speter	  switches[n_switches].part1 = &argv[i][0];
379818334Speter	  switches[n_switches].args = 0;
379990277Sobrien	  switches[n_switches].live_cond = SWITCH_OK;
380052520Sobrien	  switches[n_switches].validated = 0;
380118334Speter	  n_switches++;
380218334Speter	}
380318334Speter      else if (strncmp (argv[i], "-Wl,", 4) == 0)
380418334Speter	{
380518334Speter	  int prev, j;
380618334Speter	  /* Split the argument at commas.  */
380718334Speter	  prev = 4;
380818334Speter	  for (j = 4; argv[i][j]; j++)
380918334Speter	    if (argv[i][j] == ',')
381018334Speter	      {
381150599Sobrien		infiles[n_infiles].language = "*";
381218334Speter		infiles[n_infiles++].name
381318334Speter		  = save_string (argv[i] + prev, j - prev);
381418334Speter		prev = j + 1;
381518334Speter	      }
381618334Speter	  /* Record the part after the last comma.  */
381750599Sobrien	  infiles[n_infiles].language = "*";
381818334Speter	  infiles[n_infiles++].name = argv[i] + prev;
381918334Speter	}
382018334Speter      else if (strcmp (argv[i], "-Xlinker") == 0)
382118334Speter	{
382250599Sobrien	  infiles[n_infiles].language = "*";
382318334Speter	  infiles[n_infiles++].name = argv[++i];
382418334Speter	}
382577389Sobrien      else if (strcmp (argv[i], "-l") == 0)
382677389Sobrien	{ /* POSIX allows separation of -l and the lib arg;
382777389Sobrien	     canonicalize by concatenating -l with its arg */
382877389Sobrien	  infiles[n_infiles].language = "*";
382977389Sobrien	  infiles[n_infiles++].name = concat ("-l", argv[++i], NULL);
383077389Sobrien	}
383118334Speter      else if (strncmp (argv[i], "-l", 2) == 0)
383218334Speter	{
383350599Sobrien	  infiles[n_infiles].language = "*";
383418334Speter	  infiles[n_infiles++].name = argv[i];
383518334Speter	}
383650599Sobrien      else if (strcmp (argv[i], "-specs") == 0)
383750599Sobrien	i++;
383850599Sobrien      else if (strncmp (argv[i], "-specs=", 7) == 0)
383950599Sobrien	;
384090277Sobrien      else if (strcmp (argv[i], "-time") == 0)
384190277Sobrien	;
384290277Sobrien      else if ((save_temps_flag || report_times)
384390277Sobrien	       && strcmp (argv[i], "-pipe") == 0)
384490277Sobrien	{
384590277Sobrien	  /* -save-temps overrides -pipe, so that temp files are produced */
384690277Sobrien	  if (save_temps_flag)
384790277Sobrien	    error ("warning: -pipe ignored because -save-temps specified");
3848117413Skan	  /* -time overrides -pipe because we can't get correct stats when
384990277Sobrien	     multiple children are running at once.  */
385090277Sobrien	  else if (report_times)
385190277Sobrien	    error ("warning: -pipe ignored because -time specified");
385290277Sobrien	}
385390277Sobrien      else if (strcmp (argv[i], "-###") == 0)
385490277Sobrien	;
385518334Speter      else if (argv[i][0] == '-' && argv[i][1] != 0)
385618334Speter	{
385790277Sobrien	  const char *p = &argv[i][1];
385890277Sobrien	  int c = *p;
385918334Speter
386018334Speter	  if (c == 'x')
386118334Speter	    {
386218334Speter	      if (p[1] == 0 && i + 1 == argc)
386318334Speter		fatal ("argument to `-x' is missing");
386418334Speter	      if (p[1] == 0)
386518334Speter		spec_lang = argv[++i];
386618334Speter	      else
386718334Speter		spec_lang = p + 1;
386818334Speter	      if (! strcmp (spec_lang, "none"))
386918334Speter		/* Suppress the warning if -xnone comes after the last input
387018334Speter		   file, because alternate command interfaces like g++ might
387118334Speter		   find it useful to place -xnone after each input file.  */
387218334Speter		spec_lang = 0;
387318334Speter	      else
387418334Speter		last_language_n_infiles = n_infiles;
387518334Speter	      continue;
387618334Speter	    }
387718334Speter	  switches[n_switches].part1 = p;
387818334Speter	  /* Deal with option arguments in separate argv elements.  */
387918334Speter	  if ((SWITCH_TAKES_ARG (c) > (p[1] != 0))
388018334Speter	      || WORD_SWITCH_TAKES_ARG (p))
388118334Speter	    {
388218334Speter	      int j = 0;
388318334Speter	      int n_args = WORD_SWITCH_TAKES_ARG (p);
388418334Speter
388518334Speter	      if (n_args == 0)
388618334Speter		{
388718334Speter		  /* Count only the option arguments in separate argv elements.  */
388818334Speter		  n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0);
388918334Speter		}
389018334Speter	      if (i + n_args >= argc)
389118334Speter		fatal ("argument to `-%s' is missing", p);
389218334Speter	      switches[n_switches].args
389390277Sobrien		= (const char **) xmalloc ((n_args + 1) * sizeof(const char *));
389418334Speter	      while (j < n_args)
389518334Speter		switches[n_switches].args[j++] = argv[++i];
389618334Speter	      /* Null-terminate the vector.  */
389718334Speter	      switches[n_switches].args[j] = 0;
389818334Speter	    }
389990277Sobrien	  else if (strchr (switches_need_spaces, c))
390018334Speter	    {
390150599Sobrien	      /* On some systems, ld cannot handle some options without
390250599Sobrien		 a space.  So split the option from its argument.  */
390350599Sobrien	      char *part1 = (char *) xmalloc (2);
390450599Sobrien	      part1[0] = c;
390550599Sobrien	      part1[1] = '\0';
390690277Sobrien
390750599Sobrien	      switches[n_switches].part1 = part1;
390890277Sobrien	      switches[n_switches].args
390990277Sobrien		= (const char **) xmalloc (2 * sizeof (const char *));
391090277Sobrien	      switches[n_switches].args[0] = xstrdup (p+1);
391118334Speter	      switches[n_switches].args[1] = 0;
391218334Speter	    }
391318334Speter	  else
391418334Speter	    switches[n_switches].args = 0;
391518334Speter
391690277Sobrien	  switches[n_switches].live_cond = SWITCH_OK;
391752520Sobrien	  switches[n_switches].validated = 0;
391890277Sobrien	  switches[n_switches].ordering = 0;
391990277Sobrien	  /* These are always valid, since gcc.c itself understands it.  */
392090277Sobrien	  if (!strcmp (p, "save-temps")
392190277Sobrien	      || !strcmp (p, "static-libgcc")
392290277Sobrien	      || !strcmp (p, "shared-libgcc"))
392352520Sobrien	    switches[n_switches].validated = 1;
392490277Sobrien	  else
392590277Sobrien	    {
392690277Sobrien	      char ch = switches[n_switches].part1[0];
3927117413Skan	      if (ch == 'B')
392890277Sobrien		switches[n_switches].validated = 1;
392990277Sobrien	    }
393018334Speter	  n_switches++;
393118334Speter	}
393218334Speter      else
393318334Speter	{
393490277Sobrien#ifdef HAVE_TARGET_OBJECT_SUFFIX
393590277Sobrien	  argv[i] = convert_filename (argv[i], 0, access (argv[i], F_OK));
393618334Speter#endif
393718334Speter
393890277Sobrien	  if (strcmp (argv[i], "-") != 0 && access (argv[i], F_OK) < 0)
393918334Speter	    {
394018334Speter	      perror_with_name (argv[i]);
394118334Speter	      error_count++;
394218334Speter	    }
394318334Speter	  else
394418334Speter	    {
394518334Speter	      infiles[n_infiles].language = spec_lang;
394618334Speter	      infiles[n_infiles++].name = argv[i];
394718334Speter	    }
394818334Speter	}
394918334Speter    }
395018334Speter
395118334Speter  if (n_infiles == last_language_n_infiles && spec_lang != 0)
395290277Sobrien    error ("warning: `-x %s' after last input file has no effect", spec_lang);
395318334Speter
395490277Sobrien  /* Ensure we only invoke each subprocess once.  */
395590277Sobrien  if (target_help_flag || print_help_list)
395690277Sobrien    {
395790277Sobrien      n_infiles = 1;
395890277Sobrien
395990277Sobrien      /* Create a dummy input file, so that we can pass --target-help on to
396090277Sobrien	 the various sub-processes.  */
396190277Sobrien      infiles[0].language = "c";
396290277Sobrien      infiles[0].name   = "help-dummy";
396390277Sobrien
396490277Sobrien      if (target_help_flag)
396590277Sobrien	{
396690277Sobrien	  switches[n_switches].part1     = "--target-help";
396790277Sobrien	  switches[n_switches].args      = 0;
396890277Sobrien	  switches[n_switches].live_cond = SWITCH_OK;
396990277Sobrien	  switches[n_switches].validated = 0;
397090277Sobrien
397190277Sobrien	  n_switches++;
397290277Sobrien	}
397390277Sobrien
397490277Sobrien      if (print_help_list)
397590277Sobrien	{
397690277Sobrien	  switches[n_switches].part1     = "--help";
397790277Sobrien	  switches[n_switches].args      = 0;
397890277Sobrien	  switches[n_switches].live_cond = SWITCH_OK;
397990277Sobrien	  switches[n_switches].validated = 0;
398090277Sobrien
398190277Sobrien	  n_switches++;
398290277Sobrien	}
398390277Sobrien    }
398490277Sobrien
398518334Speter  switches[n_switches].part1 = 0;
398618334Speter  infiles[n_infiles].name = 0;
398718334Speter}
398890277Sobrien
398990277Sobrien/* Store switches not filtered out by %{<S} in spec in COLLECT_GCC_OPTIONS
399090277Sobrien   and place that in the environment.  */
399190277Sobrien
399290277Sobrienstatic void
399390277Sobrienset_collect_gcc_options ()
399490277Sobrien{
399590277Sobrien  int i;
399690277Sobrien  int first_time;
399790277Sobrien
399890277Sobrien  /* Build COLLECT_GCC_OPTIONS to have all of the options specified to
399990277Sobrien     the compiler.  */
400090277Sobrien  obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
400190277Sobrien		sizeof ("COLLECT_GCC_OPTIONS=") - 1);
400290277Sobrien
400390277Sobrien  first_time = TRUE;
400490277Sobrien  for (i = 0; (int) i < n_switches; i++)
400590277Sobrien    {
400690277Sobrien      const char *const *args;
400790277Sobrien      const char *p, *q;
400890277Sobrien      if (!first_time)
400990277Sobrien	obstack_grow (&collect_obstack, " ", 1);
401090277Sobrien
401190277Sobrien      first_time = FALSE;
401290277Sobrien
401390277Sobrien      /* Ignore elided switches.  */
401490277Sobrien      if (switches[i].live_cond == SWITCH_IGNORE)
401590277Sobrien	continue;
401690277Sobrien
401790277Sobrien      obstack_grow (&collect_obstack, "'-", 2);
401890277Sobrien      q = switches[i].part1;
401990277Sobrien      while ((p = strchr (q, '\'')))
402090277Sobrien	{
402190277Sobrien	  obstack_grow (&collect_obstack, q, p - q);
402290277Sobrien	  obstack_grow (&collect_obstack, "'\\''", 4);
402390277Sobrien	  q = ++p;
402490277Sobrien	}
402590277Sobrien      obstack_grow (&collect_obstack, q, strlen (q));
402690277Sobrien      obstack_grow (&collect_obstack, "'", 1);
402790277Sobrien
402890277Sobrien      for (args = switches[i].args; args && *args; args++)
402990277Sobrien	{
403090277Sobrien	  obstack_grow (&collect_obstack, " '", 2);
403190277Sobrien	  q = *args;
403290277Sobrien	  while ((p = strchr (q, '\'')))
403390277Sobrien	    {
403490277Sobrien	      obstack_grow (&collect_obstack, q, p - q);
403590277Sobrien	      obstack_grow (&collect_obstack, "'\\''", 4);
403690277Sobrien	      q = ++p;
403790277Sobrien	    }
403890277Sobrien	  obstack_grow (&collect_obstack, q, strlen (q));
403990277Sobrien	  obstack_grow (&collect_obstack, "'", 1);
404090277Sobrien	}
404190277Sobrien    }
404290277Sobrien  obstack_grow (&collect_obstack, "\0", 1);
404390277Sobrien  putenv (obstack_finish (&collect_obstack));
404490277Sobrien}
404518334Speter
404618334Speter/* Process a spec string, accumulating and running commands.  */
404718334Speter
404818334Speter/* These variables describe the input file name.
404918334Speter   input_file_number is the index on outfiles of this file,
405018334Speter   so that the output file name can be stored for later use by %o.
405118334Speter   input_basename is the start of the part of the input file
405218334Speter   sans all directory names, and basename_length is the number
405318334Speter   of characters starting there excluding the suffix .c or whatever.  */
405418334Speter
405552520Sobrienconst char *input_filename;
405618334Speterstatic int input_file_number;
405750599Sobriensize_t input_filename_length;
405818334Speterstatic int basename_length;
405990277Sobrienstatic int suffixed_basename_length;
406052520Sobrienstatic const char *input_basename;
406152520Sobrienstatic const char *input_suffix;
406290277Sobrienstatic struct stat input_stat;
406390277Sobrienstatic int input_stat_set;
406418334Speter
406590277Sobrien/* The compiler used to process the current input file.  */
406690277Sobrienstatic struct compiler *input_file_compiler;
406790277Sobrien
406818334Speter/* These are variables used within do_spec and do_spec_1.  */
406918334Speter
407018334Speter/* Nonzero if an arg has been started and not yet terminated
407118334Speter   (with space, tab or newline).  */
407218334Speterstatic int arg_going;
407318334Speter
407418334Speter/* Nonzero means %d or %g has been seen; the next arg to be terminated
407518334Speter   is a temporary file name.  */
407618334Speterstatic int delete_this_arg;
407718334Speter
407818334Speter/* Nonzero means %w has been seen; the next arg to be terminated
407918334Speter   is the output file name of this compilation.  */
408018334Speterstatic int this_is_output_file;
408118334Speter
408218334Speter/* Nonzero means %s has been seen; the next arg to be terminated
408318334Speter   is the name of a library file and we should try the standard
408418334Speter   search dirs for it.  */
408518334Speterstatic int this_is_library_file;
408618334Speter
408718334Speter/* Nonzero means that the input of this command is coming from a pipe.  */
408818334Speterstatic int input_from_pipe;
408918334Speter
409090277Sobrien/* Nonnull means substitute this for any suffix when outputting a switches
409190277Sobrien   arguments.  */
409290277Sobrienstatic const char *suffix_subst;
409390277Sobrien
409418334Speter/* Process the spec SPEC and run the commands specified therein.
409518334Speter   Returns 0 if the spec is successfully processed; -1 if failed.  */
409618334Speter
409750599Sobrienint
409818334Speterdo_spec (spec)
409952520Sobrien     const char *spec;
410018334Speter{
410118334Speter  int value;
410218334Speter
4103117413Skan  value = do_spec_2 (spec);
410418334Speter
410518334Speter  /* Force out any unfinished command.
410618334Speter     If -pipe, this forces out the last command if it ended in `|'.  */
410718334Speter  if (value == 0)
410818334Speter    {
410918334Speter      if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
411018334Speter	argbuf_index--;
411118334Speter
411290277Sobrien      set_collect_gcc_options ();
411390277Sobrien
411418334Speter      if (argbuf_index > 0)
411518334Speter	value = execute ();
411618334Speter    }
411718334Speter
411818334Speter  return value;
411918334Speter}
412018334Speter
4121117413Skanstatic int
4122117413Skando_spec_2 (spec)
4123117413Skan     const char *spec;
4124117413Skan{
4125117413Skan  clear_args ();
4126117413Skan  arg_going = 0;
4127117413Skan  delete_this_arg = 0;
4128117413Skan  this_is_output_file = 0;
4129117413Skan  this_is_library_file = 0;
4130117413Skan  input_from_pipe = 0;
4131117413Skan  suffix_subst = NULL;
4132117413Skan
4133117413Skan  return do_spec_1 (spec, 0, NULL);
4134117413Skan}
4135117413Skan
4136117413Skan
4137117413Skan/* Process the given spec string and add any new options to the end
4138117413Skan   of the switches/n_switches array.  */
4139117413Skan
4140117413Skanstatic void
4141117413Skando_self_spec (spec)
4142117413Skan     const char *spec;
4143117413Skan{
4144117413Skan  do_spec_2 (spec);
4145117413Skan  do_spec_1 (" ", 0, NULL);
4146117413Skan
4147117413Skan  if (argbuf_index > 0)
4148117413Skan    {
4149117413Skan      int i, first;
4150117413Skan
4151117413Skan      first = n_switches;
4152117413Skan      n_switches += argbuf_index;
4153117413Skan      switches = xrealloc (switches,
4154117413Skan			   sizeof (struct switchstr) * (n_switches + 1));
4155117413Skan
4156117413Skan      switches[n_switches] = switches[first];
4157117413Skan      for (i = 0; i < argbuf_index; i++)
4158117413Skan	{
4159117413Skan	  struct switchstr *sw;
4160117413Skan
4161117413Skan	  /* Each switch should start with '-'.  */
4162117413Skan	  if (argbuf[i][0] != '-')
4163117413Skan	    abort ();
4164117413Skan
4165117413Skan	  sw = &switches[i + first];
4166117413Skan	  sw->part1 = &argbuf[i][1];
4167117413Skan	  sw->args = 0;
4168117413Skan	  sw->live_cond = SWITCH_OK;
4169117413Skan	  sw->validated = 0;
4170117413Skan	  sw->ordering = 0;
4171117413Skan	}
4172117413Skan    }
4173117413Skan}
4174117413Skan
417518334Speter/* Process the sub-spec SPEC as a portion of a larger spec.
417618334Speter   This is like processing a whole spec except that we do
417718334Speter   not initialize at the beginning and we do not supply a
417818334Speter   newline by default at the end.
417918334Speter   INSWITCH nonzero means don't process %-sequences in SPEC;
418018334Speter   in this case, % is treated as an ordinary character.
418118334Speter   This is used while substituting switches.
418218334Speter   INSWITCH nonzero also causes SPC not to terminate an argument.
418318334Speter
418418334Speter   Value is zero unless a line was finished
418518334Speter   and the command on that line reported an error.  */
418618334Speter
418718334Speterstatic int
418818334Speterdo_spec_1 (spec, inswitch, soft_matched_part)
418952520Sobrien     const char *spec;
419018334Speter     int inswitch;
419152520Sobrien     const char *soft_matched_part;
419218334Speter{
419390277Sobrien  const char *p = spec;
419490277Sobrien  int c;
419518334Speter  int i;
419652520Sobrien  const char *string;
419718334Speter  int value;
419818334Speter
419950599Sobrien  while ((c = *p++))
420018334Speter    /* If substituting a switch, treat all chars like letters.
420118334Speter       Otherwise, NL, SPC, TAB and % are special.  */
420218334Speter    switch (inswitch ? 'a' : c)
420318334Speter      {
420418334Speter      case '\n':
420518334Speter	/* End of line: finish any pending argument,
420618334Speter	   then run the pending command if one has been started.  */
420718334Speter	if (arg_going)
420818334Speter	  {
420918334Speter	    obstack_1grow (&obstack, 0);
421018334Speter	    string = obstack_finish (&obstack);
421118334Speter	    if (this_is_library_file)
421218334Speter	      string = find_file (string);
421318334Speter	    store_arg (string, delete_this_arg, this_is_output_file);
421418334Speter	    if (this_is_output_file)
421518334Speter	      outfiles[input_file_number] = string;
421618334Speter	  }
421718334Speter	arg_going = 0;
421818334Speter
421918334Speter	if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
422018334Speter	  {
422118334Speter	    for (i = 0; i < n_switches; i++)
422218334Speter	      if (!strcmp (switches[i].part1, "pipe"))
422318334Speter		break;
422418334Speter
422518334Speter	    /* A `|' before the newline means use a pipe here,
422618334Speter	       but only if -pipe was specified.
422718334Speter	       Otherwise, execute now and don't pass the `|' as an arg.  */
422818334Speter	    if (i < n_switches)
422918334Speter	      {
423018334Speter		input_from_pipe = 1;
423152520Sobrien		switches[i].validated = 1;
423218334Speter		break;
423318334Speter	      }
423418334Speter	    else
423518334Speter	      argbuf_index--;
423618334Speter	  }
423718334Speter
423890277Sobrien	set_collect_gcc_options ();
423990277Sobrien
424018334Speter	if (argbuf_index > 0)
424118334Speter	  {
424218334Speter	    value = execute ();
424318334Speter	    if (value)
424418334Speter	      return value;
424518334Speter	  }
424618334Speter	/* Reinitialize for a new command, and for a new argument.  */
424718334Speter	clear_args ();
424818334Speter	arg_going = 0;
424918334Speter	delete_this_arg = 0;
425018334Speter	this_is_output_file = 0;
425118334Speter	this_is_library_file = 0;
425218334Speter	input_from_pipe = 0;
425318334Speter	break;
425418334Speter
425518334Speter      case '|':
425618334Speter	/* End any pending argument.  */
425718334Speter	if (arg_going)
425818334Speter	  {
425918334Speter	    obstack_1grow (&obstack, 0);
426018334Speter	    string = obstack_finish (&obstack);
426118334Speter	    if (this_is_library_file)
426218334Speter	      string = find_file (string);
426318334Speter	    store_arg (string, delete_this_arg, this_is_output_file);
426418334Speter	    if (this_is_output_file)
426518334Speter	      outfiles[input_file_number] = string;
426618334Speter	  }
426718334Speter
426818334Speter	/* Use pipe */
426918334Speter	obstack_1grow (&obstack, c);
427018334Speter	arg_going = 1;
427118334Speter	break;
427218334Speter
427318334Speter      case '\t':
427418334Speter      case ' ':
427518334Speter	/* Space or tab ends an argument if one is pending.  */
427618334Speter	if (arg_going)
427718334Speter	  {
427818334Speter	    obstack_1grow (&obstack, 0);
427918334Speter	    string = obstack_finish (&obstack);
428018334Speter	    if (this_is_library_file)
428118334Speter	      string = find_file (string);
428218334Speter	    store_arg (string, delete_this_arg, this_is_output_file);
428318334Speter	    if (this_is_output_file)
428418334Speter	      outfiles[input_file_number] = string;
428518334Speter	  }
428618334Speter	/* Reinitialize for a new argument.  */
428718334Speter	arg_going = 0;
428818334Speter	delete_this_arg = 0;
428918334Speter	this_is_output_file = 0;
429018334Speter	this_is_library_file = 0;
429118334Speter	break;
429218334Speter
429318334Speter      case '%':
429418334Speter	switch (c = *p++)
429518334Speter	  {
429618334Speter	  case 0:
429790277Sobrien	    fatal ("invalid specification!  Bug in cc");
429818334Speter
429918334Speter	  case 'b':
430018334Speter	    obstack_grow (&obstack, input_basename, basename_length);
430118334Speter	    arg_going = 1;
430218334Speter	    break;
430318334Speter
430490277Sobrien	  case 'B':
430590277Sobrien	    obstack_grow (&obstack, input_basename, suffixed_basename_length);
430690277Sobrien	    arg_going = 1;
430790277Sobrien	    break;
430890277Sobrien
430918334Speter	  case 'd':
431018334Speter	    delete_this_arg = 2;
431118334Speter	    break;
431218334Speter
431318334Speter	  /* Dump out the directories specified with LIBRARY_PATH,
431418334Speter	     followed by the absolute directories
431518334Speter	     that we search for startfiles.  */
431618334Speter	  case 'D':
431718334Speter	    {
431818334Speter	      struct prefix_list *pl = startfile_prefixes.plist;
431950599Sobrien	      size_t bufsize = 100;
432018334Speter	      char *buffer = (char *) xmalloc (bufsize);
432118334Speter	      int idx;
432218334Speter
432318334Speter	      for (; pl; pl = pl->next)
432418334Speter		{
432518334Speter#ifdef RELATIVE_PREFIX_NOT_LINKDIR
432618334Speter		  /* Used on systems which record the specified -L dirs
432718334Speter		     and use them to search for dynamic linking.  */
432818334Speter		  /* Relative directories always come from -B,
432918334Speter		     and it is better not to use them for searching
433090277Sobrien		     at run time.  In particular, stage1 loses.  */
433190277Sobrien		  if (!IS_ABSOLUTE_PATHNAME (pl->prefix))
433218334Speter		    continue;
433318334Speter#endif
433418334Speter		  /* Try subdirectory if there is one.  */
4335104763Skan		  if (multilib_dir != NULL
4336104763Skan		      || (pl->os_multilib && multilib_os_dir != NULL))
433718334Speter		    {
4338104763Skan		      const char *multi_dir;
4339104763Skan
4340104763Skan		      multi_dir = pl->os_multilib ? multilib_os_dir
4341104763Skan						  : multilib_dir;
4342104763Skan		      if (machine_suffix && multilib_dir)
434318334Speter			{
434418334Speter			  if (strlen (pl->prefix) + strlen (machine_suffix)
434518334Speter			      >= bufsize)
434618334Speter			    bufsize = (strlen (pl->prefix)
434718334Speter				       + strlen (machine_suffix)) * 2 + 1;
434818334Speter			  buffer = (char *) xrealloc (buffer, bufsize);
434918334Speter			  strcpy (buffer, pl->prefix);
435018334Speter			  strcat (buffer, machine_suffix);
435118334Speter			  if (is_directory (buffer, multilib_dir, 1))
435218334Speter			    {
435390277Sobrien			      do_spec_1 ("-L", 0, NULL);
435418334Speter#ifdef SPACE_AFTER_L_OPTION
435590277Sobrien			      do_spec_1 (" ", 0, NULL);
435618334Speter#endif
435790277Sobrien			      do_spec_1 (buffer, 1, NULL);
435890277Sobrien			      do_spec_1 (multilib_dir, 1, NULL);
435918334Speter			      /* Make this a separate argument.  */
436090277Sobrien			      do_spec_1 (" ", 0, NULL);
436118334Speter			    }
436218334Speter			}
436318334Speter		      if (!pl->require_machine_suffix)
436418334Speter			{
4365104763Skan			  if (is_directory (pl->prefix, multi_dir, 1))
436618334Speter			    {
436790277Sobrien			      do_spec_1 ("-L", 0, NULL);
436818334Speter#ifdef SPACE_AFTER_L_OPTION
436990277Sobrien			      do_spec_1 (" ", 0, NULL);
437018334Speter#endif
437190277Sobrien			      do_spec_1 (pl->prefix, 1, NULL);
4372104763Skan			      do_spec_1 (multi_dir, 1, NULL);
437318334Speter			      /* Make this a separate argument.  */
437490277Sobrien			      do_spec_1 (" ", 0, NULL);
437518334Speter			    }
437618334Speter			}
437718334Speter		    }
437818334Speter		  if (machine_suffix)
437918334Speter		    {
438018334Speter		      if (is_directory (pl->prefix, machine_suffix, 1))
438118334Speter			{
438290277Sobrien			  do_spec_1 ("-L", 0, NULL);
438318334Speter#ifdef SPACE_AFTER_L_OPTION
438490277Sobrien			  do_spec_1 (" ", 0, NULL);
438518334Speter#endif
438690277Sobrien			  do_spec_1 (pl->prefix, 1, NULL);
438718334Speter			  /* Remove slash from machine_suffix.  */
438818334Speter			  if (strlen (machine_suffix) >= bufsize)
438918334Speter			    bufsize = strlen (machine_suffix) * 2 + 1;
439018334Speter			  buffer = (char *) xrealloc (buffer, bufsize);
439118334Speter			  strcpy (buffer, machine_suffix);
439218334Speter			  idx = strlen (buffer);
439352520Sobrien			  if (IS_DIR_SEPARATOR (buffer[idx - 1]))
439418334Speter			    buffer[idx - 1] = 0;
439590277Sobrien			  do_spec_1 (buffer, 1, NULL);
439618334Speter			  /* Make this a separate argument.  */
439790277Sobrien			  do_spec_1 (" ", 0, NULL);
439818334Speter			}
439918334Speter		    }
440018334Speter		  if (!pl->require_machine_suffix)
440118334Speter		    {
440218334Speter		      if (is_directory (pl->prefix, "", 1))
440318334Speter			{
440490277Sobrien			  do_spec_1 ("-L", 0, NULL);
440518334Speter#ifdef SPACE_AFTER_L_OPTION
440690277Sobrien			  do_spec_1 (" ", 0, NULL);
440718334Speter#endif
440818334Speter			  /* Remove slash from pl->prefix.  */
440918334Speter			  if (strlen (pl->prefix) >= bufsize)
441018334Speter			    bufsize = strlen (pl->prefix) * 2 + 1;
441118334Speter			  buffer = (char *) xrealloc (buffer, bufsize);
441218334Speter			  strcpy (buffer, pl->prefix);
441318334Speter			  idx = strlen (buffer);
441452520Sobrien			  if (IS_DIR_SEPARATOR (buffer[idx - 1]))
441518334Speter			    buffer[idx - 1] = 0;
441690277Sobrien			  do_spec_1 (buffer, 1, NULL);
441718334Speter			  /* Make this a separate argument.  */
441890277Sobrien			  do_spec_1 (" ", 0, NULL);
441918334Speter			}
442018334Speter		    }
442118334Speter		}
442218334Speter	      free (buffer);
442318334Speter	    }
442418334Speter	    break;
442518334Speter
442618334Speter	  case 'e':
442752520Sobrien	    /* %efoo means report an error with `foo' as error message
442818334Speter	       and don't execute any more commands for this file.  */
442918334Speter	    {
443052520Sobrien	      const char *q = p;
443118334Speter	      char *buf;
443290277Sobrien	      while (*p != 0 && *p != '\n')
443390277Sobrien		p++;
443418334Speter	      buf = (char *) alloca (p - q + 1);
443518334Speter	      strncpy (buf, q, p - q);
443618334Speter	      buf[p - q] = 0;
443790277Sobrien	      error ("%s", buf);
443818334Speter	      return -1;
443918334Speter	    }
444018334Speter	    break;
444190277Sobrien	  case 'n':
4442117413Skan	    /* %nfoo means report a notice with `foo' on stderr.  */
444390277Sobrien	    {
444490277Sobrien	      const char *q = p;
444590277Sobrien	      char *buf;
444690277Sobrien	      while (*p != 0 && *p != '\n')
444790277Sobrien		p++;
444890277Sobrien	      buf = (char *) alloca (p - q + 1);
444990277Sobrien	      strncpy (buf, q, p - q);
445090277Sobrien	      buf[p - q] = 0;
445190277Sobrien	      notice ("%s\n", buf);
445290277Sobrien	      if (*p)
445390277Sobrien		p++;
445490277Sobrien	    }
445590277Sobrien	    break;
445618334Speter
445790277Sobrien	  case 'j':
445890277Sobrien	    {
445990277Sobrien	      struct stat st;
446090277Sobrien
446190277Sobrien	      /* If save_temps_flag is off, and the HOST_BIT_BUCKET is defined,
446290277Sobrien		 and it is not a directory, and it is writable, use it.
446390277Sobrien		 Otherwise, fall through and treat this like any other
446490277Sobrien		 temporary file.  */
446590277Sobrien
446690277Sobrien	      if ((!save_temps_flag)
446790277Sobrien		  && (stat (HOST_BIT_BUCKET, &st) == 0) && (!S_ISDIR (st.st_mode))
446890277Sobrien		  && (access (HOST_BIT_BUCKET, W_OK) == 0))
446990277Sobrien		{
447090277Sobrien		  obstack_grow (&obstack, HOST_BIT_BUCKET,
447190277Sobrien				strlen (HOST_BIT_BUCKET));
447290277Sobrien		  delete_this_arg = 0;
447390277Sobrien		  arg_going = 1;
447490277Sobrien		  break;
447590277Sobrien		}
447690277Sobrien	    }
447718334Speter	  case 'g':
447818334Speter	  case 'u':
447918334Speter	  case 'U':
448018334Speter	      {
448118334Speter		struct temp_name *t;
448250599Sobrien		int suffix_length;
448352520Sobrien		const char *suffix = p;
448490277Sobrien		char *saved_suffix = NULL;
448518334Speter
448690277Sobrien		while (*p == '.' || ISALPHA ((unsigned char) *p))
448790277Sobrien		  p++;
448890277Sobrien		suffix_length = p - suffix;
448950599Sobrien		if (p[0] == '%' && p[1] == 'O')
449050599Sobrien		  {
449150599Sobrien		    p += 2;
449250599Sobrien		    /* We don't support extra suffix characters after %O.  */
449390277Sobrien		    if (*p == '.' || ISALPHA ((unsigned char) *p))
449450599Sobrien		      abort ();
449590277Sobrien		    if (suffix_length == 0)
449690277Sobrien		      suffix = TARGET_OBJECT_SUFFIX;
449790277Sobrien		    else
449890277Sobrien		      {
449990277Sobrien			saved_suffix
450090277Sobrien			  = (char *) xmalloc (suffix_length
450190277Sobrien					      + strlen (TARGET_OBJECT_SUFFIX));
450290277Sobrien			strncpy (saved_suffix, suffix, suffix_length);
450390277Sobrien			strcpy (saved_suffix + suffix_length,
450490277Sobrien				TARGET_OBJECT_SUFFIX);
450590277Sobrien		      }
450690277Sobrien		    suffix_length += strlen (TARGET_OBJECT_SUFFIX);
450750599Sobrien		  }
4508117413Skan
450990277Sobrien		/* If the input_filename has the same suffix specified
451090277Sobrien		   for the %g, %u, or %U, and -save-temps is specified,
451190277Sobrien		   we could end up using that file as an intermediate
451290277Sobrien		   thus clobbering the user's source file (.e.g.,
451390277Sobrien		   gcc -save-temps foo.s would clobber foo.s with the
451490277Sobrien		   output of cpp0).  So check for this condition and
451590277Sobrien		   generate a temp file as the intermediate.  */
4516117413Skan
451790277Sobrien		if (save_temps_flag)
451850599Sobrien		  {
451990277Sobrien		    temp_filename_length = basename_length + suffix_length;
452090277Sobrien		    temp_filename = alloca (temp_filename_length + 1);
452190277Sobrien		    strncpy ((char *) temp_filename, input_basename, basename_length);
452290277Sobrien		    strncpy ((char *) temp_filename + basename_length, suffix,
452390277Sobrien		    	     suffix_length);
452490277Sobrien		    *((char *) temp_filename + temp_filename_length) = '\0';
452590277Sobrien		    if (strcmp (temp_filename, input_filename) != 0)
452690277Sobrien		      {
452790277Sobrien		      	struct stat st_temp;
4528117413Skan
452990277Sobrien		      	/* Note, set_input() resets input_stat_set to 0.  */
453090277Sobrien		      	if (input_stat_set == 0)
453190277Sobrien		      	  {
453290277Sobrien		      	    input_stat_set = stat (input_filename, &input_stat);
453390277Sobrien		      	    if (input_stat_set >= 0)
453490277Sobrien		      	      input_stat_set = 1;
453590277Sobrien		      	  }
4536117413Skan
453790277Sobrien		      	/* If we have the stat for the input_filename
453890277Sobrien		      	   and we can do the stat for the temp_filename
453990277Sobrien		      	   then the they could still refer to the same
454090277Sobrien		      	   file if st_dev/st_ino's are the same.  */
4541117413Skan
454290277Sobrien			if (input_stat_set != 1
454390277Sobrien			    || stat (temp_filename, &st_temp) < 0
454490277Sobrien			    || input_stat.st_dev != st_temp.st_dev
454590277Sobrien			    || input_stat.st_ino != st_temp.st_ino)
4546117413Skan			  {
454790277Sobrien			    temp_filename = save_string (temp_filename,
454890277Sobrien							 temp_filename_length + 1);
454990277Sobrien			    obstack_grow (&obstack, temp_filename,
455090277Sobrien			    			    temp_filename_length);
455190277Sobrien			    arg_going = 1;
4552117413Skan			    delete_this_arg = 0;
455390277Sobrien			    break;
455490277Sobrien			  }
455590277Sobrien		      }
455650599Sobrien		  }
455750599Sobrien
455818334Speter		/* See if we already have an association of %g/%u/%U and
455918334Speter		   suffix.  */
456018334Speter		for (t = temp_names; t; t = t->next)
456150599Sobrien		  if (t->length == suffix_length
456250599Sobrien		      && strncmp (t->suffix, suffix, suffix_length) == 0
456318334Speter		      && t->unique == (c != 'g'))
456418334Speter		    break;
456518334Speter
456690277Sobrien		/* Make a new association if needed.  %u and %j
456790277Sobrien		   require one.  */
456890277Sobrien		if (t == 0 || c == 'u' || c == 'j')
456918334Speter		  {
457018334Speter		    if (t == 0)
457118334Speter		      {
457218334Speter			t = (struct temp_name *) xmalloc (sizeof (struct temp_name));
457318334Speter			t->next = temp_names;
457418334Speter			temp_names = t;
457518334Speter		      }
457650599Sobrien		    t->length = suffix_length;
457790277Sobrien		    if (saved_suffix)
457890277Sobrien		      {
457990277Sobrien			t->suffix = saved_suffix;
458090277Sobrien			saved_suffix = NULL;
458190277Sobrien		      }
458290277Sobrien		    else
458390277Sobrien		      t->suffix = save_string (suffix, suffix_length);
458418334Speter		    t->unique = (c != 'g');
458550599Sobrien		    temp_filename = make_temp_file (t->suffix);
458650599Sobrien		    temp_filename_length = strlen (temp_filename);
458718334Speter		    t->filename = temp_filename;
458818334Speter		    t->filename_length = temp_filename_length;
458918334Speter		  }
459018334Speter
459190277Sobrien		if (saved_suffix)
459290277Sobrien		  free (saved_suffix);
459390277Sobrien
459418334Speter		obstack_grow (&obstack, t->filename, t->filename_length);
459518334Speter		delete_this_arg = 1;
459618334Speter	      }
459718334Speter	    arg_going = 1;
459818334Speter	    break;
459918334Speter
460018334Speter	  case 'i':
460118334Speter	    obstack_grow (&obstack, input_filename, input_filename_length);
460218334Speter	    arg_going = 1;
460318334Speter	    break;
460418334Speter
460518334Speter	  case 'I':
460618334Speter	    {
460718334Speter	      struct prefix_list *pl = include_prefixes.plist;
460818334Speter
460918334Speter	      if (gcc_exec_prefix)
461018334Speter		{
461190277Sobrien		  do_spec_1 ("-iprefix", 1, NULL);
461218334Speter		  /* Make this a separate argument.  */
461390277Sobrien		  do_spec_1 (" ", 0, NULL);
461490277Sobrien		  do_spec_1 (gcc_exec_prefix, 1, NULL);
461590277Sobrien		  do_spec_1 (" ", 0, NULL);
461618334Speter		}
461718334Speter
461818334Speter	      for (; pl; pl = pl->next)
461918334Speter		{
462090277Sobrien		  do_spec_1 ("-isystem", 1, NULL);
462118334Speter		  /* Make this a separate argument.  */
462290277Sobrien		  do_spec_1 (" ", 0, NULL);
462390277Sobrien		  do_spec_1 (pl->prefix, 1, NULL);
462490277Sobrien		  do_spec_1 (" ", 0, NULL);
462518334Speter		}
462618334Speter	    }
462718334Speter	    break;
462818334Speter
462918334Speter	  case 'o':
463052520Sobrien	    {
463152520Sobrien	      int max = n_infiles;
463252520Sobrien	      max += lang_specific_extra_outfiles;
463318334Speter
463452520Sobrien	      for (i = 0; i < max; i++)
463552520Sobrien		if (outfiles[i])
463652520Sobrien		  store_arg (outfiles[i], 0, 0);
463752520Sobrien	      break;
463852520Sobrien	    }
463952520Sobrien
464018334Speter	  case 'O':
464190277Sobrien	    obstack_grow (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
464218334Speter	    arg_going = 1;
464318334Speter	    break;
464418334Speter
464518334Speter	  case 's':
464618334Speter	    this_is_library_file = 1;
464718334Speter	    break;
464818334Speter
464918334Speter	  case 'w':
465018334Speter	    this_is_output_file = 1;
465118334Speter	    break;
465218334Speter
465318334Speter	  case 'W':
465418334Speter	    {
465550599Sobrien	      int cur_index = argbuf_index;
465618334Speter	      /* Handle the {...} following the %W.  */
465718334Speter	      if (*p != '{')
465818334Speter		abort ();
465918334Speter	      p = handle_braces (p + 1);
466018334Speter	      if (p == 0)
466118334Speter		return -1;
466218334Speter	      /* If any args were output, mark the last one for deletion
466318334Speter		 on failure.  */
466450599Sobrien	      if (argbuf_index != cur_index)
466518334Speter		record_temp_file (argbuf[argbuf_index - 1], 0, 1);
466618334Speter	      break;
466718334Speter	    }
466818334Speter
466918334Speter	  /* %x{OPTION} records OPTION for %X to output.  */
467018334Speter	  case 'x':
467118334Speter	    {
467252520Sobrien	      const char *p1 = p;
467318334Speter	      char *string;
467418334Speter
467518334Speter	      /* Skip past the option value and make a copy.  */
467618334Speter	      if (*p != '{')
467718334Speter		abort ();
467818334Speter	      while (*p++ != '}')
467918334Speter		;
468018334Speter	      string = save_string (p1 + 1, p - p1 - 2);
468118334Speter
468218334Speter	      /* See if we already recorded this option.  */
468318334Speter	      for (i = 0; i < n_linker_options; i++)
468418334Speter		if (! strcmp (string, linker_options[i]))
468518334Speter		  {
468618334Speter		    free (string);
468718334Speter		    return 0;
468818334Speter		  }
468918334Speter
469018334Speter	      /* This option is new; add it.  */
469150599Sobrien	      add_linker_option (string, strlen (string));
469218334Speter	    }
469318334Speter	    break;
469418334Speter
469518334Speter	  /* Dump out the options accumulated previously using %x.  */
469618334Speter	  case 'X':
469718334Speter	    for (i = 0; i < n_linker_options; i++)
469818334Speter	      {
469990277Sobrien		do_spec_1 (linker_options[i], 1, NULL);
470018334Speter		/* Make each accumulated option a separate argument.  */
470190277Sobrien		do_spec_1 (" ", 0, NULL);
470218334Speter	      }
470318334Speter	    break;
470418334Speter
470518334Speter	  /* Dump out the options accumulated previously using -Wa,.  */
470618334Speter	  case 'Y':
470718334Speter	    for (i = 0; i < n_assembler_options; i++)
470818334Speter	      {
470990277Sobrien		do_spec_1 (assembler_options[i], 1, NULL);
471018334Speter		/* Make each accumulated option a separate argument.  */
471190277Sobrien		do_spec_1 (" ", 0, NULL);
471218334Speter	      }
471318334Speter	    break;
471418334Speter
471518334Speter	  /* Dump out the options accumulated previously using -Wp,.  */
471618334Speter	  case 'Z':
471718334Speter	    for (i = 0; i < n_preprocessor_options; i++)
471818334Speter	      {
471990277Sobrien		do_spec_1 (preprocessor_options[i], 1, NULL);
472018334Speter		/* Make each accumulated option a separate argument.  */
472190277Sobrien		do_spec_1 (" ", 0, NULL);
472218334Speter	      }
472318334Speter	    break;
472418334Speter
472518334Speter	    /* Here are digits and numbers that just process
472618334Speter	       a certain constant string as a spec.  */
472718334Speter
472818334Speter	  case '1':
472990277Sobrien	    value = do_spec_1 (cc1_spec, 0, NULL);
473018334Speter	    if (value != 0)
473118334Speter	      return value;
473218334Speter	    break;
473318334Speter
473418334Speter	  case '2':
473590277Sobrien	    value = do_spec_1 (cc1plus_spec, 0, NULL);
473618334Speter	    if (value != 0)
473718334Speter	      return value;
473818334Speter	    break;
473918334Speter
474018334Speter	  case 'a':
474190277Sobrien	    value = do_spec_1 (asm_spec, 0, NULL);
474218334Speter	    if (value != 0)
474318334Speter	      return value;
474418334Speter	    break;
474518334Speter
474618334Speter	  case 'A':
474790277Sobrien	    value = do_spec_1 (asm_final_spec, 0, NULL);
474818334Speter	    if (value != 0)
474918334Speter	      return value;
475018334Speter	    break;
475118334Speter
475218334Speter	  case 'C':
475390277Sobrien	    {
475490277Sobrien	      const char *const spec
4755117413Skan		= (input_file_compiler->cpp_spec
4756117413Skan		   ? input_file_compiler->cpp_spec
475790277Sobrien		   : cpp_spec);
475890277Sobrien	      value = do_spec_1 (spec, 0, NULL);
475990277Sobrien	      if (value != 0)
476090277Sobrien		return value;
476190277Sobrien	    }
476218334Speter	    break;
476318334Speter
476418334Speter	  case 'E':
476590277Sobrien	    value = do_spec_1 (endfile_spec, 0, NULL);
476618334Speter	    if (value != 0)
476718334Speter	      return value;
476818334Speter	    break;
476918334Speter
477018334Speter	  case 'l':
477190277Sobrien	    value = do_spec_1 (link_spec, 0, NULL);
477218334Speter	    if (value != 0)
477318334Speter	      return value;
477418334Speter	    break;
477518334Speter
477618334Speter	  case 'L':
477790277Sobrien	    value = do_spec_1 (lib_spec, 0, NULL);
477818334Speter	    if (value != 0)
477918334Speter	      return value;
478018334Speter	    break;
478118334Speter
478218334Speter	  case 'G':
478390277Sobrien	    value = do_spec_1 (libgcc_spec, 0, NULL);
478418334Speter	    if (value != 0)
478518334Speter	      return value;
478618334Speter	    break;
478718334Speter
478890277Sobrien	  case 'M':
478990277Sobrien	    if (multilib_dir && strcmp (multilib_dir, ".") != 0)
479090277Sobrien	      {
479190277Sobrien		char *p;
479290277Sobrien		const char *q;
479390277Sobrien		size_t len;
479490277Sobrien
479590277Sobrien		len = strlen (multilib_dir);
479690277Sobrien		obstack_blank (&obstack, len + 1);
479790277Sobrien		p = obstack_next_free (&obstack) - (len + 1);
479890277Sobrien
479990277Sobrien		*p++ = '_';
480090277Sobrien		for (q = multilib_dir; *q ; ++q, ++p)
480190277Sobrien		  *p = (IS_DIR_SEPARATOR (*q) ? '_' : *q);
480290277Sobrien	      }
480390277Sobrien	    break;
480490277Sobrien
480518334Speter	  case 'p':
480618334Speter	    {
480718334Speter	      char *x = (char *) alloca (strlen (cpp_predefines) + 1);
480818334Speter	      char *buf = x;
480990277Sobrien	      const char *y;
481018334Speter
481118334Speter	      /* Copy all of the -D options in CPP_PREDEFINES into BUF.  */
481218334Speter	      y = cpp_predefines;
481318334Speter	      while (*y != 0)
481418334Speter		{
481518334Speter		  if (! strncmp (y, "-D", 2))
481618334Speter		    /* Copy the whole option.  */
481718334Speter		    while (*y && *y != ' ' && *y != '\t')
481818334Speter		      *x++ = *y++;
481918334Speter		  else if (*y == ' ' || *y == '\t')
482018334Speter		    /* Copy whitespace to the result.  */
482118334Speter		    *x++ = *y++;
482218334Speter		  /* Don't copy other options.  */
482318334Speter		  else
482418334Speter		    y++;
482518334Speter		}
482618334Speter
482718334Speter	      *x = 0;
482818334Speter
482990277Sobrien	      value = do_spec_1 (buf, 0, NULL);
483018334Speter	      if (value != 0)
483118334Speter		return value;
483218334Speter	    }
483318334Speter	    break;
483418334Speter
483518334Speter	  case 'P':
483618334Speter	    {
483718334Speter	      char *x = (char *) alloca (strlen (cpp_predefines) * 4 + 1);
483818334Speter	      char *buf = x;
483990277Sobrien	      const char *y;
484018334Speter
484118334Speter	      /* Copy all of CPP_PREDEFINES into BUF,
484290277Sobrien		 but force them all into the reserved name space if they
484390277Sobrien		 aren't already there.  The reserved name space is all
484490277Sobrien		 identifiers beginning with two underscores or with one
484590277Sobrien		 underscore and a capital letter.  We do the forcing by
484690277Sobrien		 adding up to two underscores to the beginning and end
484790277Sobrien		 of each symbol. e.g. mips, _mips, mips_, and _mips_ all
484890277Sobrien		 become __mips__.  */
484918334Speter	      y = cpp_predefines;
485018334Speter	      while (*y != 0)
485118334Speter		{
485218334Speter		  if (! strncmp (y, "-D", 2))
485318334Speter		    {
485418334Speter		      int flag = 0;
485518334Speter
485618334Speter		      *x++ = *y++;
485718334Speter		      *x++ = *y++;
485818334Speter
485918334Speter		      if (*y != '_'
486090277Sobrien			  || (*(y + 1) != '_'
486190277Sobrien			      && ! ISUPPER ((unsigned char) *(y + 1))))
486290277Sobrien			{
486318334Speter			  /* Stick __ at front of macro name.  */
486490277Sobrien			  if (*y != '_')
486590277Sobrien			    *x++ = '_';
486618334Speter			  *x++ = '_';
486718334Speter			  /* Arrange to stick __ at the end as well.  */
486818334Speter			  flag = 1;
486918334Speter			}
487018334Speter
487118334Speter		      /* Copy the macro name.  */
487218334Speter		      while (*y && *y != '=' && *y != ' ' && *y != '\t')
487318334Speter			*x++ = *y++;
487418334Speter
487518334Speter		      if (flag)
487690277Sobrien			{
487790277Sobrien			  if (x[-1] != '_')
487890277Sobrien			    {
487990277Sobrien			      if (x[-2] != '_')
488090277Sobrien				*x++ = '_';
488190277Sobrien			      *x++ = '_';
488290277Sobrien			    }
488318334Speter			}
488418334Speter
488518334Speter		      /* Copy the value given, if any.  */
488618334Speter		      while (*y && *y != ' ' && *y != '\t')
488718334Speter			*x++ = *y++;
488818334Speter		    }
488918334Speter		  else if (*y == ' ' || *y == '\t')
489018334Speter		    /* Copy whitespace to the result.  */
489118334Speter		    *x++ = *y++;
489218334Speter		  /* Don't copy -A options  */
489318334Speter		  else
489418334Speter		    y++;
489518334Speter		}
489618334Speter	      *x++ = ' ';
489718334Speter
489818334Speter	      /* Copy all of CPP_PREDEFINES into BUF,
489918334Speter		 but put __ after every -D.  */
490018334Speter	      y = cpp_predefines;
490118334Speter	      while (*y != 0)
490218334Speter		{
490318334Speter		  if (! strncmp (y, "-D", 2))
490418334Speter		    {
490518334Speter		      y += 2;
490618334Speter
490718334Speter		      if (*y != '_'
490890277Sobrien			  || (*(y + 1) != '_'
490990277Sobrien			      && ! ISUPPER ((unsigned char) *(y + 1))))
491090277Sobrien			{
491118334Speter			  /* Stick -D__ at front of macro name.  */
491218334Speter			  *x++ = '-';
491318334Speter			  *x++ = 'D';
491490277Sobrien			  if (*y != '_')
491590277Sobrien			    *x++ = '_';
491618334Speter			  *x++ = '_';
491718334Speter
491818334Speter			  /* Copy the macro name.  */
491918334Speter			  while (*y && *y != '=' && *y != ' ' && *y != '\t')
492018334Speter			    *x++ = *y++;
492118334Speter
492218334Speter			  /* Copy the value given, if any.  */
492318334Speter			  while (*y && *y != ' ' && *y != '\t')
492418334Speter			    *x++ = *y++;
492518334Speter			}
492618334Speter		      else
492718334Speter			{
492818334Speter			  /* Do not copy this macro - we have just done it before */
492918334Speter			  while (*y && *y != ' ' && *y != '\t')
493018334Speter			    y++;
493118334Speter			}
493218334Speter		    }
493318334Speter		  else if (*y == ' ' || *y == '\t')
493418334Speter		    /* Copy whitespace to the result.  */
493518334Speter		    *x++ = *y++;
493690277Sobrien		  /* Don't copy -A options.  */
493718334Speter		  else
493818334Speter		    y++;
493918334Speter		}
494018334Speter	      *x++ = ' ';
494118334Speter
494218334Speter	      /* Copy all of the -A options in CPP_PREDEFINES into BUF.  */
494318334Speter	      y = cpp_predefines;
494418334Speter	      while (*y != 0)
494518334Speter		{
494618334Speter		  if (! strncmp (y, "-A", 2))
494718334Speter		    /* Copy the whole option.  */
494818334Speter		    while (*y && *y != ' ' && *y != '\t')
494918334Speter		      *x++ = *y++;
495018334Speter		  else if (*y == ' ' || *y == '\t')
495118334Speter		    /* Copy whitespace to the result.  */
495218334Speter		    *x++ = *y++;
495318334Speter		  /* Don't copy other options.  */
495418334Speter		  else
495518334Speter		    y++;
495618334Speter		}
495718334Speter
495818334Speter	      *x = 0;
495918334Speter
496090277Sobrien	      value = do_spec_1 (buf, 0, NULL);
496118334Speter	      if (value != 0)
496218334Speter		return value;
496318334Speter	    }
496418334Speter	    break;
496518334Speter
496618334Speter	  case 'S':
496790277Sobrien	    value = do_spec_1 (startfile_spec, 0, NULL);
496818334Speter	    if (value != 0)
496918334Speter	      return value;
497018334Speter	    break;
497118334Speter
497218334Speter	    /* Here we define characters other than letters and digits.  */
497318334Speter
497418334Speter	  case '{':
497518334Speter	    p = handle_braces (p);
497618334Speter	    if (p == 0)
497718334Speter	      return -1;
497818334Speter	    break;
497918334Speter
4980117413Skan	  case ':':
4981117413Skan	    p = handle_spec_function (p);
4982117413Skan	    if (p == 0)
4983117413Skan	      return -1;
4984117413Skan	    break;
4985117413Skan
498618334Speter	  case '%':
498718334Speter	    obstack_1grow (&obstack, '%');
498818334Speter	    break;
498918334Speter
4990117413Skan	  case '.':
4991117413Skan	    {
4992117413Skan	      unsigned len = 0;
499390277Sobrien
4994117413Skan	      while (p[len] && p[len] != ' ' && p[len] != '%')
4995117413Skan		len++;
4996117413Skan	      suffix_subst = save_string (p - 1, len + 1);
4997117413Skan	      p += len;
4998117413Skan	    }
499990277Sobrien	   break;
5000117413Skan
500118334Speter	  case '*':
500290277Sobrien	    if (soft_matched_part)
500390277Sobrien	      {
500490277Sobrien		do_spec_1 (soft_matched_part, 1, NULL);
500590277Sobrien		do_spec_1 (" ", 0, NULL);
500690277Sobrien	      }
500790277Sobrien	    else
500890277Sobrien	      /* Catch the case where a spec string contains something like
500990277Sobrien		 '%{foo:%*}'.  ie there is no * in the pattern on the left
501090277Sobrien		 hand side of the :.  */
501190277Sobrien	      error ("spec failure: '%%*' has not been initialized by pattern match");
501218334Speter	    break;
501318334Speter
501418334Speter	    /* Process a string found as the value of a spec given by name.
501518334Speter	       This feature allows individual machine descriptions
501618334Speter	       to add and use their own specs.
501718334Speter	       %[...] modifies -D options the way %P does;
501818334Speter	       %(...) uses the spec unmodified.  */
501950599Sobrien	  case '[':
502090277Sobrien	    error ("warning: use of obsolete %%[ operator in specs");
502118334Speter	  case '(':
502218334Speter	    {
502352520Sobrien	      const char *name = p;
502418334Speter	      struct spec_list *sl;
502518334Speter	      int len;
502618334Speter
502718334Speter	      /* The string after the S/P is the name of a spec that is to be
502850599Sobrien		 processed.  */
502918334Speter	      while (*p && *p != ')' && *p != ']')
503018334Speter		p++;
503118334Speter
503290277Sobrien	      /* See if it's in the list.  */
503318334Speter	      for (len = p - name, sl = specs; sl; sl = sl->next)
503450599Sobrien		if (sl->name_len == len && !strncmp (sl->name, name, len))
503518334Speter		  {
503650599Sobrien		    name = *(sl->ptr_spec);
503750599Sobrien#ifdef DEBUG_SPECS
503852520Sobrien		    notice ("Processing spec %c%s%c, which is '%s'\n",
503952520Sobrien			    c, sl->name, (c == '(') ? ')' : ']', name);
504050599Sobrien#endif
504118334Speter		    break;
504218334Speter		  }
504318334Speter
504418334Speter	      if (sl)
504518334Speter		{
504618334Speter		  if (c == '(')
504718334Speter		    {
504890277Sobrien		      value = do_spec_1 (name, 0, NULL);
504918334Speter		      if (value != 0)
505018334Speter			return value;
505118334Speter		    }
505218334Speter		  else
505318334Speter		    {
505418334Speter		      char *x = (char *) alloca (strlen (name) * 2 + 1);
505518334Speter		      char *buf = x;
505652520Sobrien		      const char *y = name;
505750599Sobrien		      int flag = 0;
505818334Speter
505918334Speter		      /* Copy all of NAME into BUF, but put __ after
506090277Sobrien			 every -D and at the end of each arg.  */
506118334Speter		      while (1)
506218334Speter			{
506318334Speter			  if (! strncmp (y, "-D", 2))
506418334Speter			    {
506518334Speter			      *x++ = '-';
506618334Speter			      *x++ = 'D';
506718334Speter			      *x++ = '_';
506818334Speter			      *x++ = '_';
506918334Speter			      y += 2;
507050599Sobrien			      flag = 1;
507150599Sobrien			      continue;
507218334Speter			    }
507390277Sobrien			  else if (flag
507490277Sobrien				   && (*y == ' ' || *y == '\t' || *y == '='
507590277Sobrien				       || *y == '}' || *y == 0))
507618334Speter			    {
507718334Speter			      *x++ = '_';
507818334Speter			      *x++ = '_';
507950599Sobrien			      flag = 0;
508018334Speter			    }
508190277Sobrien			  if (*y == 0)
508250599Sobrien			    break;
508318334Speter			  else
508418334Speter			    *x++ = *y++;
508518334Speter			}
508618334Speter		      *x = 0;
508718334Speter
508890277Sobrien		      value = do_spec_1 (buf, 0, NULL);
508918334Speter		      if (value != 0)
509018334Speter			return value;
509118334Speter		    }
509218334Speter		}
509318334Speter
509418334Speter	      /* Discard the closing paren or bracket.  */
509518334Speter	      if (*p)
509618334Speter		p++;
509718334Speter	    }
509818334Speter	    break;
509918334Speter
510018334Speter	  case 'v':
510118334Speter	    {
510218334Speter	      int c1 = *p++;  /* Select first or second version number.  */
510390277Sobrien	      const char *v = compiler_version;
510490277Sobrien	      const char *q;
510590277Sobrien	      static const char zeroc = '0';
510650599Sobrien
510750599Sobrien	      /* The format of the version string is
510850599Sobrien		 ([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)?  */
510950599Sobrien
511050599Sobrien	      /* Ignore leading non-digits.  i.e. "foo-" in "foo-2.7.2".  */
511150599Sobrien	      while (! ISDIGIT (*v))
511250599Sobrien		v++;
511350599Sobrien	      if (v > compiler_version && v[-1] != '-')
511450599Sobrien		abort ();
511550599Sobrien
511618334Speter	      /* If desired, advance to second version number.  */
511790277Sobrien	      if (c1 >= '2')
511818334Speter		{
511950599Sobrien		  /* Set V after the first period.  */
512050599Sobrien		  while (ISDIGIT (*v))
512118334Speter		    v++;
512250599Sobrien		  if (*v != '.')
512350599Sobrien		    abort ();
512450599Sobrien		  v++;
512518334Speter		}
512650599Sobrien
512790277Sobrien	      /* If desired, advance to third version number.
512890277Sobrien                 But don't complain if it's not present */
512990277Sobrien	      if (c1 == '3')
513090277Sobrien		{
513190277Sobrien		  /* Set V after the second period.  */
513290277Sobrien		  while (ISDIGIT (*v))
513390277Sobrien		    v++;
513490277Sobrien		  if ((*v != 0) && (*v != ' ') && (*v != '.') && (*v != '-'))
513590277Sobrien		    abort ();
513690277Sobrien		  if (*v != 0)
513790277Sobrien		    v++;
513890277Sobrien		}
513990277Sobrien
514018334Speter	      /* Set Q at the next period or at the end.  */
514118334Speter	      q = v;
514250599Sobrien	      while (ISDIGIT (*q))
514318334Speter		q++;
514490277Sobrien	      if (*q != 0 && q > v && *q != ' ' && *q != '.' && *q != '-')
514550599Sobrien		abort ();
514650599Sobrien
514790277Sobrien	      if (q > v)
514890277Sobrien		/* Put that part into the command.  */
514990277Sobrien		obstack_grow (&obstack, v, q - v);
515090277Sobrien	      else
515190277Sobrien		/* Default to "0" */
515290277Sobrien		obstack_grow (&obstack, &zeroc, 1);
515318334Speter	      arg_going = 1;
515418334Speter	    }
515518334Speter	    break;
515618334Speter
515718334Speter	  case '|':
515818334Speter	    if (input_from_pipe)
515990277Sobrien	      do_spec_1 ("-", 0, NULL);
516018334Speter	    break;
516118334Speter
516218334Speter	  default:
516390277Sobrien	    error ("spec failure: unrecognized spec option '%c'", c);
516490277Sobrien	    break;
516518334Speter	  }
516618334Speter	break;
516718334Speter
516818334Speter      case '\\':
516918334Speter	/* Backslash: treat next character as ordinary.  */
517018334Speter	c = *p++;
517118334Speter
517218334Speter	/* fall through */
517318334Speter      default:
517418334Speter	/* Ordinary character: put it into the current argument.  */
517518334Speter	obstack_1grow (&obstack, c);
517618334Speter	arg_going = 1;
517718334Speter      }
517818334Speter
5179117413Skan  /* End of string.  If we are processing a spec function, we need to
5180117413Skan     end any pending argument.  */
5181117413Skan  if (processing_spec_function && arg_going)
5182117413Skan    {
5183117413Skan      obstack_1grow (&obstack, 0);
5184117413Skan      string = obstack_finish (&obstack);
5185117413Skan      if (this_is_library_file)
5186117413Skan        string = find_file (string);
5187117413Skan      store_arg (string, delete_this_arg, this_is_output_file);
5188117413Skan      if (this_is_output_file)
5189117413Skan        outfiles[input_file_number] = string;
5190117413Skan      arg_going = 0;
5191117413Skan    }
5192117413Skan
519390277Sobrien  return 0;
519418334Speter}
519518334Speter
5196117413Skan/* Look up a spec function.  */
5197117413Skan
5198117413Skanstatic const struct spec_function *
5199117413Skanlookup_spec_function (name)
5200117413Skan     const char *name;
5201117413Skan{
5202117413Skan  static const struct spec_function * const spec_function_tables[] =
5203117413Skan  {
5204117413Skan    static_spec_functions,
5205117413Skan    lang_specific_spec_functions,
5206117413Skan  };
5207117413Skan  const struct spec_function *sf;
5208117413Skan  unsigned int i;
5209117413Skan
5210117413Skan  for (i = 0; i < ARRAY_SIZE (spec_function_tables); i++)
5211117413Skan    {
5212117413Skan      for (sf = spec_function_tables[i]; sf->name != NULL; sf++)
5213117413Skan	if (strcmp (sf->name, name) == 0)
5214117413Skan	  return sf;
5215117413Skan    }
5216117413Skan
5217117413Skan  return NULL;
5218117413Skan}
5219117413Skan
5220117413Skan/* Evaluate a spec function.  */
5221117413Skan
5222117413Skanstatic const char *
5223117413Skaneval_spec_function (func, args)
5224117413Skan     const char *func, *args;
5225117413Skan{
5226117413Skan  const struct spec_function *sf;
5227117413Skan  const char *funcval;
5228117413Skan
5229117413Skan  /* Saved spec processing context.  */
5230117413Skan  int save_argbuf_index;
5231117413Skan  int save_argbuf_length;
5232117413Skan  const char **save_argbuf;
5233117413Skan
5234117413Skan  int save_arg_going;
5235117413Skan  int save_delete_this_arg;
5236117413Skan  int save_this_is_output_file;
5237117413Skan  int save_this_is_library_file;
5238117413Skan  int save_input_from_pipe;
5239117413Skan  const char *save_suffix_subst;
5240117413Skan
5241117413Skan
5242117413Skan  sf = lookup_spec_function (func);
5243117413Skan  if (sf == NULL)
5244117413Skan    fatal ("unknown spec function `%s'", func);
5245117413Skan
5246117413Skan  /* Push the spec processing context.  */
5247117413Skan  save_argbuf_index = argbuf_index;
5248117413Skan  save_argbuf_length = argbuf_length;
5249117413Skan  save_argbuf = argbuf;
5250117413Skan
5251117413Skan  save_arg_going = arg_going;
5252117413Skan  save_delete_this_arg = delete_this_arg;
5253117413Skan  save_this_is_output_file = this_is_output_file;
5254117413Skan  save_this_is_library_file = this_is_library_file;
5255117413Skan  save_input_from_pipe = input_from_pipe;
5256117413Skan  save_suffix_subst = suffix_subst;
5257117413Skan
5258117413Skan  /* Create a new spec processing context, and build the function
5259117413Skan     arguments.  */
5260117413Skan
5261117413Skan  alloc_args ();
5262117413Skan  if (do_spec_2 (args) < 0)
5263117413Skan    fatal ("error in args to spec function `%s'", func);
5264117413Skan
5265117413Skan  /* argbuf_index is an index for the next argument to be inserted, and
5266117413Skan     so contains the count of the args already inserted.  */
5267117413Skan
5268117413Skan  funcval = (*sf->func) (argbuf_index, argbuf);
5269117413Skan
5270117413Skan  /* Pop the spec processing context.  */
5271117413Skan  argbuf_index = save_argbuf_index;
5272117413Skan  argbuf_length = save_argbuf_length;
5273117413Skan  free (argbuf);
5274117413Skan  argbuf = save_argbuf;
5275117413Skan
5276117413Skan  arg_going = save_arg_going;
5277117413Skan  delete_this_arg = save_delete_this_arg;
5278117413Skan  this_is_output_file = save_this_is_output_file;
5279117413Skan  this_is_library_file = save_this_is_library_file;
5280117413Skan  input_from_pipe = save_input_from_pipe;
5281117413Skan  suffix_subst = save_suffix_subst;
5282117413Skan
5283117413Skan  return funcval;
5284117413Skan}
5285117413Skan
5286117413Skan/* Handle a spec function call of the form:
5287117413Skan
5288117413Skan   %:function(args)
5289117413Skan
5290117413Skan   ARGS is processed as a spec in a separate context and split into an
5291117413Skan   argument vector in the normal fashion.  The function returns a string
5292117413Skan   containing a spec which we then process in the caller's context, or
5293117413Skan   NULL if no processing is required.  */
5294117413Skan
5295117413Skanstatic const char *
5296117413Skanhandle_spec_function (p)
5297117413Skan     const char *p;
5298117413Skan{
5299117413Skan  char *func, *args;
5300117413Skan  const char *endp, *funcval;
5301117413Skan  int count;
5302117413Skan
5303117413Skan  processing_spec_function++;
5304117413Skan
5305117413Skan  /* Get the function name.  */
5306117413Skan  for (endp = p; *endp != '\0'; endp++)
5307117413Skan    {
5308117413Skan      if (*endp == '(')		/* ) */
5309117413Skan        break;
5310117413Skan      /* Only allow [A-Za-z0-9], -, and _ in function names.  */
5311117413Skan      if (!ISALNUM (*endp) && !(*endp == '-' || *endp == '_'))
5312117413Skan	fatal ("malformed spec function name");
5313117413Skan    }
5314117413Skan  if (*endp != '(')		/* ) */
5315117413Skan    fatal ("no arguments for spec function");
5316117413Skan  func = save_string (p, endp - p);
5317117413Skan  p = ++endp;
5318117413Skan
5319117413Skan  /* Get the arguments.  */
5320117413Skan  for (count = 0; *endp != '\0'; endp++)
5321117413Skan    {
5322117413Skan      /* ( */
5323117413Skan      if (*endp == ')')
5324117413Skan	{
5325117413Skan	  if (count == 0)
5326117413Skan	    break;
5327117413Skan	  count--;
5328117413Skan	}
5329117413Skan      else if (*endp == '(')	/* ) */
5330117413Skan	count++;
5331117413Skan    }
5332117413Skan  /* ( */
5333117413Skan  if (*endp != ')')
5334117413Skan    fatal ("malformed spec function arguments");
5335117413Skan  args = save_string (p, endp - p);
5336117413Skan  p = ++endp;
5337117413Skan
5338117413Skan  /* p now points to just past the end of the spec function expression.  */
5339117413Skan
5340117413Skan  funcval = eval_spec_function (func, args);
5341117413Skan  if (funcval != NULL && do_spec_1 (funcval, 0, NULL) < 0)
5342117413Skan    p = NULL;
5343117413Skan
5344117413Skan  free (func);
5345117413Skan  free (args);
5346117413Skan
5347117413Skan  processing_spec_function--;
5348117413Skan
5349117413Skan  return p;
5350117413Skan}
5351117413Skan
535218334Speter/* Return 0 if we call do_spec_1 and that returns -1.  */
535318334Speter
535452520Sobrienstatic const char *
535518334Speterhandle_braces (p)
535690277Sobrien     const char *p;
535718334Speter{
535852520Sobrien  const char *filter, *body = NULL, *endbody = NULL;
535950599Sobrien  int pipe_p = 0;
536090277Sobrien  int true_once = 0;	/* If, in %{a|b:d}, at least one of a,b was seen.  */
536150599Sobrien  int negate;
536250599Sobrien  int suffix;
536350599Sobrien  int include_blanks = 1;
536490277Sobrien  int elide_switch = 0;
536590277Sobrien  int ordered = 0;
536618334Speter
536750599Sobrien  if (*p == '^')
536890277Sobrien    {
536990277Sobrien      /* A '^' after the open-brace means to not give blanks before args.  */
537090277Sobrien      include_blanks = 0;
537190277Sobrien      ++p;
537290277Sobrien    }
537350599Sobrien
537418334Speter  if (*p == '|')
537590277Sobrien    {
537690277Sobrien      /* A `|' after the open-brace means,
537790277Sobrien	 if the test fails, output a single minus sign rather than nothing.
537890277Sobrien	 This is used in %{|!pipe:...}.  */
537990277Sobrien      pipe_p = 1;
538090277Sobrien      ++p;
538190277Sobrien    }
538218334Speter
538390277Sobrien  if (*p == '<')
538490277Sobrien    {
538590277Sobrien      /* A `<' after the open-brace means that the switch should be
538690277Sobrien	 removed from the command-line.  */
538790277Sobrien      elide_switch = 1;
538890277Sobrien      ++p;
538990277Sobrien    }
539090277Sobrien
539150599Sobriennext_member:
539250599Sobrien  negate = suffix = 0;
539350599Sobrien
539418334Speter  if (*p == '!')
539518334Speter    /* A `!' after the open-brace negates the condition:
539618334Speter       succeed if the specified switch is not present.  */
539718334Speter    negate = 1, ++p;
539818334Speter
539918334Speter  if (*p == '.')
540018334Speter    /* A `.' after the open-brace means test against the current suffix.  */
540118334Speter    {
540250599Sobrien      if (pipe_p)
540318334Speter	abort ();
540418334Speter
540518334Speter      suffix = 1;
540618334Speter      ++p;
540718334Speter    }
540818334Speter
540990277Sobrien  if (elide_switch && (negate || pipe_p || suffix))
541090277Sobrien    {
541190277Sobrien      /* It doesn't make sense to mix elision with other flags.  We
541290277Sobrien	 could fatal() here, but the standard seems to be to abort.  */
541390277Sobrien      abort ();
541490277Sobrien    }
541590277Sobrien
541690277Sobrien next_ampersand:
541718334Speter  filter = p;
541890277Sobrien  while (*p != ':' && *p != '}' && *p != '|' && *p != '&')
541990277Sobrien    p++;
542050599Sobrien
542190277Sobrien  if (*p == '|' && (pipe_p || ordered))
542250599Sobrien    abort ();
542350599Sobrien
542450599Sobrien  if (!body)
542518334Speter    {
542690277Sobrien      if (*p != '}' && *p != '&')
542790277Sobrien	{
542890277Sobrien	  int count = 1;
542990277Sobrien	  const char *q = p;
543050599Sobrien
543190277Sobrien	  while (*q++ != ':')
543290277Sobrien	    continue;
543350599Sobrien	  body = q;
543490277Sobrien
543550599Sobrien	  while (count > 0)
543650599Sobrien	    {
543750599Sobrien	      if (*q == '{')
543890277Sobrien		count++;
543950599Sobrien	      else if (*q == '}')
544090277Sobrien		count--;
544150599Sobrien	      else if (*q == 0)
544290277Sobrien		fatal ("mismatched braces in specs");
544350599Sobrien	      q++;
544450599Sobrien	    }
544550599Sobrien	  endbody = q;
544618334Speter	}
544750599Sobrien      else
544890277Sobrien	body = p, endbody = p + 1;
544918334Speter    }
545018334Speter
545118334Speter  if (suffix)
545218334Speter    {
545318334Speter      int found = (input_suffix != 0
545490277Sobrien		   && (long) strlen (input_suffix) == (long) (p - filter)
545518334Speter		   && strncmp (input_suffix, filter, p - filter) == 0);
545618334Speter
545750599Sobrien      if (body[0] == '}')
545818334Speter	abort ();
545918334Speter
546018334Speter      if (negate != found
546190277Sobrien	  && do_spec_1 (save_string (body, endbody-body-1), 0, NULL) < 0)
546218334Speter	return 0;
546318334Speter    }
546490277Sobrien  else if (p[-1] == '*' && (p[0] == '}' || p[0] == '&'))
546518334Speter    {
546618334Speter      /* Substitute all matching switches as separate args.  */
546790277Sobrien      int i;
546890277Sobrien
546918334Speter      for (i = 0; i < n_switches; i++)
547090277Sobrien	if (!strncmp (switches[i].part1, filter, p - 1 - filter)
547190277Sobrien	    && check_live_switch (i, p - 1 - filter))
547290277Sobrien	  {
547390277Sobrien	    if (elide_switch)
547490277Sobrien	      {
547590277Sobrien		switches[i].live_cond = SWITCH_IGNORE;
547690277Sobrien		switches[i].validated = 1;
547790277Sobrien	      }
547890277Sobrien	    else
547990277Sobrien	      ordered = 1, switches[i].ordering = 1;
548090277Sobrien	  }
548118334Speter    }
548218334Speter  else
548318334Speter    {
548418334Speter      /* Test for presence of the specified switch.  */
548590277Sobrien      int i;
548618334Speter      int present = 0;
548718334Speter
548818334Speter      /* If name specified ends in *, as in {x*:...},
548918334Speter	 check for %* and handle that case.  */
549018334Speter      if (p[-1] == '*' && !negate)
549118334Speter	{
549218334Speter	  int substitution;
549352520Sobrien	  const char *r = body;
549418334Speter
549518334Speter	  /* First see whether we have %*.  */
549618334Speter	  substitution = 0;
549750599Sobrien	  while (r < endbody)
549818334Speter	    {
549918334Speter	      if (*r == '%' && r[1] == '*')
550018334Speter		substitution = 1;
550118334Speter	      r++;
550218334Speter	    }
550318334Speter	  /* If we do, handle that case.  */
550418334Speter	  if (substitution)
550518334Speter	    {
550618334Speter	      /* Substitute all matching switches as separate args.
550718334Speter		 But do this by substituting for %*
550818334Speter		 in the text that follows the colon.  */
550918334Speter
551018334Speter	      unsigned hard_match_len = p - filter - 1;
551150599Sobrien	      char *string = save_string (body, endbody - body - 1);
551218334Speter
551318334Speter	      for (i = 0; i < n_switches; i++)
551418334Speter		if (!strncmp (switches[i].part1, filter, hard_match_len)
551518334Speter		    && check_live_switch (i, -1))
551618334Speter		  {
551718334Speter		    do_spec_1 (string, 0, &switches[i].part1[hard_match_len]);
551818334Speter		    /* Pass any arguments this switch has.  */
551950599Sobrien		    give_switch (i, 1, 1);
552090277Sobrien		    suffix_subst = NULL;
552118334Speter		  }
552218334Speter
552350599Sobrien	      /* We didn't match.  Try again.  */
552450599Sobrien	      if (*p++ == '|')
552550599Sobrien		goto next_member;
552650599Sobrien	      return endbody;
552718334Speter	    }
552818334Speter	}
552918334Speter
553018334Speter      /* If name specified ends in *, as in {x*:...},
553118334Speter	 check for presence of any switch name starting with x.  */
553218334Speter      if (p[-1] == '*')
553318334Speter	{
553418334Speter	  for (i = 0; i < n_switches; i++)
553518334Speter	    {
553618334Speter	      unsigned hard_match_len = p - filter - 1;
553718334Speter
553818334Speter	      if (!strncmp (switches[i].part1, filter, hard_match_len)
553918334Speter		  && check_live_switch (i, hard_match_len))
554018334Speter		{
554118334Speter		  present = 1;
554290277Sobrien		  break;
554318334Speter		}
554418334Speter	    }
554518334Speter	}
554618334Speter      /* Otherwise, check for presence of exact name specified.  */
554718334Speter      else
554818334Speter	{
554918334Speter	  for (i = 0; i < n_switches; i++)
555018334Speter	    {
555118334Speter	      if (!strncmp (switches[i].part1, filter, p - filter)
555218334Speter		  && switches[i].part1[p - filter] == 0
555318334Speter		  && check_live_switch (i, -1))
555418334Speter		{
555518334Speter		  present = 1;
555618334Speter		  break;
555718334Speter		}
555818334Speter	    }
555918334Speter	}
556018334Speter
556150599Sobrien      /* If it is as desired (present for %{s...}, absent for %{!s...})
556218334Speter	 then substitute either the switch or the specified
556318334Speter	 conditional text.  */
556418334Speter      if (present != negate)
556518334Speter	{
556690277Sobrien	  if (elide_switch)
556718334Speter	    {
556890277Sobrien	      switches[i].live_cond = SWITCH_IGNORE;
556990277Sobrien	      switches[i].validated = 1;
557018334Speter	    }
557190277Sobrien	  else if (ordered || *p == '&')
557290277Sobrien	    ordered = 1, switches[i].ordering = 1;
557390277Sobrien	  else if (*p == '}')
557490277Sobrien	    give_switch (i, 0, include_blanks);
557518334Speter	  else
557690277Sobrien	    /* Even if many alternatives are matched, only output once.  */
557790277Sobrien	    true_once = 1;
557818334Speter	}
557950599Sobrien      else if (pipe_p)
558018334Speter	{
558118334Speter	  /* Here if a %{|...} conditional fails: output a minus sign,
558218334Speter	     which means "standard output" or "standard input".  */
558390277Sobrien	  do_spec_1 ("-", 0, NULL);
558450599Sobrien	  return endbody;
558518334Speter	}
558618334Speter    }
558718334Speter
558850599Sobrien  /* We didn't match; try again.  */
558950599Sobrien  if (*p++ == '|')
559050599Sobrien    goto next_member;
559150599Sobrien
559290277Sobrien  if (p[-1] == '&')
559390277Sobrien    {
559490277Sobrien      body = 0;
559590277Sobrien      goto next_ampersand;
559690277Sobrien    }
559790277Sobrien
559890277Sobrien  if (ordered)
559990277Sobrien    {
560090277Sobrien      int i;
560190277Sobrien      /* Doing this set of switches later preserves their command-line
560290277Sobrien	 ordering.  This is needed for e.g. -U, -D and -A.  */
560390277Sobrien      for (i = 0; i < n_switches; i++)
560490277Sobrien	if (switches[i].ordering == 1)
560590277Sobrien	  {
560690277Sobrien	    switches[i].ordering = 0;
560790277Sobrien	    give_switch (i, 0, include_blanks);
560890277Sobrien	  }
560990277Sobrien    }
561090277Sobrien  /* Process the spec just once, regardless of match count.  */
561190277Sobrien  else if (true_once)
561290277Sobrien    {
561390277Sobrien      if (do_spec_1 (save_string (body, endbody - body - 1),
561490277Sobrien		     0, NULL) < 0)
561590277Sobrien	return 0;
561690277Sobrien    }
561790277Sobrien
561850599Sobrien  return endbody;
561918334Speter}
562018334Speter
562118334Speter/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch
562218334Speter   on the command line.  PREFIX_LENGTH is the length of XXX in an {XXX*}
562318334Speter   spec, or -1 if either exact match or %* is used.
562418334Speter
562518334Speter   A -O switch is obsoleted by a later -O switch.  A -f, -m, or -W switch
562618334Speter   whose value does not begin with "no-" is obsoleted by the same value
562718334Speter   with the "no-", similarly for a switch with the "no-" prefix.  */
562818334Speter
562918334Speterstatic int
563018334Spetercheck_live_switch (switchnum, prefix_length)
563118334Speter     int switchnum;
563218334Speter     int prefix_length;
563318334Speter{
563452520Sobrien  const char *name = switches[switchnum].part1;
563518334Speter  int i;
563618334Speter
563718334Speter  /* In the common case of {<at-most-one-letter>*}, a negating
563818334Speter     switch would always match, so ignore that case.  We will just
563918334Speter     send the conflicting switches to the compiler phase.  */
564018334Speter  if (prefix_length >= 0 && prefix_length <= 1)
564118334Speter    return 1;
564218334Speter
564318334Speter  /* If we already processed this switch and determined if it was
564418334Speter     live or not, return our past determination.  */
564518334Speter  if (switches[switchnum].live_cond != 0)
564618334Speter    return switches[switchnum].live_cond > 0;
564718334Speter
564818334Speter  /* Now search for duplicate in a manner that depends on the name.  */
564918334Speter  switch (*name)
565018334Speter    {
565118334Speter    case 'O':
565290277Sobrien      for (i = switchnum + 1; i < n_switches; i++)
565390277Sobrien	if (switches[i].part1[0] == 'O')
565490277Sobrien	  {
565590277Sobrien	    switches[switchnum].validated = 1;
565690277Sobrien	    switches[switchnum].live_cond = SWITCH_FALSE;
565790277Sobrien	    return 0;
565890277Sobrien	  }
565918334Speter      break;
566018334Speter
566118334Speter    case 'W':  case 'f':  case 'm':
566218334Speter      if (! strncmp (name + 1, "no-", 3))
566318334Speter	{
566450599Sobrien	  /* We have Xno-YYY, search for XYYY.  */
566518334Speter	  for (i = switchnum + 1; i < n_switches; i++)
566618334Speter	    if (switches[i].part1[0] == name[0]
566718334Speter		&& ! strcmp (&switches[i].part1[1], &name[4]))
566890277Sobrien	      {
566990277Sobrien		switches[switchnum].validated = 1;
567090277Sobrien		switches[switchnum].live_cond = SWITCH_FALSE;
567190277Sobrien		return 0;
567290277Sobrien	      }
567318334Speter	}
567418334Speter      else
567518334Speter	{
567618334Speter	  /* We have XYYY, search for Xno-YYY.  */
567718334Speter	  for (i = switchnum + 1; i < n_switches; i++)
567818334Speter	    if (switches[i].part1[0] == name[0]
567918334Speter		&& switches[i].part1[1] == 'n'
568018334Speter		&& switches[i].part1[2] == 'o'
568118334Speter		&& switches[i].part1[3] == '-'
568218334Speter		&& !strcmp (&switches[i].part1[4], &name[1]))
568390277Sobrien	      {
568490277Sobrien		switches[switchnum].validated = 1;
568590277Sobrien		switches[switchnum].live_cond = SWITCH_FALSE;
568690277Sobrien		return 0;
568790277Sobrien	      }
568818334Speter	}
568918334Speter      break;
569018334Speter    }
569118334Speter
569218334Speter  /* Otherwise the switch is live.  */
569390277Sobrien  switches[switchnum].live_cond = SWITCH_LIVE;
569418334Speter  return 1;
569518334Speter}
569618334Speter
569718334Speter/* Pass a switch to the current accumulating command
569818334Speter   in the same form that we received it.
569918334Speter   SWITCHNUM identifies the switch; it is an index into
570018334Speter   the vector of switches gcc received, which is `switches'.
570118334Speter   This cannot fail since it never finishes a command line.
570218334Speter
570350599Sobrien   If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument.
570418334Speter
570550599Sobrien   If INCLUDE_BLANKS is nonzero, then we include blanks before each argument
570650599Sobrien   of the switch.  */
570750599Sobrien
570818334Speterstatic void
570950599Sobriengive_switch (switchnum, omit_first_word, include_blanks)
571018334Speter     int switchnum;
571118334Speter     int omit_first_word;
571250599Sobrien     int include_blanks;
571318334Speter{
571490277Sobrien  if (switches[switchnum].live_cond == SWITCH_IGNORE)
571590277Sobrien    return;
571690277Sobrien
571718334Speter  if (!omit_first_word)
571818334Speter    {
571990277Sobrien      do_spec_1 ("-", 0, NULL);
572090277Sobrien      do_spec_1 (switches[switchnum].part1, 1, NULL);
572118334Speter    }
572250599Sobrien
572318334Speter  if (switches[switchnum].args != 0)
572418334Speter    {
572590277Sobrien      const char **p;
572618334Speter      for (p = switches[switchnum].args; *p; p++)
572718334Speter	{
572890277Sobrien	  const char *arg = *p;
572990277Sobrien
573050599Sobrien	  if (include_blanks)
573190277Sobrien	    do_spec_1 (" ", 0, NULL);
573290277Sobrien	  if (suffix_subst)
573390277Sobrien	    {
573490277Sobrien	      unsigned length = strlen (arg);
573590277Sobrien	      int dot = 0;
573690277Sobrien
573790277Sobrien	      while (length-- && !IS_DIR_SEPARATOR (arg[length]))
573890277Sobrien		if (arg[length] == '.')
573990277Sobrien		  {
574090277Sobrien		    ((char *)arg)[length] = 0;
574190277Sobrien		    dot = 1;
574290277Sobrien		    break;
574390277Sobrien		  }
574490277Sobrien	      do_spec_1 (arg, 1, NULL);
574590277Sobrien	      if (dot)
574690277Sobrien		((char *)arg)[length] = '.';
574790277Sobrien	      do_spec_1 (suffix_subst, 1, NULL);
574890277Sobrien	    }
574990277Sobrien	  else
575090277Sobrien	    do_spec_1 (arg, 1, NULL);
575118334Speter	}
575218334Speter    }
575350599Sobrien
575490277Sobrien  do_spec_1 (" ", 0, NULL);
575552520Sobrien  switches[switchnum].validated = 1;
575618334Speter}
575718334Speter
575818334Speter/* Search for a file named NAME trying various prefixes including the
575918334Speter   user's -B prefix and some standard ones.
576018334Speter   Return the absolute file name found.  If nothing is found, return NAME.  */
576118334Speter
576252520Sobrienstatic const char *
576318334Speterfind_file (name)
576452520Sobrien     const char *name;
576518334Speter{
576618334Speter  char *newname;
576718334Speter
576818334Speter  /* Try multilib_dir if it is defined.  */
5769104763Skan  if (multilib_os_dir != NULL)
577018334Speter    {
5771104763Skan      newname = find_a_file (&startfile_prefixes, name, R_OK, 1);
577218334Speter
577318334Speter      /* If we don't find it in the multi library dir, then fall
577418334Speter	 through and look for it in the normal places.  */
577518334Speter      if (newname != NULL)
577618334Speter	return newname;
577718334Speter    }
577818334Speter
5779104763Skan  newname = find_a_file (&startfile_prefixes, name, R_OK, 0);
578018334Speter  return newname ? newname : name;
578118334Speter}
578218334Speter
578318334Speter/* Determine whether a directory exists.  If LINKER, return 0 for
578418334Speter   certain fixed names not needed by the linker.  If not LINKER, it is
578518334Speter   only important to return 0 if the host machine has a small ARG_MAX
578618334Speter   limit.  */
578718334Speter
578818334Speterstatic int
578918334Speteris_directory (path1, path2, linker)
579052520Sobrien     const char *path1;
579152520Sobrien     const char *path2;
579218334Speter     int linker;
579318334Speter{
579418334Speter  int len1 = strlen (path1);
579518334Speter  int len2 = strlen (path2);
579618334Speter  char *path = (char *) alloca (3 + len1 + len2);
579718334Speter  char *cp;
579818334Speter  struct stat st;
579918334Speter
580018334Speter#ifndef SMALL_ARG_MAX
580118334Speter  if (! linker)
580218334Speter    return 1;
580318334Speter#endif
580418334Speter
580518334Speter  /* Construct the path from the two parts.  Ensure the string ends with "/.".
580618334Speter     The resulting path will be a directory even if the given path is a
580718334Speter     symbolic link.  */
580852520Sobrien  memcpy (path, path1, len1);
580952520Sobrien  memcpy (path + len1, path2, len2);
581018334Speter  cp = path + len1 + len2;
581152520Sobrien  if (!IS_DIR_SEPARATOR (cp[-1]))
581218334Speter    *cp++ = DIR_SEPARATOR;
581318334Speter  *cp++ = '.';
581418334Speter  *cp = '\0';
581518334Speter
581651232Sbde#ifndef FREEBSD_NATIVE
581718334Speter  /* Exclude directories that the linker is known to search.  */
581818334Speter  if (linker
581918334Speter      && ((cp - path == 6
582090277Sobrien	   && strcmp (path, concat (dir_separator_str, "lib",
582190277Sobrien				    dir_separator_str, ".", NULL)) == 0)
582218334Speter	  || (cp - path == 10
582390277Sobrien	      && strcmp (path, concat (dir_separator_str, "usr",
582490277Sobrien				       dir_separator_str, "lib",
582590277Sobrien				       dir_separator_str, ".", NULL)) == 0)))
582618334Speter    return 0;
582751232Sbde#endif /* FREEBSD_NATIVE */
582818334Speter
582918334Speter  return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
583018334Speter}
583190277Sobrien
583290277Sobrien/* Set up the various global variables to indicate that we're processing
583390277Sobrien   the input file named FILENAME.  */
583490277Sobrien
583590277Sobrienvoid
583690277Sobrienset_input (filename)
583790277Sobrien     const char *filename;
583890277Sobrien{
583990277Sobrien  const char *p;
584090277Sobrien
584190277Sobrien  input_filename = filename;
584290277Sobrien  input_filename_length = strlen (input_filename);
584390277Sobrien
584490277Sobrien  input_basename = input_filename;
584590277Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM
584690277Sobrien  /* Skip drive name so 'x:foo' is handled properly.  */
584790277Sobrien  if (input_basename[1] == ':')
584890277Sobrien    input_basename += 2;
584990277Sobrien#endif
585090277Sobrien  for (p = input_basename; *p; p++)
585190277Sobrien    if (IS_DIR_SEPARATOR (*p))
585290277Sobrien      input_basename = p + 1;
585390277Sobrien
585490277Sobrien  /* Find a suffix starting with the last period,
585590277Sobrien     and set basename_length to exclude that suffix.  */
585690277Sobrien  basename_length = strlen (input_basename);
585790277Sobrien  suffixed_basename_length = basename_length;
585890277Sobrien  p = input_basename + basename_length;
585990277Sobrien  while (p != input_basename && *p != '.')
586090277Sobrien    --p;
586190277Sobrien  if (*p == '.' && p != input_basename)
586290277Sobrien    {
586390277Sobrien      basename_length = p - input_basename;
586490277Sobrien      input_suffix = p + 1;
586590277Sobrien    }
586690277Sobrien  else
586790277Sobrien    input_suffix = "";
5868117413Skan
586990277Sobrien  /* If a spec for 'g', 'u', or 'U' is seen with -save-temps then
587090277Sobrien     we will need to do a stat on the input_filename.  The
587190277Sobrien     INPUT_STAT_SET signals that the stat is needed.  */
587290277Sobrien  input_stat_set = 0;
587390277Sobrien}
587418334Speter
587518334Speter/* On fatal signals, delete all the temporary files.  */
587618334Speter
587718334Speterstatic void
587818334Speterfatal_error (signum)
587918334Speter     int signum;
588018334Speter{
588118334Speter  signal (signum, SIG_DFL);
588218334Speter  delete_failure_queue ();
588318334Speter  delete_temp_files ();
588418334Speter  /* Get the same signal again, this time not handled,
588518334Speter     so its normal effect occurs.  */
588618334Speter  kill (getpid (), signum);
588718334Speter}
588818334Speter
588990277Sobrienextern int main PARAMS ((int, const char *const *));
589090277Sobrien
589118334Speterint
589218334Spetermain (argc, argv)
589318334Speter     int argc;
589490277Sobrien     const char *const *argv;
589518334Speter{
589690277Sobrien  size_t i;
589718334Speter  int value;
589818334Speter  int linker_was_run = 0;
589918334Speter  char *explicit_link_files;
590018334Speter  char *specs_file;
590152520Sobrien  const char *p;
590250599Sobrien  struct user_specs *uptr;
590318334Speter
590418334Speter  p = argv[0] + strlen (argv[0]);
590552520Sobrien  while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
590652520Sobrien    --p;
590718334Speter  programname = p;
590818334Speter
590990277Sobrien  xmalloc_set_program_name (programname);
591090277Sobrien
591190277Sobrien#ifdef GCC_DRIVER_HOST_INITIALIZATION
591290277Sobrien  /* Perform host dependent initialization when needed.  */
591390277Sobrien  GCC_DRIVER_HOST_INITIALIZATION;
591452520Sobrien#endif
591552520Sobrien
591690277Sobrien  gcc_init_libintl ();
591790277Sobrien
591818334Speter  if (signal (SIGINT, SIG_IGN) != SIG_IGN)
591918334Speter    signal (SIGINT, fatal_error);
592018334Speter#ifdef SIGHUP
592118334Speter  if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
592218334Speter    signal (SIGHUP, fatal_error);
592318334Speter#endif
592418334Speter  if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
592518334Speter    signal (SIGTERM, fatal_error);
592618334Speter#ifdef SIGPIPE
592718334Speter  if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
592818334Speter    signal (SIGPIPE, fatal_error);
592918334Speter#endif
593090277Sobrien#ifdef SIGCHLD
593190277Sobrien  /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
593290277Sobrien     receive the signal.  A different setting is inheritable */
593390277Sobrien  signal (SIGCHLD, SIG_DFL);
593490277Sobrien#endif
593518334Speter
5936117413Skan  /* Allocate the argument vector.  */
5937117413Skan  alloc_args ();
593818334Speter
593918334Speter  obstack_init (&obstack);
594018334Speter
594150599Sobrien  /* Build multilib_select, et. al from the separate lines that make up each
594250599Sobrien     multilib selection.  */
594350599Sobrien  {
594490277Sobrien    const char *const *q = multilib_raw;
594550599Sobrien    int need_space;
594650599Sobrien
594750599Sobrien    obstack_init (&multilib_obstack);
594850599Sobrien    while ((p = *q++) != (char *) 0)
594950599Sobrien      obstack_grow (&multilib_obstack, p, strlen (p));
595050599Sobrien
595150599Sobrien    obstack_1grow (&multilib_obstack, 0);
595250599Sobrien    multilib_select = obstack_finish (&multilib_obstack);
595350599Sobrien
595450599Sobrien    q = multilib_matches_raw;
595550599Sobrien    while ((p = *q++) != (char *) 0)
595650599Sobrien      obstack_grow (&multilib_obstack, p, strlen (p));
595750599Sobrien
595850599Sobrien    obstack_1grow (&multilib_obstack, 0);
595950599Sobrien    multilib_matches = obstack_finish (&multilib_obstack);
596050599Sobrien
596190277Sobrien    q = multilib_exclusions_raw;
596290277Sobrien    while ((p = *q++) != (char *) 0)
596390277Sobrien      obstack_grow (&multilib_obstack, p, strlen (p));
596490277Sobrien
596590277Sobrien    obstack_1grow (&multilib_obstack, 0);
596690277Sobrien    multilib_exclusions = obstack_finish (&multilib_obstack);
596790277Sobrien
596850599Sobrien    need_space = FALSE;
596990277Sobrien    for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++)
597050599Sobrien      {
597150599Sobrien	if (need_space)
597250599Sobrien	  obstack_1grow (&multilib_obstack, ' ');
597350599Sobrien	obstack_grow (&multilib_obstack,
597450599Sobrien		      multilib_defaults_raw[i],
597550599Sobrien		      strlen (multilib_defaults_raw[i]));
597650599Sobrien	need_space = TRUE;
597750599Sobrien      }
597850599Sobrien
597950599Sobrien    obstack_1grow (&multilib_obstack, 0);
598050599Sobrien    multilib_defaults = obstack_finish (&multilib_obstack);
598150599Sobrien  }
598250599Sobrien
598318334Speter  /* Set up to remember the pathname of gcc and any options
598418334Speter     needed for collect.  We use argv[0] instead of programname because
598518334Speter     we need the complete pathname.  */
598618334Speter  obstack_init (&collect_obstack);
598790277Sobrien  obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1);
598890277Sobrien  obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1);
598918334Speter  putenv (obstack_finish (&collect_obstack));
599018334Speter
599118334Speter#ifdef INIT_ENVIRONMENT
599218334Speter  /* Set up any other necessary machine specific environment variables.  */
599318334Speter  putenv (INIT_ENVIRONMENT);
599418334Speter#endif
599518334Speter
599618334Speter  /* Make a table of what switches there are (switches, n_switches).
599718334Speter     Make a table of specified input files (infiles, n_infiles).
599818334Speter     Decode switches that are handled locally.  */
599918334Speter
600018334Speter  process_command (argc, argv);
600118334Speter
6002117413Skan  /* Process DRIVER_SELF_SPECS, adding any new options to the end
6003117413Skan     of the command line.  */
6004117413Skan
6005117413Skan  for (i = 0; i < ARRAY_SIZE (driver_self_specs); i++)
6006117413Skan    do_self_spec (driver_self_specs[i]);
6007117413Skan
600818334Speter  /* Initialize the vector of specs to just the default.
600918334Speter     This means one element containing 0s, as a terminator.  */
601018334Speter
601118334Speter  compilers = (struct compiler *) xmalloc (sizeof default_compilers);
601290277Sobrien  memcpy ((char *) compilers, (char *) default_compilers,
601390277Sobrien	  sizeof default_compilers);
601418334Speter  n_compilers = n_default_compilers;
601518334Speter
601618334Speter  /* Read specs from a file if there is one.  */
601718334Speter
601891561Sobrien#ifdef FREEBSD_NATIVE
601991561Sobrien  just_machine_suffix = "";
602091561Sobrien#else	/* FREEBSD_NATIVE */
602150599Sobrien  machine_suffix = concat (spec_machine, dir_separator_str,
602290277Sobrien			   spec_version, dir_separator_str, NULL);
602390277Sobrien  just_machine_suffix = concat (spec_machine, dir_separator_str, NULL);
602450599Sobrien#endif /* FREEBSD_NATIVE */
602518334Speter
6026104763Skan  specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, 0);
602718334Speter  /* Read the specs file unless it is a default one.  */
602818334Speter  if (specs_file != 0 && strcmp (specs_file, "specs"))
602950599Sobrien    read_specs (specs_file, TRUE);
603050599Sobrien  else
603150599Sobrien    init_spec ();
603218334Speter
603350599Sobrien  /* We need to check standard_exec_prefix/just_machine_suffix/specs
603490277Sobrien     for any override of as, ld and libraries.  */
603597902Sobrien  specs_file = (char *) alloca (strlen (FBSD_DATA_PREFIX)
603650599Sobrien				+ strlen (just_machine_suffix)
603750599Sobrien				+ sizeof ("specs"));
603850599Sobrien
603997902Sobrien  strcpy (specs_file, FBSD_DATA_PREFIX);
604050599Sobrien  strcat (specs_file, just_machine_suffix);
604150599Sobrien  strcat (specs_file, "specs");
604250599Sobrien  if (access (specs_file, R_OK) == 0)
604350599Sobrien    read_specs (specs_file, TRUE);
604490277Sobrien
6045117413Skan  /* If not cross-compiling, look for startfiles in the standard places.
6046117413Skan     Similarly, don't add the standard prefixes if startfile handling
6047117413Skan     will be under control of startfile_prefix_spec.  */
6048117413Skan  if (*cross_compile == '0' && *startfile_prefix_spec == 0)
604918334Speter    {
605090277Sobrien      if (*md_exec_prefix)
605190277Sobrien	{
605290277Sobrien	  add_prefix (&exec_prefixes, md_exec_prefix, "GCC",
6053104763Skan		      PREFIX_PRIORITY_LAST, 0, NULL, 0);
605490277Sobrien	  add_prefix (&startfile_prefixes, md_exec_prefix, "GCC",
6055104763Skan		      PREFIX_PRIORITY_LAST, 0, NULL, 0);
605690277Sobrien	}
605718334Speter
605890277Sobrien      if (*md_startfile_prefix)
605990277Sobrien	add_prefix (&startfile_prefixes, md_startfile_prefix, "GCC",
6060104763Skan		    PREFIX_PRIORITY_LAST, 0, NULL, 1);
606118334Speter
606290277Sobrien      if (*md_startfile_prefix_1)
606390277Sobrien	add_prefix (&startfile_prefixes, md_startfile_prefix_1, "GCC",
6064104763Skan		    PREFIX_PRIORITY_LAST, 0, NULL, 1);
606518334Speter
606618334Speter      /* If standard_startfile_prefix is relative, base it on
606718334Speter	 standard_exec_prefix.  This lets us move the installed tree
606818334Speter	 as a unit.  If GCC_EXEC_PREFIX is defined, base
606918334Speter	 standard_startfile_prefix on that as well.  */
607090277Sobrien      if (IS_ABSOLUTE_PATHNAME (standard_startfile_prefix))
607150599Sobrien	add_prefix (&startfile_prefixes, standard_startfile_prefix, "BINUTILS",
6072104763Skan		    PREFIX_PRIORITY_LAST, 0, NULL, 1);
607318334Speter      else
607418334Speter	{
607518334Speter	  if (gcc_exec_prefix)
607618334Speter	    add_prefix (&startfile_prefixes,
607750599Sobrien			concat (gcc_exec_prefix, machine_suffix,
607890277Sobrien				standard_startfile_prefix, NULL),
6079104763Skan			NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1);
608018334Speter	  add_prefix (&startfile_prefixes,
608150599Sobrien		      concat (standard_exec_prefix,
608250599Sobrien			      machine_suffix,
608390277Sobrien			      standard_startfile_prefix, NULL),
6084104763Skan		      NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1);
608590277Sobrien	}
608618334Speter
608718346Speter#ifndef FREEBSD_NATIVE
608850599Sobrien      add_prefix (&startfile_prefixes, standard_startfile_prefix_1,
6089104763Skan		  "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1);
609050599Sobrien      add_prefix (&startfile_prefixes, standard_startfile_prefix_2,
6091104763Skan		  "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1);
609291561Sobrien#endif	/* not FREEBSD_NATIVE */
609318334Speter#if 0 /* Can cause surprises, and one can use -B./ instead.  */
609490277Sobrien      add_prefix (&startfile_prefixes, "./", NULL,
6095104763Skan		  PREFIX_PRIORITY_LAST, 1, NULL, 0);
609618334Speter#endif
609718334Speter    }
609818334Speter  else
609918334Speter    {
610090277Sobrien      if (!IS_ABSOLUTE_PATHNAME (standard_startfile_prefix)
610190277Sobrien	  && gcc_exec_prefix)
610218334Speter	add_prefix (&startfile_prefixes,
610350599Sobrien		    concat (gcc_exec_prefix, machine_suffix,
610490277Sobrien			    standard_startfile_prefix, NULL),
6105104763Skan		    "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1);
610691651Sobrien#ifdef CROSS_STARTFILE_PREFIX
610791651Sobrien	add_prefix (&startfile_prefixes, CROSS_STARTFILE_PREFIX, "BINUTILS",
6108104763Skan		    PREFIX_PRIORITY_LAST, 0, NULL, 1);
610991651Sobrien#endif
611018334Speter    }
611118334Speter
6112117413Skan  if (*startfile_prefix_spec != 0
6113117413Skan      && do_spec_2 (startfile_prefix_spec) == 0
6114117413Skan      && do_spec_1 (" ", 0, NULL) == 0)
6115117413Skan    {
6116117413Skan      int ndx;
6117117413Skan      for (ndx = 0; ndx < argbuf_index; ndx++)
6118117413Skan	add_prefix (&startfile_prefixes, argbuf[ndx], "BINUTILS",
6119117413Skan		    PREFIX_PRIORITY_LAST, 0, NULL, 1);
6120117413Skan    }
6121117413Skan
612252520Sobrien  /* Process any user specified specs in the order given on the command
612352520Sobrien     line.  */
612452520Sobrien  for (uptr = user_specs_head; uptr; uptr = uptr->next)
612552520Sobrien    {
6126104763Skan      char *filename = find_a_file (&startfile_prefixes, uptr->filename,
6127104763Skan				    R_OK, 0);
612852520Sobrien      read_specs (filename ? filename : uptr->filename, FALSE);
612952520Sobrien    }
613052520Sobrien
613118334Speter  /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake.  */
613218334Speter  if (gcc_exec_prefix)
613390277Sobrien    gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
613490277Sobrien			      spec_version, dir_separator_str, NULL);
613518334Speter
613618334Speter  /* Now we have the specs.
613718334Speter     Set the `valid' bits for switches that match anything in any spec.  */
613818334Speter
613918334Speter  validate_all_switches ();
614018334Speter
614118334Speter  /* Now that we have the switches and the specs, set
614218334Speter     the subdirectory based on the options.  */
614318334Speter  set_multilib_dir ();
614418334Speter
614518334Speter  /* Warn about any switches that no pass was interested in.  */
614618334Speter
614790277Sobrien  for (i = 0; (int) i < n_switches; i++)
614852520Sobrien    if (! switches[i].validated)
614918334Speter      error ("unrecognized option `-%s'", switches[i].part1);
615018334Speter
615118334Speter  /* Obey some of the options.  */
615218334Speter
615318334Speter  if (print_search_dirs)
615418334Speter    {
615590277Sobrien      printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix);
615690277Sobrien      printf (_("programs: %s\n"), build_search_list (&exec_prefixes, "", 0));
615790277Sobrien      printf (_("libraries: %s\n"), build_search_list (&startfile_prefixes, "", 0));
615890277Sobrien      return (0);
615918334Speter    }
616018334Speter
616118334Speter  if (print_file_name)
616218334Speter    {
616318334Speter      printf ("%s\n", find_file (print_file_name));
616490277Sobrien      return (0);
616518334Speter    }
616618334Speter
616718334Speter  if (print_prog_name)
616818334Speter    {
6169104763Skan      char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK, 0);
617018334Speter      printf ("%s\n", (newname ? newname : print_prog_name));
617190277Sobrien      return (0);
617218334Speter    }
617318334Speter
617418334Speter  if (print_multi_lib)
617518334Speter    {
617618334Speter      print_multilib_info ();
617790277Sobrien      return (0);
617818334Speter    }
617918334Speter
618018334Speter  if (print_multi_directory)
618118334Speter    {
618218334Speter      if (multilib_dir == NULL)
618318334Speter	printf (".\n");
618418334Speter      else
618518334Speter	printf ("%s\n", multilib_dir);
618690277Sobrien      return (0);
618718334Speter    }
618818334Speter
6189104763Skan  if (print_multi_os_directory)
6190104763Skan    {
6191104763Skan      if (multilib_os_dir == NULL)
6192104763Skan	printf (".\n");
6193104763Skan      else
6194104763Skan	printf ("%s\n", multilib_os_dir);
6195104763Skan      return (0);
6196104763Skan    }
6197104763Skan
619890277Sobrien  if (target_help_flag)
619990277Sobrien   {
620090277Sobrien      /* Print if any target specific options.  */
620190277Sobrien
620290277Sobrien      /* We do not exit here. Instead we have created a fake input file
620390277Sobrien         called 'target-dummy' which needs to be compiled, and we pass this
620490277Sobrien         on to the various sub-processes, along with the --target-help
620590277Sobrien         switch.  */
620690277Sobrien    }
620790277Sobrien
620850599Sobrien  if (print_help_list)
620950599Sobrien    {
621050599Sobrien      display_help ();
621150599Sobrien
621250599Sobrien      if (! verbose_flag)
621350599Sobrien	{
621490277Sobrien	  printf (_("\nFor bug reporting instructions, please see:\n"));
6215117413Skan	  printf ("%s.\n", bug_report_url);
621690277Sobrien
621790277Sobrien	  return (0);
621850599Sobrien	}
621950599Sobrien
622050599Sobrien      /* We do not exit here.  Instead we have created a fake input file
622150599Sobrien	 called 'help-dummy' which needs to be compiled, and we pass this
622290277Sobrien	 on the various sub-processes, along with the --help switch.  */
622350599Sobrien    }
622490277Sobrien
622518334Speter  if (verbose_flag)
622618334Speter    {
622750599Sobrien      int n;
622890277Sobrien      const char *thrmod;
622950599Sobrien
623090277Sobrien      notice ("Configured with: %s\n", configuration_arguments);
623190277Sobrien
623290277Sobrien#ifdef THREAD_MODEL_SPEC
623390277Sobrien      /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
623490277Sobrien	 but there's no point in doing all this processing just to get
623590277Sobrien	 thread_model back.  */
623690277Sobrien      obstack_init (&obstack);
623790277Sobrien      do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
623890277Sobrien      obstack_1grow (&obstack, '\0');
623990277Sobrien      thrmod = obstack_finish (&obstack);
624090277Sobrien#else
624190277Sobrien      thrmod = thread_model;
624290277Sobrien#endif
624390277Sobrien
624490277Sobrien      notice ("Thread model: %s\n", thrmod);
624590277Sobrien
624650599Sobrien      /* compiler_version is truncated at the first space when initialized
624750599Sobrien	 from version string, so truncate version_string at the first space
624850599Sobrien	 before comparing.  */
624950599Sobrien      for (n = 0; version_string[n]; n++)
625050599Sobrien	if (version_string[n] == ' ')
625150599Sobrien	  break;
625250599Sobrien
625350599Sobrien      if (! strncmp (version_string, compiler_version, n)
625450599Sobrien	  && compiler_version[n] == 0)
625552520Sobrien	notice ("gcc version %s\n", version_string);
625618334Speter      else
625752520Sobrien	notice ("gcc driver version %s executing gcc version %s\n",
625852520Sobrien		version_string, compiler_version);
625918334Speter
626018334Speter      if (n_infiles == 0)
626190277Sobrien	return (0);
626218334Speter    }
626318334Speter
626450599Sobrien  if (n_infiles == added_libraries)
626518346Speter    fatal ("No input files specified");
626618334Speter
626718334Speter  /* Make a place to record the compiler output file names
626818334Speter     that correspond to the input files.  */
626918334Speter
627050599Sobrien  i = n_infiles;
627150599Sobrien  i += lang_specific_extra_outfiles;
627290277Sobrien  outfiles = (const char **) xcalloc (i, sizeof (char *));
627318334Speter
627418334Speter  /* Record which files were specified explicitly as link input.  */
627518334Speter
627690277Sobrien  explicit_link_files = xcalloc (1, n_infiles);
627718334Speter
627890277Sobrien  for (i = 0; (int) i < n_infiles; i++)
627918334Speter    {
628018334Speter      int this_file_error = 0;
628118334Speter
628218334Speter      /* Tell do_spec what to substitute for %i.  */
628318334Speter
628418334Speter      input_file_number = i;
628590277Sobrien      set_input (infiles[i].name);
628618334Speter
628718334Speter      /* Use the same thing in %o, unless cp->spec says otherwise.  */
628818334Speter
628918334Speter      outfiles[i] = input_filename;
629018334Speter
629118334Speter      /* Figure out which compiler from the file's suffix.  */
629218334Speter
629390277Sobrien      input_file_compiler
629490277Sobrien	= lookup_compiler (infiles[i].name, input_filename_length,
629590277Sobrien			   infiles[i].language);
6296117413Skan
629790277Sobrien      if (input_file_compiler)
629818334Speter	{
629918334Speter	  /* Ok, we found an applicable compiler.  Run its spec.  */
630018334Speter
630190277Sobrien	  if (input_file_compiler->spec[0] == '#')
630218334Speter	    {
630390277Sobrien	      error ("%s: %s compiler not installed on this system",
630490277Sobrien		     input_filename, &input_file_compiler->spec[1]);
630590277Sobrien	      this_file_error = 1;
630618334Speter	    }
630718334Speter	  else
630890277Sobrien	    {
630990277Sobrien	      value = do_spec (input_file_compiler->spec);
631090277Sobrien	      if (value < 0)
631190277Sobrien		this_file_error = 1;
631290277Sobrien	    }
631318334Speter	}
631418334Speter
631518334Speter      /* If this file's name does not contain a recognized suffix,
631618334Speter	 record it as explicit linker input.  */
631718334Speter
631818334Speter      else
631918334Speter	explicit_link_files[i] = 1;
632018334Speter
632118334Speter      /* Clear the delete-on-failure queue, deleting the files in it
632218334Speter	 if this compilation failed.  */
632318334Speter
632418334Speter      if (this_file_error)
632518334Speter	{
632618334Speter	  delete_failure_queue ();
632718334Speter	  error_count++;
632818334Speter	}
632918334Speter      /* If this compilation succeeded, don't delete those files later.  */
633018334Speter      clear_failure_queue ();
633118334Speter    }
633218334Speter
633390277Sobrien  /* Reset the output file name to the first input file name, for use
633490277Sobrien     with %b in LINK_SPEC on a target that prefers not to emit a.out
633590277Sobrien     by default.  */
633690277Sobrien  if (n_infiles > 0)
633790277Sobrien    set_input (infiles[0].name);
633890277Sobrien
633952520Sobrien  if (error_count == 0)
634052520Sobrien    {
634152520Sobrien      /* Make sure INPUT_FILE_NUMBER points to first available open
634252520Sobrien	 slot.  */
634352520Sobrien      input_file_number = n_infiles;
634452520Sobrien      if (lang_specific_pre_link ())
634552520Sobrien	error_count++;
634652520Sobrien    }
634750599Sobrien
634818334Speter  /* Run ld to link all the compiler output files.  */
634918334Speter
635018334Speter  if (error_count == 0)
635118334Speter    {
635218334Speter      int tmp = execution_count;
635318334Speter
635490277Sobrien      /* We'll use ld if we can't find collect2.  */
635550599Sobrien      if (! strcmp (linker_name_spec, "collect2"))
635650599Sobrien	{
6357104763Skan	  char *s = find_a_file (&exec_prefixes, "collect2", X_OK, 0);
635850599Sobrien	  if (s == NULL)
635950599Sobrien	    linker_name_spec = "ld";
636050599Sobrien	}
636118334Speter      /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
636218334Speter	 for collect.  */
636390277Sobrien      putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH");
636490277Sobrien      putenv_from_prefixes (&startfile_prefixes, LIBRARY_PATH_ENV);
636518334Speter
636618334Speter      value = do_spec (link_command_spec);
636718334Speter      if (value < 0)
636818334Speter	error_count = 1;
636918334Speter      linker_was_run = (tmp != execution_count);
637018334Speter    }
637118334Speter
637218334Speter  /* If options said don't run linker,
637318334Speter     complain about input files to be given to the linker.  */
637418334Speter
637518334Speter  if (! linker_was_run && error_count == 0)
637690277Sobrien    for (i = 0; (int) i < n_infiles; i++)
637718334Speter      if (explicit_link_files[i])
637890277Sobrien	error ("%s: linker input file unused because linking not done",
637918334Speter	       outfiles[i]);
638018334Speter
638118334Speter  /* Delete some or all of the temporary files we made.  */
638218334Speter
638318334Speter  if (error_count)
638418334Speter    delete_failure_queue ();
638518334Speter  delete_temp_files ();
638618334Speter
638750599Sobrien  if (print_help_list)
638850599Sobrien    {
638990277Sobrien      printf (("\nFor bug reporting instructions, please see:\n"));
6390117413Skan      printf ("%s\n", bug_report_url);
639150599Sobrien    }
639290277Sobrien
639390277Sobrien  return (signal_count != 0 ? 2
639490277Sobrien	  : error_count > 0 ? (pass_exit_codes ? greatest_status : 1)
639590277Sobrien	  : 0);
639618334Speter}
639718334Speter
639818334Speter/* Find the proper compilation spec for the file name NAME,
639918334Speter   whose length is LENGTH.  LANGUAGE is the specified language,
640050599Sobrien   or 0 if this file is to be passed to the linker.  */
640118334Speter
640218334Speterstatic struct compiler *
640318334Speterlookup_compiler (name, length, language)
640452520Sobrien     const char *name;
640550599Sobrien     size_t length;
640652520Sobrien     const char *language;
640718334Speter{
640818334Speter  struct compiler *cp;
640918334Speter
641090277Sobrien  /* If this was specified by the user to be a linker input, indicate that.  */
641150599Sobrien  if (language != 0 && language[0] == '*')
641250599Sobrien    return 0;
641350599Sobrien
641450599Sobrien  /* Otherwise, look for the language, if one is spec'd.  */
641518334Speter  if (language != 0)
641618334Speter    {
641718334Speter      for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
641850599Sobrien	if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language))
641950599Sobrien	  return cp;
642050599Sobrien
642118334Speter      error ("language %s not recognized", language);
642250599Sobrien      return 0;
642318334Speter    }
642418334Speter
642518334Speter  /* Look for a suffix.  */
642618334Speter  for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
642718334Speter    {
642818334Speter      if (/* The suffix `-' matches only the file name `-'.  */
642918334Speter	  (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
643050599Sobrien	  || (strlen (cp->suffix) < length
643150599Sobrien	      /* See if the suffix matches the end of NAME.  */
643250599Sobrien	      && !strcmp (cp->suffix,
643350599Sobrien			  name + length - strlen (cp->suffix))
643450599Sobrien	 ))
6435117413Skan	break;
643690277Sobrien    }
643750599Sobrien
643890277Sobrien#if defined (OS2) ||defined (HAVE_DOS_BASED_FILE_SYSTEM)
643990277Sobrien  /* look again, but case-insensitively this time.  */
644090277Sobrien  if (cp < compilers)
644190277Sobrien    for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
644290277Sobrien      {
644390277Sobrien	if (/* The suffix `-' matches only the file name `-'.  */
644490277Sobrien	    (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
644590277Sobrien	    || (strlen (cp->suffix) < length
644690277Sobrien		/* See if the suffix matches the end of NAME.  */
644790277Sobrien		&& ((!strcmp (cp->suffix,
644890277Sobrien			     name + length - strlen (cp->suffix))
644990277Sobrien		     || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
645090277Sobrien		    && !strcasecmp (cp->suffix,
645190277Sobrien				    name + length - strlen (cp->suffix)))
645290277Sobrien	   ))
645390277Sobrien	  break;
645490277Sobrien      }
645590277Sobrien#endif
645650599Sobrien
645790277Sobrien  if (cp >= compilers)
645890277Sobrien    {
645990277Sobrien      if (cp->spec[0] != '@')
646090277Sobrien	/* A non-alias entry: return it.  */
646190277Sobrien	return cp;
646290277Sobrien
646390277Sobrien      /* An alias entry maps a suffix to a language.
646490277Sobrien	 Search for the language; pass 0 for NAME and LENGTH
646590277Sobrien	 to avoid infinite recursion if language not found.  */
646690277Sobrien      return lookup_compiler (NULL, 0, cp->spec + 1);
646718334Speter    }
646818334Speter  return 0;
646918334Speter}
647018334Speter
647118334Speterstatic char *
647218334Spetersave_string (s, len)
647390277Sobrien     const char *s;
647490277Sobrien     int len;
647518334Speter{
647690277Sobrien  char *result = xmalloc (len + 1);
647718334Speter
647890277Sobrien  memcpy (result, s, len);
647918334Speter  result[len] = 0;
648018334Speter  return result;
648118334Speter}
648218334Speter
648390277Sobrienvoid
648418334Speterpfatal_with_name (name)
648552520Sobrien     const char *name;
648618334Speter{
648752520Sobrien  perror_with_name (name);
648852520Sobrien  delete_temp_files ();
648952520Sobrien  exit (1);
649018334Speter}
649118334Speter
649218334Speterstatic void
649318334Speterperror_with_name (name)
649452520Sobrien     const char *name;
649518334Speter{
649652520Sobrien  error ("%s: %s", name, xstrerror (errno));
649718334Speter}
649818334Speter
649918334Speterstatic void
650050599Sobrienpfatal_pexecute (errmsg_fmt, errmsg_arg)
650152520Sobrien     const char *errmsg_fmt;
650252520Sobrien     const char *errmsg_arg;
650318334Speter{
650450599Sobrien  if (errmsg_arg)
650550599Sobrien    {
650652520Sobrien      int save_errno = errno;
650752520Sobrien
650850599Sobrien      /* Space for trailing '\0' is in %s.  */
650950599Sobrien      char *msg = xmalloc (strlen (errmsg_fmt) + strlen (errmsg_arg));
651050599Sobrien      sprintf (msg, errmsg_fmt, errmsg_arg);
651150599Sobrien      errmsg_fmt = msg;
651252520Sobrien
651352520Sobrien      errno = save_errno;
651450599Sobrien    }
651550599Sobrien
651652520Sobrien  pfatal_with_name (errmsg_fmt);
651718334Speter}
651818334Speter
651990277Sobrien/* Output an error message and exit */
652018334Speter
652118334Spetervoid
652218334Speterfancy_abort ()
652318334Speter{
652490277Sobrien  fatal ("internal gcc abort");
652518334Speter}
652618334Speter
652718334Speter/* Output an error message and exit */
652818334Speter
652952520Sobrienvoid
653090277Sobrienfatal VPARAMS ((const char *msgid, ...))
653118334Speter{
653290277Sobrien  VA_OPEN (ap, msgid);
653390277Sobrien  VA_FIXEDARG (ap, const char *, msgid);
653418334Speter
653518334Speter  fprintf (stderr, "%s: ", programname);
653652520Sobrien  vfprintf (stderr, _(msgid), ap);
653790277Sobrien  VA_CLOSE (ap);
653818334Speter  fprintf (stderr, "\n");
653918334Speter  delete_temp_files ();
654018334Speter  exit (1);
654118334Speter}
654218334Speter
654390277Sobrienvoid
654490277Sobrienerror VPARAMS ((const char *msgid, ...))
654518334Speter{
654690277Sobrien  VA_OPEN (ap, msgid);
654790277Sobrien  VA_FIXEDARG (ap, const char *, msgid);
654818334Speter
654918334Speter  fprintf (stderr, "%s: ", programname);
655052520Sobrien  vfprintf (stderr, _(msgid), ap);
655190277Sobrien  VA_CLOSE (ap);
655218334Speter
655318334Speter  fprintf (stderr, "\n");
655418334Speter}
655552520Sobrien
655652520Sobrienstatic void
655790277Sobriennotice VPARAMS ((const char *msgid, ...))
655852520Sobrien{
655990277Sobrien  VA_OPEN (ap, msgid);
656090277Sobrien  VA_FIXEDARG (ap, const char *, msgid);
656152520Sobrien
656252520Sobrien  vfprintf (stderr, _(msgid), ap);
656390277Sobrien  VA_CLOSE (ap);
656452520Sobrien}
656518334Speter
656618334Speterstatic void
656718334Spetervalidate_all_switches ()
656818334Speter{
656918334Speter  struct compiler *comp;
657090277Sobrien  const char *p;
657190277Sobrien  char c;
657218334Speter  struct spec_list *spec;
657318334Speter
657490277Sobrien  for (comp = compilers; comp->spec; comp++)
657518334Speter    {
657690277Sobrien      p = comp->spec;
657790277Sobrien      while ((c = *p++))
657896285Sobrien	if (c == '%' && (*p == '{' || (*p == 'W' && *++p == '{')))
657990277Sobrien	  /* We have a switch spec.  */
658090277Sobrien	  validate_switches (p + 1);
658118334Speter    }
658218334Speter
658390277Sobrien  /* Look through the linked list of specs read from the specs file.  */
658490277Sobrien  for (spec = specs; spec; spec = spec->next)
658518334Speter    {
658650599Sobrien      p = *(spec->ptr_spec);
658750599Sobrien      while ((c = *p++))
658896285Sobrien	if (c == '%' && (*p == '{' || (*p == 'W' && *++p == '{')))
658918334Speter	  /* We have a switch spec.  */
659018334Speter	  validate_switches (p + 1);
659118334Speter    }
659218334Speter
659318334Speter  p = link_command_spec;
659450599Sobrien  while ((c = *p++))
659596285Sobrien    if (c == '%' && (*p == '{' || (*p == 'W' && *++p == '{')))
659618334Speter      /* We have a switch spec.  */
659718334Speter      validate_switches (p + 1);
659818334Speter}
659918334Speter
660018334Speter/* Look at the switch-name that comes after START
660118334Speter   and mark as valid all supplied switches that match it.  */
660218334Speter
660318334Speterstatic void
660418334Spetervalidate_switches (start)
660552520Sobrien     const char *start;
660618334Speter{
660790277Sobrien  const char *p = start;
660852520Sobrien  const char *filter;
660990277Sobrien  int i;
661090277Sobrien  int suffix;
661118334Speter
661218334Speter  if (*p == '|')
661318334Speter    ++p;
661418334Speter
661590277Sobriennext_member:
661618334Speter  if (*p == '!')
661718334Speter    ++p;
661818334Speter
661990277Sobrien  suffix = 0;
662018334Speter  if (*p == '.')
662118334Speter    suffix = 1, ++p;
662218334Speter
662318334Speter  filter = p;
662490277Sobrien  while (*p != ':' && *p != '}' && *p != '|' && *p != '&')
662590277Sobrien    p++;
662618334Speter
662718334Speter  if (suffix)
662818334Speter    ;
662918334Speter  else if (p[-1] == '*')
663018334Speter    {
663118334Speter      /* Mark all matching switches as valid.  */
663218334Speter      for (i = 0; i < n_switches; i++)
663390277Sobrien	if (!strncmp (switches[i].part1, filter, p - filter - 1))
663452520Sobrien	  switches[i].validated = 1;
663518334Speter    }
663618334Speter  else
663718334Speter    {
663818334Speter      /* Mark an exact matching switch as valid.  */
663918334Speter      for (i = 0; i < n_switches; i++)
664018334Speter	{
664118334Speter	  if (!strncmp (switches[i].part1, filter, p - filter)
664218334Speter	      && switches[i].part1[p - filter] == 0)
664352520Sobrien	    switches[i].validated = 1;
664418334Speter	}
664518334Speter    }
664690277Sobrien
664790277Sobrien  if (*p++ == '|' || p[-1] == '&')
664890277Sobrien    goto next_member;
664918334Speter}
665018334Speter
6651104763Skanstruct mdswitchstr
6652104763Skan{
6653104763Skan  const char *str;
6654104763Skan  int len;
6655104763Skan};
6656104763Skan
6657104763Skanstatic struct mdswitchstr *mdswitches;
6658104763Skanstatic int n_mdswitches;
6659104763Skan
666050599Sobrien/* Check whether a particular argument was used.  The first time we
666150599Sobrien   canonicalize the switches to keep only the ones we care about.  */
666218334Speter
666318334Speterstatic int
666418334Speterused_arg (p, len)
666552520Sobrien     const char *p;
666618334Speter     int len;
666718334Speter{
666890277Sobrien  struct mswitchstr
666990277Sobrien  {
667090277Sobrien    const char *str;
667190277Sobrien    const char *replace;
667250599Sobrien    int len;
667350599Sobrien    int rep_len;
667450599Sobrien  };
667518334Speter
667650599Sobrien  static struct mswitchstr *mswitches;
667750599Sobrien  static int n_mswitches;
667850599Sobrien  int i, j;
667950599Sobrien
668050599Sobrien  if (!mswitches)
668150599Sobrien    {
668250599Sobrien      struct mswitchstr *matches;
668390277Sobrien      const char *q;
668450599Sobrien      int cnt = 0;
668550599Sobrien
668690277Sobrien      /* Break multilib_matches into the component strings of string
668790277Sobrien         and replacement string.  */
668850599Sobrien      for (q = multilib_matches; *q != '\0'; q++)
668950599Sobrien	if (*q == ';')
669050599Sobrien	  cnt++;
669150599Sobrien
669290277Sobrien      matches =
669390277Sobrien	(struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt);
669450599Sobrien      i = 0;
669550599Sobrien      q = multilib_matches;
669650599Sobrien      while (*q != '\0')
669750599Sobrien	{
669850599Sobrien	  matches[i].str = q;
669950599Sobrien	  while (*q != ' ')
670050599Sobrien	    {
670150599Sobrien	      if (*q == '\0')
670250599Sobrien		abort ();
670350599Sobrien	      q++;
670450599Sobrien	    }
670550599Sobrien	  matches[i].len = q - matches[i].str;
670650599Sobrien
670750599Sobrien	  matches[i].replace = ++q;
670850599Sobrien	  while (*q != ';' && *q != '\0')
670950599Sobrien	    {
671050599Sobrien	      if (*q == ' ')
671150599Sobrien		abort ();
671250599Sobrien	      q++;
671350599Sobrien	    }
671450599Sobrien	  matches[i].rep_len = q - matches[i].replace;
671550599Sobrien	  i++;
671650599Sobrien	  if (*q == ';')
671790277Sobrien	    q++;
671850599Sobrien	}
671950599Sobrien
672050599Sobrien      /* Now build a list of the replacement string for switches that we care
672150599Sobrien	 about.  Make sure we allocate at least one entry.  This prevents
672250599Sobrien	 xmalloc from calling fatal, and prevents us from re-executing this
672350599Sobrien	 block of code.  */
672450599Sobrien      mswitches
6725104763Skan	= (struct mswitchstr *)
6726104763Skan	  xmalloc (sizeof (struct mswitchstr)
6727104763Skan		   * (n_mdswitches + (n_switches ? n_switches : 1)));
672850599Sobrien      for (i = 0; i < n_switches; i++)
672950599Sobrien	{
673050599Sobrien	  int xlen = strlen (switches[i].part1);
673150599Sobrien	  for (j = 0; j < cnt; j++)
673290277Sobrien	    if (xlen == matches[j].len
673390277Sobrien		&& ! strncmp (switches[i].part1, matches[j].str, xlen))
673450599Sobrien	      {
673550599Sobrien		mswitches[n_mswitches].str = matches[j].replace;
673650599Sobrien		mswitches[n_mswitches].len = matches[j].rep_len;
673790277Sobrien		mswitches[n_mswitches].replace = (char *) 0;
673850599Sobrien		mswitches[n_mswitches].rep_len = 0;
673950599Sobrien		n_mswitches++;
674050599Sobrien		break;
674150599Sobrien	      }
674250599Sobrien	}
6743104763Skan
6744104763Skan      /* Add MULTILIB_DEFAULTS switches too, as long as they were not present
6745104763Skan	 on the command line nor any options mutually incompatible with
6746104763Skan	 them.  */
6747104763Skan      for (i = 0; i < n_mdswitches; i++)
6748104763Skan	{
6749104763Skan	  const char *r;
6750104763Skan
6751104763Skan	  for (q = multilib_options; *q != '\0'; q++)
6752104763Skan	    {
6753104763Skan	      while (*q == ' ')
6754104763Skan		q++;
6755104763Skan
6756104763Skan	      r = q;
6757104763Skan	      while (strncmp (q, mdswitches[i].str, mdswitches[i].len) != 0
6758104763Skan		     || strchr (" /", q[mdswitches[i].len]) == NULL)
6759104763Skan		{
6760104763Skan		  while (*q != ' ' && *q != '/' && *q != '\0')
6761104763Skan		    q++;
6762104763Skan		  if (*q != '/')
6763104763Skan		    break;
6764104763Skan		  q++;
6765104763Skan		}
6766104763Skan
6767104763Skan	      if (*q != ' ' && *q != '\0')
6768104763Skan		{
6769104763Skan		  while (*r != ' ' && *r != '\0')
6770104763Skan		    {
6771104763Skan		      q = r;
6772104763Skan		      while (*q != ' ' && *q != '/' && *q != '\0')
6773104763Skan			q++;
6774104763Skan
6775104763Skan		      if (used_arg (r, q - r))
6776104763Skan			break;
6777104763Skan
6778104763Skan		      if (*q != '/')
6779104763Skan			{
6780104763Skan			  mswitches[n_mswitches].str = mdswitches[i].str;
6781104763Skan			  mswitches[n_mswitches].len = mdswitches[i].len;
6782104763Skan			  mswitches[n_mswitches].replace = (char *) 0;
6783104763Skan			  mswitches[n_mswitches].rep_len = 0;
6784104763Skan			  n_mswitches++;
6785104763Skan			  break;
6786104763Skan			}
6787104763Skan
6788104763Skan		      r = q + 1;
6789104763Skan		    }
6790104763Skan		  break;
6791104763Skan		}
6792104763Skan	    }
6793104763Skan	}
679450599Sobrien    }
679550599Sobrien
679650599Sobrien  for (i = 0; i < n_mswitches; i++)
679750599Sobrien    if (len == mswitches[i].len && ! strncmp (p, mswitches[i].str, len))
679818334Speter      return 1;
679950599Sobrien
680018334Speter  return 0;
680118334Speter}
680218334Speter
680318334Speterstatic int
680418334Speterdefault_arg (p, len)
680552520Sobrien     const char *p;
680618334Speter     int len;
680718334Speter{
6808104763Skan  int i;
680918334Speter
6810104763Skan  for (i = 0; i < n_mdswitches; i++)
6811104763Skan    if (len == mdswitches[i].len && ! strncmp (p, mdswitches[i].str, len))
6812104763Skan      return 1;
681318334Speter
681418334Speter  return 0;
681518334Speter}
681618334Speter
681790277Sobrien/* Work out the subdirectory to use based on the options. The format of
681890277Sobrien   multilib_select is a list of elements. Each element is a subdirectory
681990277Sobrien   name followed by a list of options followed by a semicolon. The format
682090277Sobrien   of multilib_exclusions is the same, but without the preceding
682190277Sobrien   directory. First gcc will check the exclusions, if none of the options
682290277Sobrien   beginning with an exclamation point are present, and all of the other
682390277Sobrien   options are present, then we will ignore this completely. Passing
682490277Sobrien   that, gcc will consider each multilib_select in turn using the same
682590277Sobrien   rules for matching the options. If a match is found, that subdirectory
682690277Sobrien   will be used.  */
682718334Speter
682818334Speterstatic void
682918334Speterset_multilib_dir ()
683018334Speter{
683190277Sobrien  const char *p;
683290277Sobrien  unsigned int this_path_len;
683390277Sobrien  const char *this_path, *this_arg;
6834104763Skan  const char *start, *end;
683518334Speter  int not_arg;
6836104763Skan  int ok, ndfltok, first;
683718334Speter
6838104763Skan  n_mdswitches = 0;
6839104763Skan  start = multilib_defaults;
6840104763Skan  while (*start == ' ' || *start == '\t')
6841104763Skan    start++;
6842104763Skan  while (*start != '\0')
6843104763Skan    {
6844104763Skan      n_mdswitches++;
6845104763Skan      while (*start != ' ' && *start != '\t' && *start != '\0')
6846104763Skan	start++;
6847104763Skan      while (*start == ' ' || *start == '\t')
6848104763Skan        start++;
6849104763Skan    }
6850104763Skan
6851104763Skan  if (n_mdswitches)
6852104763Skan    {
6853104763Skan      int i = 0;
6854104763Skan
6855104763Skan      mdswitches
6856104763Skan        = (struct mdswitchstr *) xmalloc (sizeof (struct mdswitchstr)
6857104763Skan					  * n_mdswitches);
6858104763Skan      for (start = multilib_defaults; *start != '\0'; start = end + 1)
6859104763Skan	{
6860104763Skan	  while (*start == ' ' || *start == '\t')
6861104763Skan	    start++;
6862104763Skan
6863104763Skan	  if (*start == '\0')
6864104763Skan	    break;
6865104763Skan
6866104763Skan	  for (end = start + 1;
6867104763Skan	       *end != ' ' && *end != '\t' && *end != '\0'; end++)
6868104763Skan	    ;
6869104763Skan
6870104763Skan	  obstack_grow (&multilib_obstack, start, end - start);
6871104763Skan	  obstack_1grow (&multilib_obstack, 0);
6872104763Skan	  mdswitches[i].str = obstack_finish (&multilib_obstack);
6873104763Skan	  mdswitches[i++].len = end - start;
6874104763Skan
6875104763Skan	  if (*end == '\0')
6876104763Skan	    break;
6877104763Skan	}
6878104763Skan    }
6879104763Skan
688090277Sobrien  p = multilib_exclusions;
688118334Speter  while (*p != '\0')
688218334Speter    {
688318334Speter      /* Ignore newlines.  */
688418334Speter      if (*p == '\n')
688518334Speter	{
688618334Speter	  ++p;
688718334Speter	  continue;
688818334Speter	}
688918334Speter
689090277Sobrien      /* Check the arguments.  */
689190277Sobrien      ok = 1;
689290277Sobrien      while (*p != ';')
689390277Sobrien	{
689490277Sobrien	  if (*p == '\0')
689590277Sobrien	    abort ();
689690277Sobrien
689790277Sobrien	  if (! ok)
689890277Sobrien	    {
689990277Sobrien	      ++p;
690090277Sobrien	      continue;
690190277Sobrien	    }
690290277Sobrien
690390277Sobrien	  this_arg = p;
690490277Sobrien	  while (*p != ' ' && *p != ';')
690590277Sobrien	    {
690690277Sobrien	      if (*p == '\0')
690790277Sobrien		abort ();
690890277Sobrien	      ++p;
690990277Sobrien	    }
691090277Sobrien
691190277Sobrien	  if (*this_arg != '!')
691290277Sobrien	    not_arg = 0;
691390277Sobrien	  else
691490277Sobrien	    {
691590277Sobrien	      not_arg = 1;
691690277Sobrien	      ++this_arg;
691790277Sobrien	    }
691890277Sobrien
691990277Sobrien	  ok = used_arg (this_arg, p - this_arg);
692090277Sobrien	  if (not_arg)
692190277Sobrien	    ok = ! ok;
692290277Sobrien
692390277Sobrien	  if (*p == ' ')
692490277Sobrien	    ++p;
692590277Sobrien	}
692690277Sobrien
692790277Sobrien      if (ok)
692890277Sobrien	return;
692990277Sobrien
693090277Sobrien      ++p;
693190277Sobrien    }
693290277Sobrien
6933104763Skan  first = 1;
693490277Sobrien  p = multilib_select;
693590277Sobrien  while (*p != '\0')
693690277Sobrien    {
693790277Sobrien      /* Ignore newlines.  */
693890277Sobrien      if (*p == '\n')
693990277Sobrien	{
694090277Sobrien	  ++p;
694190277Sobrien	  continue;
694290277Sobrien	}
694390277Sobrien
694418334Speter      /* Get the initial path.  */
694518334Speter      this_path = p;
694618334Speter      while (*p != ' ')
694718334Speter	{
694818334Speter	  if (*p == '\0')
694918334Speter	    abort ();
695018334Speter	  ++p;
695118334Speter	}
695218334Speter      this_path_len = p - this_path;
695318334Speter
695418334Speter      /* Check the arguments.  */
695518334Speter      ok = 1;
6956104763Skan      ndfltok = 1;
695718334Speter      ++p;
695818334Speter      while (*p != ';')
695918334Speter	{
696018334Speter	  if (*p == '\0')
696118334Speter	    abort ();
696218334Speter
696318334Speter	  if (! ok)
696418334Speter	    {
696518334Speter	      ++p;
696618334Speter	      continue;
696718334Speter	    }
696818334Speter
696918334Speter	  this_arg = p;
697018334Speter	  while (*p != ' ' && *p != ';')
697118334Speter	    {
697218334Speter	      if (*p == '\0')
697318334Speter		abort ();
697418334Speter	      ++p;
697518334Speter	    }
697618334Speter
697718334Speter	  if (*this_arg != '!')
697818334Speter	    not_arg = 0;
697918334Speter	  else
698018334Speter	    {
698118334Speter	      not_arg = 1;
698218334Speter	      ++this_arg;
698318334Speter	    }
698418334Speter
698518334Speter	  /* If this is a default argument, we can just ignore it.
698618334Speter	     This is true even if this_arg begins with '!'.  Beginning
698718334Speter	     with '!' does not mean that this argument is necessarily
698818334Speter	     inappropriate for this library: it merely means that
698918334Speter	     there is a more specific library which uses this
699018334Speter	     argument.  If this argument is a default, we need not
699118334Speter	     consider that more specific library.  */
6992104763Skan	  ok = used_arg (this_arg, p - this_arg);
6993104763Skan	  if (not_arg)
6994104763Skan	    ok = ! ok;
699518334Speter
6996104763Skan	  if (! ok)
6997104763Skan	    ndfltok = 0;
6998104763Skan
6999104763Skan	  if (default_arg (this_arg, p - this_arg))
7000104763Skan	    ok = 1;
7001104763Skan
700218334Speter	  if (*p == ' ')
700318334Speter	    ++p;
700418334Speter	}
700518334Speter
7006104763Skan      if (ok && first)
700718334Speter	{
700818334Speter	  if (this_path_len != 1
700918334Speter	      || this_path[0] != '.')
701018334Speter	    {
701190277Sobrien	      char *new_multilib_dir = xmalloc (this_path_len + 1);
7012104763Skan	      char *q;
7013104763Skan
701452520Sobrien	      strncpy (new_multilib_dir, this_path, this_path_len);
701552520Sobrien	      new_multilib_dir[this_path_len] = '\0';
7016104763Skan	      q = strchr (new_multilib_dir, ':');
7017104763Skan	      if (q != NULL)
7018104763Skan		*q = '\0';
701952520Sobrien	      multilib_dir = new_multilib_dir;
702018334Speter	    }
7021104763Skan	  first = 0;
702218334Speter	}
702318334Speter
7024104763Skan      if (ndfltok)
7025104763Skan	{
7026104763Skan	  const char *q = this_path, *end = this_path + this_path_len;
7027104763Skan
7028104763Skan	  while (q < end && *q != ':')
7029104763Skan	    q++;
7030104763Skan	  if (q < end)
7031104763Skan	    {
7032104763Skan	      char *new_multilib_os_dir = xmalloc (end - q);
7033104763Skan	      memcpy (new_multilib_os_dir, q + 1, end - q - 1);
7034104763Skan	      new_multilib_os_dir[end - q - 1] = '\0';
7035104763Skan	      multilib_os_dir = new_multilib_os_dir;
7036104763Skan	      break;
7037104763Skan	    }
7038104763Skan	}
7039104763Skan
704018334Speter      ++p;
704190277Sobrien    }
7042104763Skan
7043104763Skan  if (multilib_dir == NULL && multilib_os_dir != NULL
7044104763Skan      && strcmp (multilib_os_dir, ".") == 0)
7045104763Skan    {
7046104763Skan      free ((char *) multilib_os_dir);
7047104763Skan      multilib_os_dir = NULL;
7048104763Skan    }
7049104763Skan  else if (multilib_dir != NULL && multilib_os_dir == NULL)
7050104763Skan    multilib_os_dir = multilib_dir;
705118334Speter}
705218334Speter
705318334Speter/* Print out the multiple library subdirectory selection
705418334Speter   information.  This prints out a series of lines.  Each line looks
705518334Speter   like SUBDIRECTORY;@OPTION@OPTION, with as many options as is
705618334Speter   required.  Only the desired options are printed out, the negative
705718334Speter   matches.  The options are print without a leading dash.  There are
705818334Speter   no spaces to make it easy to use the information in the shell.
705918334Speter   Each subdirectory is printed only once.  This assumes the ordering
706090277Sobrien   generated by the genmultilib script. Also, we leave out ones that match
706190277Sobrien   the exclusions.  */
706218334Speter
706318334Speterstatic void
706418334Speterprint_multilib_info ()
706518334Speter{
706690277Sobrien  const char *p = multilib_select;
706790277Sobrien  const char *last_path = 0, *this_path;
706818334Speter  int skip;
706990277Sobrien  unsigned int last_path_len = 0;
707018334Speter
707118334Speter  while (*p != '\0')
707218334Speter    {
707390277Sobrien      skip = 0;
707418334Speter      /* Ignore newlines.  */
707518334Speter      if (*p == '\n')
707618334Speter	{
707718334Speter	  ++p;
707818334Speter	  continue;
707918334Speter	}
708018334Speter
708118334Speter      /* Get the initial path.  */
708218334Speter      this_path = p;
708318334Speter      while (*p != ' ')
708418334Speter	{
708518334Speter	  if (*p == '\0')
708618334Speter	    abort ();
708718334Speter	  ++p;
708818334Speter	}
708918334Speter
7090104763Skan      /* When --disable-multilib was used but target defines
7091104763Skan	 MULTILIB_OSDIRNAMES, entries starting with .: are there just
7092104763Skan	 to find multilib_os_dir, so skip them from output.  */
7093104763Skan      if (this_path[0] == '.' && this_path[1] == ':')
7094104763Skan	skip = 1;
7095104763Skan
709690277Sobrien      /* Check for matches with the multilib_exclusions. We don't bother
709790277Sobrien         with the '!' in either list. If any of the exclusion rules match
709890277Sobrien         all of its options with the select rule, we skip it.  */
709990277Sobrien      {
710090277Sobrien	const char *e = multilib_exclusions;
710190277Sobrien	const char *this_arg;
710218334Speter
710390277Sobrien	while (*e != '\0')
710490277Sobrien	  {
710590277Sobrien	    int m = 1;
710690277Sobrien	    /* Ignore newlines.  */
710790277Sobrien	    if (*e == '\n')
710890277Sobrien	      {
710990277Sobrien		++e;
711090277Sobrien		continue;
711190277Sobrien	      }
711218334Speter
711390277Sobrien	    /* Check the arguments.  */
711490277Sobrien	    while (*e != ';')
711590277Sobrien	      {
711690277Sobrien		const char *q;
711790277Sobrien		int mp = 0;
711890277Sobrien
711990277Sobrien		if (*e == '\0')
712090277Sobrien		  abort ();
712190277Sobrien
712290277Sobrien		if (! m)
712390277Sobrien		  {
712490277Sobrien		    ++e;
712590277Sobrien		    continue;
712690277Sobrien		  }
712790277Sobrien
712890277Sobrien		this_arg = e;
712990277Sobrien
713090277Sobrien		while (*e != ' ' && *e != ';')
713190277Sobrien		  {
713290277Sobrien		    if (*e == '\0')
713390277Sobrien		      abort ();
713490277Sobrien		    ++e;
713590277Sobrien		  }
713690277Sobrien
713790277Sobrien		q = p + 1;
713890277Sobrien		while (*q != ';')
713990277Sobrien		  {
714090277Sobrien		    const char *arg;
714190277Sobrien		    int len = e - this_arg;
714290277Sobrien
714390277Sobrien		    if (*q == '\0')
714490277Sobrien		      abort ();
714590277Sobrien
714690277Sobrien		    arg = q;
714790277Sobrien
714890277Sobrien		    while (*q != ' ' && *q != ';')
714990277Sobrien		      {
715090277Sobrien			if (*q == '\0')
715190277Sobrien			  abort ();
715290277Sobrien			++q;
715390277Sobrien		      }
715490277Sobrien
715590277Sobrien		    if (! strncmp (arg, this_arg, (len < q - arg) ? q - arg : len) ||
715690277Sobrien			default_arg (this_arg, e - this_arg))
715790277Sobrien		      {
715890277Sobrien			mp = 1;
715990277Sobrien			break;
716090277Sobrien		      }
716190277Sobrien
716290277Sobrien		    if (*q == ' ')
716390277Sobrien		      ++q;
716490277Sobrien		  }
716590277Sobrien
716690277Sobrien		if (! mp)
716790277Sobrien		  m = 0;
716890277Sobrien
716990277Sobrien		if (*e == ' ')
717090277Sobrien		  ++e;
717190277Sobrien	      }
717290277Sobrien
717390277Sobrien	    if (m)
717490277Sobrien	      {
717590277Sobrien		skip = 1;
717690277Sobrien		break;
717790277Sobrien	      }
717890277Sobrien
717990277Sobrien	    if (*e != '\0')
718090277Sobrien	      ++e;
718190277Sobrien	  }
718290277Sobrien      }
718390277Sobrien
718490277Sobrien      if (! skip)
718590277Sobrien	{
718690277Sobrien	  /* If this is a duplicate, skip it.  */
718790277Sobrien	  skip = (last_path != 0 && (unsigned int) (p - this_path) == last_path_len
718890277Sobrien		  && ! strncmp (last_path, this_path, last_path_len));
718990277Sobrien
719090277Sobrien	  last_path = this_path;
719190277Sobrien	  last_path_len = p - this_path;
719290277Sobrien	}
719390277Sobrien
719418334Speter      /* If this directory requires any default arguments, we can skip
719518334Speter	 it.  We will already have printed a directory identical to
719618334Speter	 this one which does not require that default argument.  */
719718334Speter      if (! skip)
719818334Speter	{
719990277Sobrien	  const char *q;
720018334Speter
720118334Speter	  q = p + 1;
720218334Speter	  while (*q != ';')
720318334Speter	    {
720490277Sobrien	      const char *arg;
720518334Speter
720618334Speter	      if (*q == '\0')
720718334Speter		abort ();
720818334Speter
720918334Speter	      if (*q == '!')
721018334Speter		arg = NULL;
721118334Speter	      else
721218334Speter		arg = q;
721318334Speter
721418334Speter	      while (*q != ' ' && *q != ';')
721518334Speter		{
721618334Speter		  if (*q == '\0')
721718334Speter		    abort ();
721818334Speter		  ++q;
721918334Speter		}
722018334Speter
722118334Speter	      if (arg != NULL
722218334Speter		  && default_arg (arg, q - arg))
722318334Speter		{
722418334Speter		  skip = 1;
722518334Speter		  break;
722618334Speter		}
722718334Speter
722818334Speter	      if (*q == ' ')
722918334Speter		++q;
723018334Speter	    }
723118334Speter	}
723218334Speter
723318334Speter      if (! skip)
723418334Speter	{
723590277Sobrien	  const char *p1;
723618334Speter
7237104763Skan	  for (p1 = last_path; p1 < p && *p1 != ':'; p1++)
723818334Speter	    putchar (*p1);
723918334Speter	  putchar (';');
724018334Speter	}
724118334Speter
724218334Speter      ++p;
724318334Speter      while (*p != ';')
724418334Speter	{
724518334Speter	  int use_arg;
724618334Speter
724718334Speter	  if (*p == '\0')
724818334Speter	    abort ();
724918334Speter
725018334Speter	  if (skip)
725118334Speter	    {
725218334Speter	      ++p;
725318334Speter	      continue;
725418334Speter	    }
725518334Speter
725618334Speter	  use_arg = *p != '!';
725718334Speter
725818334Speter	  if (use_arg)
725918334Speter	    putchar ('@');
726018334Speter
726118334Speter	  while (*p != ' ' && *p != ';')
726218334Speter	    {
726318334Speter	      if (*p == '\0')
726418334Speter		abort ();
726518334Speter	      if (use_arg)
726618334Speter		putchar (*p);
726718334Speter	      ++p;
726818334Speter	    }
726918334Speter
727018334Speter	  if (*p == ' ')
727118334Speter	    ++p;
727218334Speter	}
727318334Speter
727418334Speter      if (! skip)
727550599Sobrien	{
727690277Sobrien	  /* If there are extra options, print them now.  */
727750599Sobrien	  if (multilib_extra && *multilib_extra)
727850599Sobrien	    {
727950599Sobrien	      int print_at = TRUE;
728090277Sobrien	      const char *q;
728118334Speter
728250599Sobrien	      for (q = multilib_extra; *q != '\0'; q++)
728350599Sobrien		{
728450599Sobrien		  if (*q == ' ')
728550599Sobrien		    print_at = TRUE;
728650599Sobrien		  else
728750599Sobrien		    {
728850599Sobrien		      if (print_at)
728950599Sobrien			putchar ('@');
729050599Sobrien		      putchar (*q);
729150599Sobrien		      print_at = FALSE;
729250599Sobrien		    }
729350599Sobrien		}
729450599Sobrien	    }
729590277Sobrien
729650599Sobrien	  putchar ('\n');
729750599Sobrien	}
729850599Sobrien
729918334Speter      ++p;
730018334Speter    }
730118334Speter}
7302117413Skan
7303117413Skan/* if-exists built-in spec function.
7304117413Skan
7305117413Skan   Checks to see if the file specified by the absolute pathname in
7306117413Skan   ARGS exists.  Returns that pathname if found.
7307117413Skan
7308117413Skan   The usual use for this function is to check for a library file
7309117413Skan   (whose name has been expanded with %s).  */
7310117413Skan
7311117413Skanstatic const char *
7312117413Skanif_exists_spec_function (argc, argv)
7313117413Skan     int argc;
7314117413Skan     const char **argv;
7315117413Skan{
7316117413Skan  /* Must have only one argument.  */
7317117413Skan  if (argc == 1 && IS_ABSOLUTE_PATHNAME (argv[0]) && ! access (argv[0], R_OK))
7318117413Skan    return argv[0];
7319117413Skan
7320117413Skan  return NULL;
7321117413Skan}
7322117413Skan
7323117413Skan/* if-exists-else built-in spec function.
7324117413Skan
7325117413Skan   This is like if-exists, but takes an additional argument which
7326117413Skan   is returned if the first argument does not exist.  */
7327117413Skan
7328117413Skanstatic const char *
7329117413Skanif_exists_else_spec_function (argc, argv)
7330117413Skan     int argc;
7331117413Skan     const char **argv;
7332117413Skan{
7333117413Skan  /* Must have exactly two arguments.  */
7334117413Skan  if (argc != 2)
7335117413Skan    return NULL;
7336117413Skan
7337117413Skan  if (IS_ABSOLUTE_PATHNAME (argv[0]) && ! access (argv[0], R_OK))
7338117413Skan    return argv[0];
7339117413Skan
7340117413Skan  return argv[1];
7341117413Skan}
7342