gcc.c revision 146908
118334Speter/* Compiler driver program that can handle many languages.
290277Sobrien   Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3132733Skan   1999, 2000, 2001, 2002, 2003, 2004 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 146908 2005-06-03 04:02:20Z 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"
77132733Skan#include "coretypes.h"
78132733Skan#include "multilib.h" /* before tm.h */
79132733Skan#include "tm.h"
8050599Sobrien#include <signal.h>
8190277Sobrien#if ! defined( SIGCHLD ) && defined( SIGCLD )
8290277Sobrien#  define SIGCHLD SIGCLD
8390277Sobrien#endif
8450599Sobrien#include "obstack.h"
8552520Sobrien#include "intl.h"
8652520Sobrien#include "prefix.h"
8790277Sobrien#include "gcc.h"
8890277Sobrien#include "flags.h"
8918334Speter
9090277Sobrien#ifdef HAVE_SYS_RESOURCE_H
9190277Sobrien#include <sys/resource.h>
9218334Speter#endif
9390277Sobrien#if defined (HAVE_DECL_GETRUSAGE) && !HAVE_DECL_GETRUSAGE
94132733Skanextern int getrusage (int, struct rusage *);
9590277Sobrien#endif
9618334Speter
9790277Sobrien/* By default there is no special suffix for target executables.  */
9890277Sobrien/* FIXME: when autoconf is fixed, remove the host check - dj */
9990277Sobrien#if defined(TARGET_EXECUTABLE_SUFFIX) && defined(HOST_EXECUTABLE_SUFFIX)
10090277Sobrien#define HAVE_TARGET_EXECUTABLE_SUFFIX
10118334Speter#endif
10218334Speter
10390277Sobrien/* By default there is no special suffix for host executables.  */
10490277Sobrien#ifdef HOST_EXECUTABLE_SUFFIX
10590277Sobrien#define HAVE_HOST_EXECUTABLE_SUFFIX
10618334Speter#else
10790277Sobrien#define HOST_EXECUTABLE_SUFFIX ""
10818334Speter#endif
10918334Speter
11090277Sobrien/* By default, the suffix for target object files is ".o".  */
11190277Sobrien#ifdef TARGET_OBJECT_SUFFIX
11290277Sobrien#define HAVE_TARGET_OBJECT_SUFFIX
11390277Sobrien#else
11490277Sobrien#define TARGET_OBJECT_SUFFIX ".o"
11518334Speter#endif
11618334Speter
11790277Sobrienstatic const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
11852520Sobrien
11990277Sobrien/* Most every one is fine with LIBRARY_PATH.  For some, it conflicts.  */
12090277Sobrien#ifndef LIBRARY_PATH_ENV
12190277Sobrien#define LIBRARY_PATH_ENV "LIBRARY_PATH"
12290277Sobrien#endif
12390277Sobrien
12450599Sobrien#ifndef HAVE_KILL
12550599Sobrien#define kill(p,s) raise(s)
12618334Speter#endif
12718334Speter
12818334Speter/* If a stage of compilation returns an exit status >= 1,
12918334Speter   compilation of that file ceases.  */
13018334Speter
13118334Speter#define MIN_FATAL_STATUS 1
13218334Speter
13390277Sobrien/* Flag set by cppspec.c to 1.  */
13490277Sobrienint is_cpp_driver;
13590277Sobrien
13690277Sobrien/* Flag saying to pass the greatest exit code returned by a sub-process
13790277Sobrien   to the calling program.  */
13890277Sobrienstatic int pass_exit_codes;
13990277Sobrien
14090277Sobrien/* Definition of string containing the arguments given to configure.  */
14190277Sobrien#include "configargs.h"
14290277Sobrien
14318334Speter/* Flag saying to print the directories gcc will search through looking for
14418334Speter   programs, libraries, etc.  */
14518334Speter
14618334Speterstatic int print_search_dirs;
14718334Speter
14818334Speter/* Flag saying to print the full filename of this file
14918334Speter   as found through our usual search mechanism.  */
15018334Speter
15152520Sobrienstatic const char *print_file_name = NULL;
15218334Speter
15350599Sobrien/* As print_file_name, but search for executable file.  */
15418334Speter
15552520Sobrienstatic const char *print_prog_name = NULL;
15618334Speter
15718334Speter/* Flag saying to print the relative path we'd use to
15818334Speter   find libgcc.a given the current compiler flags.  */
15918334Speter
16018334Speterstatic int print_multi_directory;
16118334Speter
162104763Skan/* Flag saying to print the relative path we'd use to
163104763Skan   find OS libraries given the current compiler flags.  */
164104763Skan
165104763Skanstatic int print_multi_os_directory;
166104763Skan
16718334Speter/* Flag saying to print the list of subdirectories and
16818334Speter   compiler flags used to select them in a standard form.  */
16918334Speter
17018334Speterstatic int print_multi_lib;
17118334Speter
17250599Sobrien/* Flag saying to print the command line options understood by gcc and its
17350599Sobrien   sub-processes.  */
17450599Sobrien
17550599Sobrienstatic int print_help_list;
17650599Sobrien
17718334Speter/* Flag indicating whether we should print the command and arguments */
17818334Speter
17918334Speterstatic int verbose_flag;
18018334Speter
18190277Sobrien/* Flag indicating whether we should ONLY print the command and
18290277Sobrien   arguments (like verbose_flag) without executing the command.
18390277Sobrien   Displayed arguments are quoted so that the generated command
18490277Sobrien   line is suitable for execution.  This is intended for use in
18590277Sobrien   shell scripts to capture the driver-generated command line.  */
18690277Sobrienstatic int verbose_only_flag;
18790277Sobrien
18890277Sobrien/* Flag indicating to print target specific command line options.  */
18990277Sobrien
19090277Sobrienstatic int target_help_flag;
19190277Sobrien
19290277Sobrien/* Flag indicating whether we should report subprocess execution times
19390277Sobrien   (if this is supported by the system - see pexecute.c).  */
19490277Sobrien
19590277Sobrienstatic int report_times;
19690277Sobrien
197132733Skan/* Nonzero means place this string before uses of /, so that include
198132733Skan   and library files can be found in an alternate location.  */
199132733Skan
200132733Skan#ifdef TARGET_SYSTEM_ROOT
201132733Skanstatic const char *target_system_root = TARGET_SYSTEM_ROOT;
202132733Skan#else
203132733Skanstatic const char *target_system_root = 0;
204132733Skan#endif
205132733Skan
206132733Skan/* Nonzero means pass the updated target_system_root to the compiler.  */
207132733Skan
208132733Skanstatic int target_system_root_changed;
209132733Skan
210132733Skan/* Nonzero means append this string to target_system_root.  */
211132733Skan
212132733Skanstatic const char *target_sysroot_suffix = 0;
213132733Skan
214132733Skan/* Nonzero means append this string to target_system_root for headers.  */
215132733Skan
216132733Skanstatic const char *target_sysroot_hdrs_suffix = 0;
217132733Skan
21818334Speter/* Nonzero means write "temp" files in source directory
21918334Speter   and use the source file's name in them, and don't delete them.  */
22018334Speter
22118334Speterstatic int save_temps_flag;
22218334Speter
223132733Skan/* Nonzero means use pipes to communicate between subprocesses.
224132733Skan   Overridden by either of the above two flags.  */
225132733Skan
226132733Skanstatic int use_pipes;
227132733Skan
22818334Speter/* The compiler version.  */
22918334Speter
23090277Sobrienstatic const char *compiler_version;
23118334Speter
23218334Speter/* The target version specified with -V */
23318334Speter
234117413Skanstatic const char *const spec_version = DEFAULT_TARGET_VERSION;
23518334Speter
23618334Speter/* The target machine specified with -b.  */
23718334Speter
23852520Sobrienstatic const char *spec_machine = DEFAULT_TARGET_MACHINE;
23918334Speter
24018334Speter/* Nonzero if cross-compiling.
24118334Speter   When -b is used, the value comes from the `specs' file.  */
24218334Speter
24318334Speter#ifdef CROSS_COMPILE
24490277Sobrienstatic const char *cross_compile = "1";
24518334Speter#else
24690277Sobrienstatic const char *cross_compile = "0";
24718334Speter#endif
24818334Speter
24990277Sobrien#ifdef MODIFY_TARGET_NAME
25090277Sobrien
25190277Sobrien/* Information on how to alter the target name based on a command-line
25290277Sobrien   switch.  The only case we support now is simply appending or deleting a
25390277Sobrien   string to or from the end of the first part of the configuration name.  */
25490277Sobrien
25590277Sobrienstatic const struct modify_target
25690277Sobrien{
25790277Sobrien  const char *const sw;
25890277Sobrien  const enum add_del {ADD, DELETE} add_del;
25990277Sobrien  const char *const str;
26090277Sobrien}
26190277Sobrienmodify_target[] = MODIFY_TARGET_NAME;
26290277Sobrien#endif
263117413Skan
26418334Speter/* The number of errors that have occurred; the link phase will not be
265117413Skan   run if this is nonzero.  */
26618334Speterstatic int error_count = 0;
26718334Speter
26890277Sobrien/* Greatest exit code of sub-processes that has been encountered up to
26990277Sobrien   now.  */
27090277Sobrienstatic int greatest_status = 1;
27190277Sobrien
27218334Speter/* This is the obstack which we use to allocate many strings.  */
27318334Speter
27418334Speterstatic struct obstack obstack;
27518334Speter
27618334Speter/* This is the obstack to build an environment variable to pass to
27718334Speter   collect2 that describes all of the relevant switches of what to
27818334Speter   pass the compiler in building the list of pointers to constructors
27918334Speter   and destructors.  */
28018334Speter
28118334Speterstatic struct obstack collect_obstack;
28218334Speter
28390277Sobrien/* These structs are used to collect resource usage information for
28490277Sobrien   subprocesses.  */
28590277Sobrien#ifdef HAVE_GETRUSAGE
28690277Sobrienstatic struct rusage rus, prus;
28790277Sobrien#endif
28818334Speter
28918334Speter/* Forward declaration for prototypes.  */
29018334Speterstruct path_prefix;
29118334Speter
292132733Skanstatic void init_spec (void);
293132733Skanstatic void store_arg (const char *, int, int);
294132733Skanstatic char *load_specs (const char *);
295132733Skanstatic void read_specs (const char *, int);
296132733Skanstatic void set_spec (const char *, const char *);
297132733Skanstatic struct compiler *lookup_compiler (const char *, size_t, const char *);
298132733Skanstatic char *build_search_list (struct path_prefix *, const char *, int);
299132733Skanstatic void putenv_from_prefixes (struct path_prefix *, const char *);
300132733Skanstatic int access_check (const char *, int);
301132733Skanstatic char *find_a_file (struct path_prefix *, const char *, int, int);
302132733Skanstatic void add_prefix (struct path_prefix *, const char *, const char *,
303132733Skan			int, int, int *, int);
304132733Skanstatic void add_sysrooted_prefix (struct path_prefix *, const char *,
305132733Skan				  const char *, int, int, int *, int);
306132733Skanstatic void translate_options (int *, const char *const **);
307132733Skanstatic char *skip_whitespace (char *);
308132733Skanstatic void delete_if_ordinary (const char *);
309132733Skanstatic void delete_temp_files (void);
310132733Skanstatic void delete_failure_queue (void);
311132733Skanstatic void clear_failure_queue (void);
312132733Skanstatic int check_live_switch (int, int);
313132733Skanstatic const char *handle_braces (const char *);
314132733Skanstatic inline bool input_suffix_matches (const char *, const char *);
315132733Skanstatic inline bool switch_matches (const char *, const char *, int);
316132733Skanstatic inline void mark_matching_switches (const char *, const char *, int);
317132733Skanstatic inline void process_marked_switches (void);
318132733Skanstatic const char *process_brace_body (const char *, const char *, const char *, int, int);
319132733Skanstatic const struct spec_function *lookup_spec_function (const char *);
320132733Skanstatic const char *eval_spec_function (const char *, const char *);
321132733Skanstatic const char *handle_spec_function (const char *);
322132733Skanstatic char *save_string (const char *, int);
323132733Skanstatic void set_collect_gcc_options (void);
324132733Skanstatic int do_spec_1 (const char *, int, const char *);
325132733Skanstatic int do_spec_2 (const char *);
326132733Skanstatic void do_option_spec (const char *, const char *);
327132733Skanstatic void do_self_spec (const char *);
328132733Skanstatic const char *find_file (const char *);
329132733Skanstatic int is_directory (const char *, const char *, int);
330132733Skanstatic const char *validate_switches (const char *);
331132733Skanstatic void validate_all_switches (void);
332132733Skanstatic inline void validate_switches_from_spec (const char *);
333132733Skanstatic void give_switch (int, int);
334132733Skanstatic int used_arg (const char *, int);
335132733Skanstatic int default_arg (const char *, int);
336132733Skanstatic void set_multilib_dir (void);
337132733Skanstatic void print_multilib_info (void);
338132733Skanstatic void perror_with_name (const char *);
339132733Skanstatic void pfatal_pexecute (const char *, const char *) ATTRIBUTE_NORETURN;
340132733Skanstatic void notice (const char *, ...) ATTRIBUTE_PRINTF_1;
341132733Skanstatic void display_help (void);
342132733Skanstatic void add_preprocessor_option (const char *, int);
343132733Skanstatic void add_assembler_option (const char *, int);
344132733Skanstatic void add_linker_option (const char *, int);
345132733Skanstatic void process_command (int, const char **);
346132733Skanstatic int execute (void);
347132733Skanstatic void alloc_args (void);
348132733Skanstatic void clear_args (void);
349132733Skanstatic void fatal_error (int);
35090277Sobrien#ifdef ENABLE_SHARED_LIBGCC
351132733Skanstatic void init_gcc_specs (struct obstack *, const char *, const char *,
352132733Skan			    const char *);
35390277Sobrien#endif
35490277Sobrien#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
355132733Skanstatic const char *convert_filename (const char *, int, int);
35690277Sobrien#endif
357117413Skan
358132733Skanstatic const char *if_exists_spec_function (int, const char **);
359132733Skanstatic const char *if_exists_else_spec_function (int, const char **);
36090277Sobrien
36190277Sobrien/* The Specs Language
36218334Speter
36390277SobrienSpecs are strings containing lines, each of which (if not blank)
36418334Speteris made up of a program name, and arguments separated by spaces.
36518334SpeterThe program name must be exact and start from root, since no path
36618334Speteris searched and it is unreliable to depend on the current working directory.
36718334SpeterRedirection of input or output is not supported; the subprograms must
36818334Speteraccept filenames saying what files to read and write.
36918334Speter
37018334SpeterIn addition, the specs can contain %-sequences to substitute variable text
37118334Speteror for conditional text.  Here is a table of all defined %-sequences.
37218334SpeterNote that spaces are not generated automatically around the results of
37318334Speterexpanding these sequences; therefore, you can concatenate them together
37418334Speteror with constant text in a single argument.
37518334Speter
37618334Speter %%	substitute one % into the program name or argument.
37718334Speter %i     substitute the name of the input file being processed.
37818334Speter %b     substitute the basename of the input file being processed.
37918334Speter	This is the substring up to (and not including) the last period
38018334Speter	and not including the directory.
38190277Sobrien %B	same as %b, but include the file suffix (text after the last period).
38250599Sobrien %gSUFFIX
38350599Sobrien	substitute a file name that has suffix SUFFIX and is chosen
38450599Sobrien	once per compilation, and mark the argument a la %d.  To reduce
38550599Sobrien	exposure to denial-of-service attacks, the file name is now
38650599Sobrien	chosen in a way that is hard to predict even when previously
38750599Sobrien	chosen file names are known.  For example, `%g.s ... %g.o ... %g.s'
38850599Sobrien	might turn into `ccUVUUAU.s ccXYAXZ12.o ccUVUUAU.s'.  SUFFIX matches
38990277Sobrien	the regexp "[.A-Za-z]*%O"; "%O" is treated exactly as if it
39090277Sobrien	had been pre-processed.  Previously, %g was simply substituted
39190277Sobrien	with a file name chosen once per compilation, without regard
39290277Sobrien	to any appended suffix (which was therefore treated just like
39390277Sobrien	ordinary text), making such attacks more likely to succeed.
394132733Skan %|SUFFIX
395132733Skan	like %g, but if -pipe is in effect, expands simply to "-".
396132733Skan %mSUFFIX
397132733Skan        like %g, but if -pipe is in effect, expands to nothing.  (We have both
398132733Skan	%| and %m to accommodate differences between system assemblers; see
399132733Skan	the AS_NEEDS_DASH_FOR_PIPED_INPUT target macro.)
40050599Sobrien %uSUFFIX
40150599Sobrien	like %g, but generates a new temporary file name even if %uSUFFIX
40250599Sobrien	was already seen.
40350599Sobrien %USUFFIX
40450599Sobrien	substitutes the last file name generated with %uSUFFIX, generating a
40550599Sobrien	new one if there is no such last file name.  In the absence of any
40650599Sobrien	%uSUFFIX, this is just like %gSUFFIX, except they don't share
40750599Sobrien	the same suffix "space", so `%g.s ... %U.s ... %g.s ... %U.s'
40850599Sobrien	would involve the generation of two distinct file names, one
40950599Sobrien	for each `%g.s' and another for each `%U.s'.  Previously, %U was
41050599Sobrien	simply substituted with a file name chosen for the previous %u,
41150599Sobrien	without regard to any appended suffix.
41290277Sobrien %jSUFFIX
41390277Sobrien        substitutes the name of the HOST_BIT_BUCKET, if any, and if it is
41490277Sobrien        writable, and if save-temps is off; otherwise, substitute the name
41590277Sobrien        of a temporary file, just like %u.  This temporary file is not
41690277Sobrien        meant for communication between processes, but rather as a junk
41790277Sobrien        disposal mechanism.
41890277Sobrien %.SUFFIX
41990277Sobrien        substitutes .SUFFIX for the suffixes of a matched switch's args when
42090277Sobrien        it is subsequently output with %*. SUFFIX is terminated by the next
42190277Sobrien        space or %.
42218334Speter %d	marks the argument containing or following the %d as a
42318334Speter	temporary file name, so that that file will be deleted if CC exits
42418334Speter	successfully.  Unlike %g, this contributes no text to the argument.
42518334Speter %w	marks the argument containing or following the %w as the
42618334Speter	"output file" of this compilation.  This puts the argument
42718334Speter	into the sequence of arguments that %o will substitute later.
428132733Skan %V	indicates that this compilation produces no "output file".
42918334Speter %W{...}
43018334Speter	like %{...} but mark last argument supplied within
43118334Speter	as a file to be deleted on failure.
43218334Speter %o	substitutes the names of all the output files, with spaces
43318334Speter	automatically placed around them.  You should write spaces
43418334Speter	around the %o as well or the results are undefined.
43518334Speter	%o is for use in the specs for running the linker.
43618334Speter	Input files whose names have no recognized suffix are not compiled
43718334Speter	at all, but they are included among the output files, so they will
43818334Speter	be linked.
43950599Sobrien %O	substitutes the suffix for object files.  Note that this is
44090277Sobrien        handled specially when it immediately follows %g, %u, or %U
44190277Sobrien	(with or without a suffix argument) because of the need for
44290277Sobrien	those to form complete file names.  The handling is such that
44390277Sobrien	%O is treated exactly as if it had already been substituted,
44490277Sobrien	except that %g, %u, and %U do not currently support additional
44590277Sobrien	SUFFIX characters following %O as they would following, for
44690277Sobrien	example, `.o'.
447132733Skan %I	Substitute any of -iprefix (made from GCC_EXEC_PREFIX), -isysroot
448132733Skan	(made from TARGET_SYSTEM_ROOT), and -isystem (made from COMPILER_PATH
449132733Skan	and -B options) as necessary.
45018334Speter %s     current argument is the name of a library or startup file of some sort.
45118334Speter        Search for that file in a standard list of directories
45218334Speter	and substitute the full name found.
45318334Speter %eSTR  Print STR as an error message.  STR is terminated by a newline.
45418334Speter        Use this when inconsistent options are detected.
455117413Skan %nSTR  Print STR as a notice.  STR is terminated by a newline.
45618334Speter %x{OPTION}	Accumulate an option for %X.
45718334Speter %X	Output the accumulated linker options specified by compilations.
45818334Speter %Y	Output the accumulated assembler options specified by compilations.
45918334Speter %Z	Output the accumulated preprocessor options specified by compilations.
46018334Speter %a     process ASM_SPEC as a spec.
46118334Speter        This allows config.h to specify part of the spec for running as.
46218334Speter %A	process ASM_FINAL_SPEC as a spec.  A capital A is actually
46318334Speter	used here.  This can be used to run a post-processor after the
46450599Sobrien	assembler has done its job.
46518334Speter %D	Dump out a -L option for each directory in startfile_prefixes.
46618334Speter	If multilib_dir is set, extra entries are generated with it affixed.
46718334Speter %l     process LINK_SPEC as a spec.
46818334Speter %L     process LIB_SPEC as a spec.
46918334Speter %G     process LIBGCC_SPEC as a spec.
47090277Sobrien %M     output multilib_dir with directory separators replaced with "_";
47190277Sobrien	if multilib_dir is not set or is ".", output "".
47218334Speter %S     process STARTFILE_SPEC as a spec.  A capital S is actually used here.
47318334Speter %E     process ENDFILE_SPEC as a spec.  A capital E is actually used here.
47490277Sobrien %C     process CPP_SPEC as a spec.
47518334Speter %1	process CC1_SPEC as a spec.
47618334Speter %2	process CC1PLUS_SPEC as a spec.
47718334Speter %*	substitute the variable part of a matched option.  (See below.)
47818334Speter	Note that each comma in the substituted string is replaced by
47918334Speter	a single space.
480132733Skan %<S    remove all occurrences of -S from the command line.
481132733Skan        Note - this command is position dependent.  % commands in the
482132733Skan        spec string before this one will see -S, % commands in the
483132733Skan        spec string after this one will not.
484132733Skan %<S*	remove all occurrences of all switches beginning with -S from the
485132733Skan        command line.
486117413Skan %:function(args)
487117413Skan	Call the named function FUNCTION, passing it ARGS.  ARGS is
488117413Skan	first processed as a nested spec string, then split into an
489117413Skan	argument vector in the usual fashion.  The function returns
490117413Skan	a string which is processed as if it had appeared literally
491117413Skan	as part of the current spec.
49218334Speter %{S}   substitutes the -S switch, if that switch was given to CC.
49318334Speter	If that switch was not specified, this substitutes nothing.
49418334Speter	Here S is a metasyntactic variable.
49518334Speter %{S*}  substitutes all the switches specified to CC whose names start
49690277Sobrien	with -S.  This is used for -o, -I, etc; switches that take
49718334Speter	arguments.  CC considers `-o foo' as being one switch whose
49818334Speter	name starts with `o'.  %{o*} would substitute this text,
49918334Speter	including the space; thus, two arguments would be generated.
50090277Sobrien %{S*&T*} likewise, but preserve order of S and T options (the order
501132733Skan	of S and T in the spec is not significant).  Can be any number
502132733Skan	of ampersand-separated variables; for each the wild card is
503132733Skan	optional.  Useful for CPP as %{D*&U*&A*}.
504132733Skan
505132733Skan %{S:X}   substitutes X, if the -S switch was given to CC.
506132733Skan %{!S:X}  substitutes X, if the -S switch was NOT given to CC.
507132733Skan %{S*:X}  substitutes X if one or more switches whose names start
508132733Skan          with -S was given to CC.  Normally X is substituted only
509132733Skan          once, no matter how many such switches appeared.  However,
510132733Skan          if %* appears somewhere in X, then X will be substituted
511132733Skan          once for each matching switch, with the %* replaced by the
512132733Skan          part of that switch that matched the '*'.
513132733Skan %{.S:X}  substitutes X, if processing a file with suffix S.
514132733Skan %{!.S:X} substitutes X, if NOT processing a file with suffix S.
515132733Skan
516132733Skan %{S|T:X} substitutes X if either -S or -T was given to CC.  This may be
517132733Skan	  combined with !, ., and * as above binding stronger than the OR.
518132733Skan	  If %* appears in X, all of the alternatives must be starred, and
519132733Skan	  only the first matching alternative is substituted.
520132733Skan %{S:X;   if S was given to CC, substitutes X;
521132733Skan   T:Y;   else if T was given to CC, substitutes Y;
522132733Skan    :D}   else substitutes D.  There can be as many clauses as you need.
523132733Skan          This may be combined with ., !, |, and * as above.
524132733Skan
52518334Speter %(Spec) processes a specification defined in a specs file as *Spec:
52618334Speter %[Spec] as above, but put __ around -D arguments
52718334Speter
528132733SkanThe conditional text X in a %{S:X} or similar construct may contain
52918334Speterother nested % constructs or spaces, or even newlines.  They are
530132733Skanprocessed as usual, as described above.  Trailing white space in X is
531132733Skanignored.  White space may also appear anywhere on the left side of the
532132733Skancolon in these constructs, except between . or * and the corresponding
533132733Skanword.
53418334Speter
53518334SpeterThe -O, -f, -m, and -W switches are handled specifically in these
53618334Speterconstructs.  If another value of -O or the negated form of a -f, -m, or
53718334Speter-W switch is found later in the command line, the earlier switch
53818334Spetervalue is ignored, except with {S*} where S is just one letter; this
53918334Speterpasses all matching options.
54018334Speter
54150599SobrienThe character | at the beginning of the predicate text is used to indicate
54250599Sobrienthat a command should be piped to the following command, but only if -pipe
54350599Sobrienis specified.
54418334Speter
54518334SpeterNote that it is built into CC which switches take arguments and which
54618334Speterdo not.  You might think it would be useful to generalize this to
54718334Speterallow each compiler's spec to say which switches take arguments.  But
54818334Speterthis cannot be done in a consistent fashion.  CC cannot even decide
54918334Speterwhich input files have been specified without knowing which switches
55018334Spetertake arguments, and it must know which input files to compile in order
55118334Speterto tell which compilers to run.
55218334Speter
55318334SpeterCC also knows implicitly that arguments starting in `-l' are to be
55418334Spetertreated as compiler output files, and passed to the linker in their
55518334Speterproper position among the other output files.  */
55618334Speter
55796285Sobrien/* Define the macros used for specs %a, %l, %L, %S, %C, %1.  */
55818334Speter
55918334Speter/* config.h can define ASM_SPEC to provide extra args to the assembler
56018334Speter   or extra switch-translations.  */
56118334Speter#ifndef ASM_SPEC
56218334Speter#define ASM_SPEC ""
56318334Speter#endif
56418334Speter
56518334Speter/* config.h can define ASM_FINAL_SPEC to run a post processor after
56618334Speter   the assembler has run.  */
56718334Speter#ifndef ASM_FINAL_SPEC
56818334Speter#define ASM_FINAL_SPEC ""
56918334Speter#endif
57018334Speter
57118334Speter/* config.h can define CPP_SPEC to provide extra args to the C preprocessor
57218334Speter   or extra switch-translations.  */
57318334Speter#ifndef CPP_SPEC
57418334Speter#define CPP_SPEC ""
57518334Speter#endif
57618334Speter
57718334Speter/* config.h can define CC1_SPEC to provide extra args to cc1 and cc1plus
57818334Speter   or extra switch-translations.  */
57918334Speter#ifndef CC1_SPEC
58018334Speter#define CC1_SPEC ""
58118334Speter#endif
58218334Speter
58318334Speter/* config.h can define CC1PLUS_SPEC to provide extra args to cc1plus
58418334Speter   or extra switch-translations.  */
58518334Speter#ifndef CC1PLUS_SPEC
58618334Speter#define CC1PLUS_SPEC ""
58718334Speter#endif
58818334Speter
58918334Speter/* config.h can define LINK_SPEC to provide extra args to the linker
59018334Speter   or extra switch-translations.  */
59118334Speter#ifndef LINK_SPEC
59218334Speter#define LINK_SPEC ""
59318334Speter#endif
59418334Speter
59518334Speter/* config.h can define LIB_SPEC to override the default libraries.  */
59618334Speter#ifndef LIB_SPEC
59718334Speter#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
59818334Speter#endif
59918334Speter
60018334Speter/* config.h can define LIBGCC_SPEC to override how and when libgcc.a is
60118334Speter   included.  */
60218334Speter#ifndef LIBGCC_SPEC
60318334Speter#if defined(LINK_LIBGCC_SPECIAL) || defined(LINK_LIBGCC_SPECIAL_1)
60418334Speter/* Have gcc do the search for libgcc.a.  */
60550599Sobrien#define LIBGCC_SPEC "libgcc.a%s"
60618334Speter#else
60750599Sobrien#define LIBGCC_SPEC "-lgcc"
60818334Speter#endif
60918334Speter#endif
61018334Speter
61118334Speter/* config.h can define STARTFILE_SPEC to override the default crt0 files.  */
61218334Speter#ifndef STARTFILE_SPEC
61318334Speter#define STARTFILE_SPEC  \
61418334Speter  "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}"
61518334Speter#endif
61618334Speter
61750599Sobrien/* config.h can define SWITCHES_NEED_SPACES to control which options
61850599Sobrien   require spaces between the option and the argument.  */
61918334Speter#ifndef SWITCHES_NEED_SPACES
62018334Speter#define SWITCHES_NEED_SPACES ""
62118334Speter#endif
62218334Speter
62318334Speter/* config.h can define ENDFILE_SPEC to override the default crtn files.  */
62418334Speter#ifndef ENDFILE_SPEC
62518334Speter#define ENDFILE_SPEC ""
62618334Speter#endif
62718334Speter
62850599Sobrien#ifndef LINKER_NAME
62950599Sobrien#define LINKER_NAME "collect2"
63018334Speter#endif
63118334Speter
63290277Sobrien/* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g'
63390277Sobrien   to the assembler.  */
63490277Sobrien#ifndef ASM_DEBUG_SPEC
63590277Sobrien# if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \
63690277Sobrien     && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
63790277Sobrien#  define ASM_DEBUG_SPEC					\
63890277Sobrien      (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG			\
63990277Sobrien       ? "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}"	\
64090277Sobrien       : "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}")
64190277Sobrien# else
64290277Sobrien#  if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
64390277Sobrien#   define ASM_DEBUG_SPEC "%{g*:--gstabs}"
64490277Sobrien#  endif
64590277Sobrien#  if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG)
64690277Sobrien#   define ASM_DEBUG_SPEC "%{g*:--gdwarf2}"
64790277Sobrien#  endif
64890277Sobrien# endif
64990277Sobrien#endif
65090277Sobrien#ifndef ASM_DEBUG_SPEC
65190277Sobrien# define ASM_DEBUG_SPEC ""
65290277Sobrien#endif
65318334Speter
65490277Sobrien/* Here is the spec for running the linker, after compiling all files.  */
65590277Sobrien
65696285Sobrien/* This is overridable by the target in case they need to specify the
65796285Sobrien   -lgcc and -lc order specially, yet not require them to override all
65896285Sobrien   of LINK_COMMAND_SPEC.  */
65996285Sobrien#ifndef LINK_GCC_C_SEQUENCE_SPEC
66096285Sobrien#define LINK_GCC_C_SEQUENCE_SPEC "%G %L %G"
66196285Sobrien#endif
66296285Sobrien
663132733Skan#ifndef LINK_PIE_SPEC
664132733Skan#ifdef HAVE_LD_PIE
665132733Skan#define LINK_PIE_SPEC "%{pie:-pie} "
666132733Skan#else
667132733Skan#define LINK_PIE_SPEC "%{pie:} "
668132733Skan#endif
669132733Skan#endif
670132733Skan
67190277Sobrien/* -u* was put back because both BSD and SysV seem to support it.  */
67290277Sobrien/* %{static:} simply prevents an error message if the target machine
67390277Sobrien   doesn't handle -static.  */
67490277Sobrien/* We want %{T*} after %{L*} and %D so that it can be used to specify linker
67590277Sobrien   scripts which exist in user specified directories, or in standard
67690277Sobrien   directories.  */
67790277Sobrien#ifndef LINK_COMMAND_SPEC
67890277Sobrien#define LINK_COMMAND_SPEC "\
67990277Sobrien%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
680132733Skan    %(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
681132733Skan    %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
682132733Skan    %{static:} %{L*} %(link_libgcc) %o %{fprofile-arcs|fprofile-generate:-lgcov}\
683132733Skan    %{!nostdlib:%{!nodefaultlibs:%(link_gcc_c_sequence)}}\
68490277Sobrien    %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
68590277Sobrien#endif
68690277Sobrien
68790277Sobrien#ifndef LINK_LIBGCC_SPEC
68890277Sobrien# ifdef LINK_LIBGCC_SPECIAL
68990277Sobrien/* Don't generate -L options for startfile prefix list.  */
69090277Sobrien#  define LINK_LIBGCC_SPEC ""
69190277Sobrien# else
69290277Sobrien/* Do generate them.  */
69390277Sobrien#  define LINK_LIBGCC_SPEC "%D"
69490277Sobrien# endif
69590277Sobrien#endif
69690277Sobrien
697117413Skan#ifndef STARTFILE_PREFIX_SPEC
698117413Skan# define STARTFILE_PREFIX_SPEC ""
699117413Skan#endif
700117413Skan
701132733Skan#ifndef SYSROOT_SUFFIX_SPEC
702132733Skan# define SYSROOT_SUFFIX_SPEC ""
703132733Skan#endif
704132733Skan
705132733Skan#ifndef SYSROOT_HEADERS_SUFFIX_SPEC
706132733Skan# define SYSROOT_HEADERS_SUFFIX_SPEC ""
707132733Skan#endif
708132733Skan
709117413Skanstatic const char *asm_debug;
71090277Sobrienstatic const char *cpp_spec = CPP_SPEC;
71190277Sobrienstatic const char *cc1_spec = CC1_SPEC;
71290277Sobrienstatic const char *cc1plus_spec = CC1PLUS_SPEC;
71396285Sobrienstatic const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC;
71490277Sobrienstatic const char *asm_spec = ASM_SPEC;
71590277Sobrienstatic const char *asm_final_spec = ASM_FINAL_SPEC;
71690277Sobrienstatic const char *link_spec = LINK_SPEC;
71790277Sobrienstatic const char *lib_spec = LIB_SPEC;
71890277Sobrienstatic const char *libgcc_spec = LIBGCC_SPEC;
71990277Sobrienstatic const char *endfile_spec = ENDFILE_SPEC;
72090277Sobrienstatic const char *startfile_spec = STARTFILE_SPEC;
72190277Sobrienstatic const char *switches_need_spaces = SWITCHES_NEED_SPACES;
72290277Sobrienstatic const char *linker_name_spec = LINKER_NAME;
72390277Sobrienstatic const char *link_command_spec = LINK_COMMAND_SPEC;
72490277Sobrienstatic const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
725117413Skanstatic const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC;
726132733Skanstatic const char *sysroot_suffix_spec = SYSROOT_SUFFIX_SPEC;
727132733Skanstatic const char *sysroot_hdrs_suffix_spec = SYSROOT_HEADERS_SUFFIX_SPEC;
72890277Sobrien
72990277Sobrien/* Standard options to cpp, cc1, and as, to reduce duplication in specs.
73090277Sobrien   There should be no need to override these in target dependent files,
73190277Sobrien   but we need to copy them to the specs file so that newer versions
73290277Sobrien   of the GCC driver can correctly drive older tool chains with the
73390277Sobrien   appropriate -B options.  */
73490277Sobrien
735117413Skan/* When cpplib handles traditional preprocessing, get rid of this, and
736117413Skan   call cc1 (or cc1obj in objc/lang-specs.h) from the main specs so
737117413Skan   that we default the front end language better.  */
73890277Sobrienstatic const char *trad_capable_cpp =
739117413Skan"cc1 -E %{traditional|ftraditional|traditional-cpp:-traditional-cpp}";
74090277Sobrien
741107594Sobrien/* We don't wrap .d files in %W{} since a missing .d file, and
742107594Sobrien   therefore no dependency entry, confuses make into thinking a .o
743107594Sobrien   file that happens to exist is up-to-date.  */
74490277Sobrienstatic const char *cpp_unique_options =
745132733Skan"%{C|CC:%{!E:%eGCC does not support -C or -CC without -E}}\
746117413Skan %{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*} %{P} %I\
747107594Sobrien %{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\
748107594Sobrien %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\
749107594Sobrien %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\
75096285Sobrien %{!E:%{!M:%{!MM:%{MD|MMD:%{o*:-MQ %*}}}}}\
751146908Skan %{remap} %{g3:-dD} %{H} %C %{D*&U*&A*} %{i*} %Z %i\
75296285Sobrien %{E|M|MM:%W{o*}}";
75390277Sobrien
75490277Sobrien/* This contains cpp options which are common with cc1_options and are passed
755117413Skan   only when preprocessing only to avoid duplication.  We pass the cc1 spec
756117413Skan   options to the preprocessor so that it the cc1 spec may manipulate
757117413Skan   options used to set target flags.  Those special target flags settings may
758117413Skan   in turn cause preprocessor symbols to be defined specially.  */
75990277Sobrienstatic const char *cpp_options =
760146908Skan"%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w}\
761146908Skan %{f*} %{g*:%{!g0:%{!fno-working-directory:-fworking-directory}}} %{O*}\
762146908Skan %{undef}";
76390277Sobrien
764117413Skan/* This contains cpp options which are not passed when the preprocessor
765117413Skan   output will be used by another program.  */
766117413Skanstatic const char *cpp_debug_options = "%{d*}";
767117413Skan
76890277Sobrien/* NB: This is shared amongst all front-ends.  */
76990277Sobrienstatic const char *cc1_options =
77090277Sobrien"%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
77190277Sobrien %1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\
772132733Skan %{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}%{!c:%{!S:-auxbase %b}}\
773146908Skan %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs}\
774117413Skan %{v:-version} %{pg:-p} %{p} %{f*} %{undef}\
77590277Sobrien %{Qn:-fno-ident} %{--help:--help}\
77690277Sobrien %{--target-help:--target-help}\
77790277Sobrien %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\
77890277Sobrien %{fsyntax-only:-o %j} %{-param*}";
77990277Sobrien
78090277Sobrienstatic const char *asm_options =
78190277Sobrien"%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
78290277Sobrien
78390277Sobrienstatic const char *invoke_as =
784132733Skan#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
785132733Skan"%{!S:-o %|.s |\n as %(asm_options) %|.s %A }";
786132733Skan#else
787132733Skan"%{!S:-o %|.s |\n as %(asm_options) %m.s %A }";
788132733Skan#endif
78990277Sobrien
79050599Sobrien/* Some compilers have limits on line lengths, and the multilib_select
79150599Sobrien   and/or multilib_matches strings can be very long, so we build them at
79250599Sobrien   run time.  */
79350599Sobrienstatic struct obstack multilib_obstack;
79490277Sobrienstatic const char *multilib_select;
79590277Sobrienstatic const char *multilib_matches;
79690277Sobrienstatic const char *multilib_defaults;
79790277Sobrienstatic const char *multilib_exclusions;
79850599Sobrien
79950599Sobrien/* Check whether a particular argument is a default argument.  */
80050599Sobrien
80150599Sobrien#ifndef MULTILIB_DEFAULTS
80250599Sobrien#define MULTILIB_DEFAULTS { "" }
80350599Sobrien#endif
80450599Sobrien
80590277Sobrienstatic const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
80650599Sobrien
807117413Skan#ifndef DRIVER_SELF_SPECS
808117413Skan#define DRIVER_SELF_SPECS ""
809117413Skan#endif
810117413Skan
811117413Skanstatic const char *const driver_self_specs[] = { DRIVER_SELF_SPECS };
812117413Skan
813132733Skan#ifndef OPTION_DEFAULT_SPECS
814132733Skan#define OPTION_DEFAULT_SPECS { "", "" }
815132733Skan#endif
816132733Skan
817132733Skanstruct default_spec
818132733Skan{
819132733Skan  const char *name;
820132733Skan  const char *spec;
821132733Skan};
822132733Skan
823132733Skanstatic const struct default_spec
824132733Skan  option_default_specs[] = { OPTION_DEFAULT_SPECS };
825132733Skan
82690277Sobrienstruct user_specs
82790277Sobrien{
82850599Sobrien  struct user_specs *next;
82952520Sobrien  const char *filename;
83050599Sobrien};
83150599Sobrien
83250599Sobrienstatic struct user_specs *user_specs_head, *user_specs_tail;
83350599Sobrien
83450599Sobrien#ifndef SWITCH_TAKES_ARG
83550599Sobrien#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
83618334Speter#endif
83718334Speter
83818334Speter#ifndef WORD_SWITCH_TAKES_ARG
83918334Speter#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
84018334Speter#endif
84118334Speter
84290277Sobrien#ifdef HAVE_TARGET_EXECUTABLE_SUFFIX
84350599Sobrien/* This defines which switches stop a full compilation.  */
84450599Sobrien#define DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) \
84550599Sobrien  ((CHAR) == 'c' || (CHAR) == 'S')
84650599Sobrien
84750599Sobrien#ifndef SWITCH_CURTAILS_COMPILATION
84850599Sobrien#define SWITCH_CURTAILS_COMPILATION(CHAR) \
84950599Sobrien  DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR)
85050599Sobrien#endif
85150599Sobrien#endif
85250599Sobrien
85318334Speter/* Record the mapping from file suffixes for compilation specs.  */
85418334Speter
85518334Speterstruct compiler
85618334Speter{
85752520Sobrien  const char *suffix;		/* Use this compiler for input files
85818334Speter				   whose names end in this suffix.  */
85918334Speter
86090277Sobrien  const char *spec;		/* To use this compiler, run this spec.  */
86190277Sobrien
86290277Sobrien  const char *cpp_spec;         /* If non-NULL, substitute this spec
86390277Sobrien				   for `%C', rather than the usual
86490277Sobrien				   cpp_spec.  */
86518334Speter};
86618334Speter
86718334Speter/* Pointer to a vector of `struct compiler' that gives the spec for
86818334Speter   compiling a file, based on its suffix.
86918334Speter   A file that does not end in any of these suffixes will be passed
87018334Speter   unchanged to the loader and nothing else will be done to it.
87118334Speter
87218334Speter   An entry containing two 0s is used to terminate the vector.
87318334Speter
87418334Speter   If multiple entries match a file, the last matching one is used.  */
87518334Speter
87618334Speterstatic struct compiler *compilers;
87718334Speter
87818334Speter/* Number of entries in `compilers', not counting the null terminator.  */
87918334Speter
88018334Speterstatic int n_compilers;
88118334Speter
88218334Speter/* The default list of file name suffixes and their compilation specs.  */
88318334Speter
88490277Sobrienstatic const struct compiler default_compilers[] =
88518334Speter{
88650599Sobrien  /* Add lists of suffixes of known languages here.  If those languages
88750599Sobrien     were not present when we built the driver, we will hit these copies
88850599Sobrien     and be given a more meaningful error than "file not used since
88950599Sobrien     linking is not done".  */
89090277Sobrien  {".m",  "#Objective-C", 0}, {".mi",  "#Objective-C", 0},
89190277Sobrien  {".cc", "#C++", 0}, {".cxx", "#C++", 0}, {".cpp", "#C++", 0},
89290277Sobrien  {".cp", "#C++", 0}, {".c++", "#C++", 0}, {".C", "#C++", 0},
893132733Skan  {".CPP", "#C++", 0}, {".ii", "#C++", 0},
89490277Sobrien  {".ads", "#Ada", 0}, {".adb", "#Ada", 0},
89590277Sobrien  {".f", "#Fortran", 0}, {".for", "#Fortran", 0}, {".fpp", "#Fortran", 0},
89690277Sobrien  {".F", "#Fortran", 0}, {".FOR", "#Fortran", 0}, {".FPP", "#Fortran", 0},
89790277Sobrien  {".r", "#Ratfor", 0},
89890277Sobrien  {".p", "#Pascal", 0}, {".pas", "#Pascal", 0},
89990277Sobrien  {".java", "#Java", 0}, {".class", "#Java", 0},
90090277Sobrien  {".zip", "#Java", 0}, {".jar", "#Java", 0},
90150599Sobrien  /* Next come the entries for C.  */
90290277Sobrien  {".c", "@c", 0},
90318334Speter  {"@c",
90490277Sobrien   /* cc1 has an integrated ISO C preprocessor.  We should invoke the
905117413Skan      external preprocessor if -save-temps is given.  */
906117413Skan     "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
90790277Sobrien      %{!E:%{!M:%{!MM:\
908117413Skan          %{traditional|ftraditional:\
909117413Skan%eGNU C no longer supports -traditional without -E}\
910117413Skan	  %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
911132733Skan		%(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\
912132733Skan		    cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \
913132733Skan			%(cc1_options)}\
914117413Skan	  %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
915117413Skan		cc1 %(cpp_unique_options) %(cc1_options)}}}\
91690277Sobrien        %{!fsyntax-only:%(invoke_as)}}}}", 0},
91718334Speter  {"-",
918146908Skan   "%{!E:%e-E or -x required when input is from standard input}\
919117413Skan    %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 0},
92090277Sobrien  {".h", "@c-header", 0},
92118334Speter  {"@c-header",
922132733Skan   /* cc1 has an integrated ISO C preprocessor.  We should invoke the
923132733Skan      external preprocessor if -save-temps is given.  */
924132733Skan     "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
925132733Skan      %{!E:%{!M:%{!MM:\
926132733Skan	  %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
927132733Skan		%(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\
928132733Skan		    cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \
929132733Skan			%(cc1_options)\
930132733Skan                        -o %g.s %{!o*:--output-pch=%i.gch}\
931132733Skan                        %W{o*:--output-pch=%*}%V}\
932132733Skan	  %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
933132733Skan		cc1 %(cpp_unique_options) %(cc1_options)\
934132733Skan                    -o %g.s %{!o*:--output-pch=%i.gch}\
935132733Skan                    %W{o*:--output-pch=%*}%V}}}}}}", 0},
93690277Sobrien  {".i", "@cpp-output", 0},
93718334Speter  {"@cpp-output",
93890277Sobrien   "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0},
93990277Sobrien  {".s", "@assembler", 0},
94018334Speter  {"@assembler",
94190277Sobrien   "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0},
94290277Sobrien  {".S", "@assembler-with-cpp", 0},
94318334Speter  {"@assembler-with-cpp",
944132733Skan#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
94590277Sobrien   "%(trad_capable_cpp) -lang-asm %(cpp_options)\
946117413Skan      %{E|M|MM:%(cpp_debug_options)}\
947132733Skan      %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
948132733Skan       as %(asm_debug) %(asm_options) %|.s %A }}}}"
949132733Skan#else
950132733Skan   "%(trad_capable_cpp) -lang-asm %(cpp_options)\
951132733Skan      %{E|M|MM:%(cpp_debug_options)}\
952132733Skan      %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
953132733Skan       as %(asm_debug) %(asm_options) %m.s %A }}}}"
954132733Skan#endif
955132733Skan   , 0},
956132733Skan
95718334Speter#include "specs.h"
958132733Skan  /* Mark end of table.  */
95990277Sobrien  {0, 0, 0}
96018334Speter};
96118334Speter
96218334Speter/* Number of elements in default_compilers, not counting the terminator.  */
96318334Speter
964117413Skanstatic const int n_default_compilers = ARRAY_SIZE (default_compilers) - 1;
96518334Speter
96618334Speter/* A vector of options to give to the linker.
96718334Speter   These options are accumulated by %x,
96818334Speter   and substituted into the linker command with %X.  */
96918334Speterstatic int n_linker_options;
97018334Speterstatic char **linker_options;
97118334Speter
97218334Speter/* A vector of options to give to the assembler.
97318334Speter   These options are accumulated by -Wa,
97418334Speter   and substituted into the assembler command with %Y.  */
97518334Speterstatic int n_assembler_options;
97618334Speterstatic char **assembler_options;
97718334Speter
97818334Speter/* A vector of options to give to the preprocessor.
97918334Speter   These options are accumulated by -Wp,
98018334Speter   and substituted into the preprocessor command with %Z.  */
98118334Speterstatic int n_preprocessor_options;
98218334Speterstatic char **preprocessor_options;
98318334Speter
98418334Speter/* Define how to map long options into short ones.  */
98518334Speter
98618334Speter/* This structure describes one mapping.  */
98718334Speterstruct option_map
98818334Speter{
98918334Speter  /* The long option's name.  */
99090277Sobrien  const char *const name;
99118334Speter  /* The equivalent short option.  */
99290277Sobrien  const char *const equivalent;
99318334Speter  /* Argument info.  A string of flag chars; NULL equals no options.
99418334Speter     a => argument required.
99518334Speter     o => argument optional.
99618334Speter     j => join argument to equivalent, making one word.
99718334Speter     * => require other text after NAME as an argument.  */
99890277Sobrien  const char *const arg_info;
99918334Speter};
100018334Speter
100118334Speter/* This is the table of mappings.  Mappings are tried sequentially
100218334Speter   for each option encountered; the first one that matches, wins.  */
100318334Speter
100490277Sobrienstatic const struct option_map option_map[] =
100518334Speter {
100618334Speter   {"--all-warnings", "-Wall", 0},
100718334Speter   {"--ansi", "-ansi", 0},
100818334Speter   {"--assemble", "-S", 0},
100918334Speter   {"--assert", "-A", "a"},
101052520Sobrien   {"--classpath", "-fclasspath=", "aj"},
101196285Sobrien   {"--bootclasspath", "-fbootclasspath=", "aj"},
101296285Sobrien   {"--CLASSPATH", "-fclasspath=", "aj"},
101318334Speter   {"--comments", "-C", 0},
1014117413Skan   {"--comments-in-macros", "-CC", 0},
101518334Speter   {"--compile", "-c", 0},
101618334Speter   {"--debug", "-g", "oj"},
101750599Sobrien   {"--define-macro", "-D", "aj"},
101818334Speter   {"--dependencies", "-M", 0},
101918334Speter   {"--dump", "-d", "a"},
102018334Speter   {"--dumpbase", "-dumpbase", "a"},
102118334Speter   {"--entry", "-e", 0},
102218334Speter   {"--extra-warnings", "-W", 0},
102318334Speter   {"--for-assembler", "-Wa", "a"},
102418334Speter   {"--for-linker", "-Xlinker", "a"},
102518334Speter   {"--force-link", "-u", "a"},
102618334Speter   {"--imacros", "-imacros", "a"},
102718334Speter   {"--include", "-include", "a"},
102818334Speter   {"--include-barrier", "-I-", 0},
102950599Sobrien   {"--include-directory", "-I", "aj"},
103018334Speter   {"--include-directory-after", "-idirafter", "a"},
103118334Speter   {"--include-prefix", "-iprefix", "a"},
103218334Speter   {"--include-with-prefix", "-iwithprefix", "a"},
103318334Speter   {"--include-with-prefix-before", "-iwithprefixbefore", "a"},
103418334Speter   {"--include-with-prefix-after", "-iwithprefix", "a"},
103518334Speter   {"--language", "-x", "a"},
103618334Speter   {"--library-directory", "-L", "a"},
103718334Speter   {"--machine", "-m", "aj"},
103818334Speter   {"--machine-", "-m", "*j"},
103996285Sobrien   {"--no-integrated-cpp", "-no-integrated-cpp", 0},
104018334Speter   {"--no-line-commands", "-P", 0},
104118334Speter   {"--no-precompiled-includes", "-noprecomp", 0},
104218334Speter   {"--no-standard-includes", "-nostdinc", 0},
104318334Speter   {"--no-standard-libraries", "-nostdlib", 0},
104418334Speter   {"--no-warnings", "-w", 0},
104518334Speter   {"--optimize", "-O", "oj"},
104618334Speter   {"--output", "-o", "a"},
104752520Sobrien   {"--output-class-directory", "-foutput-class-dir=", "ja"},
104890277Sobrien   {"--param", "--param", "a"},
104918334Speter   {"--pedantic", "-pedantic", 0},
105018334Speter   {"--pedantic-errors", "-pedantic-errors", 0},
1051132733Skan   {"--pie", "-pie", 0},
105218334Speter   {"--pipe", "-pipe", 0},
105318334Speter   {"--prefix", "-B", "a"},
105418334Speter   {"--preprocess", "-E", 0},
105518334Speter   {"--print-search-dirs", "-print-search-dirs", 0},
105618334Speter   {"--print-file-name", "-print-file-name=", "aj"},
105718334Speter   {"--print-libgcc-file-name", "-print-libgcc-file-name", 0},
105818334Speter   {"--print-missing-file-dependencies", "-MG", 0},
105918334Speter   {"--print-multi-lib", "-print-multi-lib", 0},
106018334Speter   {"--print-multi-directory", "-print-multi-directory", 0},
1061104763Skan   {"--print-multi-os-directory", "-print-multi-os-directory", 0},
106218334Speter   {"--print-prog-name", "-print-prog-name=", "aj"},
106318334Speter   {"--profile", "-p", 0},
106418334Speter   {"--profile-blocks", "-a", 0},
106518334Speter   {"--quiet", "-q", 0},
106696285Sobrien   {"--resource", "-fcompile-resource=", "aj"},
106718334Speter   {"--save-temps", "-save-temps", 0},
106818334Speter   {"--shared", "-shared", 0},
106918334Speter   {"--silent", "-q", 0},
107050599Sobrien   {"--specs", "-specs=", "aj"},
107118334Speter   {"--static", "-static", 0},
107252520Sobrien   {"--std", "-std=", "aj"},
107318334Speter   {"--symbolic", "-symbolic", 0},
107490277Sobrien   {"--time", "-time", 0},
107518334Speter   {"--trace-includes", "-H", 0},
107618334Speter   {"--traditional", "-traditional", 0},
107718334Speter   {"--traditional-cpp", "-traditional-cpp", 0},
107818334Speter   {"--trigraphs", "-trigraphs", 0},
107950599Sobrien   {"--undefine-macro", "-U", "aj"},
108018334Speter   {"--user-dependencies", "-MM", 0},
108118334Speter   {"--verbose", "-v", 0},
108218334Speter   {"--warn-", "-W", "*j"},
108318334Speter   {"--write-dependencies", "-MD", 0},
108418334Speter   {"--write-user-dependencies", "-MMD", 0},
108518334Speter   {"--", "-f", "*j"}
108618334Speter };
108718334Speter
108890277Sobrien
108990277Sobrien#ifdef TARGET_OPTION_TRANSLATE_TABLE
109090277Sobrienstatic const struct {
109190277Sobrien  const char *const option_found;
109290277Sobrien  const char *const replacements;
109390277Sobrien} target_option_translations[] =
109490277Sobrien{
109590277Sobrien  TARGET_OPTION_TRANSLATE_TABLE,
109690277Sobrien  { 0, 0 }
109790277Sobrien};
109890277Sobrien#endif
109990277Sobrien
110018334Speter/* Translate the options described by *ARGCP and *ARGVP.
110118334Speter   Make a new vector and store it back in *ARGVP,
110218334Speter   and store its length in *ARGVC.  */
110318334Speter
110418334Speterstatic void
1105132733Skantranslate_options (int *argcp, const char *const **argvp)
110618334Speter{
110752520Sobrien  int i;
110818334Speter  int argc = *argcp;
110990277Sobrien  const char *const *argv = *argvp;
111090277Sobrien  int newvsize = (argc + 2) * 2 * sizeof (const char *);
1111132733Skan  const char **newv = xmalloc (newvsize);
111218334Speter  int newindex = 0;
111318334Speter
111418334Speter  i = 0;
111518334Speter  newv[newindex++] = argv[i++];
111618334Speter
111718334Speter  while (i < argc)
111818334Speter    {
111990277Sobrien#ifdef TARGET_OPTION_TRANSLATE_TABLE
112090277Sobrien      int tott_idx;
112190277Sobrien
112290277Sobrien      for (tott_idx = 0;
112390277Sobrien	   target_option_translations[tott_idx].option_found;
112490277Sobrien	   tott_idx++)
112590277Sobrien	{
112690277Sobrien	  if (strcmp (target_option_translations[tott_idx].option_found,
112790277Sobrien		      argv[i]) == 0)
112890277Sobrien	    {
112990277Sobrien	      int spaces = 1;
113090277Sobrien	      const char *sp;
113190277Sobrien	      char *np;
113290277Sobrien
113390277Sobrien	      for (sp = target_option_translations[tott_idx].replacements;
113490277Sobrien		   *sp; sp++)
113590277Sobrien		{
113690277Sobrien		  if (*sp == ' ')
113790277Sobrien		    spaces ++;
113890277Sobrien		}
113990277Sobrien
114090277Sobrien	      newvsize += spaces * sizeof (const char *);
1141132733Skan	      newv =  xrealloc (newv, newvsize);
114290277Sobrien
114390277Sobrien	      sp = target_option_translations[tott_idx].replacements;
114490277Sobrien	      np = xstrdup (sp);
114590277Sobrien
114690277Sobrien	      while (1)
114790277Sobrien		{
114890277Sobrien		  while (*np == ' ')
114990277Sobrien		    np++;
115090277Sobrien		  if (*np == 0)
115190277Sobrien		    break;
115290277Sobrien		  newv[newindex++] = np;
115390277Sobrien		  while (*np != ' ' && *np)
115490277Sobrien		    np++;
115590277Sobrien		  if (*np == 0)
115690277Sobrien		    break;
115790277Sobrien		  *np++ = 0;
115890277Sobrien		}
115990277Sobrien
116090277Sobrien	      i ++;
116190277Sobrien	      break;
116290277Sobrien	    }
116390277Sobrien	}
116490277Sobrien      if (target_option_translations[tott_idx].option_found)
116590277Sobrien	continue;
116690277Sobrien#endif
116790277Sobrien
116818334Speter      /* Translate -- options.  */
116918334Speter      if (argv[i][0] == '-' && argv[i][1] == '-')
117018334Speter	{
117152520Sobrien	  size_t j;
117218334Speter	  /* Find a mapping that applies to this option.  */
117390277Sobrien	  for (j = 0; j < ARRAY_SIZE (option_map); j++)
117418334Speter	    {
117550599Sobrien	      size_t optlen = strlen (option_map[j].name);
117650599Sobrien	      size_t arglen = strlen (argv[i]);
117750599Sobrien	      size_t complen = arglen > optlen ? optlen : arglen;
117852520Sobrien	      const char *arginfo = option_map[j].arg_info;
117918334Speter
118018334Speter	      if (arginfo == 0)
118118334Speter		arginfo = "";
118218334Speter
118318334Speter	      if (!strncmp (argv[i], option_map[j].name, complen))
118418334Speter		{
118552520Sobrien		  const char *arg = 0;
118618334Speter
118718334Speter		  if (arglen < optlen)
118818334Speter		    {
118952520Sobrien		      size_t k;
119090277Sobrien		      for (k = j + 1; k < ARRAY_SIZE (option_map); k++)
119118334Speter			if (strlen (option_map[k].name) >= arglen
119218334Speter			    && !strncmp (argv[i], option_map[k].name, arglen))
119318334Speter			  {
119490277Sobrien			    error ("ambiguous abbreviation %s", argv[i]);
119518334Speter			    break;
119618334Speter			  }
119718334Speter
119890277Sobrien		      if (k != ARRAY_SIZE (option_map))
119918334Speter			break;
120018334Speter		    }
120118334Speter
120218334Speter		  if (arglen > optlen)
120318334Speter		    {
120418334Speter		      /* If the option has an argument, accept that.  */
120518334Speter		      if (argv[i][optlen] == '=')
120618334Speter			arg = argv[i] + optlen + 1;
120718334Speter
120818334Speter		      /* If this mapping requires extra text at end of name,
120918334Speter			 accept that as "argument".  */
121090277Sobrien		      else if (strchr (arginfo, '*') != 0)
121118334Speter			arg = argv[i] + optlen;
121218334Speter
121318334Speter		      /* Otherwise, extra text at end means mismatch.
121418334Speter			 Try other mappings.  */
121518334Speter		      else
121618334Speter			continue;
121718334Speter		    }
121818334Speter
121990277Sobrien		  else if (strchr (arginfo, '*') != 0)
122018334Speter		    {
122190277Sobrien		      error ("incomplete `%s' option", option_map[j].name);
122218334Speter		      break;
122318334Speter		    }
122418334Speter
122518334Speter		  /* Handle arguments.  */
122690277Sobrien		  if (strchr (arginfo, 'a') != 0)
122718334Speter		    {
122818334Speter		      if (arg == 0)
122918334Speter			{
123018334Speter			  if (i + 1 == argc)
123118334Speter			    {
123290277Sobrien			      error ("missing argument to `%s' option",
123318334Speter				     option_map[j].name);
123418334Speter			      break;
123518334Speter			    }
123618334Speter
123718334Speter			  arg = argv[++i];
123818334Speter			}
123918334Speter		    }
124090277Sobrien		  else if (strchr (arginfo, '*') != 0)
124118334Speter		    ;
124290277Sobrien		  else if (strchr (arginfo, 'o') == 0)
124318334Speter		    {
124418334Speter		      if (arg != 0)
124590277Sobrien			error ("extraneous argument to `%s' option",
124618334Speter			       option_map[j].name);
124718334Speter		      arg = 0;
124818334Speter		    }
124918334Speter
125018334Speter		  /* Store the translation as one argv elt or as two.  */
125190277Sobrien		  if (arg != 0 && strchr (arginfo, 'j') != 0)
125250599Sobrien		    newv[newindex++] = concat (option_map[j].equivalent, arg,
125390277Sobrien					       NULL);
125418334Speter		  else if (arg != 0)
125518334Speter		    {
125618334Speter		      newv[newindex++] = option_map[j].equivalent;
125718334Speter		      newv[newindex++] = arg;
125818334Speter		    }
125918334Speter		  else
126018334Speter		    newv[newindex++] = option_map[j].equivalent;
126118334Speter
126218334Speter		  break;
126318334Speter		}
126418334Speter	    }
126518334Speter	  i++;
126618334Speter	}
126718334Speter
126818334Speter      /* Handle old-fashioned options--just copy them through,
126918334Speter	 with their arguments.  */
127018334Speter      else if (argv[i][0] == '-')
127118334Speter	{
127252520Sobrien	  const char *p = argv[i] + 1;
127318334Speter	  int c = *p;
127418334Speter	  int nskip = 1;
127518334Speter
127618334Speter	  if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
127718334Speter	    nskip += SWITCH_TAKES_ARG (c) - (p[1] != 0);
127818334Speter	  else if (WORD_SWITCH_TAKES_ARG (p))
127918334Speter	    nskip += WORD_SWITCH_TAKES_ARG (p);
1280117413Skan	  else if ((c == 'B' || c == 'b' || c == 'x')
128118334Speter		   && p[1] == 0)
128218334Speter	    nskip += 1;
128318334Speter	  else if (! strcmp (p, "Xlinker"))
128418334Speter	    nskip += 1;
1285132733Skan	  else if (! strcmp (p, "Xpreprocessor"))
1286132733Skan	    nskip += 1;
1287132733Skan	  else if (! strcmp (p, "Xassembler"))
1288132733Skan	    nskip += 1;
128918334Speter
129018334Speter	  /* Watch out for an option at the end of the command line that
129118334Speter	     is missing arguments, and avoid skipping past the end of the
129218334Speter	     command line.  */
129318334Speter	  if (nskip + i > argc)
129418334Speter	    nskip = argc - i;
129518334Speter
129618334Speter	  while (nskip > 0)
129718334Speter	    {
129818334Speter	      newv[newindex++] = argv[i++];
129918334Speter	      nskip--;
130018334Speter	    }
130118334Speter	}
130218334Speter      else
130318334Speter	/* Ordinary operands, or +e options.  */
130418334Speter	newv[newindex++] = argv[i++];
130518334Speter    }
130618334Speter
130718334Speter  newv[newindex] = 0;
130818334Speter
130918334Speter  *argvp = newv;
131018334Speter  *argcp = newindex;
131118334Speter}
131218334Speter
131318334Speterstatic char *
1314132733Skanskip_whitespace (char *p)
131518334Speter{
131618334Speter  while (1)
131718334Speter    {
131818334Speter      /* A fully-blank line is a delimiter in the SPEC file and shouldn't
131918334Speter	 be considered whitespace.  */
132018334Speter      if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n')
132118334Speter	return p + 1;
132218334Speter      else if (*p == '\n' || *p == ' ' || *p == '\t')
132318334Speter	p++;
132418334Speter      else if (*p == '#')
132518334Speter	{
132690277Sobrien	  while (*p != '\n')
132790277Sobrien	    p++;
132818334Speter	  p++;
132918334Speter	}
133018334Speter      else
133118334Speter	break;
133218334Speter    }
133318334Speter
133418334Speter  return p;
133518334Speter}
133690277Sobrien/* Structures to keep track of prefixes to try when looking for files.  */
133790277Sobrien
133890277Sobrienstruct prefix_list
133990277Sobrien{
134090277Sobrien  const char *prefix;	      /* String to prepend to the path.  */
134190277Sobrien  struct prefix_list *next;   /* Next in linked list.  */
134290277Sobrien  int require_machine_suffix; /* Don't use without machine_suffix.  */
134390277Sobrien  /* 2 means try both machine_suffix and just_machine_suffix.  */
134490277Sobrien  int *used_flag_ptr;	      /* 1 if a file was found with this prefix.  */
1345104763Skan  int priority;		      /* Sort key - priority within list.  */
1346104763Skan  int os_multilib;	      /* 1 if OS multilib scheme should be used,
1347104763Skan				 0 for GCC multilib scheme.  */
134890277Sobrien};
134990277Sobrien
135090277Sobrienstruct path_prefix
135190277Sobrien{
135290277Sobrien  struct prefix_list *plist;  /* List of prefixes to try */
135390277Sobrien  int max_len;                /* Max length of a prefix in PLIST */
135490277Sobrien  const char *name;           /* Name of this list (used in config stuff) */
135590277Sobrien};
135690277Sobrien
135790277Sobrien/* List of prefixes to try when looking for executables.  */
135890277Sobrien
135990277Sobrienstatic struct path_prefix exec_prefixes = { 0, 0, "exec" };
136090277Sobrien
136190277Sobrien/* List of prefixes to try when looking for startup (crt0) files.  */
136290277Sobrien
136390277Sobrienstatic struct path_prefix startfile_prefixes = { 0, 0, "startfile" };
136490277Sobrien
136590277Sobrien/* List of prefixes to try when looking for include files.  */
136690277Sobrien
136790277Sobrienstatic struct path_prefix include_prefixes = { 0, 0, "include" };
136890277Sobrien
136990277Sobrien/* Suffix to attach to directories searched for commands.
137090277Sobrien   This looks like `MACHINE/VERSION/'.  */
137190277Sobrien
137290277Sobrienstatic const char *machine_suffix = 0;
137390277Sobrien
137490277Sobrien/* Suffix to attach to directories searched for commands.
137590277Sobrien   This is just `MACHINE/'.  */
137690277Sobrien
137790277Sobrienstatic const char *just_machine_suffix = 0;
137890277Sobrien
137990277Sobrien/* Adjusted value of GCC_EXEC_PREFIX envvar.  */
138090277Sobrien
138190277Sobrienstatic const char *gcc_exec_prefix;
138290277Sobrien
1383132733Skan/* Adjusted value of standard_libexec_prefix.  */
1384132733Skan
1385132733Skanstatic const char *gcc_libexec_prefix;
1386132733Skan
138790277Sobrien/* Default prefixes to attach to command names.  */
138890277Sobrien
138990277Sobrien#ifdef CROSS_COMPILE  /* Don't use these prefixes for a cross compiler.  */
139090277Sobrien#undef MD_EXEC_PREFIX
139190277Sobrien#undef MD_STARTFILE_PREFIX
139290277Sobrien#undef MD_STARTFILE_PREFIX_1
139390277Sobrien#endif
139490277Sobrien
139590277Sobrien/* If no prefixes defined, use the null string, which will disable them.  */
139690277Sobrien#ifndef MD_EXEC_PREFIX
139790277Sobrien#define MD_EXEC_PREFIX ""
139890277Sobrien#endif
139990277Sobrien#ifndef MD_STARTFILE_PREFIX
140090277Sobrien#define MD_STARTFILE_PREFIX ""
140190277Sobrien#endif
140290277Sobrien#ifndef MD_STARTFILE_PREFIX_1
140390277Sobrien#define MD_STARTFILE_PREFIX_1 ""
140490277Sobrien#endif
140590277Sobrien
140690277Sobrienstatic const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX;
1407132733Skanstatic const char *const standard_exec_prefix_1 = "/usr/libexec/gcc/";
1408132733Skanstatic const char *const standard_exec_prefix_2 = "/usr/lib/gcc/";
140990277Sobrienstatic const char *md_exec_prefix = MD_EXEC_PREFIX;
141090277Sobrien
141190277Sobrienstatic const char *md_startfile_prefix = MD_STARTFILE_PREFIX;
141290277Sobrienstatic const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
141390277Sobrienstatic const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
141490277Sobrienstatic const char *const standard_startfile_prefix_1 = "/lib/";
141590277Sobrienstatic const char *const standard_startfile_prefix_2 = "/usr/lib/";
141690277Sobrien
141790277Sobrienstatic const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
141890277Sobrienstatic const char *tooldir_prefix;
141990277Sobrien
142096736Sru#ifndef FREEBSD_NATIVE
142190277Sobrienstatic const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
142296736Sru#endif	/* not FREEBSD_NATIVE */
142390277Sobrien
1424132733Skanstatic const char *standard_libexec_prefix = STANDARD_LIBEXEC_PREFIX;
1425132733Skan
142690277Sobrien/* Subdirectory to use for locating libraries.  Set by
142790277Sobrien   set_multilib_dir based on the compilation options.  */
142890277Sobrien
142990277Sobrienstatic const char *multilib_dir;
1430104763Skan
1431104763Skan/* Subdirectory to use for locating libraries in OS conventions.  Set by
1432104763Skan   set_multilib_dir based on the compilation options.  */
1433104763Skan
1434104763Skanstatic const char *multilib_os_dir;
143518334Speter
143650599Sobrien/* Structure to keep track of the specs that have been defined so far.
143750599Sobrien   These are accessed using %(specname) or %[specname] in a compiler
143850599Sobrien   or link spec.  */
143918334Speter
144018334Speterstruct spec_list
144118334Speter{
144250599Sobrien				/* The following 2 fields must be first */
144350599Sobrien				/* to allow EXTRA_SPECS to be initialized */
144490277Sobrien  const char *name;		/* name of the spec.  */
144590277Sobrien  const char *ptr;		/* available ptr if no static pointer */
144650599Sobrien
144750599Sobrien				/* The following fields are not initialized */
144850599Sobrien				/* by EXTRA_SPECS */
144990277Sobrien  const char **ptr_spec;	/* pointer to the spec itself.  */
145050599Sobrien  struct spec_list *next;	/* Next spec in linked list.  */
145150599Sobrien  int name_len;			/* length of the name */
145250599Sobrien  int alloc_p;			/* whether string was allocated */
145318334Speter};
145418334Speter
145550599Sobrien#define INIT_STATIC_SPEC(NAME,PTR) \
145690277Sobrien{ NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, 0 }
145718334Speter
145890277Sobrien/* List of statically defined specs.  */
145990277Sobrienstatic struct spec_list static_specs[] =
146090277Sobrien{
146150599Sobrien  INIT_STATIC_SPEC ("asm",			&asm_spec),
146290277Sobrien  INIT_STATIC_SPEC ("asm_debug",		&asm_debug),
146350599Sobrien  INIT_STATIC_SPEC ("asm_final",		&asm_final_spec),
146490277Sobrien  INIT_STATIC_SPEC ("asm_options",		&asm_options),
146590277Sobrien  INIT_STATIC_SPEC ("invoke_as",		&invoke_as),
146650599Sobrien  INIT_STATIC_SPEC ("cpp",			&cpp_spec),
146790277Sobrien  INIT_STATIC_SPEC ("cpp_options",		&cpp_options),
1468117413Skan  INIT_STATIC_SPEC ("cpp_debug_options",	&cpp_debug_options),
146990277Sobrien  INIT_STATIC_SPEC ("cpp_unique_options",	&cpp_unique_options),
147090277Sobrien  INIT_STATIC_SPEC ("trad_capable_cpp",		&trad_capable_cpp),
147150599Sobrien  INIT_STATIC_SPEC ("cc1",			&cc1_spec),
147290277Sobrien  INIT_STATIC_SPEC ("cc1_options",		&cc1_options),
147350599Sobrien  INIT_STATIC_SPEC ("cc1plus",			&cc1plus_spec),
147496285Sobrien  INIT_STATIC_SPEC ("link_gcc_c_sequence",	&link_gcc_c_sequence_spec),
147550599Sobrien  INIT_STATIC_SPEC ("endfile",			&endfile_spec),
147650599Sobrien  INIT_STATIC_SPEC ("link",			&link_spec),
147750599Sobrien  INIT_STATIC_SPEC ("lib",			&lib_spec),
147850599Sobrien  INIT_STATIC_SPEC ("libgcc",			&libgcc_spec),
147950599Sobrien  INIT_STATIC_SPEC ("startfile",		&startfile_spec),
148050599Sobrien  INIT_STATIC_SPEC ("switches_need_spaces",	&switches_need_spaces),
148150599Sobrien  INIT_STATIC_SPEC ("cross_compile",		&cross_compile),
148250599Sobrien  INIT_STATIC_SPEC ("version",			&compiler_version),
148350599Sobrien  INIT_STATIC_SPEC ("multilib",			&multilib_select),
148450599Sobrien  INIT_STATIC_SPEC ("multilib_defaults",	&multilib_defaults),
148550599Sobrien  INIT_STATIC_SPEC ("multilib_extra",		&multilib_extra),
148650599Sobrien  INIT_STATIC_SPEC ("multilib_matches",		&multilib_matches),
148790277Sobrien  INIT_STATIC_SPEC ("multilib_exclusions",	&multilib_exclusions),
1488104763Skan  INIT_STATIC_SPEC ("multilib_options",		&multilib_options),
148950599Sobrien  INIT_STATIC_SPEC ("linker",			&linker_name_spec),
149090277Sobrien  INIT_STATIC_SPEC ("link_libgcc",		&link_libgcc_spec),
149190277Sobrien  INIT_STATIC_SPEC ("md_exec_prefix",		&md_exec_prefix),
149290277Sobrien  INIT_STATIC_SPEC ("md_startfile_prefix",	&md_startfile_prefix),
149390277Sobrien  INIT_STATIC_SPEC ("md_startfile_prefix_1",	&md_startfile_prefix_1),
1494117413Skan  INIT_STATIC_SPEC ("startfile_prefix_spec",	&startfile_prefix_spec),
1495132733Skan  INIT_STATIC_SPEC ("sysroot_suffix_spec",	&sysroot_suffix_spec),
1496132733Skan  INIT_STATIC_SPEC ("sysroot_hdrs_suffix_spec",	&sysroot_hdrs_suffix_spec),
149750599Sobrien};
149850599Sobrien
149950599Sobrien#ifdef EXTRA_SPECS		/* additional specs needed */
150052520Sobrien/* Structure to keep track of just the first two args of a spec_list.
150190277Sobrien   That is all that the EXTRA_SPECS macro gives us.  */
150252520Sobrienstruct spec_list_1
150352520Sobrien{
150490277Sobrien  const char *const name;
150590277Sobrien  const char *const ptr;
150652520Sobrien};
150752520Sobrien
150890277Sobrienstatic const struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
150990277Sobrienstatic struct spec_list *extra_specs = (struct spec_list *) 0;
151050599Sobrien#endif
151150599Sobrien
151250599Sobrien/* List of dynamically allocates specs that have been defined so far.  */
151350599Sobrien
151490277Sobrienstatic struct spec_list *specs = (struct spec_list *) 0;
151590277Sobrien
1516117413Skan/* List of static spec functions.  */
1517117413Skan
1518117413Skanstatic const struct spec_function static_spec_functions[] =
1519117413Skan{
1520117413Skan  { "if-exists",		if_exists_spec_function },
1521117413Skan  { "if-exists-else",		if_exists_else_spec_function },
1522117413Skan  { 0, 0 }
1523117413Skan};
1524117413Skan
1525117413Skanstatic int processing_spec_function;
1526117413Skan
152790277Sobrien/* Add appropriate libgcc specs to OBSTACK, taking into account
152890277Sobrien   various permutations of -shared-libgcc, -shared, and such.  */
152950599Sobrien
153090277Sobrien#ifdef ENABLE_SHARED_LIBGCC
153190277Sobrienstatic void
1532132733Skaninit_gcc_specs (struct obstack *obstack, const char *shared_name,
1533132733Skan		const char *static_name, const char *eh_name)
153490277Sobrien{
153596285Sobrien  char *buf;
153690277Sobrien
153796285Sobrien  buf = concat ("%{static|static-libgcc:", static_name, " ", eh_name,
153896285Sobrien		"}%{!static:%{!static-libgcc:",
1539132733Skan#ifdef HAVE_LD_AS_NEEDED
1540132733Skan		"%{!shared-libgcc:", static_name,
1541132733Skan		" --as-needed ", shared_name, " --no-as-needed}"
1542132733Skan		"%{shared-libgcc:", shared_name, "%{!shared: ", static_name,
1543132733Skan		"}",
1544132733Skan#else
154596285Sobrien		"%{!shared:%{!shared-libgcc:", static_name, " ",
154696285Sobrien		eh_name, "}%{shared-libgcc:", shared_name, " ",
154796285Sobrien		static_name, "}}%{shared:",
154890277Sobrien#ifdef LINK_EH_SPEC
154996285Sobrien		"%{shared-libgcc:", shared_name,
155096285Sobrien		"}%{!shared-libgcc:", static_name, "}",
155190277Sobrien#else
155296285Sobrien		shared_name,
155390277Sobrien#endif
1554132733Skan#endif
155596285Sobrien		"}}}", NULL);
155696285Sobrien
155796285Sobrien  obstack_grow (obstack, buf, strlen (buf));
155896285Sobrien  free (buf);
155990277Sobrien}
156090277Sobrien#endif /* ENABLE_SHARED_LIBGCC */
156190277Sobrien
156250599Sobrien/* Initialize the specs lookup routines.  */
156350599Sobrien
156450599Sobrienstatic void
1565132733Skaninit_spec (void)
156650599Sobrien{
156790277Sobrien  struct spec_list *next = (struct spec_list *) 0;
156890277Sobrien  struct spec_list *sl   = (struct spec_list *) 0;
156950599Sobrien  int i;
157050599Sobrien
157150599Sobrien  if (specs)
157290277Sobrien    return;			/* Already initialized.  */
157350599Sobrien
157450599Sobrien  if (verbose_flag)
157590277Sobrien    notice ("Using built-in specs.\n");
157650599Sobrien
157750599Sobrien#ifdef EXTRA_SPECS
1578132733Skan  extra_specs = xcalloc (sizeof (struct spec_list),
1579132733Skan			 ARRAY_SIZE (extra_specs_1));
158090277Sobrien
158190277Sobrien  for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--)
158250599Sobrien    {
158350599Sobrien      sl = &extra_specs[i];
158452520Sobrien      sl->name = extra_specs_1[i].name;
158552520Sobrien      sl->ptr = extra_specs_1[i].ptr;
158650599Sobrien      sl->next = next;
158750599Sobrien      sl->name_len = strlen (sl->name);
158850599Sobrien      sl->ptr_spec = &sl->ptr;
158950599Sobrien      next = sl;
159050599Sobrien    }
159150599Sobrien#endif
159250599Sobrien
1593117413Skan  /* Initialize here, not in definition.  The IRIX 6 O32 cc sometimes chokes
1594117413Skan     on ?: in file-scope variable initializations.  */
1595117413Skan  asm_debug = ASM_DEBUG_SPEC;
1596117413Skan
159790277Sobrien  for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
159850599Sobrien    {
159950599Sobrien      sl = &static_specs[i];
160050599Sobrien      sl->next = next;
160150599Sobrien      next = sl;
160250599Sobrien    }
160350599Sobrien
160490277Sobrien#ifdef ENABLE_SHARED_LIBGCC
160590277Sobrien  /* ??? If neither -shared-libgcc nor --static-libgcc was
160690277Sobrien     seen, then we should be making an educated guess.  Some proposed
160790277Sobrien     heuristics for ELF include:
160890277Sobrien
160990277Sobrien	(1) If "-Wl,--export-dynamic", then it's a fair bet that the
161090277Sobrien	    program will be doing dynamic loading, which will likely
161190277Sobrien	    need the shared libgcc.
161290277Sobrien
161390277Sobrien	(2) If "-ldl", then it's also a fair bet that we're doing
161490277Sobrien	    dynamic loading.
161590277Sobrien
161690277Sobrien	(3) For each ET_DYN we're linking against (either through -lfoo
161790277Sobrien	    or /some/path/foo.so), check to see whether it or one of
161890277Sobrien	    its dependencies depends on a shared libgcc.
161990277Sobrien
162090277Sobrien	(4) If "-shared"
162190277Sobrien
162290277Sobrien	    If the runtime is fixed to look for program headers instead
162390277Sobrien	    of calling __register_frame_info at all, for each object,
162490277Sobrien	    use the shared libgcc if any EH symbol referenced.
162590277Sobrien
162690277Sobrien	    If crtstuff is fixed to not invoke __register_frame_info
162790277Sobrien	    automatically, for each object, use the shared libgcc if
162890277Sobrien	    any non-empty unwind section found.
162990277Sobrien
163090277Sobrien     Doing any of this probably requires invoking an external program to
163190277Sobrien     do the actual object file scanning.  */
163290277Sobrien  {
163390277Sobrien    const char *p = libgcc_spec;
163490277Sobrien    int in_sep = 1;
1635117413Skan
163690277Sobrien    /* Transform the extant libgcc_spec into one that uses the shared libgcc
163790277Sobrien       when given the proper command line arguments.  */
163890277Sobrien    while (*p)
163990277Sobrien      {
1640117413Skan	if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0)
164190277Sobrien	  {
164290277Sobrien	    init_gcc_specs (&obstack,
164390277Sobrien#ifdef NO_SHARED_LIBGCC_MULTILIB
164490277Sobrien			    "-lgcc_s"
164590277Sobrien#else
164690277Sobrien			    "-lgcc_s%M"
164790277Sobrien#endif
1648146908Skan#ifdef USE_LIBUNWIND_EXCEPTIONS
1649146908Skan			    " -lunwind"
1650146908Skan#endif
1651132733Skan			    ,
1652132733Skan			    "-lgcc",
1653132733Skan			    "-lgcc_eh"
1654122197Skan#ifdef USE_LIBUNWIND_EXCEPTIONS
1655146908Skan# ifdef HAVE_LD_STATIC_DYNAMIC
1656146908Skan			    " %{!static:-Bstatic} -lunwind %{!static:-Bdynamic}"
1657146908Skan# else
1658122197Skan			    " -lunwind"
1659146908Skan# endif
1660122197Skan#endif
1661132733Skan			    );
1662132733Skan
166390277Sobrien	    p += 5;
166490277Sobrien	    in_sep = 0;
166590277Sobrien	  }
166690277Sobrien	else if (in_sep && *p == 'l' && strncmp (p, "libgcc.a%s", 10) == 0)
166790277Sobrien	  {
166890277Sobrien	    /* Ug.  We don't know shared library extensions.  Hope that
166990277Sobrien	       systems that use this form don't do shared libraries.  */
167090277Sobrien	    init_gcc_specs (&obstack,
167190277Sobrien#ifdef NO_SHARED_LIBGCC_MULTILIB
167290277Sobrien			    "-lgcc_s"
167390277Sobrien#else
167490277Sobrien			    "-lgcc_s%M"
167590277Sobrien#endif
167690277Sobrien			    ,
167790277Sobrien			    "libgcc.a%s",
1678132733Skan			    "libgcc_eh.a%s"
1679132733Skan#ifdef USE_LIBUNWIND_EXCEPTIONS
1680132733Skan			    " -lunwind"
1681132733Skan#endif
1682132733Skan			    );
168390277Sobrien	    p += 10;
168490277Sobrien	    in_sep = 0;
168590277Sobrien	  }
168690277Sobrien	else
168790277Sobrien	  {
168890277Sobrien	    obstack_1grow (&obstack, *p);
168990277Sobrien	    in_sep = (*p == ' ');
169090277Sobrien	    p += 1;
169190277Sobrien	  }
169290277Sobrien      }
169390277Sobrien
169490277Sobrien    obstack_1grow (&obstack, '\0');
169590277Sobrien    libgcc_spec = obstack_finish (&obstack);
169690277Sobrien  }
169790277Sobrien#endif
169890277Sobrien#ifdef USE_AS_TRADITIONAL_FORMAT
169990277Sobrien  /* Prepend "--traditional-format" to whatever asm_spec we had before.  */
170090277Sobrien  {
170190277Sobrien    static const char tf[] = "--traditional-format ";
170290277Sobrien    obstack_grow (&obstack, tf, sizeof(tf) - 1);
170390277Sobrien    obstack_grow0 (&obstack, asm_spec, strlen (asm_spec));
170490277Sobrien    asm_spec = obstack_finish (&obstack);
170590277Sobrien  }
170690277Sobrien#endif
170790277Sobrien#ifdef LINK_EH_SPEC
170890277Sobrien  /* Prepend LINK_EH_SPEC to whatever link_spec we had before.  */
170990277Sobrien  obstack_grow (&obstack, LINK_EH_SPEC, sizeof(LINK_EH_SPEC) - 1);
171090277Sobrien  obstack_grow0 (&obstack, link_spec, strlen (link_spec));
171190277Sobrien  link_spec = obstack_finish (&obstack);
171290277Sobrien#endif
171390277Sobrien
171450599Sobrien  specs = sl;
171550599Sobrien}
171650599Sobrien
171718334Speter/* Change the value of spec NAME to SPEC.  If SPEC is empty, then the spec is
171818334Speter   removed; If the spec starts with a + then SPEC is added to the end of the
171950599Sobrien   current spec.  */
172018334Speter
172118334Speterstatic void
1722132733Skanset_spec (const char *name, const char *spec)
172318334Speter{
172418334Speter  struct spec_list *sl;
172590277Sobrien  const char *old_spec;
172650599Sobrien  int name_len = strlen (name);
172750599Sobrien  int i;
172818334Speter
172990277Sobrien  /* If this is the first call, initialize the statically allocated specs.  */
173050599Sobrien  if (!specs)
173150599Sobrien    {
173290277Sobrien      struct spec_list *next = (struct spec_list *) 0;
173390277Sobrien      for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
173450599Sobrien	{
173550599Sobrien	  sl = &static_specs[i];
173650599Sobrien	  sl->next = next;
173750599Sobrien	  next = sl;
173850599Sobrien	}
173950599Sobrien      specs = sl;
174050599Sobrien    }
174150599Sobrien
174290277Sobrien  /* See if the spec already exists.  */
174318334Speter  for (sl = specs; sl; sl = sl->next)
174450599Sobrien    if (name_len == sl->name_len && !strcmp (sl->name, name))
174518334Speter      break;
174618334Speter
174718334Speter  if (!sl)
174818334Speter    {
174990277Sobrien      /* Not found - make it.  */
1750132733Skan      sl = xmalloc (sizeof (struct spec_list));
175190277Sobrien      sl->name = xstrdup (name);
175250599Sobrien      sl->name_len = name_len;
175350599Sobrien      sl->ptr_spec = &sl->ptr;
175450599Sobrien      sl->alloc_p = 0;
175550599Sobrien      *(sl->ptr_spec) = "";
175618334Speter      sl->next = specs;
175718334Speter      specs = sl;
175818334Speter    }
175918334Speter
176050599Sobrien  old_spec = *(sl->ptr_spec);
176152520Sobrien  *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1]))
176290277Sobrien		     ? concat (old_spec, spec + 1, NULL)
176390277Sobrien		     : xstrdup (spec));
176418334Speter
176550599Sobrien#ifdef DEBUG_SPECS
176650599Sobrien  if (verbose_flag)
176752520Sobrien    notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
176850599Sobrien#endif
176950599Sobrien
177090277Sobrien  /* Free the old spec.  */
177150599Sobrien  if (old_spec && sl->alloc_p)
1772132733Skan    free ((void *) old_spec);
177350599Sobrien
177450599Sobrien  sl->alloc_p = 1;
177518334Speter}
177618334Speter
177718334Speter/* Accumulate a command (program name and args), and run it.  */
177818334Speter
177918334Speter/* Vector of pointers to arguments in the current line of specifications.  */
178018334Speter
178190277Sobrienstatic const char **argbuf;
178218334Speter
178318334Speter/* Number of elements allocated in argbuf.  */
178418334Speter
178518334Speterstatic int argbuf_length;
178618334Speter
178718334Speter/* Number of elements in argbuf currently in use (containing args).  */
178818334Speter
178918334Speterstatic int argbuf_index;
179018334Speter
179190277Sobrien/* This is the list of suffixes and codes (%g/%u/%U/%j) and the associated
179290277Sobrien   temp file.  If the HOST_BIT_BUCKET is used for %j, no entry is made for
179390277Sobrien   it here.  */
179450599Sobrien
179518334Speterstatic struct temp_name {
179652520Sobrien  const char *suffix;	/* suffix associated with the code.  */
179718334Speter  int length;		/* strlen (suffix).  */
179818334Speter  int unique;		/* Indicates whether %g or %u/%U was used.  */
179952520Sobrien  const char *filename;	/* associated filename.  */
180018334Speter  int filename_length;	/* strlen (filename).  */
180118334Speter  struct temp_name *next;
180218334Speter} *temp_names;
180318334Speter
180418334Speter/* Number of commands executed so far.  */
180518334Speter
180618334Speterstatic int execution_count;
180718334Speter
180818334Speter/* Number of commands that exited with a signal.  */
180918334Speter
181018334Speterstatic int signal_count;
181118334Speter
181218334Speter/* Name with which this program was invoked.  */
181318334Speter
181452520Sobrienstatic const char *programname;
181518334Speter
1816117413Skan/* Allocate the argument vector.  */
1817117413Skan
1818117413Skanstatic void
1819132733Skanalloc_args (void)
1820117413Skan{
1821117413Skan  argbuf_length = 10;
1822132733Skan  argbuf = xmalloc (argbuf_length * sizeof (const char *));
1823117413Skan}
1824117413Skan
182518334Speter/* Clear out the vector of arguments (after a command is executed).  */
182618334Speter
182718334Speterstatic void
1828132733Skanclear_args (void)
182918334Speter{
183018334Speter  argbuf_index = 0;
183118334Speter}
183218334Speter
183318334Speter/* Add one argument to the vector at the end.
183418334Speter   This is done when a space is seen or at the end of the line.
183518334Speter   If DELETE_ALWAYS is nonzero, the arg is a filename
183618334Speter    and the file should be deleted eventually.
183718334Speter   If DELETE_FAILURE is nonzero, the arg is a filename
183818334Speter    and the file should be deleted if this compilation fails.  */
183918334Speter
184018334Speterstatic void
1841132733Skanstore_arg (const char *arg, int delete_always, int delete_failure)
184218334Speter{
184318334Speter  if (argbuf_index + 1 == argbuf_length)
1844132733Skan    argbuf = xrealloc (argbuf, (argbuf_length *= 2) * sizeof (const char *));
184518334Speter
184618334Speter  argbuf[argbuf_index++] = arg;
184718334Speter  argbuf[argbuf_index] = 0;
184818334Speter
184918334Speter  if (delete_always || delete_failure)
185018334Speter    record_temp_file (arg, delete_always, delete_failure);
185118334Speter}
185218334Speter
185390277Sobrien/* Load specs from a file name named FILENAME, replacing occurrences of
185490277Sobrien   various different types of line-endings, \r\n, \n\r and just \r, with
185590277Sobrien   a single \n.  */
185650599Sobrien
185790277Sobrienstatic char *
1858132733Skanload_specs (const char *filename)
185950599Sobrien{
186050599Sobrien  int desc;
186150599Sobrien  int readlen;
186250599Sobrien  struct stat statbuf;
186350599Sobrien  char *buffer;
186490277Sobrien  char *buffer_p;
186590277Sobrien  char *specs;
186690277Sobrien  char *specs_p;
186750599Sobrien
186850599Sobrien  if (verbose_flag)
186952520Sobrien    notice ("Reading specs from %s\n", filename);
187050599Sobrien
187150599Sobrien  /* Open and stat the file.  */
187250599Sobrien  desc = open (filename, O_RDONLY, 0);
187350599Sobrien  if (desc < 0)
187450599Sobrien    pfatal_with_name (filename);
187550599Sobrien  if (stat (filename, &statbuf) < 0)
187650599Sobrien    pfatal_with_name (filename);
187750599Sobrien
187850599Sobrien  /* Read contents of file into BUFFER.  */
187950599Sobrien  buffer = xmalloc ((unsigned) statbuf.st_size + 1);
188050599Sobrien  readlen = read (desc, buffer, (unsigned) statbuf.st_size);
188150599Sobrien  if (readlen < 0)
188250599Sobrien    pfatal_with_name (filename);
188350599Sobrien  buffer[readlen] = 0;
188450599Sobrien  close (desc);
188550599Sobrien
188690277Sobrien  specs = xmalloc (readlen + 1);
188790277Sobrien  specs_p = specs;
188890277Sobrien  for (buffer_p = buffer; buffer_p && *buffer_p; buffer_p++)
188990277Sobrien    {
189090277Sobrien      int skip = 0;
189190277Sobrien      char c = *buffer_p;
189290277Sobrien      if (c == '\r')
189390277Sobrien	{
189490277Sobrien	  if (buffer_p > buffer && *(buffer_p - 1) == '\n')	/* \n\r */
189590277Sobrien	    skip = 1;
189690277Sobrien	  else if (*(buffer_p + 1) == '\n')			/* \r\n */
189790277Sobrien	    skip = 1;
189890277Sobrien	  else							/* \r */
189990277Sobrien	    c = '\n';
190090277Sobrien	}
190190277Sobrien      if (! skip)
190290277Sobrien	*specs_p++ = c;
190390277Sobrien    }
190490277Sobrien  *specs_p = '\0';
190590277Sobrien
190690277Sobrien  free (buffer);
190790277Sobrien  return (specs);
190890277Sobrien}
190990277Sobrien
191090277Sobrien/* Read compilation specs from a file named FILENAME,
191190277Sobrien   replacing the default ones.
191290277Sobrien
191390277Sobrien   A suffix which starts with `*' is a definition for
191490277Sobrien   one of the machine-specific sub-specs.  The "suffix" should be
191596285Sobrien   *asm, *cc1, *cpp, *link, *startfile, etc.
191690277Sobrien   The corresponding spec is stored in asm_spec, etc.,
191790277Sobrien   rather than in the `compilers' vector.
191890277Sobrien
191990277Sobrien   Anything invalid in the file is a fatal error.  */
192090277Sobrien
192190277Sobrienstatic void
1922132733Skanread_specs (const char *filename, int main_p)
192390277Sobrien{
192490277Sobrien  char *buffer;
192590277Sobrien  char *p;
192690277Sobrien
192790277Sobrien  buffer = load_specs (filename);
192890277Sobrien
192950599Sobrien  /* Scan BUFFER for specs, putting them in the vector.  */
193050599Sobrien  p = buffer;
193150599Sobrien  while (1)
193250599Sobrien    {
193350599Sobrien      char *suffix;
193450599Sobrien      char *spec;
193550599Sobrien      char *in, *out, *p1, *p2, *p3;
193650599Sobrien
193750599Sobrien      /* Advance P in BUFFER to the next nonblank nocomment line.  */
193850599Sobrien      p = skip_whitespace (p);
193950599Sobrien      if (*p == 0)
194050599Sobrien	break;
194150599Sobrien
194250599Sobrien      /* Is this a special command that starts with '%'? */
194350599Sobrien      /* Don't allow this for the main specs file, since it would
194450599Sobrien	 encourage people to overwrite it.  */
194550599Sobrien      if (*p == '%' && !main_p)
194650599Sobrien	{
194750599Sobrien	  p1 = p;
194850599Sobrien	  while (*p && *p != '\n')
194950599Sobrien	    p++;
195050599Sobrien
195190277Sobrien	  /* Skip '\n'.  */
195290277Sobrien	  p++;
195350599Sobrien
195490277Sobrien	  if (!strncmp (p1, "%include", sizeof ("%include") - 1)
195550599Sobrien	      && (p1[sizeof "%include" - 1] == ' '
195650599Sobrien		  || p1[sizeof "%include" - 1] == '\t'))
195750599Sobrien	    {
195850599Sobrien	      char *new_filename;
195950599Sobrien
196050599Sobrien	      p1 += sizeof ("%include");
196150599Sobrien	      while (*p1 == ' ' || *p1 == '\t')
196250599Sobrien		p1++;
196350599Sobrien
196450599Sobrien	      if (*p1++ != '<' || p[-2] != '>')
196552520Sobrien		fatal ("specs %%include syntax malformed after %ld characters",
196652520Sobrien		       (long) (p1 - buffer + 1));
196750599Sobrien
196850599Sobrien	      p[-2] = '\0';
1969104763Skan	      new_filename = find_a_file (&startfile_prefixes, p1, R_OK, 0);
197050599Sobrien	      read_specs (new_filename ? new_filename : p1, FALSE);
197150599Sobrien	      continue;
197250599Sobrien	    }
197350599Sobrien	  else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1)
197450599Sobrien		   && (p1[sizeof "%include_noerr" - 1] == ' '
197550599Sobrien		       || p1[sizeof "%include_noerr" - 1] == '\t'))
197650599Sobrien	    {
197750599Sobrien	      char *new_filename;
197850599Sobrien
197950599Sobrien	      p1 += sizeof "%include_noerr";
198090277Sobrien	      while (*p1 == ' ' || *p1 == '\t')
198190277Sobrien		p1++;
198250599Sobrien
198350599Sobrien	      if (*p1++ != '<' || p[-2] != '>')
198452520Sobrien		fatal ("specs %%include syntax malformed after %ld characters",
198552520Sobrien		       (long) (p1 - buffer + 1));
198650599Sobrien
198750599Sobrien	      p[-2] = '\0';
1988104763Skan	      new_filename = find_a_file (&startfile_prefixes, p1, R_OK, 0);
198950599Sobrien	      if (new_filename)
199050599Sobrien		read_specs (new_filename, FALSE);
199150599Sobrien	      else if (verbose_flag)
199290277Sobrien		notice ("could not find specs file %s\n", p1);
199350599Sobrien	      continue;
199450599Sobrien	    }
199550599Sobrien	  else if (!strncmp (p1, "%rename", sizeof "%rename" - 1)
199650599Sobrien		   && (p1[sizeof "%rename" - 1] == ' '
199750599Sobrien		       || p1[sizeof "%rename" - 1] == '\t'))
199850599Sobrien	    {
199950599Sobrien	      int name_len;
200050599Sobrien	      struct spec_list *sl;
2001117413Skan	      struct spec_list *newsl;
200250599Sobrien
2003117413Skan	      /* Get original name.  */
200450599Sobrien	      p1 += sizeof "%rename";
200550599Sobrien	      while (*p1 == ' ' || *p1 == '\t')
200650599Sobrien		p1++;
200750599Sobrien
200890277Sobrien	      if (! ISALPHA ((unsigned char) *p1))
200952520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
201052520Sobrien		       (long) (p1 - buffer));
201150599Sobrien
201250599Sobrien	      p2 = p1;
201390277Sobrien	      while (*p2 && !ISSPACE ((unsigned char) *p2))
201450599Sobrien		p2++;
201550599Sobrien
201650599Sobrien	      if (*p2 != ' ' && *p2 != '\t')
201752520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
201852520Sobrien		       (long) (p2 - buffer));
201950599Sobrien
202050599Sobrien	      name_len = p2 - p1;
202150599Sobrien	      *p2++ = '\0';
202250599Sobrien	      while (*p2 == ' ' || *p2 == '\t')
202350599Sobrien		p2++;
202450599Sobrien
202590277Sobrien	      if (! ISALPHA ((unsigned char) *p2))
202652520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
202752520Sobrien		       (long) (p2 - buffer));
202850599Sobrien
202990277Sobrien	      /* Get new spec name.  */
203050599Sobrien	      p3 = p2;
203190277Sobrien	      while (*p3 && !ISSPACE ((unsigned char) *p3))
203250599Sobrien		p3++;
203350599Sobrien
203490277Sobrien	      if (p3 != p - 1)
203552520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
203652520Sobrien		       (long) (p3 - buffer));
203750599Sobrien	      *p3 = '\0';
203850599Sobrien
203950599Sobrien	      for (sl = specs; sl; sl = sl->next)
204050599Sobrien		if (name_len == sl->name_len && !strcmp (sl->name, p1))
204150599Sobrien		  break;
204250599Sobrien
204350599Sobrien	      if (!sl)
204450599Sobrien		fatal ("specs %s spec was not found to be renamed", p1);
204550599Sobrien
204650599Sobrien	      if (strcmp (p1, p2) == 0)
204750599Sobrien		continue;
204850599Sobrien
2049117413Skan	      for (newsl = specs; newsl; newsl = newsl->next)
2050117413Skan		if (strcmp (newsl->name, p2) == 0)
2051117413Skan		  fatal ("%s: attempt to rename spec '%s' to already defined spec '%s'",
2052117413Skan		    filename, p1, p2);
2053117413Skan
205450599Sobrien	      if (verbose_flag)
205550599Sobrien		{
205652520Sobrien		  notice ("rename spec %s to %s\n", p1, p2);
205750599Sobrien#ifdef DEBUG_SPECS
205852520Sobrien		  notice ("spec is '%s'\n\n", *(sl->ptr_spec));
205950599Sobrien#endif
206050599Sobrien		}
206150599Sobrien
206250599Sobrien	      set_spec (p2, *(sl->ptr_spec));
206350599Sobrien	      if (sl->alloc_p)
2064132733Skan		free ((void *) *(sl->ptr_spec));
206550599Sobrien
206650599Sobrien	      *(sl->ptr_spec) = "";
206750599Sobrien	      sl->alloc_p = 0;
206850599Sobrien	      continue;
206950599Sobrien	    }
207050599Sobrien	  else
207152520Sobrien	    fatal ("specs unknown %% command after %ld characters",
207252520Sobrien		   (long) (p1 - buffer));
207350599Sobrien	}
207450599Sobrien
207550599Sobrien      /* Find the colon that should end the suffix.  */
207650599Sobrien      p1 = p;
207750599Sobrien      while (*p1 && *p1 != ':' && *p1 != '\n')
207850599Sobrien	p1++;
207950599Sobrien
208050599Sobrien      /* The colon shouldn't be missing.  */
208150599Sobrien      if (*p1 != ':')
208252520Sobrien	fatal ("specs file malformed after %ld characters",
208352520Sobrien	       (long) (p1 - buffer));
208450599Sobrien
208550599Sobrien      /* Skip back over trailing whitespace.  */
208650599Sobrien      p2 = p1;
208750599Sobrien      while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t'))
208850599Sobrien	p2--;
208950599Sobrien
209050599Sobrien      /* Copy the suffix to a string.  */
209150599Sobrien      suffix = save_string (p, p2 - p);
209250599Sobrien      /* Find the next line.  */
209350599Sobrien      p = skip_whitespace (p1 + 1);
209450599Sobrien      if (p[1] == 0)
209552520Sobrien	fatal ("specs file malformed after %ld characters",
209652520Sobrien	       (long) (p - buffer));
209750599Sobrien
209850599Sobrien      p1 = p;
209950599Sobrien      /* Find next blank line or end of string.  */
210050599Sobrien      while (*p1 && !(*p1 == '\n' && (p1[1] == '\n' || p1[1] == '\0')))
210150599Sobrien	p1++;
210250599Sobrien
210350599Sobrien      /* Specs end at the blank line and do not include the newline.  */
210450599Sobrien      spec = save_string (p, p1 - p);
210550599Sobrien      p = p1;
210650599Sobrien
210750599Sobrien      /* Delete backslash-newline sequences from the spec.  */
210850599Sobrien      in = spec;
210950599Sobrien      out = spec;
211050599Sobrien      while (*in != 0)
211150599Sobrien	{
211250599Sobrien	  if (in[0] == '\\' && in[1] == '\n')
211350599Sobrien	    in += 2;
211450599Sobrien	  else if (in[0] == '#')
211550599Sobrien	    while (*in && *in != '\n')
211650599Sobrien	      in++;
211750599Sobrien
211850599Sobrien	  else
211950599Sobrien	    *out++ = *in++;
212050599Sobrien	}
212150599Sobrien      *out = 0;
212250599Sobrien
212350599Sobrien      if (suffix[0] == '*')
212450599Sobrien	{
212550599Sobrien	  if (! strcmp (suffix, "*link_command"))
212650599Sobrien	    link_command_spec = spec;
212750599Sobrien	  else
212850599Sobrien	    set_spec (suffix + 1, spec);
212950599Sobrien	}
213050599Sobrien      else
213150599Sobrien	{
213250599Sobrien	  /* Add this pair to the vector.  */
213350599Sobrien	  compilers
2134132733Skan	    = xrealloc (compilers,
2135132733Skan			(n_compilers + 2) * sizeof (struct compiler));
213650599Sobrien
213750599Sobrien	  compilers[n_compilers].suffix = suffix;
213890277Sobrien	  compilers[n_compilers].spec = spec;
213950599Sobrien	  n_compilers++;
214090277Sobrien	  memset (&compilers[n_compilers], 0, sizeof compilers[n_compilers]);
214150599Sobrien	}
214250599Sobrien
214350599Sobrien      if (*suffix == 0)
214450599Sobrien	link_command_spec = spec;
214550599Sobrien    }
214650599Sobrien
214750599Sobrien  if (link_command_spec == 0)
214850599Sobrien    fatal ("spec file has no spec for linking");
214950599Sobrien}
215050599Sobrien
215118334Speter/* Record the names of temporary files we tell compilers to write,
215218334Speter   and delete them at the end of the run.  */
215318334Speter
215418334Speter/* This is the common prefix we use to make temp file names.
215518334Speter   It is chosen once for each run of this program.
215690277Sobrien   It is substituted into a spec by %g or %j.
215718334Speter   Thus, all temp file names contain this prefix.
215818334Speter   In practice, all temp file names start with this prefix.
215918334Speter
216018334Speter   This prefix comes from the envvar TMPDIR if it is defined;
216118334Speter   otherwise, from the P_tmpdir macro if that is defined;
216250599Sobrien   otherwise, in /usr/tmp or /tmp;
216350599Sobrien   or finally the current directory if all else fails.  */
216418334Speter
216552520Sobrienstatic const char *temp_filename;
216618334Speter
216718334Speter/* Length of the prefix.  */
216818334Speter
216918334Speterstatic int temp_filename_length;
217018334Speter
217118334Speter/* Define the list of temporary files to delete.  */
217218334Speter
217318334Speterstruct temp_file
217418334Speter{
217552520Sobrien  const char *name;
217618334Speter  struct temp_file *next;
217718334Speter};
217818334Speter
217918334Speter/* Queue of files to delete on success or failure of compilation.  */
218018334Speterstatic struct temp_file *always_delete_queue;
218118334Speter/* Queue of files to delete on failure of compilation.  */
218218334Speterstatic struct temp_file *failure_delete_queue;
218318334Speter
218418334Speter/* Record FILENAME as a file to be deleted automatically.
218518334Speter   ALWAYS_DELETE nonzero means delete it if all compilation succeeds;
218618334Speter   otherwise delete it in any case.
218718334Speter   FAIL_DELETE nonzero means delete it if a compilation step fails;
218818334Speter   otherwise delete it in any case.  */
218918334Speter
219090277Sobrienvoid
2191132733Skanrecord_temp_file (const char *filename, int always_delete, int fail_delete)
219218334Speter{
219390277Sobrien  char *const name = xstrdup (filename);
219418334Speter
219518334Speter  if (always_delete)
219618334Speter    {
219790277Sobrien      struct temp_file *temp;
219818334Speter      for (temp = always_delete_queue; temp; temp = temp->next)
219918334Speter	if (! strcmp (name, temp->name))
220018334Speter	  goto already1;
220150599Sobrien
2202132733Skan      temp = xmalloc (sizeof (struct temp_file));
220318334Speter      temp->next = always_delete_queue;
220418334Speter      temp->name = name;
220518334Speter      always_delete_queue = temp;
220650599Sobrien
220718334Speter    already1:;
220818334Speter    }
220918334Speter
221018334Speter  if (fail_delete)
221118334Speter    {
221290277Sobrien      struct temp_file *temp;
221318334Speter      for (temp = failure_delete_queue; temp; temp = temp->next)
221418334Speter	if (! strcmp (name, temp->name))
221518334Speter	  goto already2;
221650599Sobrien
2217132733Skan      temp = xmalloc (sizeof (struct temp_file));
221818334Speter      temp->next = failure_delete_queue;
221918334Speter      temp->name = name;
222018334Speter      failure_delete_queue = temp;
222150599Sobrien
222218334Speter    already2:;
222318334Speter    }
222418334Speter}
222518334Speter
222618334Speter/* Delete all the temporary files whose names we previously recorded.  */
222718334Speter
222818334Speterstatic void
2229132733Skandelete_if_ordinary (const char *name)
223018334Speter{
223118334Speter  struct stat st;
223218334Speter#ifdef DEBUG
223318334Speter  int i, c;
223418334Speter
223518334Speter  printf ("Delete %s? (y or n) ", name);
223618334Speter  fflush (stdout);
223718334Speter  i = getchar ();
223818334Speter  if (i != '\n')
223950599Sobrien    while ((c = getchar ()) != '\n' && c != EOF)
224050599Sobrien      ;
224150599Sobrien
224218334Speter  if (i == 'y' || i == 'Y')
224318334Speter#endif /* DEBUG */
224418334Speter    if (stat (name, &st) >= 0 && S_ISREG (st.st_mode))
224518334Speter      if (unlink (name) < 0)
224618334Speter	if (verbose_flag)
224718334Speter	  perror_with_name (name);
224818334Speter}
224918334Speter
225018334Speterstatic void
2251132733Skandelete_temp_files (void)
225218334Speter{
225390277Sobrien  struct temp_file *temp;
225418334Speter
225518334Speter  for (temp = always_delete_queue; temp; temp = temp->next)
225618334Speter    delete_if_ordinary (temp->name);
225718334Speter  always_delete_queue = 0;
225818334Speter}
225918334Speter
226018334Speter/* Delete all the files to be deleted on error.  */
226118334Speter
226218334Speterstatic void
2263132733Skandelete_failure_queue (void)
226418334Speter{
226590277Sobrien  struct temp_file *temp;
226618334Speter
226718334Speter  for (temp = failure_delete_queue; temp; temp = temp->next)
226818334Speter    delete_if_ordinary (temp->name);
226918334Speter}
227018334Speter
227118334Speterstatic void
2272132733Skanclear_failure_queue (void)
227318334Speter{
227418334Speter  failure_delete_queue = 0;
227518334Speter}
227618334Speter
227718334Speter/* Build a list of search directories from PATHS.
227818334Speter   PREFIX is a string to prepend to the list.
2279117413Skan   If CHECK_DIR_P is nonzero we ensure the directory exists.
228018334Speter   This is used mostly by putenv_from_prefixes so we use `collect_obstack'.
228118334Speter   It is also used by the --print-search-dirs flag.  */
228218334Speter
228318334Speterstatic char *
2284132733Skanbuild_search_list (struct path_prefix *paths, const char *prefix,
2285132733Skan		   int check_dir_p)
228618334Speter{
228718334Speter  int suffix_len = (machine_suffix) ? strlen (machine_suffix) : 0;
228818334Speter  int just_suffix_len
228918334Speter    = (just_machine_suffix) ? strlen (just_machine_suffix) : 0;
229018334Speter  int first_time = TRUE;
229118334Speter  struct prefix_list *pprefix;
229218334Speter
229318334Speter  obstack_grow (&collect_obstack, prefix, strlen (prefix));
229490277Sobrien  obstack_1grow (&collect_obstack, '=');
229518334Speter
229618334Speter  for (pprefix = paths->plist; pprefix != 0; pprefix = pprefix->next)
229718334Speter    {
229818334Speter      int len = strlen (pprefix->prefix);
229918334Speter
230018334Speter      if (machine_suffix
230150599Sobrien	  && (! check_dir_p
230218334Speter	      || is_directory (pprefix->prefix, machine_suffix, 0)))
230318334Speter	{
230418334Speter	  if (!first_time)
230518334Speter	    obstack_1grow (&collect_obstack, PATH_SEPARATOR);
230690277Sobrien
230718334Speter	  first_time = FALSE;
230818334Speter	  obstack_grow (&collect_obstack, pprefix->prefix, len);
230918334Speter	  obstack_grow (&collect_obstack, machine_suffix, suffix_len);
231018334Speter	}
231118334Speter
231218334Speter      if (just_machine_suffix
231318334Speter	  && pprefix->require_machine_suffix == 2
231450599Sobrien	  && (! check_dir_p
231518334Speter	      || is_directory (pprefix->prefix, just_machine_suffix, 0)))
231618334Speter	{
231750599Sobrien	  if (! first_time)
231818334Speter	    obstack_1grow (&collect_obstack, PATH_SEPARATOR);
231990277Sobrien
232018334Speter	  first_time = FALSE;
232118334Speter	  obstack_grow (&collect_obstack, pprefix->prefix, len);
232218334Speter	  obstack_grow (&collect_obstack, just_machine_suffix,
232318334Speter			just_suffix_len);
232418334Speter	}
232518334Speter
232650599Sobrien      if (! pprefix->require_machine_suffix)
232718334Speter	{
232850599Sobrien	  if (! first_time)
232918334Speter	    obstack_1grow (&collect_obstack, PATH_SEPARATOR);
233018334Speter
233118334Speter	  first_time = FALSE;
233218334Speter	  obstack_grow (&collect_obstack, pprefix->prefix, len);
233318334Speter	}
233418334Speter    }
233550599Sobrien
233618334Speter  obstack_1grow (&collect_obstack, '\0');
233718334Speter  return obstack_finish (&collect_obstack);
233818334Speter}
233918334Speter
234050599Sobrien/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
234150599Sobrien   for collect.  */
234218334Speter
234318334Speterstatic void
2344132733Skanputenv_from_prefixes (struct path_prefix *paths, const char *env_var)
234518334Speter{
234618334Speter  putenv (build_search_list (paths, env_var, 1));
234718334Speter}
234818334Speter
234990277Sobrien/* Check whether NAME can be accessed in MODE.  This is like access,
235090277Sobrien   except that it never considers directories to be executable.  */
235190277Sobrien
235290277Sobrienstatic int
2353132733Skanaccess_check (const char *name, int mode)
235490277Sobrien{
235590277Sobrien  if (mode == X_OK)
235690277Sobrien    {
235790277Sobrien      struct stat st;
235890277Sobrien
235990277Sobrien      if (stat (name, &st) < 0
236090277Sobrien	  || S_ISDIR (st.st_mode))
236190277Sobrien	return -1;
236290277Sobrien    }
236390277Sobrien
236490277Sobrien  return access (name, mode);
236590277Sobrien}
236690277Sobrien
236718334Speter/* Search for NAME using the prefix list PREFIXES.  MODE is passed to
236818334Speter   access to check permissions.
236950599Sobrien   Return 0 if not found, otherwise return its name, allocated with malloc.  */
237018334Speter
237118334Speterstatic char *
2372132733Skanfind_a_file (struct path_prefix *pprefix, const char *name, int mode,
2373132733Skan	     int multilib)
237418334Speter{
237518334Speter  char *temp;
237690277Sobrien  const char *const file_suffix =
237790277Sobrien    ((mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : "");
237818334Speter  struct prefix_list *pl;
237918334Speter  int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1;
2380104763Skan  const char *multilib_name, *multilib_os_name;
238118334Speter
238252520Sobrien#ifdef DEFAULT_ASSEMBLER
238390277Sobrien  if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0)
238490277Sobrien    return xstrdup (DEFAULT_ASSEMBLER);
238552520Sobrien#endif
238652520Sobrien
238752520Sobrien#ifdef DEFAULT_LINKER
238890277Sobrien  if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0)
238990277Sobrien    return xstrdup (DEFAULT_LINKER);
239052520Sobrien#endif
239152520Sobrien
239218334Speter  if (machine_suffix)
239318334Speter    len += strlen (machine_suffix);
239418334Speter
2395104763Skan  multilib_name = name;
2396104763Skan  multilib_os_name = name;
2397104763Skan  if (multilib && multilib_os_dir)
2398104763Skan    {
2399104763Skan      int len1 = multilib_dir ? strlen (multilib_dir) + 1 : 0;
2400104763Skan      int len2 = strlen (multilib_os_dir) + 1;
2401104763Skan
2402104763Skan      len += len1 > len2 ? len1 : len2;
2403104763Skan      if (multilib_dir)
2404104763Skan	multilib_name = ACONCAT ((multilib_dir, dir_separator_str, name,
2405104763Skan				  NULL));
2406104763Skan      if (strcmp (multilib_os_dir, ".") != 0)
2407104763Skan	multilib_os_name = ACONCAT ((multilib_os_dir, dir_separator_str, name,
2408104763Skan				    NULL));
2409104763Skan    }
2410104763Skan
241118334Speter  temp = xmalloc (len);
241218334Speter
241318334Speter  /* Determine the filename to execute (special case for absolute paths).  */
241418334Speter
2415132733Skan  if (IS_ABSOLUTE_PATH (name))
241618334Speter    {
241752520Sobrien      if (access (name, mode) == 0)
241818334Speter	{
241918334Speter	  strcpy (temp, name);
242018334Speter	  return temp;
242118334Speter	}
242218334Speter    }
242318334Speter  else
242418334Speter    for (pl = pprefix->plist; pl; pl = pl->next)
242518334Speter      {
2426104763Skan	const char *this_name
2427104763Skan	  = pl->os_multilib ? multilib_os_name : multilib_name;
2428104763Skan
242918334Speter	if (machine_suffix)
243018334Speter	  {
243118334Speter	    /* Some systems have a suffix for executable files.
243218334Speter	       So try appending that first.  */
243318334Speter	    if (file_suffix[0] != 0)
243418334Speter	      {
243518334Speter		strcpy (temp, pl->prefix);
243618334Speter		strcat (temp, machine_suffix);
2437104763Skan		strcat (temp, multilib_name);
243818334Speter		strcat (temp, file_suffix);
243990277Sobrien		if (access_check (temp, mode) == 0)
244018334Speter		  {
244118334Speter		    if (pl->used_flag_ptr != 0)
244218334Speter		      *pl->used_flag_ptr = 1;
244318334Speter		    return temp;
244418334Speter		  }
244518334Speter	      }
244618334Speter
2447104763Skan	    /* Now try just the multilib_name.  */
244818334Speter	    strcpy (temp, pl->prefix);
244918334Speter	    strcat (temp, machine_suffix);
2450104763Skan	    strcat (temp, multilib_name);
245190277Sobrien	    if (access_check (temp, mode) == 0)
245218334Speter	      {
245318334Speter		if (pl->used_flag_ptr != 0)
245418334Speter		  *pl->used_flag_ptr = 1;
245518334Speter		return temp;
245618334Speter	      }
245718334Speter	  }
245818334Speter
245918334Speter	/* Certain prefixes are tried with just the machine type,
246018334Speter	   not the version.  This is used for finding as, ld, etc.  */
246118334Speter	if (just_machine_suffix && pl->require_machine_suffix == 2)
246218334Speter	  {
246318334Speter	    /* Some systems have a suffix for executable files.
246418334Speter	       So try appending that first.  */
246518334Speter	    if (file_suffix[0] != 0)
246618334Speter	      {
246718334Speter		strcpy (temp, pl->prefix);
246818334Speter		strcat (temp, just_machine_suffix);
2469104763Skan		strcat (temp, multilib_name);
247018334Speter		strcat (temp, file_suffix);
247190277Sobrien		if (access_check (temp, mode) == 0)
247218334Speter		  {
247318334Speter		    if (pl->used_flag_ptr != 0)
247418334Speter		      *pl->used_flag_ptr = 1;
247518334Speter		    return temp;
247618334Speter		  }
247718334Speter	      }
247818334Speter
247918334Speter	    strcpy (temp, pl->prefix);
248018334Speter	    strcat (temp, just_machine_suffix);
2481104763Skan	    strcat (temp, multilib_name);
248290277Sobrien	    if (access_check (temp, mode) == 0)
248318334Speter	      {
248418334Speter		if (pl->used_flag_ptr != 0)
248518334Speter		  *pl->used_flag_ptr = 1;
248618334Speter		return temp;
248718334Speter	      }
248818334Speter	  }
248918334Speter
249018334Speter	/* Certain prefixes can't be used without the machine suffix
249118334Speter	   when the machine or version is explicitly specified.  */
249250599Sobrien	if (! pl->require_machine_suffix)
249318334Speter	  {
249418334Speter	    /* Some systems have a suffix for executable files.
249518334Speter	       So try appending that first.  */
249618334Speter	    if (file_suffix[0] != 0)
249718334Speter	      {
249818334Speter		strcpy (temp, pl->prefix);
2499104763Skan		strcat (temp, this_name);
250018334Speter		strcat (temp, file_suffix);
250190277Sobrien		if (access_check (temp, mode) == 0)
250218334Speter		  {
250318334Speter		    if (pl->used_flag_ptr != 0)
250418334Speter		      *pl->used_flag_ptr = 1;
250518334Speter		    return temp;
250618334Speter		  }
250718334Speter	      }
250818334Speter
250918334Speter	    strcpy (temp, pl->prefix);
2510104763Skan	    strcat (temp, this_name);
251190277Sobrien	    if (access_check (temp, mode) == 0)
251218334Speter	      {
251318334Speter		if (pl->used_flag_ptr != 0)
251418334Speter		  *pl->used_flag_ptr = 1;
251518334Speter		return temp;
251618334Speter	      }
251718334Speter	  }
251818334Speter      }
251918334Speter
252018334Speter  free (temp);
252118334Speter  return 0;
252218334Speter}
252318334Speter
252490277Sobrien/* Ranking of prefixes in the sort list. -B prefixes are put before
252590277Sobrien   all others.  */
252618334Speter
252790277Sobrienenum path_prefix_priority
252890277Sobrien{
252990277Sobrien  PREFIX_PRIORITY_B_OPT,
253090277Sobrien  PREFIX_PRIORITY_LAST
253190277Sobrien};
253290277Sobrien
2533132733Skan/* Add an entry for PREFIX in PLIST.  The PLIST is kept in ascending
253490277Sobrien   order according to PRIORITY.  Within each PRIORITY, new entries are
253590277Sobrien   appended.
253690277Sobrien
253718334Speter   If WARN is nonzero, we will warn if no file is found
253818334Speter   through this prefix.  WARN should point to an int
253918334Speter   which will be set to 1 if this entry is used.
254018334Speter
254150599Sobrien   COMPONENT is the value to be passed to update_path.
254250599Sobrien
254318334Speter   REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without
254418334Speter   the complete value of machine_suffix.
254518334Speter   2 means try both machine_suffix and just_machine_suffix.  */
254618334Speter
254718334Speterstatic void
2548132733Skanadd_prefix (struct path_prefix *pprefix, const char *prefix,
2549132733Skan	    const char *component, /* enum prefix_priority */ int priority,
2550132733Skan	    int require_machine_suffix, int *warn, int os_multilib)
255118334Speter{
255218334Speter  struct prefix_list *pl, **prev;
255318334Speter  int len;
255418334Speter
255590277Sobrien  for (prev = &pprefix->plist;
255690277Sobrien       (*prev) != NULL && (*prev)->priority <= priority;
255790277Sobrien       prev = &(*prev)->next)
255890277Sobrien    ;
255918334Speter
2560132733Skan  /* Keep track of the longest prefix.  */
256118334Speter
256250599Sobrien  prefix = update_path (prefix, component);
256318334Speter  len = strlen (prefix);
256418334Speter  if (len > pprefix->max_len)
256518334Speter    pprefix->max_len = len;
256618334Speter
2567132733Skan  pl = xmalloc (sizeof (struct prefix_list));
256890277Sobrien  pl->prefix = prefix;
256918334Speter  pl->require_machine_suffix = require_machine_suffix;
257018334Speter  pl->used_flag_ptr = warn;
257190277Sobrien  pl->priority = priority;
2572104763Skan  pl->os_multilib = os_multilib;
257318334Speter  if (warn)
257418334Speter    *warn = 0;
257518334Speter
2576132733Skan  /* Insert after PREV.  */
257790277Sobrien  pl->next = (*prev);
257890277Sobrien  (*prev) = pl;
257918334Speter}
2580132733Skan
2581132733Skan/* Same as add_prefix, but prepending target_system_root to prefix.  */
2582132733Skanstatic void
2583132733Skanadd_sysrooted_prefix (struct path_prefix *pprefix, const char *prefix,
2584132733Skan		      const char *component,
2585132733Skan		      /* enum prefix_priority */ int priority,
2586132733Skan		      int require_machine_suffix, int *warn, int os_multilib)
2587132733Skan{
2588132733Skan  if (!IS_ABSOLUTE_PATH (prefix))
2589132733Skan    abort ();
2590132733Skan
2591132733Skan  if (target_system_root)
2592132733Skan    {
2593132733Skan      if (target_sysroot_suffix)
2594132733Skan	  prefix = concat (target_sysroot_suffix, prefix, NULL);
2595132733Skan      prefix = concat (target_system_root, prefix, NULL);
2596132733Skan
2597132733Skan      /* We have to override this because GCC's notion of sysroot
2598132733Skan	 moves along with GCC.  */
2599132733Skan      component = "GCC";
2600132733Skan    }
2601132733Skan
2602132733Skan  add_prefix (pprefix, prefix, component, priority,
2603132733Skan	      require_machine_suffix, warn, os_multilib);
2604132733Skan}
260518334Speter
260618334Speter/* Execute the command specified by the arguments on the current line of spec.
260718334Speter   When using pipes, this includes several piped-together commands
260818334Speter   with `|' between them.
260918334Speter
261018334Speter   Return 0 if successful, -1 if failed.  */
261118334Speter
261218334Speterstatic int
2613132733Skanexecute (void)
261418334Speter{
261518334Speter  int i;
261618334Speter  int n_commands;		/* # of command.  */
261718334Speter  char *string;
261818334Speter  struct command
261990277Sobrien  {
262090277Sobrien    const char *prog;		/* program name.  */
262190277Sobrien    const char **argv;		/* vector of args.  */
262290277Sobrien    int pid;			/* pid of process for this command.  */
262390277Sobrien  };
262418334Speter
262518334Speter  struct command *commands;	/* each command buffer with above info.  */
262618334Speter
2627117413Skan  if (processing_spec_function)
2628117413Skan    abort ();
2629117413Skan
263018334Speter  /* Count # of piped commands.  */
263118334Speter  for (n_commands = 1, i = 0; i < argbuf_index; i++)
263218334Speter    if (strcmp (argbuf[i], "|") == 0)
263318334Speter      n_commands++;
263418334Speter
263518334Speter  /* Get storage for each command.  */
2636132733Skan  commands = alloca (n_commands * sizeof (struct command));
263718334Speter
263818334Speter  /* Split argbuf into its separate piped processes,
263918334Speter     and record info about each one.
264018334Speter     Also search for the programs that are to be run.  */
264118334Speter
264218334Speter  commands[0].prog = argbuf[0]; /* first command.  */
264318334Speter  commands[0].argv = &argbuf[0];
2644104763Skan  string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, 0);
264550599Sobrien
264618334Speter  if (string)
264718334Speter    commands[0].argv[0] = string;
264818334Speter
264918334Speter  for (n_commands = 1, i = 0; i < argbuf_index; i++)
265018334Speter    if (strcmp (argbuf[i], "|") == 0)
265118334Speter      {				/* each command.  */
265252520Sobrien#if defined (__MSDOS__) || defined (OS2) || defined (VMS)
265390277Sobrien	fatal ("-pipe not supported");
265418334Speter#endif
265518334Speter	argbuf[i] = 0;	/* termination of command args.  */
265618334Speter	commands[n_commands].prog = argbuf[i + 1];
265718334Speter	commands[n_commands].argv = &argbuf[i + 1];
2658104763Skan	string = find_a_file (&exec_prefixes, commands[n_commands].prog,
2659104763Skan			      X_OK, 0);
266018334Speter	if (string)
266118334Speter	  commands[n_commands].argv[0] = string;
266218334Speter	n_commands++;
266318334Speter      }
266418334Speter
266518334Speter  argbuf[argbuf_index] = 0;
266618334Speter
266718334Speter  /* If -v, print what we are about to do, and maybe query.  */
266818334Speter
266918334Speter  if (verbose_flag)
267018334Speter    {
267150599Sobrien      /* For help listings, put a blank line between sub-processes.  */
267250599Sobrien      if (print_help_list)
267350599Sobrien	fputc ('\n', stderr);
267490277Sobrien
267518334Speter      /* Print each piped command as a separate line.  */
267690277Sobrien      for (i = 0; i < n_commands; i++)
267718334Speter	{
267890277Sobrien	  const char *const *j;
267918334Speter
2680117413Skan	  if (verbose_only_flag)
2681117413Skan	    {
268290277Sobrien	      for (j = commands[i].argv; *j; j++)
268390277Sobrien		{
268490277Sobrien		  const char *p;
268590277Sobrien		  fprintf (stderr, " \"");
268690277Sobrien		  for (p = *j; *p; ++p)
268790277Sobrien		    {
268890277Sobrien		      if (*p == '"' || *p == '\\' || *p == '$')
268990277Sobrien			fputc ('\\', stderr);
269090277Sobrien		      fputc (*p, stderr);
269190277Sobrien		    }
269290277Sobrien		  fputc ('"', stderr);
269390277Sobrien		}
2694117413Skan	    }
2695117413Skan	  else
269690277Sobrien	    for (j = commands[i].argv; *j; j++)
269790277Sobrien	      fprintf (stderr, " %s", *j);
269818334Speter
269918334Speter	  /* Print a pipe symbol after all but the last command.  */
270018334Speter	  if (i + 1 != n_commands)
270118334Speter	    fprintf (stderr, " |");
270218334Speter	  fprintf (stderr, "\n");
270318334Speter	}
270418334Speter      fflush (stderr);
270590277Sobrien      if (verbose_only_flag != 0)
2706132733Skan        {
2707132733Skan	  /* verbose_only_flag should act as if the spec was
2708132733Skan	     executed, so increment execution_count before
2709132733Skan	     returning.  This prevents spurious warnings about
2710132733Skan	     unused linker input files, etc.  */
2711132733Skan	  execution_count++;
2712132733Skan	  return 0;
2713132733Skan        }
271418334Speter#ifdef DEBUG
271552520Sobrien      notice ("\nGo ahead? (y or n) ");
271618334Speter      fflush (stderr);
271718334Speter      i = getchar ();
271818334Speter      if (i != '\n')
271950599Sobrien	while (getchar () != '\n')
272050599Sobrien	  ;
272150599Sobrien
272218334Speter      if (i != 'y' && i != 'Y')
272318334Speter	return 0;
272418334Speter#endif /* DEBUG */
272518334Speter    }
272618334Speter
2727117413Skan#ifdef ENABLE_VALGRIND_CHECKING
2728132733Skan  /* Run the each command through valgrind.  To simplify prepending the
2729117413Skan     path to valgrind and the option "-q" (for quiet operation unless
2730117413Skan     something triggers), we allocate a separate argv array.  */
2731117413Skan
2732117413Skan  for (i = 0; i < n_commands; i++)
2733117413Skan    {
2734117413Skan      const char **argv;
2735117413Skan      int argc;
2736117413Skan      int j;
2737117413Skan
2738117413Skan      for (argc = 0; commands[i].argv[argc] != NULL; argc++)
2739117413Skan	;
2740117413Skan
2741117413Skan      argv = alloca ((argc + 3) * sizeof (char *));
2742117413Skan
2743117413Skan      argv[0] = VALGRIND_PATH;
2744117413Skan      argv[1] = "-q";
2745117413Skan      for (j = 2; j < argc + 2; j++)
2746117413Skan	argv[j] = commands[i].argv[j - 2];
2747117413Skan      argv[j] = NULL;
2748117413Skan
2749117413Skan      commands[i].argv = argv;
2750117413Skan      commands[i].prog = argv[0];
2751117413Skan    }
2752117413Skan#endif
2753117413Skan
275418334Speter  /* Run each piped subprocess.  */
275518334Speter
275618334Speter  for (i = 0; i < n_commands; i++)
275718334Speter    {
275850599Sobrien      char *errmsg_fmt, *errmsg_arg;
275990277Sobrien      const char *string = commands[i].argv[0];
276018334Speter
276190277Sobrien      /* For some bizarre reason, the second argument of execvp() is
276290277Sobrien	 char *const *, not const char *const *.  */
276390277Sobrien      commands[i].pid = pexecute (string, (char *const *) commands[i].argv,
276450599Sobrien				  programname, temp_filename,
276550599Sobrien				  &errmsg_fmt, &errmsg_arg,
276650599Sobrien				  ((i == 0 ? PEXECUTE_FIRST : 0)
276750599Sobrien				   | (i + 1 == n_commands ? PEXECUTE_LAST : 0)
276850599Sobrien				   | (string == commands[i].prog
276950599Sobrien				      ? PEXECUTE_SEARCH : 0)
277050599Sobrien				   | (verbose_flag ? PEXECUTE_VERBOSE : 0)));
277118334Speter
277250599Sobrien      if (commands[i].pid == -1)
277350599Sobrien	pfatal_pexecute (errmsg_fmt, errmsg_arg);
277450599Sobrien
277518334Speter      if (string != commands[i].prog)
2776132733Skan	free ((void *) string);
277718334Speter    }
277818334Speter
277918334Speter  execution_count++;
278018334Speter
278118334Speter  /* Wait for all the subprocesses to finish.
278218334Speter     We don't care what order they finish in;
278318334Speter     we know that N_COMMANDS waits will get them all.
278418334Speter     Ignore subprocesses that we don't know about,
278518334Speter     since they can be spawned by the process that exec'ed us.  */
278618334Speter
278718334Speter  {
278818334Speter    int ret_code = 0;
278990277Sobrien#ifdef HAVE_GETRUSAGE
279090277Sobrien    struct timeval d;
279190277Sobrien    double ut = 0.0, st = 0.0;
279290277Sobrien#endif
279318334Speter
279490277Sobrien    for (i = 0; i < n_commands;)
279518334Speter      {
279618334Speter	int j;
279718334Speter	int status;
279818334Speter	int pid;
279918334Speter
280050599Sobrien	pid = pwait (commands[i].pid, &status, 0);
280118334Speter	if (pid < 0)
280218334Speter	  abort ();
280318334Speter
280490277Sobrien#ifdef HAVE_GETRUSAGE
280590277Sobrien	if (report_times)
280690277Sobrien	  {
280790277Sobrien	    /* getrusage returns the total resource usage of all children
280890277Sobrien	       up to now.  Copy the previous values into prus, get the
280990277Sobrien	       current statistics, then take the difference.  */
281090277Sobrien
281190277Sobrien	    prus = rus;
281290277Sobrien	    getrusage (RUSAGE_CHILDREN, &rus);
281390277Sobrien	    d.tv_sec = rus.ru_utime.tv_sec - prus.ru_utime.tv_sec;
281490277Sobrien	    d.tv_usec = rus.ru_utime.tv_usec - prus.ru_utime.tv_usec;
281590277Sobrien	    ut = (double) d.tv_sec + (double) d.tv_usec / 1.0e6;
281690277Sobrien
281790277Sobrien	    d.tv_sec = rus.ru_stime.tv_sec - prus.ru_stime.tv_sec;
281890277Sobrien	    d.tv_usec = rus.ru_stime.tv_usec - prus.ru_stime.tv_usec;
281990277Sobrien	    st = (double) d.tv_sec + (double) d.tv_usec / 1.0e6;
282090277Sobrien	  }
282190277Sobrien#endif
282290277Sobrien
282318334Speter	for (j = 0; j < n_commands; j++)
282418334Speter	  if (commands[j].pid == pid)
282518334Speter	    {
282618334Speter	      i++;
282790277Sobrien	      if (WIFSIGNALED (status))
282818334Speter		{
282990277Sobrien#ifdef SIGPIPE
283090277Sobrien		  /* SIGPIPE is a special case.  It happens in -pipe mode
283190277Sobrien		     when the compiler dies before the preprocessor is
283290277Sobrien		     done, or the assembler dies before the compiler is
283390277Sobrien		     done.  There's generally been an error already, and
283490277Sobrien		     this is just fallout.  So don't generate another error
283590277Sobrien		     unless we would otherwise have succeeded.  */
283690277Sobrien		  if (WTERMSIG (status) == SIGPIPE
283790277Sobrien		      && (signal_count || greatest_status >= MIN_FATAL_STATUS))
283890277Sobrien		    ;
283990277Sobrien		  else
284090277Sobrien#endif
284190277Sobrien		    fatal ("\
284290277SobrienInternal error: %s (program %s)\n\
284390277SobrienPlease submit a full bug report.\n\
284490277SobrienSee %s for instructions.",
284590277Sobrien			   strsignal (WTERMSIG (status)), commands[j].prog,
2846117413Skan			   bug_report_url);
284790277Sobrien		  signal_count++;
284890277Sobrien		  ret_code = -1;
284918334Speter		}
285090277Sobrien	      else if (WIFEXITED (status)
285190277Sobrien		       && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
285290277Sobrien		{
285390277Sobrien		  if (WEXITSTATUS (status) > greatest_status)
285490277Sobrien		    greatest_status = WEXITSTATUS (status);
285590277Sobrien		  ret_code = -1;
285690277Sobrien		}
285790277Sobrien#ifdef HAVE_GETRUSAGE
285890277Sobrien	      if (report_times && ut + st != 0)
285990277Sobrien		notice ("# %s %.2f %.2f\n", commands[j].prog, ut, st);
286090277Sobrien#endif
286118334Speter	      break;
286218334Speter	    }
286318334Speter      }
286418334Speter    return ret_code;
286518334Speter  }
286618334Speter}
286718334Speter
286818334Speter/* Find all the switches given to us
286918334Speter   and make a vector describing them.
287018334Speter   The elements of the vector are strings, one per switch given.
287118334Speter   If a switch uses following arguments, then the `part1' field
287218334Speter   is the switch itself and the `args' field
287318334Speter   is a null-terminated vector containing the following arguments.
287490277Sobrien   The `live_cond' field is:
287590277Sobrien   0 when initialized
287690277Sobrien   1 if the switch is true in a conditional spec,
287790277Sobrien   -1 if false (overridden by a later switch)
2878132733Skan   -2 if this switch should be ignored (used in %<S)
287952520Sobrien   The `validated' field is nonzero if any spec has looked at this switch;
288018334Speter   if it remains zero at the end of the run, it must be meaningless.  */
288118334Speter
288290277Sobrien#define SWITCH_OK       0
288390277Sobrien#define SWITCH_FALSE   -1
288490277Sobrien#define SWITCH_IGNORE  -2
288590277Sobrien#define SWITCH_LIVE     1
288690277Sobrien
288718334Speterstruct switchstr
288818334Speter{
288952520Sobrien  const char *part1;
289090277Sobrien  const char **args;
289118334Speter  int live_cond;
289290277Sobrien  unsigned char validated;
289390277Sobrien  unsigned char ordering;
289418334Speter};
289518334Speter
289618334Speterstatic struct switchstr *switches;
289718334Speter
289818334Speterstatic int n_switches;
289918334Speter
290018334Speterstruct infile
290118334Speter{
290252520Sobrien  const char *name;
290352520Sobrien  const char *language;
290418334Speter};
290518334Speter
290618334Speter/* Also a vector of input files specified.  */
290718334Speter
290818334Speterstatic struct infile *infiles;
290918334Speter
291090277Sobrienint n_infiles;
291118334Speter
2912132733Skan/* True if multiple input files are being compiled to a single
2913132733Skan   assembly file.  */
2914132733Skan
2915132733Skanstatic bool combine_inputs;
2916132733Skan
291752520Sobrien/* This counts the number of libraries added by lang_specific_driver, so that
291850599Sobrien   we can tell if there were any user supplied any files or libraries.  */
291950599Sobrien
292050599Sobrienstatic int added_libraries;
292150599Sobrien
292218334Speter/* And a vector of corresponding output files is made up later.  */
292318334Speter
292490277Sobrienconst char **outfiles;
292518334Speter
292650599Sobrien/* Used to track if none of the -B paths are used.  */
292750599Sobrienstatic int warn_B;
292850599Sobrien
292950599Sobrien/* Gives value to pass as "warn" to add_prefix for standard prefixes.  */
293050599Sobrienstatic int *warn_std_ptr = 0;
293150599Sobrien
293290277Sobrien#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
293350599Sobrien
293450599Sobrien/* Convert NAME to a new name if it is the standard suffix.  DO_EXE
293590277Sobrien   is true if we should look for an executable suffix.  DO_OBJ
293690277Sobrien   is true if we should look for an object suffix.  */
293750599Sobrien
293890277Sobrienstatic const char *
2939132733Skanconvert_filename (const char *name, int do_exe ATTRIBUTE_UNUSED,
2940132733Skan		  int do_obj ATTRIBUTE_UNUSED)
294150599Sobrien{
294290277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
294350599Sobrien  int i;
294490277Sobrien#endif
294552520Sobrien  int len;
294650599Sobrien
294752520Sobrien  if (name == NULL)
294852520Sobrien    return NULL;
294990277Sobrien
295052520Sobrien  len = strlen (name);
295152520Sobrien
295290277Sobrien#ifdef HAVE_TARGET_OBJECT_SUFFIX
295390277Sobrien  /* Convert x.o to x.obj if TARGET_OBJECT_SUFFIX is ".obj".  */
295490277Sobrien  if (do_obj && len > 2
295550599Sobrien      && name[len - 2] == '.'
295650599Sobrien      && name[len - 1] == 'o')
295750599Sobrien    {
295850599Sobrien      obstack_grow (&obstack, name, len - 2);
295990277Sobrien      obstack_grow0 (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
296050599Sobrien      name = obstack_finish (&obstack);
296150599Sobrien    }
296250599Sobrien#endif
296350599Sobrien
296490277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
296550599Sobrien  /* If there is no filetype, make it the executable suffix (which includes
296650599Sobrien     the ".").  But don't get confused if we have just "-o".  */
296790277Sobrien  if (! do_exe || TARGET_EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-'))
296850599Sobrien    return name;
296950599Sobrien
297050599Sobrien  for (i = len - 1; i >= 0; i--)
297152520Sobrien    if (IS_DIR_SEPARATOR (name[i]))
297250599Sobrien      break;
297350599Sobrien
297450599Sobrien  for (i++; i < len; i++)
297550599Sobrien    if (name[i] == '.')
297650599Sobrien      return name;
297750599Sobrien
297850599Sobrien  obstack_grow (&obstack, name, len);
297990277Sobrien  obstack_grow0 (&obstack, TARGET_EXECUTABLE_SUFFIX,
298090277Sobrien		 strlen (TARGET_EXECUTABLE_SUFFIX));
298150599Sobrien  name = obstack_finish (&obstack);
298250599Sobrien#endif
298350599Sobrien
298450599Sobrien  return name;
298550599Sobrien}
298650599Sobrien#endif
298750599Sobrien
298850599Sobrien/* Display the command line switches accepted by gcc.  */
298950599Sobrienstatic void
2990132733Skandisplay_help (void)
299150599Sobrien{
299290277Sobrien  printf (_("Usage: %s [options] file...\n"), programname);
299390277Sobrien  fputs (_("Options:\n"), stdout);
299450599Sobrien
299590277Sobrien  fputs (_("  -pass-exit-codes         Exit with highest error code from a phase\n"), stdout);
299690277Sobrien  fputs (_("  --help                   Display this information\n"), stdout);
299790277Sobrien  fputs (_("  --target-help            Display target specific command line options\n"), stdout);
299850599Sobrien  if (! verbose_flag)
299990277Sobrien    fputs (_("  (Use '-v --help' to display command line options of sub-processes)\n"), stdout);
300090277Sobrien  fputs (_("  -dumpspecs               Display all of the built in spec strings\n"), stdout);
300190277Sobrien  fputs (_("  -dumpversion             Display the version of the compiler\n"), stdout);
300290277Sobrien  fputs (_("  -dumpmachine             Display the compiler's target processor\n"), stdout);
300390277Sobrien  fputs (_("  -print-search-dirs       Display the directories in the compiler's search path\n"), stdout);
300490277Sobrien  fputs (_("  -print-libgcc-file-name  Display the name of the compiler's companion library\n"), stdout);
300590277Sobrien  fputs (_("  -print-file-name=<lib>   Display the full path to library <lib>\n"), stdout);
300690277Sobrien  fputs (_("  -print-prog-name=<prog>  Display the full path to compiler component <prog>\n"), stdout);
300790277Sobrien  fputs (_("  -print-multi-directory   Display the root directory for versions of libgcc\n"), stdout);
300890277Sobrien  fputs (_("\
300990277Sobrien  -print-multi-lib         Display the mapping between command line options and\n\
301090277Sobrien                           multiple library search directories\n"), stdout);
3011104763Skan  fputs (_("  -print-multi-os-directory Display the relative path to OS libraries\n"), stdout);
301290277Sobrien  fputs (_("  -Wa,<options>            Pass comma-separated <options> on to the assembler\n"), stdout);
301390277Sobrien  fputs (_("  -Wp,<options>            Pass comma-separated <options> on to the preprocessor\n"), stdout);
301490277Sobrien  fputs (_("  -Wl,<options>            Pass comma-separated <options> on to the linker\n"), stdout);
3015132733Skan  fputs (_("  -Xassembler <arg>        Pass <arg> on to the assembler\n"), stdout);
3016132733Skan  fputs (_("  -Xpreprocessor <arg>     Pass <arg> on to the preprocessor\n"), stdout);
301790277Sobrien  fputs (_("  -Xlinker <arg>           Pass <arg> on to the linker\n"), stdout);
301890277Sobrien  fputs (_("  -save-temps              Do not delete intermediate files\n"), stdout);
301990277Sobrien  fputs (_("  -pipe                    Use pipes rather than intermediate files\n"), stdout);
302090277Sobrien  fputs (_("  -time                    Time the execution of each subprocess\n"), stdout);
302190277Sobrien  fputs (_("  -specs=<file>            Override built-in specs with the contents of <file>\n"), stdout);
302290277Sobrien  fputs (_("  -std=<standard>          Assume that the input sources are for <standard>\n"), stdout);
302390277Sobrien  fputs (_("  -B <directory>           Add <directory> to the compiler's search paths\n"), stdout);
302490277Sobrien  fputs (_("  -b <machine>             Run gcc for target <machine>, if installed\n"), stdout);
302590277Sobrien  fputs (_("  -V <version>             Run gcc version number <version>, if installed\n"), stdout);
302690277Sobrien  fputs (_("  -v                       Display the programs invoked by the compiler\n"), stdout);
302790277Sobrien  fputs (_("  -###                     Like -v but options quoted and commands not executed\n"), stdout);
302890277Sobrien  fputs (_("  -E                       Preprocess only; do not compile, assemble or link\n"), stdout);
302990277Sobrien  fputs (_("  -S                       Compile only; do not assemble or link\n"), stdout);
303090277Sobrien  fputs (_("  -c                       Compile and assemble, but do not link\n"), stdout);
303190277Sobrien  fputs (_("  -o <file>                Place the output into <file>\n"), stdout);
303290277Sobrien  fputs (_("\
303390277Sobrien  -x <language>            Specify the language of the following input files\n\
3034117413Skan                           Permissible languages include: c c++ assembler none\n\
303590277Sobrien                           'none' means revert to the default behavior of\n\
303690277Sobrien                           guessing the language based on the file's extension\n\
303790277Sobrien"), stdout);
303850599Sobrien
303990277Sobrien  printf (_("\
304090277Sobrien\nOptions starting with -g, -f, -m, -O, -W, or --param are automatically\n\
304190277Sobrien passed on to the various sub-processes invoked by %s.  In order to pass\n\
304290277Sobrien other options on to these processes the -W<letter> options must be used.\n\
304390277Sobrien"), programname);
304450599Sobrien
304550599Sobrien  /* The rest of the options are displayed by invocations of the various
304650599Sobrien     sub-processes.  */
304750599Sobrien}
304850599Sobrien
304990277Sobrienstatic void
3050132733Skanadd_preprocessor_option (const char *option, int len)
305190277Sobrien{
305252520Sobrien  n_preprocessor_options++;
305390277Sobrien
305452520Sobrien  if (! preprocessor_options)
3055132733Skan    preprocessor_options = xmalloc (n_preprocessor_options * sizeof (char *));
305652520Sobrien  else
3057132733Skan    preprocessor_options = xrealloc (preprocessor_options,
3058132733Skan				     n_preprocessor_options * sizeof (char *));
305990277Sobrien
306052520Sobrien  preprocessor_options [n_preprocessor_options - 1] =
306152520Sobrien    save_string (option, len);
306250599Sobrien}
306390277Sobrien
306490277Sobrienstatic void
3065132733Skanadd_assembler_option (const char *option, int len)
306652520Sobrien{
306752520Sobrien  n_assembler_options++;
306852520Sobrien
306952520Sobrien  if (! assembler_options)
3070132733Skan    assembler_options = xmalloc (n_assembler_options * sizeof (char *));
307152520Sobrien  else
3072132733Skan    assembler_options = xrealloc (assembler_options,
3073132733Skan				  n_assembler_options * sizeof (char *));
307452520Sobrien
307552520Sobrien  assembler_options [n_assembler_options - 1] = save_string (option, len);
307650599Sobrien}
307790277Sobrien
307890277Sobrienstatic void
3079132733Skanadd_linker_option (const char *option, int len)
308052520Sobrien{
308152520Sobrien  n_linker_options++;
308252520Sobrien
308352520Sobrien  if (! linker_options)
3084132733Skan    linker_options = xmalloc (n_linker_options * sizeof (char *));
308552520Sobrien  else
3086132733Skan    linker_options = xrealloc (linker_options,
3087132733Skan			       n_linker_options * sizeof (char *));
308852520Sobrien
308952520Sobrien  linker_options [n_linker_options - 1] = save_string (option, len);
309050599Sobrien}
309150599Sobrien
309218334Speter/* Create the vector `switches' and its contents.
309318334Speter   Store its length in `n_switches'.  */
309418334Speter
309518334Speterstatic void
3096132733Skanprocess_command (int argc, const char **argv)
309718334Speter{
309890277Sobrien  int i;
309952520Sobrien  const char *temp;
310052520Sobrien  char *temp1;
310190277Sobrien  const char *spec_lang = 0;
310218334Speter  int last_language_n_infiles;
310350599Sobrien  int have_c = 0;
310450599Sobrien  int have_o = 0;
310550599Sobrien  int lang_n_infiles = 0;
310690277Sobrien#ifdef MODIFY_TARGET_NAME
310790277Sobrien  int is_modify_target_name;
310890277Sobrien  int j;
310990277Sobrien#endif
311018334Speter
3111117413Skan  GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
311218334Speter
311318334Speter  n_switches = 0;
311418334Speter  n_infiles = 0;
311550599Sobrien  added_libraries = 0;
311618334Speter
311718334Speter  /* Figure compiler version from version string.  */
311818334Speter
311990277Sobrien  compiler_version = temp1 = xstrdup (version_string);
312090277Sobrien
312152520Sobrien  for (; *temp1; ++temp1)
312218334Speter    {
312352520Sobrien      if (*temp1 == ' ')
312418334Speter	{
312552520Sobrien	  *temp1 = '\0';
312618334Speter	  break;
312718334Speter	}
312818334Speter    }
312918334Speter
3130117413Skan  /* If there is a -V or -b option (or both), process it now, before
3131117413Skan     trying to interpret the rest of the command line.  */
3132117413Skan  if (argc > 1 && argv[1][0] == '-'
3133117413Skan      && (argv[1][1] == 'V' || argv[1][1] == 'b'))
3134117413Skan    {
3135117413Skan      const char *new_version = DEFAULT_TARGET_VERSION;
3136117413Skan      const char *new_machine = DEFAULT_TARGET_MACHINE;
3137117413Skan      const char *progname = argv[0];
3138117413Skan      char **new_argv;
3139117413Skan      char *new_argv0;
3140117413Skan      int baselen;
3141132733Skan
3142117413Skan      while (argc > 1 && argv[1][0] == '-'
3143117413Skan	     && (argv[1][1] == 'V' || argv[1][1] == 'b'))
3144117413Skan	{
3145117413Skan	  char opt = argv[1][1];
3146117413Skan	  const char *arg;
3147117413Skan	  if (argv[1][2] != '\0')
3148117413Skan	    {
3149117413Skan	      arg = argv[1] + 2;
3150117413Skan	      argc -= 1;
3151117413Skan	      argv += 1;
3152117413Skan	    }
3153117413Skan	  else if (argc > 2)
3154117413Skan	    {
3155117413Skan	      arg = argv[2];
3156117413Skan	      argc -= 2;
3157117413Skan	      argv += 2;
3158117413Skan	    }
3159117413Skan	  else
3160117413Skan	    fatal ("`-%c' option must have argument", opt);
3161117413Skan	  if (opt == 'V')
3162117413Skan	    new_version = arg;
3163117413Skan	  else
3164117413Skan	    new_machine = arg;
3165117413Skan	}
3166117413Skan
3167117413Skan      for (baselen = strlen (progname); baselen > 0; baselen--)
3168117413Skan	if (IS_DIR_SEPARATOR (progname[baselen-1]))
3169117413Skan	  break;
3170132733Skan      new_argv0 = xmemdup (progname, baselen,
3171117413Skan			   baselen + concat_length (new_version, new_machine,
3172117413Skan						    "-gcc-", NULL) + 1);
3173117413Skan      strcpy (new_argv0 + baselen, new_machine);
3174117413Skan      strcat (new_argv0, "-gcc-");
3175117413Skan      strcat (new_argv0, new_version);
3176117413Skan
3177117413Skan      new_argv = xmemdup (argv, (argc + 1) * sizeof (argv[0]),
3178117413Skan			  (argc + 1) * sizeof (argv[0]));
3179117413Skan      new_argv[0] = new_argv0;
3180117413Skan
3181117413Skan      execvp (new_argv0, new_argv);
3182117413Skan      fatal ("couldn't run `%s': %s", new_argv0, xstrerror (errno));
3183117413Skan    }
3184117413Skan
318590277Sobrien  /* Set up the default search paths.  If there is no GCC_EXEC_PREFIX,
318690277Sobrien     see if we can create it from the pathname specified in argv[0].  */
318718334Speter
3188132733Skan  gcc_libexec_prefix = standard_libexec_prefix;
318996736Sru#ifndef FREEBSD_NATIVE
319090277Sobrien#ifndef VMS
319190277Sobrien  /* FIXME: make_relative_prefix doesn't yet work for VMS.  */
319290277Sobrien  if (!gcc_exec_prefix)
319390277Sobrien    {
319490277Sobrien      gcc_exec_prefix = make_relative_prefix (argv[0], standard_bindir_prefix,
319590277Sobrien					      standard_exec_prefix);
3196132733Skan      gcc_libexec_prefix = make_relative_prefix (argv[0],
3197132733Skan						 standard_bindir_prefix,
3198132733Skan						 standard_libexec_prefix);
319990277Sobrien      if (gcc_exec_prefix)
320090277Sobrien	putenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL));
320190277Sobrien    }
3202132733Skan  else
3203132733Skan    gcc_libexec_prefix = make_relative_prefix (gcc_exec_prefix,
3204132733Skan					       standard_exec_prefix,
3205132733Skan					       standard_libexec_prefix);
3206132733Skan#else
320790277Sobrien#endif
320896736Sru#endif	/* not FREEBSD_NATIVE */
320990277Sobrien
321018334Speter  if (gcc_exec_prefix)
321118334Speter    {
321250599Sobrien      int len = strlen (gcc_exec_prefix);
321390277Sobrien
3214132733Skan      if (len > (int) sizeof ("/lib/gcc/") - 1
321552520Sobrien	  && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1])))
321650599Sobrien	{
3217132733Skan	  temp = gcc_exec_prefix + len - sizeof ("/lib/gcc/") + 1;
321852520Sobrien	  if (IS_DIR_SEPARATOR (*temp)
321990277Sobrien	      && strncmp (temp + 1, "lib", 3) == 0
322052520Sobrien	      && IS_DIR_SEPARATOR (temp[4])
3221132733Skan	      && strncmp (temp + 5, "gcc", 3) == 0)
3222132733Skan	    len -= sizeof ("/lib/gcc/") - 1;
322350599Sobrien	}
322450599Sobrien
322550599Sobrien      set_std_prefix (gcc_exec_prefix, len);
3226132733Skan      add_prefix (&exec_prefixes, gcc_libexec_prefix, "GCC",
3227104763Skan		  PREFIX_PRIORITY_LAST, 0, NULL, 0);
322890277Sobrien      add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC",
3229104763Skan		  PREFIX_PRIORITY_LAST, 0, NULL, 0);
323018334Speter    }
323118334Speter
323218334Speter  /* COMPILER_PATH and LIBRARY_PATH have values
323318334Speter     that are lists of directory names with colons.  */
323418334Speter
3235117413Skan  GET_ENVIRONMENT (temp, "COMPILER_PATH");
323618334Speter  if (temp)
323718334Speter    {
323852520Sobrien      const char *startp, *endp;
3239132733Skan      char *nstore = alloca (strlen (temp) + 3);
324018334Speter
324118334Speter      startp = endp = temp;
324218334Speter      while (1)
324318334Speter	{
324418334Speter	  if (*endp == PATH_SEPARATOR || *endp == 0)
324518334Speter	    {
324690277Sobrien	      strncpy (nstore, startp, endp - startp);
324718334Speter	      if (endp == startp)
324890277Sobrien		strcpy (nstore, concat (".", dir_separator_str, NULL));
324952520Sobrien	      else if (!IS_DIR_SEPARATOR (endp[-1]))
325018334Speter		{
325190277Sobrien		  nstore[endp - startp] = DIR_SEPARATOR;
325290277Sobrien		  nstore[endp - startp + 1] = 0;
325318334Speter		}
325418334Speter	      else
325590277Sobrien		nstore[endp - startp] = 0;
325690277Sobrien	      add_prefix (&exec_prefixes, nstore, 0,
3257104763Skan			  PREFIX_PRIORITY_LAST, 0, NULL, 0);
325850599Sobrien	      add_prefix (&include_prefixes,
325990277Sobrien			  concat (nstore, "include", NULL),
3260104763Skan			  0, PREFIX_PRIORITY_LAST, 0, NULL, 0);
326118334Speter	      if (*endp == 0)
326218334Speter		break;
326318334Speter	      endp = startp = endp + 1;
326418334Speter	    }
326518334Speter	  else
326618334Speter	    endp++;
326718334Speter	}
326818334Speter    }
326918334Speter
3270117413Skan  GET_ENVIRONMENT (temp, LIBRARY_PATH_ENV);
327191651Sobrien  if (temp && *cross_compile == '0')
327218334Speter    {
327352520Sobrien      const char *startp, *endp;
3274132733Skan      char *nstore = alloca (strlen (temp) + 3);
327518334Speter
327618334Speter      startp = endp = temp;
327718334Speter      while (1)
327818334Speter	{
327918334Speter	  if (*endp == PATH_SEPARATOR || *endp == 0)
328018334Speter	    {
328190277Sobrien	      strncpy (nstore, startp, endp - startp);
328218334Speter	      if (endp == startp)
328390277Sobrien		strcpy (nstore, concat (".", dir_separator_str, NULL));
328452520Sobrien	      else if (!IS_DIR_SEPARATOR (endp[-1]))
328518334Speter		{
328690277Sobrien		  nstore[endp - startp] = DIR_SEPARATOR;
328790277Sobrien		  nstore[endp - startp + 1] = 0;
328818334Speter		}
328918334Speter	      else
329090277Sobrien		nstore[endp - startp] = 0;
329190277Sobrien	      add_prefix (&startfile_prefixes, nstore, NULL,
3292104763Skan			  PREFIX_PRIORITY_LAST, 0, NULL, 1);
329318334Speter	      if (*endp == 0)
329418334Speter		break;
329518334Speter	      endp = startp = endp + 1;
329618334Speter	    }
329718334Speter	  else
329818334Speter	    endp++;
329918334Speter	}
330018334Speter    }
330118334Speter
330218334Speter  /* Use LPATH like LIBRARY_PATH (for the CMU build program).  */
3303117413Skan  GET_ENVIRONMENT (temp, "LPATH");
330450599Sobrien  if (temp && *cross_compile == '0')
330518334Speter    {
330652520Sobrien      const char *startp, *endp;
3307132733Skan      char *nstore = alloca (strlen (temp) + 3);
330818334Speter
330918334Speter      startp = endp = temp;
331018334Speter      while (1)
331118334Speter	{
331218334Speter	  if (*endp == PATH_SEPARATOR || *endp == 0)
331318334Speter	    {
331490277Sobrien	      strncpy (nstore, startp, endp - startp);
331518334Speter	      if (endp == startp)
331690277Sobrien		strcpy (nstore, concat (".", dir_separator_str, NULL));
331752520Sobrien	      else if (!IS_DIR_SEPARATOR (endp[-1]))
331818334Speter		{
331990277Sobrien		  nstore[endp - startp] = DIR_SEPARATOR;
332090277Sobrien		  nstore[endp - startp + 1] = 0;
332118334Speter		}
332218334Speter	      else
332390277Sobrien		nstore[endp - startp] = 0;
332490277Sobrien	      add_prefix (&startfile_prefixes, nstore, NULL,
3325104763Skan			  PREFIX_PRIORITY_LAST, 0, NULL, 1);
332618334Speter	      if (*endp == 0)
332718334Speter		break;
332818334Speter	      endp = startp = endp + 1;
332918334Speter	    }
333018334Speter	  else
333118334Speter	    endp++;
333218334Speter	}
333318334Speter    }
333418334Speter
333577389Sobrien  /* Options specified as if they appeared on the command line.  */
333677389Sobrien  temp = getenv ("GCC_OPTIONS");
333777389Sobrien  if ((temp) && (strlen (temp) > 0))
333877389Sobrien    {
333977389Sobrien      int len;
334077389Sobrien      int optc = 1;
334177389Sobrien      int new_argc;
3342110024Sobrien      const char **new_argv;
334377389Sobrien      char *envopts;
334477389Sobrien
334577389Sobrien      while (isspace (*temp))
334677389Sobrien	temp++;
334777389Sobrien      len = strlen (temp);
334877389Sobrien      envopts = (char *) xmalloc (len + 1);
334977389Sobrien      strcpy (envopts, temp);
335077389Sobrien
335177389Sobrien      for (i = 0; i < (len - 1); i++)
335277389Sobrien	if ((isspace (envopts[i])) && ! (isspace (envopts[i+1])))
335377389Sobrien	  optc++;
335477389Sobrien
3355110024Sobrien      new_argv = (const char **) alloca ((optc + argc) * sizeof(char *));
335677389Sobrien
335777389Sobrien      for (i = 0, new_argc = 1; new_argc <= optc; new_argc++)
335877389Sobrien	{
335977389Sobrien	  while (isspace (envopts[i]))
336077389Sobrien	    i++;
336177389Sobrien	  new_argv[new_argc] = envopts + i;
336277389Sobrien	  while (!isspace (envopts[i]) && (envopts[i] != '\0'))
336377389Sobrien	    i++;
336477389Sobrien	  envopts[i++] = '\0';
336577389Sobrien	}
336677389Sobrien      for (i = 1; i < argc; i++)
336777389Sobrien	new_argv[new_argc++] = argv[i];
336877389Sobrien
336977389Sobrien      argv = new_argv;
337077389Sobrien      argc = new_argc;
337177389Sobrien    }
337277389Sobrien
337318334Speter  /* Convert new-style -- options to old-style.  */
3374132733Skan  translate_options (&argc, (const char *const **) &argv);
337518334Speter
337650599Sobrien  /* Do language-specific adjustment/addition of flags.  */
3377132733Skan  lang_specific_driver (&argc, (const char *const **) &argv, &added_libraries);
337850599Sobrien
337918334Speter  /* Scan argv twice.  Here, the first time, just count how many switches
338018334Speter     there will be in their vector, and how many input files in theirs.
338118334Speter     Here we also parse the switches that cc itself uses (e.g. -v).  */
338218334Speter
338318334Speter  for (i = 1; i < argc; i++)
338418334Speter    {
338518334Speter      if (! strcmp (argv[i], "-dumpspecs"))
338618334Speter	{
338750599Sobrien	  struct spec_list *sl;
338850599Sobrien	  init_spec ();
338950599Sobrien	  for (sl = specs; sl; sl = sl->next)
339050599Sobrien	    printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec));
339190277Sobrien	  if (link_command_spec)
339290277Sobrien	    printf ("*link_command:\n%s\n\n", link_command_spec);
339318334Speter	  exit (0);
339418334Speter	}
339518334Speter      else if (! strcmp (argv[i], "-dumpversion"))
339618334Speter	{
339750599Sobrien	  printf ("%s\n", spec_version);
339818334Speter	  exit (0);
339918334Speter	}
340018334Speter      else if (! strcmp (argv[i], "-dumpmachine"))
340118334Speter	{
340218334Speter	  printf ("%s\n", spec_machine);
340390277Sobrien	  exit (0);
340418334Speter	}
340590277Sobrien      else if (strcmp (argv[i], "-fversion") == 0)
340690277Sobrien	{
340790277Sobrien	  /* translate_options () has turned --version into -fversion.  */
340890277Sobrien	  printf (_("%s (GCC) %s\n"), programname, version_string);
3409132733Skan	  printf ("Copyright %s 2004 Free Software Foundation, Inc.\n",
3410132733Skan		  _("(C)"));
341190277Sobrien	  fputs (_("This is free software; see the source for copying conditions.  There is NO\n\
341290277Sobrienwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
341390277Sobrien		 stdout);
341490277Sobrien	  exit (0);
341590277Sobrien	}
341650599Sobrien      else if (strcmp (argv[i], "-fhelp") == 0)
341750599Sobrien	{
341850599Sobrien	  /* translate_options () has turned --help into -fhelp.  */
341950599Sobrien	  print_help_list = 1;
342050599Sobrien
342150599Sobrien	  /* We will be passing a dummy file on to the sub-processes.  */
342250599Sobrien	  n_infiles++;
342350599Sobrien	  n_switches++;
342490277Sobrien
342590277Sobrien	  /* CPP driver cannot obtain switch from cc1_options.  */
342690277Sobrien	  if (is_cpp_driver)
342790277Sobrien	    add_preprocessor_option ("--help", 6);
342850599Sobrien	  add_assembler_option ("--help", 6);
342950599Sobrien	  add_linker_option ("--help", 6);
343050599Sobrien	}
343190277Sobrien      else if (strcmp (argv[i], "-ftarget-help") == 0)
3432117413Skan	{
3433117413Skan	  /* translate_options() has turned --target-help into -ftarget-help.  */
3434117413Skan	  target_help_flag = 1;
343590277Sobrien
3436117413Skan	  /* We will be passing a dummy file on to the sub-processes.  */
3437117413Skan	  n_infiles++;
3438117413Skan	  n_switches++;
343990277Sobrien
344090277Sobrien	  /* CPP driver cannot obtain switch from cc1_options.  */
344190277Sobrien	  if (is_cpp_driver)
344290277Sobrien	    add_preprocessor_option ("--target-help", 13);
3443117413Skan	  add_assembler_option ("--target-help", 13);
3444117413Skan	  add_linker_option ("--target-help", 13);
3445117413Skan	}
344690277Sobrien      else if (! strcmp (argv[i], "-pass-exit-codes"))
344790277Sobrien	{
344890277Sobrien	  pass_exit_codes = 1;
344990277Sobrien	  n_switches++;
345090277Sobrien	}
345118334Speter      else if (! strcmp (argv[i], "-print-search-dirs"))
345218334Speter	print_search_dirs = 1;
345318334Speter      else if (! strcmp (argv[i], "-print-libgcc-file-name"))
345418334Speter	print_file_name = "libgcc.a";
345518334Speter      else if (! strncmp (argv[i], "-print-file-name=", 17))
345618334Speter	print_file_name = argv[i] + 17;
345718334Speter      else if (! strncmp (argv[i], "-print-prog-name=", 17))
345818334Speter	print_prog_name = argv[i] + 17;
345918334Speter      else if (! strcmp (argv[i], "-print-multi-lib"))
346018334Speter	print_multi_lib = 1;
346118334Speter      else if (! strcmp (argv[i], "-print-multi-directory"))
346218334Speter	print_multi_directory = 1;
3463104763Skan      else if (! strcmp (argv[i], "-print-multi-os-directory"))
3464104763Skan	print_multi_os_directory = 1;
346518334Speter      else if (! strncmp (argv[i], "-Wa,", 4))
346618334Speter	{
346718334Speter	  int prev, j;
346818334Speter	  /* Pass the rest of this option to the assembler.  */
346918334Speter
347018334Speter	  /* Split the argument at commas.  */
347118334Speter	  prev = 4;
347218334Speter	  for (j = 4; argv[i][j]; j++)
347318334Speter	    if (argv[i][j] == ',')
347418334Speter	      {
347550599Sobrien		add_assembler_option (argv[i] + prev, j - prev);
347618334Speter		prev = j + 1;
347718334Speter	      }
347890277Sobrien
347918334Speter	  /* Record the part after the last comma.  */
348050599Sobrien	  add_assembler_option (argv[i] + prev, j - prev);
348118334Speter	}
348218334Speter      else if (! strncmp (argv[i], "-Wp,", 4))
348318334Speter	{
348418334Speter	  int prev, j;
348518334Speter	  /* Pass the rest of this option to the preprocessor.  */
348618334Speter
348718334Speter	  /* Split the argument at commas.  */
348818334Speter	  prev = 4;
348918334Speter	  for (j = 4; argv[i][j]; j++)
349018334Speter	    if (argv[i][j] == ',')
349118334Speter	      {
349250599Sobrien		add_preprocessor_option (argv[i] + prev, j - prev);
349318334Speter		prev = j + 1;
349418334Speter	      }
349590277Sobrien
349618334Speter	  /* Record the part after the last comma.  */
349750599Sobrien	  add_preprocessor_option (argv[i] + prev, j - prev);
349818334Speter	}
349918334Speter      else if (argv[i][0] == '+' && argv[i][1] == 'e')
350018334Speter	/* The +e options to the C++ front-end.  */
350118334Speter	n_switches++;
350218334Speter      else if (strncmp (argv[i], "-Wl,", 4) == 0)
350318334Speter	{
350418334Speter	  int j;
350518334Speter	  /* Split the argument at commas.  */
350618334Speter	  for (j = 3; argv[i][j]; j++)
350718334Speter	    n_infiles += (argv[i][j] == ',');
350818334Speter	}
350918334Speter      else if (strcmp (argv[i], "-Xlinker") == 0)
351018334Speter	{
351118334Speter	  if (i + 1 == argc)
351218334Speter	    fatal ("argument to `-Xlinker' is missing");
351318334Speter
351418334Speter	  n_infiles++;
351518334Speter	  i++;
351618334Speter	}
3517132733Skan      else if (strcmp (argv[i], "-Xpreprocessor") == 0)
3518132733Skan	{
3519132733Skan	  if (i + 1 == argc)
3520132733Skan	    fatal ("argument to `-Xpreprocessor' is missing");
3521132733Skan
3522132733Skan	  add_preprocessor_option (argv[i+1], strlen (argv[i+1]));
3523132733Skan	}
3524132733Skan      else if (strcmp (argv[i], "-Xassembler") == 0)
3525132733Skan	{
3526132733Skan	  if (i + 1 == argc)
3527132733Skan	    fatal ("argument to `-Xassembler' is missing");
3528132733Skan
3529132733Skan	  add_assembler_option (argv[i+1], strlen (argv[i+1]));
3530132733Skan	}
353177389Sobrien      else if (strcmp (argv[i], "-l") == 0)
353277389Sobrien	{
353377389Sobrien	  if (i + 1 == argc)
353477389Sobrien	    fatal ("argument to `-l' is missing");
353577389Sobrien
353677389Sobrien	  n_infiles++;
353777389Sobrien	  i++;
353877389Sobrien	}
353918334Speter      else if (strncmp (argv[i], "-l", 2) == 0)
354018334Speter	n_infiles++;
354150599Sobrien      else if (strcmp (argv[i], "-save-temps") == 0)
354250599Sobrien	{
354350599Sobrien	  save_temps_flag = 1;
354450599Sobrien	  n_switches++;
354550599Sobrien	}
354650599Sobrien      else if (strcmp (argv[i], "-specs") == 0)
354750599Sobrien	{
3548132733Skan	  struct user_specs *user = xmalloc (sizeof (struct user_specs));
354950599Sobrien	  if (++i >= argc)
355050599Sobrien	    fatal ("argument to `-specs' is missing");
355150599Sobrien
355290277Sobrien	  user->next = (struct user_specs *) 0;
355350599Sobrien	  user->filename = argv[i];
355450599Sobrien	  if (user_specs_tail)
355550599Sobrien	    user_specs_tail->next = user;
355650599Sobrien	  else
355750599Sobrien	    user_specs_head = user;
355850599Sobrien	  user_specs_tail = user;
355950599Sobrien	}
356050599Sobrien      else if (strncmp (argv[i], "-specs=", 7) == 0)
356150599Sobrien	{
3562132733Skan	  struct user_specs *user = xmalloc (sizeof (struct user_specs));
356350599Sobrien	  if (strlen (argv[i]) == 7)
356450599Sobrien	    fatal ("argument to `-specs=' is missing");
356550599Sobrien
356690277Sobrien	  user->next = (struct user_specs *) 0;
356790277Sobrien	  user->filename = argv[i] + 7;
356850599Sobrien	  if (user_specs_tail)
356950599Sobrien	    user_specs_tail->next = user;
357050599Sobrien	  else
357150599Sobrien	    user_specs_head = user;
357250599Sobrien	  user_specs_tail = user;
357350599Sobrien	}
357490277Sobrien      else if (strcmp (argv[i], "-time") == 0)
357590277Sobrien	report_times = 1;
3576132733Skan      else if (strcmp (argv[i], "-pipe") == 0)
3577132733Skan	{
3578132733Skan	  /* -pipe has to go into the switches array as well as
3579132733Skan	     setting a flag.  */
3580132733Skan	  use_pipes = 1;
3581132733Skan	  n_switches++;
3582132733Skan	}
358390277Sobrien      else if (strcmp (argv[i], "-###") == 0)
358490277Sobrien	{
358590277Sobrien	  /* This is similar to -v except that there is no execution
358690277Sobrien	     of the commands and the echoed arguments are quoted.  It
358790277Sobrien	     is intended for use in shell scripts to capture the
358890277Sobrien	     driver-generated command line.  */
358990277Sobrien	  verbose_only_flag++;
359090277Sobrien	  verbose_flag++;
359190277Sobrien	}
359218334Speter      else if (argv[i][0] == '-' && argv[i][1] != 0)
359318334Speter	{
359490277Sobrien	  const char *p = &argv[i][1];
359590277Sobrien	  int c = *p;
359618334Speter
359718334Speter	  switch (c)
359818334Speter	    {
359918334Speter	    case 'b':
3600117413Skan	    case 'V':
3601117413Skan	      fatal ("`-%c' must come at the start of the command line", c);
360218334Speter	      break;
360318334Speter
360418334Speter	    case 'B':
360518334Speter	      {
360690277Sobrien		const char *value;
360790277Sobrien		int len;
360890277Sobrien
360918334Speter		if (p[1] == 0 && i + 1 == argc)
361018334Speter		  fatal ("argument to `-B' is missing");
361118334Speter		if (p[1] == 0)
361218334Speter		  value = argv[++i];
361318334Speter		else
361418334Speter		  value = p + 1;
361518334Speter
361690277Sobrien		len = strlen (value);
361790277Sobrien
361890277Sobrien		/* Catch the case where the user has forgotten to append a
361990277Sobrien		   directory separator to the path.  Note, they may be using
362090277Sobrien		   -B to add an executable name prefix, eg "i386-elf-", in
362190277Sobrien		   order to distinguish between multiple installations of
362290277Sobrien		   GCC in the same directory.  Hence we must check to see
362390277Sobrien		   if appending a directory separator actually makes a
362490277Sobrien		   valid directory name.  */
362590277Sobrien		if (! IS_DIR_SEPARATOR (value [len - 1])
362690277Sobrien		    && is_directory (value, "", 0))
362790277Sobrien		  {
362890277Sobrien		    char *tmp = xmalloc (len + 2);
362990277Sobrien		    strcpy (tmp, value);
363090277Sobrien		    tmp[len] = DIR_SEPARATOR;
363190277Sobrien		    tmp[++ len] = 0;
363290277Sobrien		    value = tmp;
363390277Sobrien		  }
3634117413Skan
363590277Sobrien		/* As a kludge, if the arg is "[foo/]stageN/", just
363690277Sobrien		   add "[foo/]include" to the include prefix.  */
363790277Sobrien		if ((len == 7
363890277Sobrien		     || (len > 7
363990277Sobrien			 && (IS_DIR_SEPARATOR (value[len - 8]))))
364090277Sobrien		    && strncmp (value + len - 7, "stage", 5) == 0
364190277Sobrien		    && ISDIGIT (value[len - 2])
364290277Sobrien		    && (IS_DIR_SEPARATOR (value[len - 1])))
364390277Sobrien		  {
364490277Sobrien		    if (len == 7)
364590277Sobrien		      add_prefix (&include_prefixes, "include", NULL,
3646104763Skan				  PREFIX_PRIORITY_B_OPT, 0, NULL, 0);
364790277Sobrien		    else
364890277Sobrien		      {
364990277Sobrien			char * string = xmalloc (len + 1);
365090277Sobrien
365190277Sobrien			strncpy (string, value, len - 7);
365290277Sobrien			strcpy (string + len - 7, "include");
365390277Sobrien			add_prefix (&include_prefixes, string, NULL,
3654104763Skan				    PREFIX_PRIORITY_B_OPT, 0, NULL, 0);
365590277Sobrien		      }
365690277Sobrien		  }
365790277Sobrien
365890277Sobrien		add_prefix (&exec_prefixes, value, NULL,
3659104763Skan			    PREFIX_PRIORITY_B_OPT, 0, &warn_B, 0);
366090277Sobrien		add_prefix (&startfile_prefixes, value, NULL,
3661104763Skan			    PREFIX_PRIORITY_B_OPT, 0, &warn_B, 0);
366290277Sobrien		add_prefix (&include_prefixes, concat (value, "include", NULL),
3663104763Skan			    NULL, PREFIX_PRIORITY_B_OPT, 0, NULL, 0);
366490277Sobrien		n_switches++;
366518334Speter	      }
366618334Speter	      break;
366718334Speter
366818334Speter	    case 'v':	/* Print our subcommands and print versions.  */
366918334Speter	      n_switches++;
367018334Speter	      /* If they do anything other than exactly `-v', don't set
367118334Speter		 verbose_flag; rather, continue on to give the error.  */
367218334Speter	      if (p[1] != 0)
367318334Speter		break;
367418334Speter	      verbose_flag++;
367518334Speter	      break;
367618334Speter
367750599Sobrien	    case 'S':
367850599Sobrien	    case 'c':
367950599Sobrien	      if (p[1] == 0)
368018334Speter		{
368150599Sobrien		  have_c = 1;
368218334Speter		  n_switches++;
368318334Speter		  break;
368418334Speter		}
368550599Sobrien	      goto normal_switch;
368650599Sobrien
368750599Sobrien	    case 'o':
368850599Sobrien	      have_o = 1;
368990277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
369050599Sobrien	      if (! have_c)
369150599Sobrien		{
369250599Sobrien		  int skip;
369390277Sobrien
369450599Sobrien		  /* Forward scan, just in case -S or -c is specified
369550599Sobrien		     after -o.  */
369650599Sobrien		  int j = i + 1;
369750599Sobrien		  if (p[1] == 0)
369850599Sobrien		    ++j;
369950599Sobrien		  while (j < argc)
370050599Sobrien		    {
370150599Sobrien		      if (argv[j][0] == '-')
370250599Sobrien			{
370350599Sobrien			  if (SWITCH_CURTAILS_COMPILATION (argv[j][1])
370450599Sobrien			      && argv[j][2] == 0)
370550599Sobrien			    {
370650599Sobrien			      have_c = 1;
370750599Sobrien			      break;
370850599Sobrien			    }
370990277Sobrien			  else if ((skip = SWITCH_TAKES_ARG (argv[j][1])))
371050599Sobrien			    j += skip - (argv[j][2] != 0);
371190277Sobrien			  else if ((skip = WORD_SWITCH_TAKES_ARG (argv[j] + 1)))
371250599Sobrien			    j += skip;
371350599Sobrien			}
371450599Sobrien		      j++;
371550599Sobrien		    }
371650599Sobrien		}
371750599Sobrien#endif
371890277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX)
371950599Sobrien	      if (p[1] == 0)
372090277Sobrien		argv[i + 1] = convert_filename (argv[i + 1], ! have_c, 0);
372150599Sobrien	      else
372290277Sobrien		argv[i] = convert_filename (argv[i], ! have_c, 0);
372350599Sobrien#endif
372450599Sobrien	      goto normal_switch;
372550599Sobrien
372618334Speter	    default:
372750599Sobrien	    normal_switch:
372890277Sobrien
372990277Sobrien#ifdef MODIFY_TARGET_NAME
373090277Sobrien	      is_modify_target_name = 0;
373190277Sobrien
3732117413Skan	      for (j = 0; j < ARRAY_SIZE (modify_target); j++)
373390277Sobrien		if (! strcmp (argv[i], modify_target[j].sw))
373490277Sobrien		  {
3735132733Skan		    char *new_name = xmalloc (strlen (modify_target[j].str)
3736132733Skan					      + strlen (spec_machine));
373790277Sobrien		    const char *p, *r;
373890277Sobrien		    char *q;
373990277Sobrien		    int made_addition = 0;
374090277Sobrien
374190277Sobrien		    is_modify_target_name = 1;
374290277Sobrien		    for (p = spec_machine, q = new_name; *p != 0; )
374390277Sobrien		      {
374490277Sobrien			if (modify_target[j].add_del == DELETE
374590277Sobrien			    && (! strncmp (q, modify_target[j].str,
374690277Sobrien					   strlen (modify_target[j].str))))
374790277Sobrien			  p += strlen (modify_target[j].str);
374890277Sobrien			else if (modify_target[j].add_del == ADD
374990277Sobrien				 && ! made_addition && *p == '-')
375090277Sobrien			  {
375190277Sobrien			    for (r = modify_target[j].str; *r != 0; )
375290277Sobrien			      *q++ = *r++;
375390277Sobrien			    made_addition = 1;
375490277Sobrien			  }
375590277Sobrien
375690277Sobrien			*q++ = *p++;
375790277Sobrien		      }
375890277Sobrien
375990277Sobrien		    spec_machine = new_name;
376090277Sobrien		  }
376190277Sobrien
376290277Sobrien	      if (is_modify_target_name)
376390277Sobrien		break;
3764117413Skan#endif
376590277Sobrien
376618334Speter	      n_switches++;
376718334Speter
376818334Speter	      if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
376918334Speter		i += SWITCH_TAKES_ARG (c) - (p[1] != 0);
377018334Speter	      else if (WORD_SWITCH_TAKES_ARG (p))
377118334Speter		i += WORD_SWITCH_TAKES_ARG (p);
377218334Speter	    }
377318334Speter	}
377418334Speter      else
377550599Sobrien	{
377650599Sobrien	  n_infiles++;
377750599Sobrien	  lang_n_infiles++;
377850599Sobrien	}
377918334Speter    }
378018334Speter
3781132733Skan  combine_inputs = (have_c && have_o && lang_n_infiles > 1);
378250599Sobrien
3783132733Skan  if ((save_temps_flag || report_times) && use_pipes)
3784132733Skan    {
3785132733Skan      /* -save-temps overrides -pipe, so that temp files are produced */
3786132733Skan      if (save_temps_flag)
3787132733Skan	error ("warning: -pipe ignored because -save-temps specified");
3788132733Skan      /* -time overrides -pipe because we can't get correct stats when
3789132733Skan	 multiple children are running at once.  */
3790132733Skan      else if (report_times)
3791132733Skan	error ("warning: -pipe ignored because -time specified");
3792132733Skan
3793132733Skan      use_pipes = 0;
3794132733Skan    }
3795132733Skan
379618334Speter  /* Set up the search paths before we go looking for config files.  */
379718334Speter
379818334Speter  /* These come before the md prefixes so that we will find gcc's subcommands
379918334Speter     (such as cpp) rather than those of the host system.  */
380018334Speter  /* Use 2 as fourth arg meaning try just the machine as a suffix,
380118334Speter     as well as trying the machine and the version.  */
380218346Speter#ifdef FREEBSD_NATIVE
3803104953Sobrien      add_prefix (&exec_prefixes, PREFIX"/bin/", "BINUTILS",
3804122632Skan		  PREFIX_PRIORITY_LAST, 0, warn_std_ptr, 0);
380591561Sobrien#endif	/* FREEBSD_NATIVE */
380618334Speter#ifndef OS2
3807132733Skan  add_prefix (&exec_prefixes, standard_libexec_prefix, "GCC",
3808104763Skan	      PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0);
3809132733Skan  add_prefix (&exec_prefixes, standard_libexec_prefix, "BINUTILS",
3810132733Skan	      PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0);
3811132733Skan#ifndef FREEBSD_NATIVE
381250599Sobrien  add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS",
3813104763Skan	      PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0);
381450599Sobrien  add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS",
3815104763Skan	      PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0);
3816132733Skan  add_prefix (&exec_prefixes, standard_exec_prefix_2, "BINUTILS",
3817132733Skan	      PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0);
3818132733Skan#endif	/* FREEBSD_NATIVE */
381918334Speter#endif
382018334Speter
382191578Sobrien#ifndef FREEBSD_NATIVE
382250599Sobrien  add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS",
3823104763Skan	      PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0);
3824132733Skan  add_prefix (&startfile_prefixes, standard_exec_prefix_2, "BINUTILS",
3825104763Skan	      PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0);
382691561Sobrien#endif	/* not FREEBSD_NATIVE */
382718334Speter
382890277Sobrien  tooldir_prefix = concat (tooldir_base_prefix, spec_machine,
382990277Sobrien			   dir_separator_str, NULL);
383018334Speter
383118334Speter  /* If tooldir is relative, base it on exec_prefixes.  A relative
383218334Speter     tooldir lets us move the installed tree as a unit.
383318334Speter
383418334Speter     If GCC_EXEC_PREFIX is defined, then we want to add two relative
383518334Speter     directories, so that we can search both the user specified directory
383618334Speter     and the standard place.  */
383718334Speter
3838132733Skan  if (!IS_ABSOLUTE_PATH (tooldir_prefix))
383918334Speter    {
384018334Speter      if (gcc_exec_prefix)
384118334Speter	{
384218334Speter	  char *gcc_exec_tooldir_prefix
384350599Sobrien	    = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
384490277Sobrien		      spec_version, dir_separator_str, tooldir_prefix, NULL);
384518334Speter
384618334Speter	  add_prefix (&exec_prefixes,
384790277Sobrien		      concat (gcc_exec_tooldir_prefix, "bin",
384890277Sobrien			      dir_separator_str, NULL),
3849104763Skan		      NULL, PREFIX_PRIORITY_LAST, 0, NULL, 0);
385018334Speter	  add_prefix (&startfile_prefixes,
385190277Sobrien		      concat (gcc_exec_tooldir_prefix, "lib",
385290277Sobrien			      dir_separator_str, NULL),
3853104763Skan		      NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1);
385418334Speter	}
385518334Speter
385650599Sobrien      tooldir_prefix = concat (standard_exec_prefix, spec_machine,
385790277Sobrien			       dir_separator_str, spec_version,
385890277Sobrien			       dir_separator_str, tooldir_prefix, NULL);
385918334Speter    }
386018334Speter
386118346Speter#ifndef FREEBSD_NATIVE
386290277Sobrien  add_prefix (&exec_prefixes,
386390277Sobrien	      concat (tooldir_prefix, "bin", dir_separator_str, NULL),
3864104763Skan	      "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 0);
386518334Speter  add_prefix (&startfile_prefixes,
386690277Sobrien	      concat (tooldir_prefix, "lib", dir_separator_str, NULL),
3867104763Skan	      "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1);
3868132733Skan
3869132733Skan#if defined(TARGET_SYSTEM_ROOT_RELOCATABLE) && !defined(VMS)
3870132733Skan  /* If the normal TARGET_SYSTEM_ROOT is inside of $exec_prefix,
3871132733Skan     then consider it to relocate with the rest of the GCC installation
3872132733Skan     if GCC_EXEC_PREFIX is set.
3873132733Skan     ``make_relative_prefix'' is not compiled for VMS, so don't call it.  */
3874132733Skan  if (target_system_root && gcc_exec_prefix)
3875132733Skan    {
3876132733Skan      char *tmp_prefix = make_relative_prefix (argv[0],
3877132733Skan					       standard_bindir_prefix,
3878132733Skan					       target_system_root);
3879132733Skan      if (tmp_prefix && access_check (tmp_prefix, F_OK) == 0)
3880132733Skan	{
3881132733Skan	  target_system_root = tmp_prefix;
3882132733Skan	  target_system_root_changed = 1;
3883132733Skan	}
3884132733Skan    }
3885132733Skan#endif
388618346Speter#endif /* FREEBSD_NATIVE */
388718334Speter
388818334Speter  /* More prefixes are enabled in main, after we read the specs file
388918334Speter     and determine whether this is cross-compilation or not.  */
389018334Speter
389118334Speter  /* Then create the space for the vectors and scan again.  */
389218334Speter
3893132733Skan  switches = xmalloc ((n_switches + 1) * sizeof (struct switchstr));
3894132733Skan  infiles = xmalloc ((n_infiles + 1) * sizeof (struct infile));
389518334Speter  n_switches = 0;
389618334Speter  n_infiles = 0;
389718334Speter  last_language_n_infiles = -1;
389818334Speter
389918334Speter  /* This, time, copy the text of each switch and store a pointer
390018334Speter     to the copy in the vector of switches.
390118334Speter     Store all the infiles in their vector.  */
390218334Speter
390318334Speter  for (i = 1; i < argc; i++)
390418334Speter    {
390518334Speter      /* Just skip the switches that were handled by the preceding loop.  */
390690277Sobrien#ifdef MODIFY_TARGET_NAME
390790277Sobrien      is_modify_target_name = 0;
390890277Sobrien
3909117413Skan      for (j = 0; j < ARRAY_SIZE (modify_target); j++)
391090277Sobrien	if (! strcmp (argv[i], modify_target[j].sw))
391190277Sobrien	  is_modify_target_name = 1;
391290277Sobrien
391390277Sobrien      if (is_modify_target_name)
391490277Sobrien	;
391590277Sobrien      else
391690277Sobrien#endif
391718334Speter      if (! strncmp (argv[i], "-Wa,", 4))
391818334Speter	;
391918334Speter      else if (! strncmp (argv[i], "-Wp,", 4))
392018334Speter	;
392190277Sobrien      else if (! strcmp (argv[i], "-pass-exit-codes"))
392290277Sobrien	;
392318334Speter      else if (! strcmp (argv[i], "-print-search-dirs"))
392418334Speter	;
392518334Speter      else if (! strcmp (argv[i], "-print-libgcc-file-name"))
392618334Speter	;
392718334Speter      else if (! strncmp (argv[i], "-print-file-name=", 17))
392818334Speter	;
392918334Speter      else if (! strncmp (argv[i], "-print-prog-name=", 17))
393018334Speter	;
393118334Speter      else if (! strcmp (argv[i], "-print-multi-lib"))
393218334Speter	;
393318334Speter      else if (! strcmp (argv[i], "-print-multi-directory"))
393418334Speter	;
3935104763Skan      else if (! strcmp (argv[i], "-print-multi-os-directory"))
3936104763Skan	;
393790277Sobrien      else if (! strcmp (argv[i], "-ftarget-help"))
393890277Sobrien	;
393990277Sobrien      else if (! strcmp (argv[i], "-fhelp"))
394090277Sobrien	;
394118334Speter      else if (argv[i][0] == '+' && argv[i][1] == 'e')
394218334Speter	{
394318334Speter	  /* Compensate for the +e options to the C++ front-end;
394418334Speter	     they're there simply for cfront call-compatibility.  We do
394518334Speter	     some magic in default_compilers to pass them down properly.
394618334Speter	     Note we deliberately start at the `+' here, to avoid passing
394718334Speter	     -e0 or -e1 down into the linker.  */
394818334Speter	  switches[n_switches].part1 = &argv[i][0];
394918334Speter	  switches[n_switches].args = 0;
395090277Sobrien	  switches[n_switches].live_cond = SWITCH_OK;
395152520Sobrien	  switches[n_switches].validated = 0;
395218334Speter	  n_switches++;
395318334Speter	}
395418334Speter      else if (strncmp (argv[i], "-Wl,", 4) == 0)
395518334Speter	{
395618334Speter	  int prev, j;
395718334Speter	  /* Split the argument at commas.  */
395818334Speter	  prev = 4;
395918334Speter	  for (j = 4; argv[i][j]; j++)
396018334Speter	    if (argv[i][j] == ',')
396118334Speter	      {
396250599Sobrien		infiles[n_infiles].language = "*";
396318334Speter		infiles[n_infiles++].name
396418334Speter		  = save_string (argv[i] + prev, j - prev);
396518334Speter		prev = j + 1;
396618334Speter	      }
396718334Speter	  /* Record the part after the last comma.  */
396850599Sobrien	  infiles[n_infiles].language = "*";
396918334Speter	  infiles[n_infiles++].name = argv[i] + prev;
397018334Speter	}
397118334Speter      else if (strcmp (argv[i], "-Xlinker") == 0)
397218334Speter	{
397350599Sobrien	  infiles[n_infiles].language = "*";
397418334Speter	  infiles[n_infiles++].name = argv[++i];
397518334Speter	}
3976132733Skan      else if (strcmp (argv[i], "-Xassembler") == 0)
3977132733Skan	{
3978132733Skan	  infiles[n_infiles].language = "*";
3979132733Skan	  infiles[n_infiles++].name = argv[++i];
3980132733Skan	}
3981132733Skan      else if (strcmp (argv[i], "-Xpreprocessor") == 0)
3982132733Skan	{
3983132733Skan	  infiles[n_infiles].language = "*";
3984132733Skan	  infiles[n_infiles++].name = argv[++i];
3985132733Skan	}
398677389Sobrien      else if (strcmp (argv[i], "-l") == 0)
398777389Sobrien	{ /* POSIX allows separation of -l and the lib arg;
398877389Sobrien	     canonicalize by concatenating -l with its arg */
398977389Sobrien	  infiles[n_infiles].language = "*";
399077389Sobrien	  infiles[n_infiles++].name = concat ("-l", argv[++i], NULL);
399177389Sobrien	}
399218334Speter      else if (strncmp (argv[i], "-l", 2) == 0)
399318334Speter	{
399450599Sobrien	  infiles[n_infiles].language = "*";
399518334Speter	  infiles[n_infiles++].name = argv[i];
399618334Speter	}
399750599Sobrien      else if (strcmp (argv[i], "-specs") == 0)
399850599Sobrien	i++;
399950599Sobrien      else if (strncmp (argv[i], "-specs=", 7) == 0)
400050599Sobrien	;
400190277Sobrien      else if (strcmp (argv[i], "-time") == 0)
400290277Sobrien	;
400390277Sobrien      else if (strcmp (argv[i], "-###") == 0)
400490277Sobrien	;
400518334Speter      else if (argv[i][0] == '-' && argv[i][1] != 0)
400618334Speter	{
400790277Sobrien	  const char *p = &argv[i][1];
400890277Sobrien	  int c = *p;
400918334Speter
401018334Speter	  if (c == 'x')
401118334Speter	    {
401218334Speter	      if (p[1] == 0 && i + 1 == argc)
401318334Speter		fatal ("argument to `-x' is missing");
401418334Speter	      if (p[1] == 0)
401518334Speter		spec_lang = argv[++i];
401618334Speter	      else
401718334Speter		spec_lang = p + 1;
401818334Speter	      if (! strcmp (spec_lang, "none"))
401918334Speter		/* Suppress the warning if -xnone comes after the last input
402018334Speter		   file, because alternate command interfaces like g++ might
402118334Speter		   find it useful to place -xnone after each input file.  */
402218334Speter		spec_lang = 0;
402318334Speter	      else
402418334Speter		last_language_n_infiles = n_infiles;
402518334Speter	      continue;
402618334Speter	    }
402718334Speter	  switches[n_switches].part1 = p;
402818334Speter	  /* Deal with option arguments in separate argv elements.  */
402918334Speter	  if ((SWITCH_TAKES_ARG (c) > (p[1] != 0))
403018334Speter	      || WORD_SWITCH_TAKES_ARG (p))
403118334Speter	    {
403218334Speter	      int j = 0;
403318334Speter	      int n_args = WORD_SWITCH_TAKES_ARG (p);
403418334Speter
403518334Speter	      if (n_args == 0)
403618334Speter		{
403718334Speter		  /* Count only the option arguments in separate argv elements.  */
403818334Speter		  n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0);
403918334Speter		}
404018334Speter	      if (i + n_args >= argc)
404118334Speter		fatal ("argument to `-%s' is missing", p);
404218334Speter	      switches[n_switches].args
4043132733Skan		= xmalloc ((n_args + 1) * sizeof(const char *));
404418334Speter	      while (j < n_args)
404518334Speter		switches[n_switches].args[j++] = argv[++i];
404618334Speter	      /* Null-terminate the vector.  */
404718334Speter	      switches[n_switches].args[j] = 0;
404818334Speter	    }
404990277Sobrien	  else if (strchr (switches_need_spaces, c))
405018334Speter	    {
405150599Sobrien	      /* On some systems, ld cannot handle some options without
405250599Sobrien		 a space.  So split the option from its argument.  */
4053132733Skan	      char *part1 = xmalloc (2);
405450599Sobrien	      part1[0] = c;
405550599Sobrien	      part1[1] = '\0';
405690277Sobrien
405750599Sobrien	      switches[n_switches].part1 = part1;
4058132733Skan	      switches[n_switches].args = xmalloc (2 * sizeof (const char *));
405990277Sobrien	      switches[n_switches].args[0] = xstrdup (p+1);
406018334Speter	      switches[n_switches].args[1] = 0;
406118334Speter	    }
406218334Speter	  else
406318334Speter	    switches[n_switches].args = 0;
406418334Speter
406590277Sobrien	  switches[n_switches].live_cond = SWITCH_OK;
406652520Sobrien	  switches[n_switches].validated = 0;
406790277Sobrien	  switches[n_switches].ordering = 0;
4068132733Skan	  /* These are always valid, since gcc.c itself understands them.  */
406990277Sobrien	  if (!strcmp (p, "save-temps")
407090277Sobrien	      || !strcmp (p, "static-libgcc")
4071132733Skan	      || !strcmp (p, "shared-libgcc")
4072132733Skan	      || !strcmp (p, "pipe"))
407352520Sobrien	    switches[n_switches].validated = 1;
407490277Sobrien	  else
407590277Sobrien	    {
407690277Sobrien	      char ch = switches[n_switches].part1[0];
4077117413Skan	      if (ch == 'B')
407890277Sobrien		switches[n_switches].validated = 1;
407990277Sobrien	    }
408018334Speter	  n_switches++;
408118334Speter	}
408218334Speter      else
408318334Speter	{
408490277Sobrien#ifdef HAVE_TARGET_OBJECT_SUFFIX
408590277Sobrien	  argv[i] = convert_filename (argv[i], 0, access (argv[i], F_OK));
408618334Speter#endif
408718334Speter
408890277Sobrien	  if (strcmp (argv[i], "-") != 0 && access (argv[i], F_OK) < 0)
408918334Speter	    {
409018334Speter	      perror_with_name (argv[i]);
409118334Speter	      error_count++;
409218334Speter	    }
409318334Speter	  else
409418334Speter	    {
409518334Speter	      infiles[n_infiles].language = spec_lang;
409618334Speter	      infiles[n_infiles++].name = argv[i];
409718334Speter	    }
409818334Speter	}
409918334Speter    }
410018334Speter
410118334Speter  if (n_infiles == last_language_n_infiles && spec_lang != 0)
410290277Sobrien    error ("warning: `-x %s' after last input file has no effect", spec_lang);
410318334Speter
410490277Sobrien  /* Ensure we only invoke each subprocess once.  */
410590277Sobrien  if (target_help_flag || print_help_list)
410690277Sobrien    {
410790277Sobrien      n_infiles = 1;
410890277Sobrien
410990277Sobrien      /* Create a dummy input file, so that we can pass --target-help on to
411090277Sobrien	 the various sub-processes.  */
411190277Sobrien      infiles[0].language = "c";
411290277Sobrien      infiles[0].name   = "help-dummy";
411390277Sobrien
411490277Sobrien      if (target_help_flag)
411590277Sobrien	{
411690277Sobrien	  switches[n_switches].part1     = "--target-help";
411790277Sobrien	  switches[n_switches].args      = 0;
411890277Sobrien	  switches[n_switches].live_cond = SWITCH_OK;
411990277Sobrien	  switches[n_switches].validated = 0;
412090277Sobrien
412190277Sobrien	  n_switches++;
412290277Sobrien	}
412390277Sobrien
412490277Sobrien      if (print_help_list)
412590277Sobrien	{
412690277Sobrien	  switches[n_switches].part1     = "--help";
412790277Sobrien	  switches[n_switches].args      = 0;
412890277Sobrien	  switches[n_switches].live_cond = SWITCH_OK;
412990277Sobrien	  switches[n_switches].validated = 0;
413090277Sobrien
413190277Sobrien	  n_switches++;
413290277Sobrien	}
413390277Sobrien    }
413490277Sobrien
413518334Speter  switches[n_switches].part1 = 0;
413618334Speter  infiles[n_infiles].name = 0;
413718334Speter}
413890277Sobrien
4139132733Skan/* Store switches not filtered out by %<S in spec in COLLECT_GCC_OPTIONS
414090277Sobrien   and place that in the environment.  */
414190277Sobrien
414290277Sobrienstatic void
4143132733Skanset_collect_gcc_options (void)
414490277Sobrien{
414590277Sobrien  int i;
414690277Sobrien  int first_time;
414790277Sobrien
414890277Sobrien  /* Build COLLECT_GCC_OPTIONS to have all of the options specified to
414990277Sobrien     the compiler.  */
415090277Sobrien  obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
415190277Sobrien		sizeof ("COLLECT_GCC_OPTIONS=") - 1);
415290277Sobrien
415390277Sobrien  first_time = TRUE;
415490277Sobrien  for (i = 0; (int) i < n_switches; i++)
415590277Sobrien    {
415690277Sobrien      const char *const *args;
415790277Sobrien      const char *p, *q;
415890277Sobrien      if (!first_time)
415990277Sobrien	obstack_grow (&collect_obstack, " ", 1);
416090277Sobrien
416190277Sobrien      first_time = FALSE;
416290277Sobrien
416390277Sobrien      /* Ignore elided switches.  */
416490277Sobrien      if (switches[i].live_cond == SWITCH_IGNORE)
416590277Sobrien	continue;
416690277Sobrien
416790277Sobrien      obstack_grow (&collect_obstack, "'-", 2);
416890277Sobrien      q = switches[i].part1;
416990277Sobrien      while ((p = strchr (q, '\'')))
417090277Sobrien	{
417190277Sobrien	  obstack_grow (&collect_obstack, q, p - q);
417290277Sobrien	  obstack_grow (&collect_obstack, "'\\''", 4);
417390277Sobrien	  q = ++p;
417490277Sobrien	}
417590277Sobrien      obstack_grow (&collect_obstack, q, strlen (q));
417690277Sobrien      obstack_grow (&collect_obstack, "'", 1);
417790277Sobrien
417890277Sobrien      for (args = switches[i].args; args && *args; args++)
417990277Sobrien	{
418090277Sobrien	  obstack_grow (&collect_obstack, " '", 2);
418190277Sobrien	  q = *args;
418290277Sobrien	  while ((p = strchr (q, '\'')))
418390277Sobrien	    {
418490277Sobrien	      obstack_grow (&collect_obstack, q, p - q);
418590277Sobrien	      obstack_grow (&collect_obstack, "'\\''", 4);
418690277Sobrien	      q = ++p;
418790277Sobrien	    }
418890277Sobrien	  obstack_grow (&collect_obstack, q, strlen (q));
418990277Sobrien	  obstack_grow (&collect_obstack, "'", 1);
419090277Sobrien	}
419190277Sobrien    }
419290277Sobrien  obstack_grow (&collect_obstack, "\0", 1);
419390277Sobrien  putenv (obstack_finish (&collect_obstack));
419490277Sobrien}
419518334Speter
419618334Speter/* Process a spec string, accumulating and running commands.  */
419718334Speter
419818334Speter/* These variables describe the input file name.
419918334Speter   input_file_number is the index on outfiles of this file,
420018334Speter   so that the output file name can be stored for later use by %o.
420118334Speter   input_basename is the start of the part of the input file
420218334Speter   sans all directory names, and basename_length is the number
420318334Speter   of characters starting there excluding the suffix .c or whatever.  */
420418334Speter
4205132733Skanstatic const char *input_filename;
420618334Speterstatic int input_file_number;
420750599Sobriensize_t input_filename_length;
420818334Speterstatic int basename_length;
420990277Sobrienstatic int suffixed_basename_length;
421052520Sobrienstatic const char *input_basename;
421152520Sobrienstatic const char *input_suffix;
421290277Sobrienstatic struct stat input_stat;
421390277Sobrienstatic int input_stat_set;
421418334Speter
421590277Sobrien/* The compiler used to process the current input file.  */
421690277Sobrienstatic struct compiler *input_file_compiler;
421790277Sobrien
421818334Speter/* These are variables used within do_spec and do_spec_1.  */
421918334Speter
422018334Speter/* Nonzero if an arg has been started and not yet terminated
422118334Speter   (with space, tab or newline).  */
422218334Speterstatic int arg_going;
422318334Speter
422418334Speter/* Nonzero means %d or %g has been seen; the next arg to be terminated
422518334Speter   is a temporary file name.  */
422618334Speterstatic int delete_this_arg;
422718334Speter
422818334Speter/* Nonzero means %w has been seen; the next arg to be terminated
422918334Speter   is the output file name of this compilation.  */
423018334Speterstatic int this_is_output_file;
423118334Speter
423218334Speter/* Nonzero means %s has been seen; the next arg to be terminated
423318334Speter   is the name of a library file and we should try the standard
423418334Speter   search dirs for it.  */
423518334Speterstatic int this_is_library_file;
423618334Speter
423718334Speter/* Nonzero means that the input of this command is coming from a pipe.  */
423818334Speterstatic int input_from_pipe;
423918334Speter
424090277Sobrien/* Nonnull means substitute this for any suffix when outputting a switches
424190277Sobrien   arguments.  */
424290277Sobrienstatic const char *suffix_subst;
424390277Sobrien
424418334Speter/* Process the spec SPEC and run the commands specified therein.
424518334Speter   Returns 0 if the spec is successfully processed; -1 if failed.  */
424618334Speter
424750599Sobrienint
4248132733Skando_spec (const char *spec)
424918334Speter{
425018334Speter  int value;
425118334Speter
4252117413Skan  value = do_spec_2 (spec);
425318334Speter
425418334Speter  /* Force out any unfinished command.
425518334Speter     If -pipe, this forces out the last command if it ended in `|'.  */
425618334Speter  if (value == 0)
425718334Speter    {
425818334Speter      if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
425918334Speter	argbuf_index--;
426018334Speter
426190277Sobrien      set_collect_gcc_options ();
426290277Sobrien
426318334Speter      if (argbuf_index > 0)
426418334Speter	value = execute ();
426518334Speter    }
426618334Speter
426718334Speter  return value;
426818334Speter}
426918334Speter
4270117413Skanstatic int
4271132733Skando_spec_2 (const char *spec)
4272117413Skan{
4273132733Skan  const char *string;
4274132733Skan  int result;
4275132733Skan
4276117413Skan  clear_args ();
4277117413Skan  arg_going = 0;
4278117413Skan  delete_this_arg = 0;
4279117413Skan  this_is_output_file = 0;
4280117413Skan  this_is_library_file = 0;
4281117413Skan  input_from_pipe = 0;
4282117413Skan  suffix_subst = NULL;
4283117413Skan
4284132733Skan  result = do_spec_1 (spec, 0, NULL);
4285132733Skan
4286132733Skan  /* End any pending argument.  */
4287132733Skan  if (arg_going)
4288132733Skan    {
4289132733Skan      obstack_1grow (&obstack, 0);
4290132733Skan      string = obstack_finish (&obstack);
4291132733Skan      if (this_is_library_file)
4292132733Skan	string = find_file (string);
4293132733Skan      store_arg (string, delete_this_arg, this_is_output_file);
4294132733Skan      if (this_is_output_file)
4295132733Skan	outfiles[input_file_number] = string;
4296132733Skan      arg_going = 0;
4297132733Skan    }
4298132733Skan
4299132733Skan  return result;
4300117413Skan}
4301117413Skan
4302117413Skan
4303117413Skan/* Process the given spec string and add any new options to the end
4304117413Skan   of the switches/n_switches array.  */
4305117413Skan
4306117413Skanstatic void
4307132733Skando_option_spec (const char *name, const char *spec)
4308117413Skan{
4309132733Skan  unsigned int i, value_count, value_len;
4310132733Skan  const char *p, *q, *value;
4311132733Skan  char *tmp_spec, *tmp_spec_p;
4312132733Skan
4313132733Skan  if (configure_default_options[0].name == NULL)
4314132733Skan    return;
4315132733Skan
4316132733Skan  for (i = 0; i < ARRAY_SIZE (configure_default_options); i++)
4317132733Skan    if (strcmp (configure_default_options[i].name, name) == 0)
4318132733Skan      break;
4319132733Skan  if (i == ARRAY_SIZE (configure_default_options))
4320132733Skan    return;
4321132733Skan
4322132733Skan  value = configure_default_options[i].value;
4323132733Skan  value_len = strlen (value);
4324132733Skan
4325132733Skan  /* Compute the size of the final spec.  */
4326132733Skan  value_count = 0;
4327132733Skan  p = spec;
4328132733Skan  while ((p = strstr (p, "%(VALUE)")) != NULL)
4329132733Skan    {
4330132733Skan      p ++;
4331132733Skan      value_count ++;
4332132733Skan    }
4333132733Skan
4334132733Skan  /* Replace each %(VALUE) by the specified value.  */
4335132733Skan  tmp_spec = alloca (strlen (spec) + 1
4336132733Skan		     + value_count * (value_len - strlen ("%(VALUE)")));
4337132733Skan  tmp_spec_p = tmp_spec;
4338132733Skan  q = spec;
4339132733Skan  while ((p = strstr (q, "%(VALUE)")) != NULL)
4340132733Skan    {
4341132733Skan      memcpy (tmp_spec_p, q, p - q);
4342132733Skan      tmp_spec_p = tmp_spec_p + (p - q);
4343132733Skan      memcpy (tmp_spec_p, value, value_len);
4344132733Skan      tmp_spec_p += value_len;
4345132733Skan      q = p + strlen ("%(VALUE)");
4346132733Skan    }
4347132733Skan  strcpy (tmp_spec_p, q);
4348132733Skan
4349132733Skan  do_self_spec (tmp_spec);
4350132733Skan}
4351132733Skan
4352132733Skan/* Process the given spec string and add any new options to the end
4353132733Skan   of the switches/n_switches array.  */
4354132733Skan
4355132733Skanstatic void
4356132733Skando_self_spec (const char *spec)
4357132733Skan{
4358117413Skan  do_spec_2 (spec);
4359117413Skan  do_spec_1 (" ", 0, NULL);
4360117413Skan
4361117413Skan  if (argbuf_index > 0)
4362117413Skan    {
4363117413Skan      int i, first;
4364117413Skan
4365117413Skan      first = n_switches;
4366117413Skan      n_switches += argbuf_index;
4367117413Skan      switches = xrealloc (switches,
4368117413Skan			   sizeof (struct switchstr) * (n_switches + 1));
4369117413Skan
4370117413Skan      switches[n_switches] = switches[first];
4371117413Skan      for (i = 0; i < argbuf_index; i++)
4372117413Skan	{
4373117413Skan	  struct switchstr *sw;
4374117413Skan
4375117413Skan	  /* Each switch should start with '-'.  */
4376117413Skan	  if (argbuf[i][0] != '-')
4377117413Skan	    abort ();
4378117413Skan
4379117413Skan	  sw = &switches[i + first];
4380117413Skan	  sw->part1 = &argbuf[i][1];
4381117413Skan	  sw->args = 0;
4382117413Skan	  sw->live_cond = SWITCH_OK;
4383117413Skan	  sw->validated = 0;
4384117413Skan	  sw->ordering = 0;
4385117413Skan	}
4386117413Skan    }
4387117413Skan}
4388117413Skan
438918334Speter/* Process the sub-spec SPEC as a portion of a larger spec.
439018334Speter   This is like processing a whole spec except that we do
439118334Speter   not initialize at the beginning and we do not supply a
439218334Speter   newline by default at the end.
439318334Speter   INSWITCH nonzero means don't process %-sequences in SPEC;
439418334Speter   in this case, % is treated as an ordinary character.
439518334Speter   This is used while substituting switches.
439618334Speter   INSWITCH nonzero also causes SPC not to terminate an argument.
439718334Speter
439818334Speter   Value is zero unless a line was finished
439918334Speter   and the command on that line reported an error.  */
440018334Speter
440118334Speterstatic int
4402132733Skando_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
440318334Speter{
440490277Sobrien  const char *p = spec;
440590277Sobrien  int c;
440618334Speter  int i;
440752520Sobrien  const char *string;
440818334Speter  int value;
440918334Speter
441050599Sobrien  while ((c = *p++))
441118334Speter    /* If substituting a switch, treat all chars like letters.
441218334Speter       Otherwise, NL, SPC, TAB and % are special.  */
441318334Speter    switch (inswitch ? 'a' : c)
441418334Speter      {
441518334Speter      case '\n':
441618334Speter	/* End of line: finish any pending argument,
441718334Speter	   then run the pending command if one has been started.  */
441818334Speter	if (arg_going)
441918334Speter	  {
442018334Speter	    obstack_1grow (&obstack, 0);
442118334Speter	    string = obstack_finish (&obstack);
442218334Speter	    if (this_is_library_file)
442318334Speter	      string = find_file (string);
442418334Speter	    store_arg (string, delete_this_arg, this_is_output_file);
442518334Speter	    if (this_is_output_file)
442618334Speter	      outfiles[input_file_number] = string;
442718334Speter	  }
442818334Speter	arg_going = 0;
442918334Speter
443018334Speter	if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
443118334Speter	  {
443218334Speter	    /* A `|' before the newline means use a pipe here,
443318334Speter	       but only if -pipe was specified.
443418334Speter	       Otherwise, execute now and don't pass the `|' as an arg.  */
4435132733Skan	    if (use_pipes)
443618334Speter	      {
443718334Speter		input_from_pipe = 1;
443818334Speter		break;
443918334Speter	      }
444018334Speter	    else
444118334Speter	      argbuf_index--;
444218334Speter	  }
444318334Speter
444490277Sobrien	set_collect_gcc_options ();
444590277Sobrien
444618334Speter	if (argbuf_index > 0)
444718334Speter	  {
444818334Speter	    value = execute ();
444918334Speter	    if (value)
445018334Speter	      return value;
445118334Speter	  }
445218334Speter	/* Reinitialize for a new command, and for a new argument.  */
445318334Speter	clear_args ();
445418334Speter	arg_going = 0;
445518334Speter	delete_this_arg = 0;
445618334Speter	this_is_output_file = 0;
445718334Speter	this_is_library_file = 0;
445818334Speter	input_from_pipe = 0;
445918334Speter	break;
446018334Speter
446118334Speter      case '|':
446218334Speter	/* End any pending argument.  */
446318334Speter	if (arg_going)
446418334Speter	  {
446518334Speter	    obstack_1grow (&obstack, 0);
446618334Speter	    string = obstack_finish (&obstack);
446718334Speter	    if (this_is_library_file)
446818334Speter	      string = find_file (string);
446918334Speter	    store_arg (string, delete_this_arg, this_is_output_file);
447018334Speter	    if (this_is_output_file)
447118334Speter	      outfiles[input_file_number] = string;
447218334Speter	  }
447318334Speter
447418334Speter	/* Use pipe */
447518334Speter	obstack_1grow (&obstack, c);
447618334Speter	arg_going = 1;
447718334Speter	break;
447818334Speter
447918334Speter      case '\t':
448018334Speter      case ' ':
448118334Speter	/* Space or tab ends an argument if one is pending.  */
448218334Speter	if (arg_going)
448318334Speter	  {
448418334Speter	    obstack_1grow (&obstack, 0);
448518334Speter	    string = obstack_finish (&obstack);
448618334Speter	    if (this_is_library_file)
448718334Speter	      string = find_file (string);
448818334Speter	    store_arg (string, delete_this_arg, this_is_output_file);
448918334Speter	    if (this_is_output_file)
449018334Speter	      outfiles[input_file_number] = string;
449118334Speter	  }
449218334Speter	/* Reinitialize for a new argument.  */
449318334Speter	arg_going = 0;
449418334Speter	delete_this_arg = 0;
449518334Speter	this_is_output_file = 0;
449618334Speter	this_is_library_file = 0;
449718334Speter	break;
449818334Speter
449918334Speter      case '%':
450018334Speter	switch (c = *p++)
450118334Speter	  {
450218334Speter	  case 0:
450390277Sobrien	    fatal ("invalid specification!  Bug in cc");
450418334Speter
450518334Speter	  case 'b':
450618334Speter	    obstack_grow (&obstack, input_basename, basename_length);
450718334Speter	    arg_going = 1;
450818334Speter	    break;
450918334Speter
451090277Sobrien	  case 'B':
451190277Sobrien	    obstack_grow (&obstack, input_basename, suffixed_basename_length);
451290277Sobrien	    arg_going = 1;
451390277Sobrien	    break;
451490277Sobrien
451518334Speter	  case 'd':
451618334Speter	    delete_this_arg = 2;
451718334Speter	    break;
451818334Speter
451918334Speter	  /* Dump out the directories specified with LIBRARY_PATH,
452018334Speter	     followed by the absolute directories
452118334Speter	     that we search for startfiles.  */
452218334Speter	  case 'D':
452318334Speter	    {
452418334Speter	      struct prefix_list *pl = startfile_prefixes.plist;
452550599Sobrien	      size_t bufsize = 100;
4526132733Skan	      char *buffer = xmalloc (bufsize);
452718334Speter	      int idx;
452818334Speter
452918334Speter	      for (; pl; pl = pl->next)
453018334Speter		{
453118334Speter#ifdef RELATIVE_PREFIX_NOT_LINKDIR
453218334Speter		  /* Used on systems which record the specified -L dirs
453318334Speter		     and use them to search for dynamic linking.  */
453418334Speter		  /* Relative directories always come from -B,
453518334Speter		     and it is better not to use them for searching
453690277Sobrien		     at run time.  In particular, stage1 loses.  */
4537132733Skan		  if (!IS_ABSOLUTE_PATH (pl->prefix))
453818334Speter		    continue;
453918334Speter#endif
454018334Speter		  /* Try subdirectory if there is one.  */
4541104763Skan		  if (multilib_dir != NULL
4542104763Skan		      || (pl->os_multilib && multilib_os_dir != NULL))
454318334Speter		    {
4544104763Skan		      const char *multi_dir;
4545104763Skan
4546104763Skan		      multi_dir = pl->os_multilib ? multilib_os_dir
4547104763Skan						  : multilib_dir;
4548104763Skan		      if (machine_suffix && multilib_dir)
454918334Speter			{
455018334Speter			  if (strlen (pl->prefix) + strlen (machine_suffix)
455118334Speter			      >= bufsize)
455218334Speter			    bufsize = (strlen (pl->prefix)
455318334Speter				       + strlen (machine_suffix)) * 2 + 1;
4554132733Skan			  buffer = xrealloc (buffer, bufsize);
455518334Speter			  strcpy (buffer, pl->prefix);
455618334Speter			  strcat (buffer, machine_suffix);
455718334Speter			  if (is_directory (buffer, multilib_dir, 1))
455818334Speter			    {
455990277Sobrien			      do_spec_1 ("-L", 0, NULL);
456018334Speter#ifdef SPACE_AFTER_L_OPTION
456190277Sobrien			      do_spec_1 (" ", 0, NULL);
456218334Speter#endif
456390277Sobrien			      do_spec_1 (buffer, 1, NULL);
456490277Sobrien			      do_spec_1 (multilib_dir, 1, NULL);
456518334Speter			      /* Make this a separate argument.  */
456690277Sobrien			      do_spec_1 (" ", 0, NULL);
456718334Speter			    }
456818334Speter			}
456918334Speter		      if (!pl->require_machine_suffix)
457018334Speter			{
4571104763Skan			  if (is_directory (pl->prefix, multi_dir, 1))
457218334Speter			    {
457390277Sobrien			      do_spec_1 ("-L", 0, NULL);
457418334Speter#ifdef SPACE_AFTER_L_OPTION
457590277Sobrien			      do_spec_1 (" ", 0, NULL);
457618334Speter#endif
457790277Sobrien			      do_spec_1 (pl->prefix, 1, NULL);
4578104763Skan			      do_spec_1 (multi_dir, 1, NULL);
457918334Speter			      /* Make this a separate argument.  */
458090277Sobrien			      do_spec_1 (" ", 0, NULL);
458118334Speter			    }
458218334Speter			}
458318334Speter		    }
458418334Speter		  if (machine_suffix)
458518334Speter		    {
458618334Speter		      if (is_directory (pl->prefix, machine_suffix, 1))
458718334Speter			{
458890277Sobrien			  do_spec_1 ("-L", 0, NULL);
458918334Speter#ifdef SPACE_AFTER_L_OPTION
459090277Sobrien			  do_spec_1 (" ", 0, NULL);
459118334Speter#endif
459290277Sobrien			  do_spec_1 (pl->prefix, 1, NULL);
459318334Speter			  /* Remove slash from machine_suffix.  */
459418334Speter			  if (strlen (machine_suffix) >= bufsize)
459518334Speter			    bufsize = strlen (machine_suffix) * 2 + 1;
4596132733Skan			  buffer = xrealloc (buffer, bufsize);
459718334Speter			  strcpy (buffer, machine_suffix);
459818334Speter			  idx = strlen (buffer);
459952520Sobrien			  if (IS_DIR_SEPARATOR (buffer[idx - 1]))
460018334Speter			    buffer[idx - 1] = 0;
460190277Sobrien			  do_spec_1 (buffer, 1, NULL);
460218334Speter			  /* Make this a separate argument.  */
460390277Sobrien			  do_spec_1 (" ", 0, NULL);
460418334Speter			}
460518334Speter		    }
460618334Speter		  if (!pl->require_machine_suffix)
460718334Speter		    {
460818334Speter		      if (is_directory (pl->prefix, "", 1))
460918334Speter			{
461090277Sobrien			  do_spec_1 ("-L", 0, NULL);
461118334Speter#ifdef SPACE_AFTER_L_OPTION
461290277Sobrien			  do_spec_1 (" ", 0, NULL);
461318334Speter#endif
461418334Speter			  /* Remove slash from pl->prefix.  */
461518334Speter			  if (strlen (pl->prefix) >= bufsize)
461618334Speter			    bufsize = strlen (pl->prefix) * 2 + 1;
4617132733Skan			  buffer = xrealloc (buffer, bufsize);
461818334Speter			  strcpy (buffer, pl->prefix);
461918334Speter			  idx = strlen (buffer);
462052520Sobrien			  if (IS_DIR_SEPARATOR (buffer[idx - 1]))
462118334Speter			    buffer[idx - 1] = 0;
462290277Sobrien			  do_spec_1 (buffer, 1, NULL);
462318334Speter			  /* Make this a separate argument.  */
462490277Sobrien			  do_spec_1 (" ", 0, NULL);
462518334Speter			}
462618334Speter		    }
462718334Speter		}
462818334Speter	      free (buffer);
462918334Speter	    }
463018334Speter	    break;
463118334Speter
463218334Speter	  case 'e':
463352520Sobrien	    /* %efoo means report an error with `foo' as error message
463418334Speter	       and don't execute any more commands for this file.  */
463518334Speter	    {
463652520Sobrien	      const char *q = p;
463718334Speter	      char *buf;
463890277Sobrien	      while (*p != 0 && *p != '\n')
463990277Sobrien		p++;
4640132733Skan	      buf = alloca (p - q + 1);
464118334Speter	      strncpy (buf, q, p - q);
464218334Speter	      buf[p - q] = 0;
464390277Sobrien	      error ("%s", buf);
464418334Speter	      return -1;
464518334Speter	    }
464618334Speter	    break;
464790277Sobrien	  case 'n':
4648117413Skan	    /* %nfoo means report a notice with `foo' on stderr.  */
464990277Sobrien	    {
465090277Sobrien	      const char *q = p;
465190277Sobrien	      char *buf;
465290277Sobrien	      while (*p != 0 && *p != '\n')
465390277Sobrien		p++;
4654132733Skan	      buf = alloca (p - q + 1);
465590277Sobrien	      strncpy (buf, q, p - q);
465690277Sobrien	      buf[p - q] = 0;
465790277Sobrien	      notice ("%s\n", buf);
465890277Sobrien	      if (*p)
465990277Sobrien		p++;
466090277Sobrien	    }
466190277Sobrien	    break;
466218334Speter
466390277Sobrien	  case 'j':
466490277Sobrien	    {
466590277Sobrien	      struct stat st;
466690277Sobrien
4667132733Skan	      /* If save_temps_flag is off, and the HOST_BIT_BUCKET is
4668132733Skan		 defined, and it is not a directory, and it is
4669132733Skan		 writable, use it.  Otherwise, treat this like any
4670132733Skan		 other temporary file.  */
467190277Sobrien
467290277Sobrien	      if ((!save_temps_flag)
467390277Sobrien		  && (stat (HOST_BIT_BUCKET, &st) == 0) && (!S_ISDIR (st.st_mode))
467490277Sobrien		  && (access (HOST_BIT_BUCKET, W_OK) == 0))
467590277Sobrien		{
467690277Sobrien		  obstack_grow (&obstack, HOST_BIT_BUCKET,
467790277Sobrien				strlen (HOST_BIT_BUCKET));
467890277Sobrien		  delete_this_arg = 0;
467990277Sobrien		  arg_going = 1;
468090277Sobrien		  break;
468190277Sobrien		}
468290277Sobrien	    }
4683132733Skan	    goto create_temp_file;
4684132733Skan	  case '|':
4685132733Skan	    if (use_pipes)
4686132733Skan	      {
4687132733Skan		obstack_1grow (&obstack, '-');
4688132733Skan		delete_this_arg = 0;
4689132733Skan		arg_going = 1;
4690132733Skan
4691132733Skan		/* consume suffix */
4692132733Skan		while (*p == '.' || ISALPHA ((unsigned char) *p))
4693132733Skan		  p++;
4694132733Skan		if (p[0] == '%' && p[1] == 'O')
4695132733Skan		  p += 2;
4696132733Skan
4697132733Skan		break;
4698132733Skan	      }
4699132733Skan	    goto create_temp_file;
4700132733Skan	  case 'm':
4701132733Skan	    if (use_pipes)
4702132733Skan	      {
4703132733Skan		/* consume suffix */
4704132733Skan		while (*p == '.' || ISALPHA ((unsigned char) *p))
4705132733Skan		  p++;
4706132733Skan		if (p[0] == '%' && p[1] == 'O')
4707132733Skan		  p += 2;
4708132733Skan
4709132733Skan		break;
4710132733Skan	      }
4711132733Skan	    goto create_temp_file;
471218334Speter	  case 'g':
471318334Speter	  case 'u':
471418334Speter	  case 'U':
4715132733Skan	  create_temp_file:
471618334Speter	      {
471718334Speter		struct temp_name *t;
471850599Sobrien		int suffix_length;
471952520Sobrien		const char *suffix = p;
472090277Sobrien		char *saved_suffix = NULL;
472118334Speter
472290277Sobrien		while (*p == '.' || ISALPHA ((unsigned char) *p))
472390277Sobrien		  p++;
472490277Sobrien		suffix_length = p - suffix;
472550599Sobrien		if (p[0] == '%' && p[1] == 'O')
472650599Sobrien		  {
472750599Sobrien		    p += 2;
472850599Sobrien		    /* We don't support extra suffix characters after %O.  */
472990277Sobrien		    if (*p == '.' || ISALPHA ((unsigned char) *p))
473050599Sobrien		      abort ();
473190277Sobrien		    if (suffix_length == 0)
473290277Sobrien		      suffix = TARGET_OBJECT_SUFFIX;
473390277Sobrien		    else
473490277Sobrien		      {
473590277Sobrien			saved_suffix
4736132733Skan			  = xmalloc (suffix_length
4737132733Skan				     + strlen (TARGET_OBJECT_SUFFIX));
473890277Sobrien			strncpy (saved_suffix, suffix, suffix_length);
473990277Sobrien			strcpy (saved_suffix + suffix_length,
474090277Sobrien				TARGET_OBJECT_SUFFIX);
474190277Sobrien		      }
474290277Sobrien		    suffix_length += strlen (TARGET_OBJECT_SUFFIX);
474350599Sobrien		  }
4744117413Skan
474590277Sobrien		/* If the input_filename has the same suffix specified
474690277Sobrien		   for the %g, %u, or %U, and -save-temps is specified,
474790277Sobrien		   we could end up using that file as an intermediate
474890277Sobrien		   thus clobbering the user's source file (.e.g.,
474990277Sobrien		   gcc -save-temps foo.s would clobber foo.s with the
475090277Sobrien		   output of cpp0).  So check for this condition and
475190277Sobrien		   generate a temp file as the intermediate.  */
4752117413Skan
475390277Sobrien		if (save_temps_flag)
475450599Sobrien		  {
475590277Sobrien		    temp_filename_length = basename_length + suffix_length;
475690277Sobrien		    temp_filename = alloca (temp_filename_length + 1);
475790277Sobrien		    strncpy ((char *) temp_filename, input_basename, basename_length);
475890277Sobrien		    strncpy ((char *) temp_filename + basename_length, suffix,
4759132733Skan			     suffix_length);
476090277Sobrien		    *((char *) temp_filename + temp_filename_length) = '\0';
476190277Sobrien		    if (strcmp (temp_filename, input_filename) != 0)
476290277Sobrien		      {
4763132733Skan			struct stat st_temp;
4764117413Skan
4765132733Skan			/* Note, set_input() resets input_stat_set to 0.  */
4766132733Skan			if (input_stat_set == 0)
4767132733Skan			  {
4768132733Skan			    input_stat_set = stat (input_filename, &input_stat);
4769132733Skan			    if (input_stat_set >= 0)
4770132733Skan			      input_stat_set = 1;
4771132733Skan			  }
4772117413Skan
4773132733Skan			/* If we have the stat for the input_filename
4774132733Skan			   and we can do the stat for the temp_filename
4775132733Skan			   then the they could still refer to the same
4776132733Skan			   file if st_dev/st_ino's are the same.  */
4777117413Skan
477890277Sobrien			if (input_stat_set != 1
477990277Sobrien			    || stat (temp_filename, &st_temp) < 0
478090277Sobrien			    || input_stat.st_dev != st_temp.st_dev
478190277Sobrien			    || input_stat.st_ino != st_temp.st_ino)
4782117413Skan			  {
478390277Sobrien			    temp_filename = save_string (temp_filename,
478490277Sobrien							 temp_filename_length + 1);
478590277Sobrien			    obstack_grow (&obstack, temp_filename,
4786132733Skan						    temp_filename_length);
478790277Sobrien			    arg_going = 1;
4788117413Skan			    delete_this_arg = 0;
478990277Sobrien			    break;
479090277Sobrien			  }
479190277Sobrien		      }
479250599Sobrien		  }
479350599Sobrien
479418334Speter		/* See if we already have an association of %g/%u/%U and
479518334Speter		   suffix.  */
479618334Speter		for (t = temp_names; t; t = t->next)
479750599Sobrien		  if (t->length == suffix_length
479850599Sobrien		      && strncmp (t->suffix, suffix, suffix_length) == 0
4799132733Skan		      && t->unique == (c == 'u' || c == 'U' || c == 'j'))
480018334Speter		    break;
480118334Speter
480290277Sobrien		/* Make a new association if needed.  %u and %j
480390277Sobrien		   require one.  */
480490277Sobrien		if (t == 0 || c == 'u' || c == 'j')
480518334Speter		  {
480618334Speter		    if (t == 0)
480718334Speter		      {
4808132733Skan			t = xmalloc (sizeof (struct temp_name));
480918334Speter			t->next = temp_names;
481018334Speter			temp_names = t;
481118334Speter		      }
481250599Sobrien		    t->length = suffix_length;
481390277Sobrien		    if (saved_suffix)
481490277Sobrien		      {
481590277Sobrien			t->suffix = saved_suffix;
481690277Sobrien			saved_suffix = NULL;
481790277Sobrien		      }
481890277Sobrien		    else
481990277Sobrien		      t->suffix = save_string (suffix, suffix_length);
4820132733Skan		    t->unique = (c == 'u' || c == 'U' || c == 'j');
482150599Sobrien		    temp_filename = make_temp_file (t->suffix);
482250599Sobrien		    temp_filename_length = strlen (temp_filename);
482318334Speter		    t->filename = temp_filename;
482418334Speter		    t->filename_length = temp_filename_length;
482518334Speter		  }
482618334Speter
482790277Sobrien		if (saved_suffix)
482890277Sobrien		  free (saved_suffix);
482990277Sobrien
483018334Speter		obstack_grow (&obstack, t->filename, t->filename_length);
483118334Speter		delete_this_arg = 1;
483218334Speter	      }
483318334Speter	    arg_going = 1;
483418334Speter	    break;
483518334Speter
483618334Speter	  case 'i':
4837132733Skan	    if (combine_inputs)
4838132733Skan	      {
4839132733Skan		for (i = 0; (int) i < n_infiles; i++)
4840132733Skan		  store_arg (infiles[i].name, 0, 0);
4841132733Skan	      }
4842132733Skan	    else
4843132733Skan	      {
4844132733Skan		obstack_grow (&obstack, input_filename, input_filename_length);
4845132733Skan		arg_going = 1;
4846132733Skan	      }
484718334Speter	    break;
484818334Speter
484918334Speter	  case 'I':
485018334Speter	    {
485118334Speter	      struct prefix_list *pl = include_prefixes.plist;
485218334Speter
485318334Speter	      if (gcc_exec_prefix)
485418334Speter		{
485590277Sobrien		  do_spec_1 ("-iprefix", 1, NULL);
485618334Speter		  /* Make this a separate argument.  */
485790277Sobrien		  do_spec_1 (" ", 0, NULL);
485890277Sobrien		  do_spec_1 (gcc_exec_prefix, 1, NULL);
485990277Sobrien		  do_spec_1 (" ", 0, NULL);
486018334Speter		}
486118334Speter
4862132733Skan	      if (target_system_root_changed ||
4863132733Skan		  (target_system_root && target_sysroot_hdrs_suffix))
4864132733Skan		{
4865132733Skan		  do_spec_1 ("-isysroot", 1, NULL);
4866132733Skan		  /* Make this a separate argument.  */
4867132733Skan		  do_spec_1 (" ", 0, NULL);
4868132733Skan		  do_spec_1 (target_system_root, 1, NULL);
4869132733Skan		  if (target_sysroot_hdrs_suffix)
4870132733Skan		    do_spec_1 (target_sysroot_hdrs_suffix, 1, NULL);
4871132733Skan		  do_spec_1 (" ", 0, NULL);
4872132733Skan		}
4873132733Skan
487418334Speter	      for (; pl; pl = pl->next)
487518334Speter		{
487690277Sobrien		  do_spec_1 ("-isystem", 1, NULL);
487718334Speter		  /* Make this a separate argument.  */
487890277Sobrien		  do_spec_1 (" ", 0, NULL);
487990277Sobrien		  do_spec_1 (pl->prefix, 1, NULL);
488090277Sobrien		  do_spec_1 (" ", 0, NULL);
488118334Speter		}
488218334Speter	    }
488318334Speter	    break;
488418334Speter
488518334Speter	  case 'o':
488652520Sobrien	    {
488752520Sobrien	      int max = n_infiles;
488852520Sobrien	      max += lang_specific_extra_outfiles;
488918334Speter
489052520Sobrien	      for (i = 0; i < max; i++)
489152520Sobrien		if (outfiles[i])
489252520Sobrien		  store_arg (outfiles[i], 0, 0);
489352520Sobrien	      break;
489452520Sobrien	    }
489552520Sobrien
489618334Speter	  case 'O':
489790277Sobrien	    obstack_grow (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
489818334Speter	    arg_going = 1;
489918334Speter	    break;
490018334Speter
490118334Speter	  case 's':
490218334Speter	    this_is_library_file = 1;
490318334Speter	    break;
490418334Speter
4905132733Skan	  case 'V':
4906132733Skan	    outfiles[input_file_number] = NULL;
4907132733Skan	    break;
4908132733Skan
490918334Speter	  case 'w':
491018334Speter	    this_is_output_file = 1;
491118334Speter	    break;
491218334Speter
491318334Speter	  case 'W':
491418334Speter	    {
491550599Sobrien	      int cur_index = argbuf_index;
491618334Speter	      /* Handle the {...} following the %W.  */
491718334Speter	      if (*p != '{')
491818334Speter		abort ();
491918334Speter	      p = handle_braces (p + 1);
492018334Speter	      if (p == 0)
492118334Speter		return -1;
4922132733Skan	      /* End any pending argument.  */
4923132733Skan	      if (arg_going)
4924132733Skan		{
4925132733Skan		  obstack_1grow (&obstack, 0);
4926132733Skan		  string = obstack_finish (&obstack);
4927132733Skan		  if (this_is_library_file)
4928132733Skan		    string = find_file (string);
4929132733Skan		  store_arg (string, delete_this_arg, this_is_output_file);
4930132733Skan		  if (this_is_output_file)
4931132733Skan		    outfiles[input_file_number] = string;
4932132733Skan		  arg_going = 0;
4933132733Skan		}
493418334Speter	      /* If any args were output, mark the last one for deletion
493518334Speter		 on failure.  */
493650599Sobrien	      if (argbuf_index != cur_index)
493718334Speter		record_temp_file (argbuf[argbuf_index - 1], 0, 1);
493818334Speter	      break;
493918334Speter	    }
494018334Speter
494118334Speter	  /* %x{OPTION} records OPTION for %X to output.  */
494218334Speter	  case 'x':
494318334Speter	    {
494452520Sobrien	      const char *p1 = p;
494518334Speter	      char *string;
494618334Speter
494718334Speter	      /* Skip past the option value and make a copy.  */
494818334Speter	      if (*p != '{')
494918334Speter		abort ();
495018334Speter	      while (*p++ != '}')
495118334Speter		;
495218334Speter	      string = save_string (p1 + 1, p - p1 - 2);
495318334Speter
495418334Speter	      /* See if we already recorded this option.  */
495518334Speter	      for (i = 0; i < n_linker_options; i++)
495618334Speter		if (! strcmp (string, linker_options[i]))
495718334Speter		  {
495818334Speter		    free (string);
495918334Speter		    return 0;
496018334Speter		  }
496118334Speter
496218334Speter	      /* This option is new; add it.  */
496350599Sobrien	      add_linker_option (string, strlen (string));
496418334Speter	    }
496518334Speter	    break;
496618334Speter
496718334Speter	  /* Dump out the options accumulated previously using %x.  */
496818334Speter	  case 'X':
496918334Speter	    for (i = 0; i < n_linker_options; i++)
497018334Speter	      {
497190277Sobrien		do_spec_1 (linker_options[i], 1, NULL);
497218334Speter		/* Make each accumulated option a separate argument.  */
497390277Sobrien		do_spec_1 (" ", 0, NULL);
497418334Speter	      }
497518334Speter	    break;
497618334Speter
497718334Speter	  /* Dump out the options accumulated previously using -Wa,.  */
497818334Speter	  case 'Y':
497918334Speter	    for (i = 0; i < n_assembler_options; i++)
498018334Speter	      {
498190277Sobrien		do_spec_1 (assembler_options[i], 1, NULL);
498218334Speter		/* Make each accumulated option a separate argument.  */
498390277Sobrien		do_spec_1 (" ", 0, NULL);
498418334Speter	      }
498518334Speter	    break;
498618334Speter
498718334Speter	  /* Dump out the options accumulated previously using -Wp,.  */
498818334Speter	  case 'Z':
498918334Speter	    for (i = 0; i < n_preprocessor_options; i++)
499018334Speter	      {
499190277Sobrien		do_spec_1 (preprocessor_options[i], 1, NULL);
499218334Speter		/* Make each accumulated option a separate argument.  */
499390277Sobrien		do_spec_1 (" ", 0, NULL);
499418334Speter	      }
499518334Speter	    break;
499618334Speter
499718334Speter	    /* Here are digits and numbers that just process
499818334Speter	       a certain constant string as a spec.  */
499918334Speter
500018334Speter	  case '1':
500190277Sobrien	    value = do_spec_1 (cc1_spec, 0, NULL);
500218334Speter	    if (value != 0)
500318334Speter	      return value;
500418334Speter	    break;
500518334Speter
500618334Speter	  case '2':
500790277Sobrien	    value = do_spec_1 (cc1plus_spec, 0, NULL);
500818334Speter	    if (value != 0)
500918334Speter	      return value;
501018334Speter	    break;
501118334Speter
501218334Speter	  case 'a':
501390277Sobrien	    value = do_spec_1 (asm_spec, 0, NULL);
501418334Speter	    if (value != 0)
501518334Speter	      return value;
501618334Speter	    break;
501718334Speter
501818334Speter	  case 'A':
501990277Sobrien	    value = do_spec_1 (asm_final_spec, 0, NULL);
502018334Speter	    if (value != 0)
502118334Speter	      return value;
502218334Speter	    break;
502318334Speter
502418334Speter	  case 'C':
502590277Sobrien	    {
502690277Sobrien	      const char *const spec
5027117413Skan		= (input_file_compiler->cpp_spec
5028117413Skan		   ? input_file_compiler->cpp_spec
502990277Sobrien		   : cpp_spec);
503090277Sobrien	      value = do_spec_1 (spec, 0, NULL);
503190277Sobrien	      if (value != 0)
503290277Sobrien		return value;
503390277Sobrien	    }
503418334Speter	    break;
503518334Speter
503618334Speter	  case 'E':
503790277Sobrien	    value = do_spec_1 (endfile_spec, 0, NULL);
503818334Speter	    if (value != 0)
503918334Speter	      return value;
504018334Speter	    break;
504118334Speter
504218334Speter	  case 'l':
504390277Sobrien	    value = do_spec_1 (link_spec, 0, NULL);
504418334Speter	    if (value != 0)
504518334Speter	      return value;
504618334Speter	    break;
504718334Speter
504818334Speter	  case 'L':
504990277Sobrien	    value = do_spec_1 (lib_spec, 0, NULL);
505018334Speter	    if (value != 0)
505118334Speter	      return value;
505218334Speter	    break;
505318334Speter
505418334Speter	  case 'G':
505590277Sobrien	    value = do_spec_1 (libgcc_spec, 0, NULL);
505618334Speter	    if (value != 0)
505718334Speter	      return value;
505818334Speter	    break;
505918334Speter
506090277Sobrien	  case 'M':
506190277Sobrien	    if (multilib_dir && strcmp (multilib_dir, ".") != 0)
506290277Sobrien	      {
506390277Sobrien		char *p;
506490277Sobrien		const char *q;
506590277Sobrien		size_t len;
506690277Sobrien
506790277Sobrien		len = strlen (multilib_dir);
506890277Sobrien		obstack_blank (&obstack, len + 1);
506990277Sobrien		p = obstack_next_free (&obstack) - (len + 1);
507090277Sobrien
507190277Sobrien		*p++ = '_';
507290277Sobrien		for (q = multilib_dir; *q ; ++q, ++p)
507390277Sobrien		  *p = (IS_DIR_SEPARATOR (*q) ? '_' : *q);
507490277Sobrien	      }
507590277Sobrien	    break;
507690277Sobrien
5077132733Skan	  case 'R':
5078132733Skan	    /* We assume there is a directory
5079132733Skan	       separator at the end of this string.  */
5080132733Skan	    if (target_system_root)
5081132733Skan	      {
5082132733Skan	        obstack_grow (&obstack, target_system_root,
5083132733Skan			      strlen (target_system_root));
5084132733Skan		if (target_sysroot_suffix)
5085132733Skan		  obstack_grow (&obstack, target_sysroot_suffix,
5086132733Skan				strlen (target_sysroot_suffix));
5087132733Skan	      }
508818334Speter	    break;
508918334Speter
509018334Speter	  case 'S':
509190277Sobrien	    value = do_spec_1 (startfile_spec, 0, NULL);
509218334Speter	    if (value != 0)
509318334Speter	      return value;
509418334Speter	    break;
509518334Speter
509618334Speter	    /* Here we define characters other than letters and digits.  */
509718334Speter
509818334Speter	  case '{':
509918334Speter	    p = handle_braces (p);
510018334Speter	    if (p == 0)
510118334Speter	      return -1;
510218334Speter	    break;
510318334Speter
5104117413Skan	  case ':':
5105117413Skan	    p = handle_spec_function (p);
5106117413Skan	    if (p == 0)
5107117413Skan	      return -1;
5108117413Skan	    break;
5109117413Skan
511018334Speter	  case '%':
511118334Speter	    obstack_1grow (&obstack, '%');
511218334Speter	    break;
511318334Speter
5114117413Skan	  case '.':
5115117413Skan	    {
5116117413Skan	      unsigned len = 0;
511790277Sobrien
5118117413Skan	      while (p[len] && p[len] != ' ' && p[len] != '%')
5119117413Skan		len++;
5120117413Skan	      suffix_subst = save_string (p - 1, len + 1);
5121117413Skan	      p += len;
5122117413Skan	    }
512390277Sobrien	   break;
5124117413Skan
5125132733Skan	   /* Henceforth ignore the option(s) matching the pattern
5126132733Skan	      after the %<.  */
5127132733Skan	  case '<':
5128132733Skan	    {
5129132733Skan	      unsigned len = 0;
5130132733Skan	      int have_wildcard = 0;
5131132733Skan	      int i;
5132132733Skan
5133132733Skan	      while (p[len] && p[len] != ' ' && p[len] != '\t')
5134132733Skan		len++;
5135132733Skan
5136132733Skan	      if (p[len-1] == '*')
5137132733Skan		have_wildcard = 1;
5138132733Skan
5139132733Skan	      for (i = 0; i < n_switches; i++)
5140132733Skan		if (!strncmp (switches[i].part1, p, len - have_wildcard)
5141132733Skan		    && (have_wildcard || switches[i].part1[len] == '\0'))
5142132733Skan		  {
5143132733Skan		    switches[i].live_cond = SWITCH_IGNORE;
5144132733Skan		    switches[i].validated = 1;
5145132733Skan		  }
5146132733Skan
5147132733Skan	      p += len;
5148132733Skan	    }
5149132733Skan	    break;
5150132733Skan
515118334Speter	  case '*':
515290277Sobrien	    if (soft_matched_part)
515390277Sobrien	      {
515490277Sobrien		do_spec_1 (soft_matched_part, 1, NULL);
515590277Sobrien		do_spec_1 (" ", 0, NULL);
515690277Sobrien	      }
515790277Sobrien	    else
515890277Sobrien	      /* Catch the case where a spec string contains something like
515990277Sobrien		 '%{foo:%*}'.  ie there is no * in the pattern on the left
516090277Sobrien		 hand side of the :.  */
516190277Sobrien	      error ("spec failure: '%%*' has not been initialized by pattern match");
516218334Speter	    break;
516318334Speter
516418334Speter	    /* Process a string found as the value of a spec given by name.
516518334Speter	       This feature allows individual machine descriptions
516618334Speter	       to add and use their own specs.
516718334Speter	       %[...] modifies -D options the way %P does;
516818334Speter	       %(...) uses the spec unmodified.  */
516950599Sobrien	  case '[':
517090277Sobrien	    error ("warning: use of obsolete %%[ operator in specs");
517118334Speter	  case '(':
517218334Speter	    {
517352520Sobrien	      const char *name = p;
517418334Speter	      struct spec_list *sl;
517518334Speter	      int len;
517618334Speter
517718334Speter	      /* The string after the S/P is the name of a spec that is to be
517850599Sobrien		 processed.  */
517918334Speter	      while (*p && *p != ')' && *p != ']')
518018334Speter		p++;
518118334Speter
518290277Sobrien	      /* See if it's in the list.  */
518318334Speter	      for (len = p - name, sl = specs; sl; sl = sl->next)
518450599Sobrien		if (sl->name_len == len && !strncmp (sl->name, name, len))
518518334Speter		  {
518650599Sobrien		    name = *(sl->ptr_spec);
518750599Sobrien#ifdef DEBUG_SPECS
518852520Sobrien		    notice ("Processing spec %c%s%c, which is '%s'\n",
518952520Sobrien			    c, sl->name, (c == '(') ? ')' : ']', name);
519050599Sobrien#endif
519118334Speter		    break;
519218334Speter		  }
519318334Speter
519418334Speter	      if (sl)
519518334Speter		{
519618334Speter		  if (c == '(')
519718334Speter		    {
519890277Sobrien		      value = do_spec_1 (name, 0, NULL);
519918334Speter		      if (value != 0)
520018334Speter			return value;
520118334Speter		    }
520218334Speter		  else
520318334Speter		    {
5204132733Skan		      char *x = alloca (strlen (name) * 2 + 1);
520518334Speter		      char *buf = x;
520652520Sobrien		      const char *y = name;
520750599Sobrien		      int flag = 0;
520818334Speter
520918334Speter		      /* Copy all of NAME into BUF, but put __ after
521090277Sobrien			 every -D and at the end of each arg.  */
521118334Speter		      while (1)
521218334Speter			{
521318334Speter			  if (! strncmp (y, "-D", 2))
521418334Speter			    {
521518334Speter			      *x++ = '-';
521618334Speter			      *x++ = 'D';
521718334Speter			      *x++ = '_';
521818334Speter			      *x++ = '_';
521918334Speter			      y += 2;
522050599Sobrien			      flag = 1;
522150599Sobrien			      continue;
522218334Speter			    }
522390277Sobrien			  else if (flag
522490277Sobrien				   && (*y == ' ' || *y == '\t' || *y == '='
522590277Sobrien				       || *y == '}' || *y == 0))
522618334Speter			    {
522718334Speter			      *x++ = '_';
522818334Speter			      *x++ = '_';
522950599Sobrien			      flag = 0;
523018334Speter			    }
523190277Sobrien			  if (*y == 0)
523250599Sobrien			    break;
523318334Speter			  else
523418334Speter			    *x++ = *y++;
523518334Speter			}
523618334Speter		      *x = 0;
523718334Speter
523890277Sobrien		      value = do_spec_1 (buf, 0, NULL);
523918334Speter		      if (value != 0)
524018334Speter			return value;
524118334Speter		    }
524218334Speter		}
524318334Speter
524418334Speter	      /* Discard the closing paren or bracket.  */
524518334Speter	      if (*p)
524618334Speter		p++;
524718334Speter	    }
524818334Speter	    break;
524918334Speter
525018334Speter	  default:
525190277Sobrien	    error ("spec failure: unrecognized spec option '%c'", c);
525290277Sobrien	    break;
525318334Speter	  }
525418334Speter	break;
525518334Speter
525618334Speter      case '\\':
525718334Speter	/* Backslash: treat next character as ordinary.  */
525818334Speter	c = *p++;
525918334Speter
5260132733Skan	/* Fall through.  */
526118334Speter      default:
526218334Speter	/* Ordinary character: put it into the current argument.  */
526318334Speter	obstack_1grow (&obstack, c);
526418334Speter	arg_going = 1;
526518334Speter      }
526618334Speter
5267117413Skan  /* End of string.  If we are processing a spec function, we need to
5268117413Skan     end any pending argument.  */
5269117413Skan  if (processing_spec_function && arg_going)
5270117413Skan    {
5271117413Skan      obstack_1grow (&obstack, 0);
5272117413Skan      string = obstack_finish (&obstack);
5273117413Skan      if (this_is_library_file)
5274117413Skan        string = find_file (string);
5275117413Skan      store_arg (string, delete_this_arg, this_is_output_file);
5276117413Skan      if (this_is_output_file)
5277117413Skan        outfiles[input_file_number] = string;
5278117413Skan      arg_going = 0;
5279117413Skan    }
5280117413Skan
528190277Sobrien  return 0;
528218334Speter}
528318334Speter
5284117413Skan/* Look up a spec function.  */
5285117413Skan
5286117413Skanstatic const struct spec_function *
5287132733Skanlookup_spec_function (const char *name)
5288117413Skan{
5289117413Skan  static const struct spec_function * const spec_function_tables[] =
5290117413Skan  {
5291117413Skan    static_spec_functions,
5292117413Skan    lang_specific_spec_functions,
5293117413Skan  };
5294117413Skan  const struct spec_function *sf;
5295117413Skan  unsigned int i;
5296117413Skan
5297117413Skan  for (i = 0; i < ARRAY_SIZE (spec_function_tables); i++)
5298117413Skan    {
5299117413Skan      for (sf = spec_function_tables[i]; sf->name != NULL; sf++)
5300117413Skan	if (strcmp (sf->name, name) == 0)
5301117413Skan	  return sf;
5302117413Skan    }
5303117413Skan
5304117413Skan  return NULL;
5305117413Skan}
5306117413Skan
5307117413Skan/* Evaluate a spec function.  */
5308117413Skan
5309117413Skanstatic const char *
5310132733Skaneval_spec_function (const char *func, const char *args)
5311117413Skan{
5312117413Skan  const struct spec_function *sf;
5313117413Skan  const char *funcval;
5314117413Skan
5315117413Skan  /* Saved spec processing context.  */
5316117413Skan  int save_argbuf_index;
5317117413Skan  int save_argbuf_length;
5318117413Skan  const char **save_argbuf;
5319117413Skan
5320117413Skan  int save_arg_going;
5321117413Skan  int save_delete_this_arg;
5322117413Skan  int save_this_is_output_file;
5323117413Skan  int save_this_is_library_file;
5324117413Skan  int save_input_from_pipe;
5325117413Skan  const char *save_suffix_subst;
5326117413Skan
5327117413Skan
5328117413Skan  sf = lookup_spec_function (func);
5329117413Skan  if (sf == NULL)
5330117413Skan    fatal ("unknown spec function `%s'", func);
5331117413Skan
5332117413Skan  /* Push the spec processing context.  */
5333117413Skan  save_argbuf_index = argbuf_index;
5334117413Skan  save_argbuf_length = argbuf_length;
5335117413Skan  save_argbuf = argbuf;
5336117413Skan
5337117413Skan  save_arg_going = arg_going;
5338117413Skan  save_delete_this_arg = delete_this_arg;
5339117413Skan  save_this_is_output_file = this_is_output_file;
5340117413Skan  save_this_is_library_file = this_is_library_file;
5341117413Skan  save_input_from_pipe = input_from_pipe;
5342117413Skan  save_suffix_subst = suffix_subst;
5343117413Skan
5344117413Skan  /* Create a new spec processing context, and build the function
5345117413Skan     arguments.  */
5346117413Skan
5347117413Skan  alloc_args ();
5348117413Skan  if (do_spec_2 (args) < 0)
5349117413Skan    fatal ("error in args to spec function `%s'", func);
5350117413Skan
5351117413Skan  /* argbuf_index is an index for the next argument to be inserted, and
5352117413Skan     so contains the count of the args already inserted.  */
5353117413Skan
5354117413Skan  funcval = (*sf->func) (argbuf_index, argbuf);
5355117413Skan
5356117413Skan  /* Pop the spec processing context.  */
5357117413Skan  argbuf_index = save_argbuf_index;
5358117413Skan  argbuf_length = save_argbuf_length;
5359117413Skan  free (argbuf);
5360117413Skan  argbuf = save_argbuf;
5361117413Skan
5362117413Skan  arg_going = save_arg_going;
5363117413Skan  delete_this_arg = save_delete_this_arg;
5364117413Skan  this_is_output_file = save_this_is_output_file;
5365117413Skan  this_is_library_file = save_this_is_library_file;
5366117413Skan  input_from_pipe = save_input_from_pipe;
5367117413Skan  suffix_subst = save_suffix_subst;
5368117413Skan
5369117413Skan  return funcval;
5370117413Skan}
5371117413Skan
5372117413Skan/* Handle a spec function call of the form:
5373117413Skan
5374117413Skan   %:function(args)
5375117413Skan
5376117413Skan   ARGS is processed as a spec in a separate context and split into an
5377117413Skan   argument vector in the normal fashion.  The function returns a string
5378117413Skan   containing a spec which we then process in the caller's context, or
5379117413Skan   NULL if no processing is required.  */
5380117413Skan
5381117413Skanstatic const char *
5382132733Skanhandle_spec_function (const char *p)
5383117413Skan{
5384117413Skan  char *func, *args;
5385117413Skan  const char *endp, *funcval;
5386117413Skan  int count;
5387117413Skan
5388117413Skan  processing_spec_function++;
5389117413Skan
5390117413Skan  /* Get the function name.  */
5391117413Skan  for (endp = p; *endp != '\0'; endp++)
5392117413Skan    {
5393117413Skan      if (*endp == '(')		/* ) */
5394117413Skan        break;
5395117413Skan      /* Only allow [A-Za-z0-9], -, and _ in function names.  */
5396117413Skan      if (!ISALNUM (*endp) && !(*endp == '-' || *endp == '_'))
5397117413Skan	fatal ("malformed spec function name");
5398117413Skan    }
5399117413Skan  if (*endp != '(')		/* ) */
5400117413Skan    fatal ("no arguments for spec function");
5401117413Skan  func = save_string (p, endp - p);
5402117413Skan  p = ++endp;
5403117413Skan
5404117413Skan  /* Get the arguments.  */
5405117413Skan  for (count = 0; *endp != '\0'; endp++)
5406117413Skan    {
5407117413Skan      /* ( */
5408117413Skan      if (*endp == ')')
5409117413Skan	{
5410117413Skan	  if (count == 0)
5411117413Skan	    break;
5412117413Skan	  count--;
5413117413Skan	}
5414117413Skan      else if (*endp == '(')	/* ) */
5415117413Skan	count++;
5416117413Skan    }
5417117413Skan  /* ( */
5418117413Skan  if (*endp != ')')
5419117413Skan    fatal ("malformed spec function arguments");
5420117413Skan  args = save_string (p, endp - p);
5421117413Skan  p = ++endp;
5422117413Skan
5423117413Skan  /* p now points to just past the end of the spec function expression.  */
5424117413Skan
5425117413Skan  funcval = eval_spec_function (func, args);
5426117413Skan  if (funcval != NULL && do_spec_1 (funcval, 0, NULL) < 0)
5427117413Skan    p = NULL;
5428117413Skan
5429117413Skan  free (func);
5430117413Skan  free (args);
5431117413Skan
5432117413Skan  processing_spec_function--;
5433117413Skan
5434117413Skan  return p;
5435117413Skan}
5436117413Skan
5437132733Skan/* Inline subroutine of handle_braces.  Returns true if the current
5438132733Skan   input suffix matches the atom bracketed by ATOM and END_ATOM.  */
5439132733Skanstatic inline bool
5440132733Skaninput_suffix_matches (const char *atom, const char *end_atom)
5441132733Skan{
5442132733Skan  return (input_suffix
5443132733Skan	  && !strncmp (input_suffix, atom, end_atom - atom)
5444132733Skan	  && input_suffix[end_atom - atom] == '\0');
5445132733Skan}
544618334Speter
5447132733Skan/* Inline subroutine of handle_braces.  Returns true if a switch
5448132733Skan   matching the atom bracketed by ATOM and END_ATOM appeared on the
5449132733Skan   command line.  */
5450132733Skanstatic inline bool
5451132733Skanswitch_matches (const char *atom, const char *end_atom, int starred)
545218334Speter{
5453132733Skan  int i;
5454132733Skan  int len = end_atom - atom;
5455132733Skan  int plen = starred ? len : -1;
545618334Speter
5457132733Skan  for (i = 0; i < n_switches; i++)
5458132733Skan    if (!strncmp (switches[i].part1, atom, len)
5459132733Skan	&& (starred || switches[i].part1[len] == '\0')
5460132733Skan	&& check_live_switch (i, plen))
5461132733Skan      return true;
546250599Sobrien
5463132733Skan  return false;
5464132733Skan}
546518334Speter
5466132733Skan/* Inline subroutine of handle_braces.  Mark all of the switches which
5467132733Skan   match ATOM (extends to END_ATOM; STARRED indicates whether there
5468132733Skan   was a star after the atom) for later processing.  */
5469132733Skanstatic inline void
5470132733Skanmark_matching_switches (const char *atom, const char *end_atom, int starred)
5471132733Skan{
5472132733Skan  int i;
5473132733Skan  int len = end_atom - atom;
5474132733Skan  int plen = starred ? len : -1;
547590277Sobrien
5476132733Skan  for (i = 0; i < n_switches; i++)
5477132733Skan    if (!strncmp (switches[i].part1, atom, len)
5478132733Skan	&& (starred || switches[i].part1[len] == '\0')
5479132733Skan	&& check_live_switch (i, plen))
5480132733Skan      switches[i].ordering = 1;
5481132733Skan}
548250599Sobrien
5483132733Skan/* Inline subroutine of handle_braces.  Process all the currently
5484132733Skan   marked switches through give_switch, and clear the marks.  */
5485132733Skanstatic inline void
5486132733Skanprocess_marked_switches (void)
5487132733Skan{
5488132733Skan  int i;
548918334Speter
5490132733Skan  for (i = 0; i < n_switches; i++)
5491132733Skan    if (switches[i].ordering == 1)
5492132733Skan      {
5493132733Skan	switches[i].ordering = 0;
5494132733Skan	give_switch (i, 0);
5495132733Skan      }
5496132733Skan}
549718334Speter
5498132733Skan/* Handle a %{ ... } construct.  P points just inside the leading {.
5499132733Skan   Returns a pointer one past the end of the brace block, or 0
5500132733Skan   if we call do_spec_1 and that returns -1.  */
550118334Speter
5502132733Skanstatic const char *
5503132733Skanhandle_braces (const char *p)
5504132733Skan{
5505132733Skan  const char *atom, *end_atom;
5506132733Skan  const char *d_atom = NULL, *d_end_atom = NULL;
550790277Sobrien
5508132733Skan  bool a_is_suffix;
5509132733Skan  bool a_is_starred;
5510132733Skan  bool a_is_negated;
5511132733Skan  bool a_matched;
551250599Sobrien
5513132733Skan  bool a_must_be_last = false;
5514132733Skan  bool ordered_set    = false;
5515132733Skan  bool disjunct_set   = false;
5516132733Skan  bool disj_matched   = false;
5517132733Skan  bool disj_starred   = true;
5518132733Skan  bool n_way_choice   = false;
5519132733Skan  bool n_way_matched  = false;
552050599Sobrien
5521132733Skan#define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0)
5522132733Skan
5523132733Skan  do
552418334Speter    {
5525132733Skan      if (a_must_be_last)
5526132733Skan	abort ();
552750599Sobrien
5528132733Skan      /* Scan one "atom" (S in the description above of %{}, possibly
5529132733Skan	 with !, ., or * modifiers).  */
5530132733Skan      a_matched = a_is_suffix = a_is_starred = a_is_negated = false;
553190277Sobrien
5532132733Skan      SKIP_WHITE();
5533132733Skan      if (*p == '!')
5534132733Skan	p++, a_is_negated = true;
553518334Speter
5536132733Skan      SKIP_WHITE();
5537132733Skan      if (*p == '.')
5538132733Skan	p++, a_is_suffix = true;
553918334Speter
5540132733Skan      atom = p;
5541132733Skan      while (ISIDNUM(*p) || *p == '-' || *p == '+' || *p == '='
5542132733Skan	     || *p == ',' || *p == '.' || *p == '@')
5543132733Skan	p++;
5544132733Skan      end_atom = p;
554518334Speter
5546132733Skan      if (*p == '*')
5547132733Skan	p++, a_is_starred = 1;
554890277Sobrien
5549132733Skan      SKIP_WHITE();
5550132733Skan      if (*p == '&' || *p == '}')
5551132733Skan	{
5552132733Skan	  /* Substitute the switch(es) indicated by the current atom.  */
5553132733Skan	  ordered_set = true;
5554132733Skan	  if (disjunct_set || n_way_choice || a_is_negated || a_is_suffix
5555132733Skan	      || atom == end_atom)
5556132733Skan	    abort ();
555718334Speter
5558132733Skan	  mark_matching_switches (atom, end_atom, a_is_starred);
5559132733Skan
5560132733Skan	  if (*p == '}')
5561132733Skan	    process_marked_switches ();
5562132733Skan	}
5563132733Skan      else if (*p == '|' || *p == ':')
556418334Speter	{
5565132733Skan	  /* Substitute some text if the current atom appears as a switch
5566132733Skan	     or suffix.  */
5567132733Skan	  disjunct_set = true;
5568132733Skan	  if (ordered_set)
5569132733Skan	    abort ();
557018334Speter
5571132733Skan	  if (atom == end_atom)
557218334Speter	    {
5573132733Skan	      if (!n_way_choice || disj_matched || *p == '|'
5574132733Skan		  || a_is_negated || a_is_suffix || a_is_starred)
5575132733Skan		abort ();
5576132733Skan
5577132733Skan	      /* An empty term may appear as the last choice of an
5578132733Skan		 N-way choice set; it means "otherwise".  */
5579132733Skan	      a_must_be_last = true;
5580132733Skan	      disj_matched = !n_way_matched;
5581132733Skan	      disj_starred = false;
558218334Speter	    }
5583132733Skan	  else
558418334Speter	    {
5585132733Skan	       if (a_is_suffix && a_is_starred)
5586132733Skan		 abort ();
558718334Speter
5588132733Skan	       if (!a_is_starred)
5589132733Skan		 disj_starred = false;
559018334Speter
5591132733Skan	       /* Don't bother testing this atom if we already have a
5592132733Skan                  match.  */
5593132733Skan	       if (!disj_matched && !n_way_matched)
5594132733Skan		 {
5595132733Skan		   if (a_is_suffix)
5596132733Skan		     a_matched = input_suffix_matches (atom, end_atom);
5597132733Skan		   else
5598132733Skan		     a_matched = switch_matches (atom, end_atom, a_is_starred);
559918334Speter
5600132733Skan		   if (a_matched != a_is_negated)
5601132733Skan		     {
5602132733Skan		       disj_matched = true;
5603132733Skan		       d_atom = atom;
5604132733Skan		       d_end_atom = end_atom;
5605132733Skan		     }
5606132733Skan		 }
560718334Speter	    }
560818334Speter
5609132733Skan	  if (*p == ':')
561018334Speter	    {
5611132733Skan	      /* Found the body, that is, the text to substitute if the
5612132733Skan		 current disjunction matches.  */
5613132733Skan	      p = process_brace_body (p + 1, d_atom, d_end_atom, disj_starred,
5614132733Skan				      disj_matched && !n_way_matched);
5615132733Skan	      if (p == 0)
5616132733Skan		return 0;
561718334Speter
5618132733Skan	      /* If we have an N-way choice, reset state for the next
5619132733Skan		 disjunction.  */
5620132733Skan	      if (*p == ';')
562118334Speter		{
5622132733Skan		  n_way_choice = true;
5623132733Skan		  n_way_matched |= disj_matched;
5624132733Skan		  disj_matched = false;
5625132733Skan		  disj_starred = true;
5626132733Skan		  d_atom = d_end_atom = NULL;
562718334Speter		}
562818334Speter	    }
562918334Speter	}
563018334Speter      else
5631132733Skan	abort ();
5632132733Skan    }
5633132733Skan  while (*p++ != '}');
563418334Speter
5635132733Skan  return p;
5636132733Skan
5637132733Skan#undef SKIP_WHITE
5638132733Skan}
5639132733Skan
5640132733Skan/* Subroutine of handle_braces.  Scan and process a brace substitution body
5641132733Skan   (X in the description of %{} syntax).  P points one past the colon;
5642132733Skan   ATOM and END_ATOM bracket the first atom which was found to be true
5643132733Skan   (present) in the current disjunction; STARRED indicates whether all
5644132733Skan   the atoms in the current disjunction were starred (for syntax validation);
5645132733Skan   MATCHED indicates whether the disjunction matched or not, and therefore
5646132733Skan   whether or not the body is to be processed through do_spec_1 or just
5647132733Skan   skipped.  Returns a pointer to the closing } or ;, or 0 if do_spec_1
5648132733Skan   returns -1.  */
5649132733Skan
5650132733Skanstatic const char *
5651132733Skanprocess_brace_body (const char *p, const char *atom, const char *end_atom,
5652132733Skan		    int starred, int matched)
5653132733Skan{
5654132733Skan  const char *body, *end_body;
5655132733Skan  unsigned int nesting_level;
5656132733Skan  bool have_subst     = false;
5657132733Skan
5658132733Skan  /* Locate the closing } or ;, honoring nested braces.
5659132733Skan     Trim trailing whitespace.  */
5660132733Skan  body = p;
5661132733Skan  nesting_level = 1;
5662132733Skan  for (;;)
5663132733Skan    {
5664132733Skan      if (*p == '{')
5665132733Skan	nesting_level++;
5666132733Skan      else if (*p == '}')
566718334Speter	{
5668132733Skan	  if (!--nesting_level)
5669132733Skan	    break;
567018334Speter	}
5671132733Skan      else if (*p == ';' && nesting_level == 1)
5672132733Skan	break;
5673132733Skan      else if (*p == '%' && p[1] == '*' && nesting_level == 1)
5674132733Skan	have_subst = true;
5675132733Skan      else if (*p == '\0')
5676132733Skan	abort ();
5677132733Skan      p++;
567818334Speter    }
567918334Speter
5680132733Skan  end_body = p;
5681132733Skan  while (end_body[-1] == ' ' || end_body[-1] == '\t')
5682132733Skan    end_body--;
568350599Sobrien
5684132733Skan  if (have_subst && !starred)
5685132733Skan    abort ();
5686132733Skan
5687132733Skan  if (matched)
568890277Sobrien    {
5689132733Skan      /* Copy the substitution body to permanent storage and execute it.
5690132733Skan	 If have_subst is false, this is a simple matter of running the
5691132733Skan	 body through do_spec_1...  */
5692132733Skan      char *string = save_string (body, end_body - body);
5693132733Skan      if (!have_subst)
5694132733Skan	{
5695132733Skan	  if (do_spec_1 (string, 0, NULL) < 0)
5696132733Skan	    return 0;
5697132733Skan	}
5698132733Skan      else
5699132733Skan	{
5700132733Skan	  /* ... but if have_subst is true, we have to process the
5701132733Skan	     body once for each matching switch, with %* set to the
5702132733Skan	     variant part of the switch.  */
5703132733Skan	  unsigned int hard_match_len = end_atom - atom;
5704132733Skan	  int i;
570590277Sobrien
5706132733Skan	  for (i = 0; i < n_switches; i++)
5707132733Skan	    if (!strncmp (switches[i].part1, atom, hard_match_len)
5708132733Skan		&& check_live_switch (i, hard_match_len))
5709132733Skan	      {
5710132733Skan		if (do_spec_1 (string, 0,
5711132733Skan			       &switches[i].part1[hard_match_len]) < 0)
5712132733Skan		  return 0;
5713132733Skan		/* Pass any arguments this switch has.  */
5714132733Skan		give_switch (i, 1);
5715132733Skan		suffix_subst = NULL;
5716132733Skan	      }
5717132733Skan	}
571890277Sobrien    }
571990277Sobrien
5720132733Skan  return p;
572118334Speter}
572218334Speter
572318334Speter/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch
572418334Speter   on the command line.  PREFIX_LENGTH is the length of XXX in an {XXX*}
572518334Speter   spec, or -1 if either exact match or %* is used.
572618334Speter
572718334Speter   A -O switch is obsoleted by a later -O switch.  A -f, -m, or -W switch
572818334Speter   whose value does not begin with "no-" is obsoleted by the same value
572918334Speter   with the "no-", similarly for a switch with the "no-" prefix.  */
573018334Speter
573118334Speterstatic int
5732132733Skancheck_live_switch (int switchnum, int prefix_length)
573318334Speter{
573452520Sobrien  const char *name = switches[switchnum].part1;
573518334Speter  int i;
573618334Speter
573718334Speter  /* In the common case of {<at-most-one-letter>*}, a negating
573818334Speter     switch would always match, so ignore that case.  We will just
573918334Speter     send the conflicting switches to the compiler phase.  */
574018334Speter  if (prefix_length >= 0 && prefix_length <= 1)
574118334Speter    return 1;
574218334Speter
574318334Speter  /* If we already processed this switch and determined if it was
574418334Speter     live or not, return our past determination.  */
574518334Speter  if (switches[switchnum].live_cond != 0)
574618334Speter    return switches[switchnum].live_cond > 0;
574718334Speter
574818334Speter  /* Now search for duplicate in a manner that depends on the name.  */
574918334Speter  switch (*name)
575018334Speter    {
575118334Speter    case 'O':
575290277Sobrien      for (i = switchnum + 1; i < n_switches; i++)
575390277Sobrien	if (switches[i].part1[0] == 'O')
575490277Sobrien	  {
575590277Sobrien	    switches[switchnum].validated = 1;
575690277Sobrien	    switches[switchnum].live_cond = SWITCH_FALSE;
575790277Sobrien	    return 0;
575890277Sobrien	  }
575918334Speter      break;
576018334Speter
576118334Speter    case 'W':  case 'f':  case 'm':
576218334Speter      if (! strncmp (name + 1, "no-", 3))
576318334Speter	{
576450599Sobrien	  /* We have Xno-YYY, search for XYYY.  */
576518334Speter	  for (i = switchnum + 1; i < n_switches; i++)
576618334Speter	    if (switches[i].part1[0] == name[0]
576718334Speter		&& ! strcmp (&switches[i].part1[1], &name[4]))
576890277Sobrien	      {
576990277Sobrien		switches[switchnum].validated = 1;
577090277Sobrien		switches[switchnum].live_cond = SWITCH_FALSE;
577190277Sobrien		return 0;
577290277Sobrien	      }
577318334Speter	}
577418334Speter      else
577518334Speter	{
577618334Speter	  /* We have XYYY, search for Xno-YYY.  */
577718334Speter	  for (i = switchnum + 1; i < n_switches; i++)
577818334Speter	    if (switches[i].part1[0] == name[0]
577918334Speter		&& switches[i].part1[1] == 'n'
578018334Speter		&& switches[i].part1[2] == 'o'
578118334Speter		&& switches[i].part1[3] == '-'
578218334Speter		&& !strcmp (&switches[i].part1[4], &name[1]))
578390277Sobrien	      {
578490277Sobrien		switches[switchnum].validated = 1;
578590277Sobrien		switches[switchnum].live_cond = SWITCH_FALSE;
578690277Sobrien		return 0;
578790277Sobrien	      }
578818334Speter	}
578918334Speter      break;
579018334Speter    }
579118334Speter
579218334Speter  /* Otherwise the switch is live.  */
579390277Sobrien  switches[switchnum].live_cond = SWITCH_LIVE;
579418334Speter  return 1;
579518334Speter}
579618334Speter
579718334Speter/* Pass a switch to the current accumulating command
579818334Speter   in the same form that we received it.
579918334Speter   SWITCHNUM identifies the switch; it is an index into
580018334Speter   the vector of switches gcc received, which is `switches'.
580118334Speter   This cannot fail since it never finishes a command line.
580218334Speter
5803132733Skan   If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument.  */
580418334Speter
580518334Speterstatic void
5806132733Skangive_switch (int switchnum, int omit_first_word)
580718334Speter{
580890277Sobrien  if (switches[switchnum].live_cond == SWITCH_IGNORE)
580990277Sobrien    return;
581090277Sobrien
581118334Speter  if (!omit_first_word)
581218334Speter    {
581390277Sobrien      do_spec_1 ("-", 0, NULL);
581490277Sobrien      do_spec_1 (switches[switchnum].part1, 1, NULL);
581518334Speter    }
581650599Sobrien
581718334Speter  if (switches[switchnum].args != 0)
581818334Speter    {
581990277Sobrien      const char **p;
582018334Speter      for (p = switches[switchnum].args; *p; p++)
582118334Speter	{
582290277Sobrien	  const char *arg = *p;
582390277Sobrien
5824132733Skan	  do_spec_1 (" ", 0, NULL);
582590277Sobrien	  if (suffix_subst)
582690277Sobrien	    {
582790277Sobrien	      unsigned length = strlen (arg);
582890277Sobrien	      int dot = 0;
582990277Sobrien
583090277Sobrien	      while (length-- && !IS_DIR_SEPARATOR (arg[length]))
583190277Sobrien		if (arg[length] == '.')
583290277Sobrien		  {
583390277Sobrien		    ((char *)arg)[length] = 0;
583490277Sobrien		    dot = 1;
583590277Sobrien		    break;
583690277Sobrien		  }
583790277Sobrien	      do_spec_1 (arg, 1, NULL);
583890277Sobrien	      if (dot)
583990277Sobrien		((char *)arg)[length] = '.';
584090277Sobrien	      do_spec_1 (suffix_subst, 1, NULL);
584190277Sobrien	    }
584290277Sobrien	  else
584390277Sobrien	    do_spec_1 (arg, 1, NULL);
584418334Speter	}
584518334Speter    }
584650599Sobrien
584790277Sobrien  do_spec_1 (" ", 0, NULL);
584852520Sobrien  switches[switchnum].validated = 1;
584918334Speter}
585018334Speter
585118334Speter/* Search for a file named NAME trying various prefixes including the
585218334Speter   user's -B prefix and some standard ones.
585318334Speter   Return the absolute file name found.  If nothing is found, return NAME.  */
585418334Speter
585552520Sobrienstatic const char *
5856132733Skanfind_file (const char *name)
585718334Speter{
585818334Speter  char *newname;
585918334Speter
586018334Speter  /* Try multilib_dir if it is defined.  */
5861104763Skan  if (multilib_os_dir != NULL)
586218334Speter    {
5863104763Skan      newname = find_a_file (&startfile_prefixes, name, R_OK, 1);
586418334Speter
586518334Speter      /* If we don't find it in the multi library dir, then fall
586618334Speter	 through and look for it in the normal places.  */
586718334Speter      if (newname != NULL)
586818334Speter	return newname;
586918334Speter    }
587018334Speter
5871104763Skan  newname = find_a_file (&startfile_prefixes, name, R_OK, 0);
587218334Speter  return newname ? newname : name;
587318334Speter}
587418334Speter
587518334Speter/* Determine whether a directory exists.  If LINKER, return 0 for
587618334Speter   certain fixed names not needed by the linker.  If not LINKER, it is
587718334Speter   only important to return 0 if the host machine has a small ARG_MAX
587818334Speter   limit.  */
587918334Speter
588018334Speterstatic int
5881132733Skanis_directory (const char *path1, const char *path2, int linker)
588218334Speter{
588318334Speter  int len1 = strlen (path1);
588418334Speter  int len2 = strlen (path2);
5885132733Skan  char *path = alloca (3 + len1 + len2);
588618334Speter  char *cp;
588718334Speter  struct stat st;
588818334Speter
588918334Speter#ifndef SMALL_ARG_MAX
589018334Speter  if (! linker)
589118334Speter    return 1;
589218334Speter#endif
589318334Speter
589418334Speter  /* Construct the path from the two parts.  Ensure the string ends with "/.".
589518334Speter     The resulting path will be a directory even if the given path is a
589618334Speter     symbolic link.  */
589752520Sobrien  memcpy (path, path1, len1);
589852520Sobrien  memcpy (path + len1, path2, len2);
589918334Speter  cp = path + len1 + len2;
590052520Sobrien  if (!IS_DIR_SEPARATOR (cp[-1]))
590118334Speter    *cp++ = DIR_SEPARATOR;
590218334Speter  *cp++ = '.';
590318334Speter  *cp = '\0';
590418334Speter
590551232Sbde#ifndef FREEBSD_NATIVE
590618334Speter  /* Exclude directories that the linker is known to search.  */
590718334Speter  if (linker
590818334Speter      && ((cp - path == 6
590990277Sobrien	   && strcmp (path, concat (dir_separator_str, "lib",
591090277Sobrien				    dir_separator_str, ".", NULL)) == 0)
591118334Speter	  || (cp - path == 10
591290277Sobrien	      && strcmp (path, concat (dir_separator_str, "usr",
591390277Sobrien				       dir_separator_str, "lib",
591490277Sobrien				       dir_separator_str, ".", NULL)) == 0)))
591518334Speter    return 0;
591651232Sbde#endif /* FREEBSD_NATIVE */
591718334Speter
591818334Speter  return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
591918334Speter}
592090277Sobrien
592190277Sobrien/* Set up the various global variables to indicate that we're processing
592290277Sobrien   the input file named FILENAME.  */
592390277Sobrien
592490277Sobrienvoid
5925132733Skanset_input (const char *filename)
592690277Sobrien{
592790277Sobrien  const char *p;
592890277Sobrien
592990277Sobrien  input_filename = filename;
593090277Sobrien  input_filename_length = strlen (input_filename);
593190277Sobrien
593290277Sobrien  input_basename = input_filename;
593390277Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM
593490277Sobrien  /* Skip drive name so 'x:foo' is handled properly.  */
593590277Sobrien  if (input_basename[1] == ':')
593690277Sobrien    input_basename += 2;
593790277Sobrien#endif
593890277Sobrien  for (p = input_basename; *p; p++)
593990277Sobrien    if (IS_DIR_SEPARATOR (*p))
594090277Sobrien      input_basename = p + 1;
594190277Sobrien
594290277Sobrien  /* Find a suffix starting with the last period,
594390277Sobrien     and set basename_length to exclude that suffix.  */
594490277Sobrien  basename_length = strlen (input_basename);
594590277Sobrien  suffixed_basename_length = basename_length;
594690277Sobrien  p = input_basename + basename_length;
594790277Sobrien  while (p != input_basename && *p != '.')
594890277Sobrien    --p;
594990277Sobrien  if (*p == '.' && p != input_basename)
595090277Sobrien    {
595190277Sobrien      basename_length = p - input_basename;
595290277Sobrien      input_suffix = p + 1;
595390277Sobrien    }
595490277Sobrien  else
595590277Sobrien    input_suffix = "";
5956117413Skan
595790277Sobrien  /* If a spec for 'g', 'u', or 'U' is seen with -save-temps then
595890277Sobrien     we will need to do a stat on the input_filename.  The
595990277Sobrien     INPUT_STAT_SET signals that the stat is needed.  */
596090277Sobrien  input_stat_set = 0;
596190277Sobrien}
596218334Speter
596318334Speter/* On fatal signals, delete all the temporary files.  */
596418334Speter
596518334Speterstatic void
5966132733Skanfatal_error (int signum)
596718334Speter{
596818334Speter  signal (signum, SIG_DFL);
596918334Speter  delete_failure_queue ();
597018334Speter  delete_temp_files ();
597118334Speter  /* Get the same signal again, this time not handled,
597218334Speter     so its normal effect occurs.  */
597318334Speter  kill (getpid (), signum);
597418334Speter}
597518334Speter
5976132733Skanextern int main (int, const char **);
597790277Sobrien
597818334Speterint
5979132733Skanmain (int argc, const char **argv)
598018334Speter{
598190277Sobrien  size_t i;
598218334Speter  int value;
598318334Speter  int linker_was_run = 0;
5984132733Skan  int num_linker_inputs = 0;
598518334Speter  char *explicit_link_files;
598618334Speter  char *specs_file;
598752520Sobrien  const char *p;
598850599Sobrien  struct user_specs *uptr;
598918334Speter
599018334Speter  p = argv[0] + strlen (argv[0]);
599152520Sobrien  while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
599252520Sobrien    --p;
599318334Speter  programname = p;
599418334Speter
599590277Sobrien  xmalloc_set_program_name (programname);
599690277Sobrien
599790277Sobrien#ifdef GCC_DRIVER_HOST_INITIALIZATION
599890277Sobrien  /* Perform host dependent initialization when needed.  */
599990277Sobrien  GCC_DRIVER_HOST_INITIALIZATION;
600052520Sobrien#endif
600152520Sobrien
600290277Sobrien  gcc_init_libintl ();
600390277Sobrien
600418334Speter  if (signal (SIGINT, SIG_IGN) != SIG_IGN)
600518334Speter    signal (SIGINT, fatal_error);
600618334Speter#ifdef SIGHUP
600718334Speter  if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
600818334Speter    signal (SIGHUP, fatal_error);
600918334Speter#endif
601018334Speter  if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
601118334Speter    signal (SIGTERM, fatal_error);
601218334Speter#ifdef SIGPIPE
601318334Speter  if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
601418334Speter    signal (SIGPIPE, fatal_error);
601518334Speter#endif
601690277Sobrien#ifdef SIGCHLD
601790277Sobrien  /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
601890277Sobrien     receive the signal.  A different setting is inheritable */
601990277Sobrien  signal (SIGCHLD, SIG_DFL);
602090277Sobrien#endif
602118334Speter
6022117413Skan  /* Allocate the argument vector.  */
6023117413Skan  alloc_args ();
602418334Speter
602518334Speter  obstack_init (&obstack);
602618334Speter
602750599Sobrien  /* Build multilib_select, et. al from the separate lines that make up each
602850599Sobrien     multilib selection.  */
602950599Sobrien  {
603090277Sobrien    const char *const *q = multilib_raw;
603150599Sobrien    int need_space;
603250599Sobrien
603350599Sobrien    obstack_init (&multilib_obstack);
603450599Sobrien    while ((p = *q++) != (char *) 0)
603550599Sobrien      obstack_grow (&multilib_obstack, p, strlen (p));
603650599Sobrien
603750599Sobrien    obstack_1grow (&multilib_obstack, 0);
603850599Sobrien    multilib_select = obstack_finish (&multilib_obstack);
603950599Sobrien
604050599Sobrien    q = multilib_matches_raw;
604150599Sobrien    while ((p = *q++) != (char *) 0)
604250599Sobrien      obstack_grow (&multilib_obstack, p, strlen (p));
604350599Sobrien
604450599Sobrien    obstack_1grow (&multilib_obstack, 0);
604550599Sobrien    multilib_matches = obstack_finish (&multilib_obstack);
604650599Sobrien
604790277Sobrien    q = multilib_exclusions_raw;
604890277Sobrien    while ((p = *q++) != (char *) 0)
604990277Sobrien      obstack_grow (&multilib_obstack, p, strlen (p));
605090277Sobrien
605190277Sobrien    obstack_1grow (&multilib_obstack, 0);
605290277Sobrien    multilib_exclusions = obstack_finish (&multilib_obstack);
605390277Sobrien
605450599Sobrien    need_space = FALSE;
605590277Sobrien    for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++)
605650599Sobrien      {
605750599Sobrien	if (need_space)
605850599Sobrien	  obstack_1grow (&multilib_obstack, ' ');
605950599Sobrien	obstack_grow (&multilib_obstack,
606050599Sobrien		      multilib_defaults_raw[i],
606150599Sobrien		      strlen (multilib_defaults_raw[i]));
606250599Sobrien	need_space = TRUE;
606350599Sobrien      }
606450599Sobrien
606550599Sobrien    obstack_1grow (&multilib_obstack, 0);
606650599Sobrien    multilib_defaults = obstack_finish (&multilib_obstack);
606750599Sobrien  }
606850599Sobrien
606918334Speter  /* Set up to remember the pathname of gcc and any options
607018334Speter     needed for collect.  We use argv[0] instead of programname because
607118334Speter     we need the complete pathname.  */
607218334Speter  obstack_init (&collect_obstack);
607390277Sobrien  obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1);
607490277Sobrien  obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1);
607518334Speter  putenv (obstack_finish (&collect_obstack));
607618334Speter
607718334Speter#ifdef INIT_ENVIRONMENT
607818334Speter  /* Set up any other necessary machine specific environment variables.  */
607918334Speter  putenv (INIT_ENVIRONMENT);
608018334Speter#endif
608118334Speter
608218334Speter  /* Make a table of what switches there are (switches, n_switches).
608318334Speter     Make a table of specified input files (infiles, n_infiles).
608418334Speter     Decode switches that are handled locally.  */
608518334Speter
608618334Speter  process_command (argc, argv);
608718334Speter
608818334Speter  /* Initialize the vector of specs to just the default.
608918334Speter     This means one element containing 0s, as a terminator.  */
609018334Speter
6091132733Skan  compilers = xmalloc (sizeof default_compilers);
6092132733Skan  memcpy (compilers, default_compilers, sizeof default_compilers);
609318334Speter  n_compilers = n_default_compilers;
609418334Speter
609518334Speter  /* Read specs from a file if there is one.  */
609618334Speter
609791561Sobrien#ifdef FREEBSD_NATIVE
609891561Sobrien  just_machine_suffix = "";
609991561Sobrien#else	/* FREEBSD_NATIVE */
610050599Sobrien  machine_suffix = concat (spec_machine, dir_separator_str,
610190277Sobrien			   spec_version, dir_separator_str, NULL);
610290277Sobrien  just_machine_suffix = concat (spec_machine, dir_separator_str, NULL);
610350599Sobrien#endif /* FREEBSD_NATIVE */
610418334Speter
6105104763Skan  specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, 0);
610618334Speter  /* Read the specs file unless it is a default one.  */
610718334Speter  if (specs_file != 0 && strcmp (specs_file, "specs"))
610850599Sobrien    read_specs (specs_file, TRUE);
610950599Sobrien  else
611050599Sobrien    init_spec ();
611118334Speter
611250599Sobrien  /* We need to check standard_exec_prefix/just_machine_suffix/specs
611390277Sobrien     for any override of as, ld and libraries.  */
611497902Sobrien  specs_file = (char *) alloca (strlen (FBSD_DATA_PREFIX)
611550599Sobrien				+ strlen (just_machine_suffix)
611650599Sobrien				+ sizeof ("specs"));
611750599Sobrien
611897902Sobrien  strcpy (specs_file, FBSD_DATA_PREFIX);
611950599Sobrien  strcat (specs_file, just_machine_suffix);
612050599Sobrien  strcat (specs_file, "specs");
612150599Sobrien  if (access (specs_file, R_OK) == 0)
612250599Sobrien    read_specs (specs_file, TRUE);
612390277Sobrien
6124132733Skan  /* Process any configure-time defaults specified for the command line
6125132733Skan     options, via OPTION_DEFAULT_SPECS.  */
6126132733Skan  for (i = 0; i < ARRAY_SIZE (option_default_specs); i++)
6127132733Skan    do_option_spec (option_default_specs[i].name,
6128132733Skan		    option_default_specs[i].spec);
6129132733Skan
6130132733Skan  /* Process DRIVER_SELF_SPECS, adding any new options to the end
6131132733Skan     of the command line.  */
6132132733Skan
6133132733Skan  for (i = 0; i < ARRAY_SIZE (driver_self_specs); i++)
6134132733Skan    do_self_spec (driver_self_specs[i]);
6135132733Skan
6136132733Skan  /* If not cross-compiling, look for executables in the standard
6137132733Skan     places.  */
6138132733Skan  if (*cross_compile == '0')
613918334Speter    {
614090277Sobrien      if (*md_exec_prefix)
614190277Sobrien	{
614290277Sobrien	  add_prefix (&exec_prefixes, md_exec_prefix, "GCC",
6143104763Skan		      PREFIX_PRIORITY_LAST, 0, NULL, 0);
614490277Sobrien	}
6145132733Skan    }
614618334Speter
6147132733Skan  /* Process sysroot_suffix_spec.  */
6148132733Skan  if (*sysroot_suffix_spec != 0
6149132733Skan      && do_spec_2 (sysroot_suffix_spec) == 0)
6150132733Skan    {
6151132733Skan      if (argbuf_index > 1)
6152132733Skan        error ("spec failure: more than one arg to SYSROOT_SUFFIX_SPEC.");
6153132733Skan      else if (argbuf_index == 1)
6154132733Skan        target_sysroot_suffix = xstrdup (argbuf[argbuf_index -1]);
6155132733Skan    }
6156132733Skan
6157132733Skan  /* Process sysroot_hdrs_suffix_spec.  */
6158132733Skan  if (*sysroot_hdrs_suffix_spec != 0
6159132733Skan      && do_spec_2 (sysroot_hdrs_suffix_spec) == 0)
6160132733Skan    {
6161132733Skan      if (argbuf_index > 1)
6162132733Skan        error ("spec failure: more than one arg to SYSROOT_HEADERS_SUFFIX_SPEC.");
6163132733Skan      else if (argbuf_index == 1)
6164132733Skan        target_sysroot_hdrs_suffix = xstrdup (argbuf[argbuf_index -1]);
6165132733Skan    }
6166132733Skan
6167132733Skan  /* Look for startfiles in the standard places.  */
6168132733Skan  if (*startfile_prefix_spec != 0
6169132733Skan      && do_spec_2 (startfile_prefix_spec) == 0
6170132733Skan      && do_spec_1 (" ", 0, NULL) == 0)
6171132733Skan    {
6172132733Skan      int ndx;
6173132733Skan      for (ndx = 0; ndx < argbuf_index; ndx++)
6174132733Skan	add_sysrooted_prefix (&startfile_prefixes, argbuf[ndx], "BINUTILS",
6175132733Skan			      PREFIX_PRIORITY_LAST, 0, NULL, 1);
6176132733Skan    }
6177132733Skan  /* We should eventually get rid of all these and stick to
6178132733Skan     startfile_prefix_spec exclusively.  */
6179132733Skan  else if (*cross_compile == '0' || target_system_root)
6180132733Skan    {
6181132733Skan      if (*md_exec_prefix)
6182132733Skan	add_sysrooted_prefix (&startfile_prefixes, md_exec_prefix, "GCC",
6183132733Skan			      PREFIX_PRIORITY_LAST, 0, NULL, 1);
6184132733Skan
618590277Sobrien      if (*md_startfile_prefix)
6186132733Skan	add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix,
6187132733Skan			      "GCC", PREFIX_PRIORITY_LAST, 0, NULL, 1);
618818334Speter
618990277Sobrien      if (*md_startfile_prefix_1)
6190132733Skan	add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix_1,
6191132733Skan			      "GCC", PREFIX_PRIORITY_LAST, 0, NULL, 1);
619218334Speter
619318334Speter      /* If standard_startfile_prefix is relative, base it on
619418334Speter	 standard_exec_prefix.  This lets us move the installed tree
619518334Speter	 as a unit.  If GCC_EXEC_PREFIX is defined, base
6196132733Skan	 standard_startfile_prefix on that as well.
6197132733Skan
6198132733Skan         If the prefix is relative, only search it for native compilers;
6199132733Skan         otherwise we will search a directory containing host libraries.  */
6200132733Skan      if (IS_ABSOLUTE_PATH (standard_startfile_prefix))
6201132733Skan	add_sysrooted_prefix (&startfile_prefixes,
6202132733Skan			      standard_startfile_prefix, "BINUTILS",
6203132733Skan			      PREFIX_PRIORITY_LAST, 0, NULL, 1);
6204132733Skan      else if (*cross_compile == '0')
620518334Speter	{
620618334Speter	  if (gcc_exec_prefix)
620718334Speter	    add_prefix (&startfile_prefixes,
620850599Sobrien			concat (gcc_exec_prefix, machine_suffix,
620990277Sobrien				standard_startfile_prefix, NULL),
6210104763Skan			NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1);
621118334Speter	  add_prefix (&startfile_prefixes,
621250599Sobrien		      concat (standard_exec_prefix,
621350599Sobrien			      machine_suffix,
621490277Sobrien			      standard_startfile_prefix, NULL),
6215104763Skan		      NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1);
621690277Sobrien	}
621718334Speter
621818346Speter#ifndef FREEBSD_NATIVE
6219132733Skan      add_sysrooted_prefix (&startfile_prefixes, standard_startfile_prefix_1,
6220132733Skan			    "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1);
6221132733Skan      add_sysrooted_prefix (&startfile_prefixes, standard_startfile_prefix_2,
6222132733Skan			    "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1);
622391561Sobrien#endif	/* not FREEBSD_NATIVE */
622418334Speter#if 0 /* Can cause surprises, and one can use -B./ instead.  */
622590277Sobrien      add_prefix (&startfile_prefixes, "./", NULL,
6226104763Skan		  PREFIX_PRIORITY_LAST, 1, NULL, 0);
622718334Speter#endif
622818334Speter    }
622918334Speter
623052520Sobrien  /* Process any user specified specs in the order given on the command
623152520Sobrien     line.  */
623252520Sobrien  for (uptr = user_specs_head; uptr; uptr = uptr->next)
623352520Sobrien    {
6234104763Skan      char *filename = find_a_file (&startfile_prefixes, uptr->filename,
6235104763Skan				    R_OK, 0);
623652520Sobrien      read_specs (filename ? filename : uptr->filename, FALSE);
623752520Sobrien    }
623852520Sobrien
623918334Speter  /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake.  */
624018334Speter  if (gcc_exec_prefix)
624190277Sobrien    gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
624290277Sobrien			      spec_version, dir_separator_str, NULL);
624318334Speter
624418334Speter  /* Now we have the specs.
624518334Speter     Set the `valid' bits for switches that match anything in any spec.  */
624618334Speter
624718334Speter  validate_all_switches ();
624818334Speter
624918334Speter  /* Now that we have the switches and the specs, set
625018334Speter     the subdirectory based on the options.  */
625118334Speter  set_multilib_dir ();
625218334Speter
625318334Speter  /* Warn about any switches that no pass was interested in.  */
625418334Speter
625590277Sobrien  for (i = 0; (int) i < n_switches; i++)
625652520Sobrien    if (! switches[i].validated)
625718334Speter      error ("unrecognized option `-%s'", switches[i].part1);
625818334Speter
625918334Speter  /* Obey some of the options.  */
626018334Speter
626118334Speter  if (print_search_dirs)
626218334Speter    {
626390277Sobrien      printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix);
626490277Sobrien      printf (_("programs: %s\n"), build_search_list (&exec_prefixes, "", 0));
626590277Sobrien      printf (_("libraries: %s\n"), build_search_list (&startfile_prefixes, "", 0));
626690277Sobrien      return (0);
626718334Speter    }
626818334Speter
626918334Speter  if (print_file_name)
627018334Speter    {
627118334Speter      printf ("%s\n", find_file (print_file_name));
627290277Sobrien      return (0);
627318334Speter    }
627418334Speter
627518334Speter  if (print_prog_name)
627618334Speter    {
6277104763Skan      char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK, 0);
627818334Speter      printf ("%s\n", (newname ? newname : print_prog_name));
627990277Sobrien      return (0);
628018334Speter    }
628118334Speter
628218334Speter  if (print_multi_lib)
628318334Speter    {
628418334Speter      print_multilib_info ();
628590277Sobrien      return (0);
628618334Speter    }
628718334Speter
628818334Speter  if (print_multi_directory)
628918334Speter    {
629018334Speter      if (multilib_dir == NULL)
629118334Speter	printf (".\n");
629218334Speter      else
629318334Speter	printf ("%s\n", multilib_dir);
629490277Sobrien      return (0);
629518334Speter    }
629618334Speter
6297104763Skan  if (print_multi_os_directory)
6298104763Skan    {
6299104763Skan      if (multilib_os_dir == NULL)
6300104763Skan	printf (".\n");
6301104763Skan      else
6302104763Skan	printf ("%s\n", multilib_os_dir);
6303104763Skan      return (0);
6304104763Skan    }
6305104763Skan
630690277Sobrien  if (target_help_flag)
630790277Sobrien   {
630890277Sobrien      /* Print if any target specific options.  */
630990277Sobrien
631090277Sobrien      /* We do not exit here. Instead we have created a fake input file
631190277Sobrien         called 'target-dummy' which needs to be compiled, and we pass this
631290277Sobrien         on to the various sub-processes, along with the --target-help
631390277Sobrien         switch.  */
631490277Sobrien    }
631590277Sobrien
631650599Sobrien  if (print_help_list)
631750599Sobrien    {
631850599Sobrien      display_help ();
631950599Sobrien
632050599Sobrien      if (! verbose_flag)
632150599Sobrien	{
632290277Sobrien	  printf (_("\nFor bug reporting instructions, please see:\n"));
6323117413Skan	  printf ("%s.\n", bug_report_url);
632490277Sobrien
632590277Sobrien	  return (0);
632650599Sobrien	}
632750599Sobrien
632850599Sobrien      /* We do not exit here.  Instead we have created a fake input file
632950599Sobrien	 called 'help-dummy' which needs to be compiled, and we pass this
633090277Sobrien	 on the various sub-processes, along with the --help switch.  */
633150599Sobrien    }
633290277Sobrien
633318334Speter  if (verbose_flag)
633418334Speter    {
633550599Sobrien      int n;
633690277Sobrien      const char *thrmod;
633750599Sobrien
633890277Sobrien      notice ("Configured with: %s\n", configuration_arguments);
633990277Sobrien
634090277Sobrien#ifdef THREAD_MODEL_SPEC
634190277Sobrien      /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
634290277Sobrien	 but there's no point in doing all this processing just to get
634390277Sobrien	 thread_model back.  */
634490277Sobrien      obstack_init (&obstack);
634590277Sobrien      do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
634690277Sobrien      obstack_1grow (&obstack, '\0');
634790277Sobrien      thrmod = obstack_finish (&obstack);
634890277Sobrien#else
634990277Sobrien      thrmod = thread_model;
635090277Sobrien#endif
635190277Sobrien
635290277Sobrien      notice ("Thread model: %s\n", thrmod);
635390277Sobrien
635450599Sobrien      /* compiler_version is truncated at the first space when initialized
635550599Sobrien	 from version string, so truncate version_string at the first space
635650599Sobrien	 before comparing.  */
635750599Sobrien      for (n = 0; version_string[n]; n++)
635850599Sobrien	if (version_string[n] == ' ')
635950599Sobrien	  break;
636050599Sobrien
636150599Sobrien      if (! strncmp (version_string, compiler_version, n)
636250599Sobrien	  && compiler_version[n] == 0)
636352520Sobrien	notice ("gcc version %s\n", version_string);
636418334Speter      else
636552520Sobrien	notice ("gcc driver version %s executing gcc version %s\n",
636652520Sobrien		version_string, compiler_version);
636718334Speter
636818334Speter      if (n_infiles == 0)
636990277Sobrien	return (0);
637018334Speter    }
637118334Speter
637250599Sobrien  if (n_infiles == added_libraries)
637318346Speter    fatal ("No input files specified");
637418334Speter
637518334Speter  /* Make a place to record the compiler output file names
637618334Speter     that correspond to the input files.  */
637718334Speter
637850599Sobrien  i = n_infiles;
637950599Sobrien  i += lang_specific_extra_outfiles;
6380132733Skan  outfiles = xcalloc (i, sizeof (char *));
638118334Speter
638218334Speter  /* Record which files were specified explicitly as link input.  */
638318334Speter
638490277Sobrien  explicit_link_files = xcalloc (1, n_infiles);
638518334Speter
6386132733Skan  if (combine_inputs)
638718334Speter    {
6388132733Skan       int lang_n_infiles = 0;
6389132733Skan       for (i = 0; (int) i < n_infiles; i++)
6390132733Skan	 {
6391132733Skan	   const char *name = infiles[i].name;
6392132733Skan	   struct compiler *compiler
6393132733Skan	     = lookup_compiler (name, strlen (name), infiles[i].language);
6394132733Skan	   if (compiler == NULL)
6395132733Skan	     error ("%s: linker input file unused because linking not done",
6396132733Skan		    name);
6397132733Skan	   else if (lang_n_infiles > 0 && compiler != input_file_compiler)
6398132733Skan	     fatal ("cannot specify -o with -c or -S and multiple languages");
6399132733Skan	   else
6400132733Skan	     {
6401132733Skan	       lang_n_infiles++;
6402132733Skan	       input_file_compiler = compiler;
6403132733Skan	     }
6404132733Skan	 }
6405132733Skan    }
6406132733Skan
6407132733Skan  for (i = 0; (int) i < (combine_inputs ? 1 : n_infiles); i++)
6408132733Skan    {
640918334Speter      int this_file_error = 0;
641018334Speter
641118334Speter      /* Tell do_spec what to substitute for %i.  */
641218334Speter
641318334Speter      input_file_number = i;
641490277Sobrien      set_input (infiles[i].name);
641518334Speter
641618334Speter      /* Use the same thing in %o, unless cp->spec says otherwise.  */
641718334Speter
641818334Speter      outfiles[i] = input_filename;
641918334Speter
642018334Speter      /* Figure out which compiler from the file's suffix.  */
642118334Speter
6422132733Skan      if (! combine_inputs)
6423132733Skan	input_file_compiler
6424132733Skan	  = lookup_compiler (infiles[i].name, input_filename_length,
6425132733Skan			     infiles[i].language);
6426117413Skan
642790277Sobrien      if (input_file_compiler)
642818334Speter	{
642918334Speter	  /* Ok, we found an applicable compiler.  Run its spec.  */
643018334Speter
643190277Sobrien	  if (input_file_compiler->spec[0] == '#')
643218334Speter	    {
643390277Sobrien	      error ("%s: %s compiler not installed on this system",
643490277Sobrien		     input_filename, &input_file_compiler->spec[1]);
643590277Sobrien	      this_file_error = 1;
643618334Speter	    }
643718334Speter	  else
643890277Sobrien	    {
643990277Sobrien	      value = do_spec (input_file_compiler->spec);
644090277Sobrien	      if (value < 0)
644190277Sobrien		this_file_error = 1;
644290277Sobrien	    }
644318334Speter	}
644418334Speter
644518334Speter      /* If this file's name does not contain a recognized suffix,
644618334Speter	 record it as explicit linker input.  */
644718334Speter
644818334Speter      else
644918334Speter	explicit_link_files[i] = 1;
645018334Speter
645118334Speter      /* Clear the delete-on-failure queue, deleting the files in it
645218334Speter	 if this compilation failed.  */
645318334Speter
645418334Speter      if (this_file_error)
645518334Speter	{
645618334Speter	  delete_failure_queue ();
645718334Speter	  error_count++;
645818334Speter	}
645918334Speter      /* If this compilation succeeded, don't delete those files later.  */
646018334Speter      clear_failure_queue ();
646118334Speter    }
646218334Speter
646390277Sobrien  /* Reset the output file name to the first input file name, for use
646490277Sobrien     with %b in LINK_SPEC on a target that prefers not to emit a.out
646590277Sobrien     by default.  */
646690277Sobrien  if (n_infiles > 0)
646790277Sobrien    set_input (infiles[0].name);
646890277Sobrien
646952520Sobrien  if (error_count == 0)
647052520Sobrien    {
647152520Sobrien      /* Make sure INPUT_FILE_NUMBER points to first available open
647252520Sobrien	 slot.  */
647352520Sobrien      input_file_number = n_infiles;
647452520Sobrien      if (lang_specific_pre_link ())
647552520Sobrien	error_count++;
647652520Sobrien    }
647750599Sobrien
6478132733Skan  /* Determine if there are any linker input files.  */
6479132733Skan  num_linker_inputs = 0;
6480132733Skan  for (i = 0; (int) i < n_infiles; i++)
6481132733Skan    if (explicit_link_files[i] || outfiles[i] != NULL)
6482132733Skan      num_linker_inputs++;
6483132733Skan
648418334Speter  /* Run ld to link all the compiler output files.  */
648518334Speter
6486132733Skan  if (num_linker_inputs > 0 && error_count == 0)
648718334Speter    {
648818334Speter      int tmp = execution_count;
648918334Speter
649090277Sobrien      /* We'll use ld if we can't find collect2.  */
649150599Sobrien      if (! strcmp (linker_name_spec, "collect2"))
649250599Sobrien	{
6493104763Skan	  char *s = find_a_file (&exec_prefixes, "collect2", X_OK, 0);
649450599Sobrien	  if (s == NULL)
649550599Sobrien	    linker_name_spec = "ld";
649650599Sobrien	}
649718334Speter      /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
649818334Speter	 for collect.  */
649990277Sobrien      putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH");
650090277Sobrien      putenv_from_prefixes (&startfile_prefixes, LIBRARY_PATH_ENV);
650118334Speter
650218334Speter      value = do_spec (link_command_spec);
650318334Speter      if (value < 0)
650418334Speter	error_count = 1;
650518334Speter      linker_was_run = (tmp != execution_count);
650618334Speter    }
650718334Speter
650818334Speter  /* If options said don't run linker,
650918334Speter     complain about input files to be given to the linker.  */
651018334Speter
651118334Speter  if (! linker_was_run && error_count == 0)
651290277Sobrien    for (i = 0; (int) i < n_infiles; i++)
651318334Speter      if (explicit_link_files[i])
651490277Sobrien	error ("%s: linker input file unused because linking not done",
651518334Speter	       outfiles[i]);
651618334Speter
651718334Speter  /* Delete some or all of the temporary files we made.  */
651818334Speter
651918334Speter  if (error_count)
652018334Speter    delete_failure_queue ();
652118334Speter  delete_temp_files ();
652218334Speter
652350599Sobrien  if (print_help_list)
652450599Sobrien    {
652590277Sobrien      printf (("\nFor bug reporting instructions, please see:\n"));
6526117413Skan      printf ("%s\n", bug_report_url);
652750599Sobrien    }
652890277Sobrien
652990277Sobrien  return (signal_count != 0 ? 2
653090277Sobrien	  : error_count > 0 ? (pass_exit_codes ? greatest_status : 1)
653190277Sobrien	  : 0);
653218334Speter}
653318334Speter
653418334Speter/* Find the proper compilation spec for the file name NAME,
653518334Speter   whose length is LENGTH.  LANGUAGE is the specified language,
653650599Sobrien   or 0 if this file is to be passed to the linker.  */
653718334Speter
653818334Speterstatic struct compiler *
6539132733Skanlookup_compiler (const char *name, size_t length, const char *language)
654018334Speter{
654118334Speter  struct compiler *cp;
654218334Speter
654390277Sobrien  /* If this was specified by the user to be a linker input, indicate that.  */
654450599Sobrien  if (language != 0 && language[0] == '*')
654550599Sobrien    return 0;
654650599Sobrien
654750599Sobrien  /* Otherwise, look for the language, if one is spec'd.  */
654818334Speter  if (language != 0)
654918334Speter    {
655018334Speter      for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
655150599Sobrien	if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language))
655250599Sobrien	  return cp;
655350599Sobrien
655418334Speter      error ("language %s not recognized", language);
655550599Sobrien      return 0;
655618334Speter    }
655718334Speter
655818334Speter  /* Look for a suffix.  */
655918334Speter  for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
656018334Speter    {
656118334Speter      if (/* The suffix `-' matches only the file name `-'.  */
656218334Speter	  (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
656350599Sobrien	  || (strlen (cp->suffix) < length
656450599Sobrien	      /* See if the suffix matches the end of NAME.  */
656550599Sobrien	      && !strcmp (cp->suffix,
656650599Sobrien			  name + length - strlen (cp->suffix))
656750599Sobrien	 ))
6568117413Skan	break;
656990277Sobrien    }
657050599Sobrien
657190277Sobrien#if defined (OS2) ||defined (HAVE_DOS_BASED_FILE_SYSTEM)
657290277Sobrien  /* look again, but case-insensitively this time.  */
657390277Sobrien  if (cp < compilers)
657490277Sobrien    for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
657590277Sobrien      {
657690277Sobrien	if (/* The suffix `-' matches only the file name `-'.  */
657790277Sobrien	    (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
657890277Sobrien	    || (strlen (cp->suffix) < length
657990277Sobrien		/* See if the suffix matches the end of NAME.  */
658090277Sobrien		&& ((!strcmp (cp->suffix,
658190277Sobrien			     name + length - strlen (cp->suffix))
658290277Sobrien		     || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
658390277Sobrien		    && !strcasecmp (cp->suffix,
658490277Sobrien				    name + length - strlen (cp->suffix)))
658590277Sobrien	   ))
658690277Sobrien	  break;
658790277Sobrien      }
658890277Sobrien#endif
658950599Sobrien
659090277Sobrien  if (cp >= compilers)
659190277Sobrien    {
659290277Sobrien      if (cp->spec[0] != '@')
659390277Sobrien	/* A non-alias entry: return it.  */
659490277Sobrien	return cp;
659590277Sobrien
659690277Sobrien      /* An alias entry maps a suffix to a language.
659790277Sobrien	 Search for the language; pass 0 for NAME and LENGTH
659890277Sobrien	 to avoid infinite recursion if language not found.  */
659990277Sobrien      return lookup_compiler (NULL, 0, cp->spec + 1);
660018334Speter    }
660118334Speter  return 0;
660218334Speter}
660318334Speter
660418334Speterstatic char *
6605132733Skansave_string (const char *s, int len)
660618334Speter{
660790277Sobrien  char *result = xmalloc (len + 1);
660818334Speter
660990277Sobrien  memcpy (result, s, len);
661018334Speter  result[len] = 0;
661118334Speter  return result;
661218334Speter}
661318334Speter
661490277Sobrienvoid
6615132733Skanpfatal_with_name (const char *name)
661618334Speter{
661752520Sobrien  perror_with_name (name);
661852520Sobrien  delete_temp_files ();
661952520Sobrien  exit (1);
662018334Speter}
662118334Speter
662218334Speterstatic void
6623132733Skanperror_with_name (const char *name)
662418334Speter{
662552520Sobrien  error ("%s: %s", name, xstrerror (errno));
662618334Speter}
662718334Speter
662818334Speterstatic void
6629132733Skanpfatal_pexecute (const char *errmsg_fmt, const char *errmsg_arg)
663018334Speter{
663150599Sobrien  if (errmsg_arg)
663250599Sobrien    {
663352520Sobrien      int save_errno = errno;
663452520Sobrien
663550599Sobrien      /* Space for trailing '\0' is in %s.  */
663650599Sobrien      char *msg = xmalloc (strlen (errmsg_fmt) + strlen (errmsg_arg));
663750599Sobrien      sprintf (msg, errmsg_fmt, errmsg_arg);
663850599Sobrien      errmsg_fmt = msg;
663952520Sobrien
664052520Sobrien      errno = save_errno;
664150599Sobrien    }
664250599Sobrien
664352520Sobrien  pfatal_with_name (errmsg_fmt);
664418334Speter}
664518334Speter
6646132733Skan/* Output an error message and exit.  */
664718334Speter
664818334Spetervoid
6649132733Skanfancy_abort (void)
665018334Speter{
665190277Sobrien  fatal ("internal gcc abort");
665218334Speter}
665318334Speter
6654132733Skan/* Output an error message and exit.  */
665518334Speter
665652520Sobrienvoid
6657132733Skanfatal (const char *msgid, ...)
665818334Speter{
6659132733Skan  va_list ap;
666018334Speter
6661132733Skan  va_start (ap, msgid);
6662132733Skan
666318334Speter  fprintf (stderr, "%s: ", programname);
666452520Sobrien  vfprintf (stderr, _(msgid), ap);
6665132733Skan  va_end (ap);
666618334Speter  fprintf (stderr, "\n");
666718334Speter  delete_temp_files ();
666818334Speter  exit (1);
666918334Speter}
667018334Speter
667190277Sobrienvoid
6672132733Skanerror (const char *msgid, ...)
667318334Speter{
6674132733Skan  va_list ap;
667518334Speter
6676132733Skan  va_start (ap, msgid);
667718334Speter  fprintf (stderr, "%s: ", programname);
667852520Sobrien  vfprintf (stderr, _(msgid), ap);
6679132733Skan  va_end (ap);
668018334Speter
668118334Speter  fprintf (stderr, "\n");
668218334Speter}
668352520Sobrien
668452520Sobrienstatic void
6685132733Skannotice (const char *msgid, ...)
668652520Sobrien{
6687132733Skan  va_list ap;
668852520Sobrien
6689132733Skan  va_start (ap, msgid);
669052520Sobrien  vfprintf (stderr, _(msgid), ap);
6691132733Skan  va_end (ap);
669252520Sobrien}
669318334Speter
6694132733Skanstatic inline void
6695132733Skanvalidate_switches_from_spec (const char *spec)
6696132733Skan{
6697132733Skan  const char *p = spec;
6698132733Skan  char c;
6699132733Skan  while ((c = *p++))
6700132733Skan    if (c == '%' && (*p == '{' || *p == '<' || (*p == 'W' && *++p == '{')))
6701132733Skan      /* We have a switch spec.  */
6702132733Skan      p = validate_switches (p + 1);
6703132733Skan}
6704132733Skan
670518334Speterstatic void
6706132733Skanvalidate_all_switches (void)
670718334Speter{
670818334Speter  struct compiler *comp;
670918334Speter  struct spec_list *spec;
671018334Speter
671190277Sobrien  for (comp = compilers; comp->spec; comp++)
6712132733Skan    validate_switches_from_spec (comp->spec);
671318334Speter
671490277Sobrien  /* Look through the linked list of specs read from the specs file.  */
671590277Sobrien  for (spec = specs; spec; spec = spec->next)
6716132733Skan    validate_switches_from_spec (*spec->ptr_spec);
671718334Speter
6718132733Skan  validate_switches_from_spec (link_command_spec);
671918334Speter}
672018334Speter
672118334Speter/* Look at the switch-name that comes after START
672218334Speter   and mark as valid all supplied switches that match it.  */
672318334Speter
6724132733Skanstatic const char *
6725132733Skanvalidate_switches (const char *start)
672618334Speter{
672790277Sobrien  const char *p = start;
6728132733Skan  const char *atom;
6729132733Skan  size_t len;
673090277Sobrien  int i;
6731132733Skan  bool suffix = false;
6732132733Skan  bool starred = false;
673318334Speter
6734132733Skan#define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0)
673518334Speter
673690277Sobriennext_member:
6737132733Skan  SKIP_WHITE ();
6738132733Skan
673918334Speter  if (*p == '!')
6740132733Skan    p++;
674118334Speter
6742132733Skan  SKIP_WHITE ();
674318334Speter  if (*p == '.')
6744132733Skan    suffix = true, p++;
674518334Speter
6746132733Skan  atom = p;
6747132733Skan  while (ISIDNUM (*p) || *p == '-' || *p == '+' || *p == '='
6748132733Skan	 || *p == ',' || *p == '.' || *p == '@')
674990277Sobrien    p++;
6750132733Skan  len = p - atom;
675118334Speter
6752132733Skan  if (*p == '*')
6753132733Skan    starred = true, p++;
6754132733Skan
6755132733Skan  SKIP_WHITE ();
6756132733Skan
6757132733Skan  if (!suffix)
675818334Speter    {
675918334Speter      /* Mark all matching switches as valid.  */
676018334Speter      for (i = 0; i < n_switches; i++)
6761132733Skan	if (!strncmp (switches[i].part1, atom, len)
6762132733Skan	    && (starred || switches[i].part1[len] == 0))
676352520Sobrien	  switches[i].validated = 1;
676418334Speter    }
6765132733Skan
6766132733Skan  if (*p) p++;
6767132733Skan  if (*p && (p[-1] == '|' || p[-1] == '&'))
6768132733Skan    goto next_member;
6769132733Skan
6770132733Skan  if (*p && p[-1] == ':')
677118334Speter    {
6772132733Skan      while (*p && *p != ';' && *p != '}')
677318334Speter	{
6774132733Skan	  if (*p == '%')
6775132733Skan	    {
6776132733Skan	      p++;
6777132733Skan	      if (*p == '{' || *p == '<')
6778132733Skan		p = validate_switches (p+1);
6779132733Skan	      else if (p[0] == 'W' && p[1] == '{')
6780132733Skan		p = validate_switches (p+2);
6781132733Skan	    }
6782132733Skan	  else
6783132733Skan	    p++;
678418334Speter	}
6785132733Skan
6786132733Skan      if (*p) p++;
6787132733Skan      if (*p && p[-1] == ';')
6788132733Skan	goto next_member;
678918334Speter    }
679090277Sobrien
6791132733Skan  return p;
6792132733Skan#undef SKIP_WHITE
679318334Speter}
679418334Speter
6795104763Skanstruct mdswitchstr
6796104763Skan{
6797104763Skan  const char *str;
6798104763Skan  int len;
6799104763Skan};
6800104763Skan
6801104763Skanstatic struct mdswitchstr *mdswitches;
6802104763Skanstatic int n_mdswitches;
6803104763Skan
680450599Sobrien/* Check whether a particular argument was used.  The first time we
680550599Sobrien   canonicalize the switches to keep only the ones we care about.  */
680618334Speter
680718334Speterstatic int
6808132733Skanused_arg (const char *p, int len)
680918334Speter{
681090277Sobrien  struct mswitchstr
681190277Sobrien  {
681290277Sobrien    const char *str;
681390277Sobrien    const char *replace;
681450599Sobrien    int len;
681550599Sobrien    int rep_len;
681650599Sobrien  };
681718334Speter
681850599Sobrien  static struct mswitchstr *mswitches;
681950599Sobrien  static int n_mswitches;
682050599Sobrien  int i, j;
682150599Sobrien
682250599Sobrien  if (!mswitches)
682350599Sobrien    {
682450599Sobrien      struct mswitchstr *matches;
682590277Sobrien      const char *q;
682650599Sobrien      int cnt = 0;
682750599Sobrien
682890277Sobrien      /* Break multilib_matches into the component strings of string
682990277Sobrien         and replacement string.  */
683050599Sobrien      for (q = multilib_matches; *q != '\0'; q++)
683150599Sobrien	if (*q == ';')
683250599Sobrien	  cnt++;
683350599Sobrien
6834132733Skan      matches = alloca ((sizeof (struct mswitchstr)) * cnt);
683550599Sobrien      i = 0;
683650599Sobrien      q = multilib_matches;
683750599Sobrien      while (*q != '\0')
683850599Sobrien	{
683950599Sobrien	  matches[i].str = q;
684050599Sobrien	  while (*q != ' ')
684150599Sobrien	    {
684250599Sobrien	      if (*q == '\0')
684350599Sobrien		abort ();
684450599Sobrien	      q++;
684550599Sobrien	    }
684650599Sobrien	  matches[i].len = q - matches[i].str;
684750599Sobrien
684850599Sobrien	  matches[i].replace = ++q;
684950599Sobrien	  while (*q != ';' && *q != '\0')
685050599Sobrien	    {
685150599Sobrien	      if (*q == ' ')
685250599Sobrien		abort ();
685350599Sobrien	      q++;
685450599Sobrien	    }
685550599Sobrien	  matches[i].rep_len = q - matches[i].replace;
685650599Sobrien	  i++;
685750599Sobrien	  if (*q == ';')
685890277Sobrien	    q++;
685950599Sobrien	}
686050599Sobrien
686150599Sobrien      /* Now build a list of the replacement string for switches that we care
686250599Sobrien	 about.  Make sure we allocate at least one entry.  This prevents
686350599Sobrien	 xmalloc from calling fatal, and prevents us from re-executing this
686450599Sobrien	 block of code.  */
686550599Sobrien      mswitches
6866132733Skan	= xmalloc (sizeof (struct mswitchstr)
6867104763Skan		   * (n_mdswitches + (n_switches ? n_switches : 1)));
686850599Sobrien      for (i = 0; i < n_switches; i++)
686950599Sobrien	{
687050599Sobrien	  int xlen = strlen (switches[i].part1);
687150599Sobrien	  for (j = 0; j < cnt; j++)
687290277Sobrien	    if (xlen == matches[j].len
687390277Sobrien		&& ! strncmp (switches[i].part1, matches[j].str, xlen))
687450599Sobrien	      {
687550599Sobrien		mswitches[n_mswitches].str = matches[j].replace;
687650599Sobrien		mswitches[n_mswitches].len = matches[j].rep_len;
687790277Sobrien		mswitches[n_mswitches].replace = (char *) 0;
687850599Sobrien		mswitches[n_mswitches].rep_len = 0;
687950599Sobrien		n_mswitches++;
688050599Sobrien		break;
688150599Sobrien	      }
688250599Sobrien	}
6883104763Skan
6884104763Skan      /* Add MULTILIB_DEFAULTS switches too, as long as they were not present
6885104763Skan	 on the command line nor any options mutually incompatible with
6886104763Skan	 them.  */
6887104763Skan      for (i = 0; i < n_mdswitches; i++)
6888104763Skan	{
6889104763Skan	  const char *r;
6890104763Skan
6891104763Skan	  for (q = multilib_options; *q != '\0'; q++)
6892104763Skan	    {
6893104763Skan	      while (*q == ' ')
6894104763Skan		q++;
6895104763Skan
6896104763Skan	      r = q;
6897104763Skan	      while (strncmp (q, mdswitches[i].str, mdswitches[i].len) != 0
6898104763Skan		     || strchr (" /", q[mdswitches[i].len]) == NULL)
6899104763Skan		{
6900104763Skan		  while (*q != ' ' && *q != '/' && *q != '\0')
6901104763Skan		    q++;
6902104763Skan		  if (*q != '/')
6903104763Skan		    break;
6904104763Skan		  q++;
6905104763Skan		}
6906104763Skan
6907104763Skan	      if (*q != ' ' && *q != '\0')
6908104763Skan		{
6909104763Skan		  while (*r != ' ' && *r != '\0')
6910104763Skan		    {
6911104763Skan		      q = r;
6912104763Skan		      while (*q != ' ' && *q != '/' && *q != '\0')
6913104763Skan			q++;
6914104763Skan
6915104763Skan		      if (used_arg (r, q - r))
6916104763Skan			break;
6917104763Skan
6918104763Skan		      if (*q != '/')
6919104763Skan			{
6920104763Skan			  mswitches[n_mswitches].str = mdswitches[i].str;
6921104763Skan			  mswitches[n_mswitches].len = mdswitches[i].len;
6922104763Skan			  mswitches[n_mswitches].replace = (char *) 0;
6923104763Skan			  mswitches[n_mswitches].rep_len = 0;
6924104763Skan			  n_mswitches++;
6925104763Skan			  break;
6926104763Skan			}
6927104763Skan
6928104763Skan		      r = q + 1;
6929104763Skan		    }
6930104763Skan		  break;
6931104763Skan		}
6932104763Skan	    }
6933104763Skan	}
693450599Sobrien    }
693550599Sobrien
693650599Sobrien  for (i = 0; i < n_mswitches; i++)
693750599Sobrien    if (len == mswitches[i].len && ! strncmp (p, mswitches[i].str, len))
693818334Speter      return 1;
693950599Sobrien
694018334Speter  return 0;
694118334Speter}
694218334Speter
694318334Speterstatic int
6944132733Skandefault_arg (const char *p, int len)
694518334Speter{
6946104763Skan  int i;
694718334Speter
6948104763Skan  for (i = 0; i < n_mdswitches; i++)
6949104763Skan    if (len == mdswitches[i].len && ! strncmp (p, mdswitches[i].str, len))
6950104763Skan      return 1;
695118334Speter
695218334Speter  return 0;
695318334Speter}
695418334Speter
695590277Sobrien/* Work out the subdirectory to use based on the options. The format of
695690277Sobrien   multilib_select is a list of elements. Each element is a subdirectory
695790277Sobrien   name followed by a list of options followed by a semicolon. The format
695890277Sobrien   of multilib_exclusions is the same, but without the preceding
695990277Sobrien   directory. First gcc will check the exclusions, if none of the options
696090277Sobrien   beginning with an exclamation point are present, and all of the other
696190277Sobrien   options are present, then we will ignore this completely. Passing
696290277Sobrien   that, gcc will consider each multilib_select in turn using the same
696390277Sobrien   rules for matching the options. If a match is found, that subdirectory
696490277Sobrien   will be used.  */
696518334Speter
696618334Speterstatic void
6967132733Skanset_multilib_dir (void)
696818334Speter{
696990277Sobrien  const char *p;
697090277Sobrien  unsigned int this_path_len;
697190277Sobrien  const char *this_path, *this_arg;
6972104763Skan  const char *start, *end;
697318334Speter  int not_arg;
6974104763Skan  int ok, ndfltok, first;
697518334Speter
6976104763Skan  n_mdswitches = 0;
6977104763Skan  start = multilib_defaults;
6978104763Skan  while (*start == ' ' || *start == '\t')
6979104763Skan    start++;
6980104763Skan  while (*start != '\0')
6981104763Skan    {
6982104763Skan      n_mdswitches++;
6983104763Skan      while (*start != ' ' && *start != '\t' && *start != '\0')
6984104763Skan	start++;
6985104763Skan      while (*start == ' ' || *start == '\t')
6986104763Skan        start++;
6987104763Skan    }
6988104763Skan
6989104763Skan  if (n_mdswitches)
6990104763Skan    {
6991104763Skan      int i = 0;
6992104763Skan
6993132733Skan      mdswitches = xmalloc (sizeof (struct mdswitchstr) * n_mdswitches);
6994104763Skan      for (start = multilib_defaults; *start != '\0'; start = end + 1)
6995104763Skan	{
6996104763Skan	  while (*start == ' ' || *start == '\t')
6997104763Skan	    start++;
6998104763Skan
6999104763Skan	  if (*start == '\0')
7000104763Skan	    break;
7001132733Skan
7002104763Skan	  for (end = start + 1;
7003104763Skan	       *end != ' ' && *end != '\t' && *end != '\0'; end++)
7004104763Skan	    ;
7005104763Skan
7006104763Skan	  obstack_grow (&multilib_obstack, start, end - start);
7007104763Skan	  obstack_1grow (&multilib_obstack, 0);
7008104763Skan	  mdswitches[i].str = obstack_finish (&multilib_obstack);
7009104763Skan	  mdswitches[i++].len = end - start;
7010104763Skan
7011104763Skan	  if (*end == '\0')
7012104763Skan	    break;
7013104763Skan	}
7014104763Skan    }
7015104763Skan
701690277Sobrien  p = multilib_exclusions;
701718334Speter  while (*p != '\0')
701818334Speter    {
701918334Speter      /* Ignore newlines.  */
702018334Speter      if (*p == '\n')
702118334Speter	{
702218334Speter	  ++p;
702318334Speter	  continue;
702418334Speter	}
702518334Speter
702690277Sobrien      /* Check the arguments.  */
702790277Sobrien      ok = 1;
702890277Sobrien      while (*p != ';')
702990277Sobrien	{
703090277Sobrien	  if (*p == '\0')
703190277Sobrien	    abort ();
703290277Sobrien
703390277Sobrien	  if (! ok)
703490277Sobrien	    {
703590277Sobrien	      ++p;
703690277Sobrien	      continue;
703790277Sobrien	    }
703890277Sobrien
703990277Sobrien	  this_arg = p;
704090277Sobrien	  while (*p != ' ' && *p != ';')
704190277Sobrien	    {
704290277Sobrien	      if (*p == '\0')
704390277Sobrien		abort ();
704490277Sobrien	      ++p;
704590277Sobrien	    }
704690277Sobrien
704790277Sobrien	  if (*this_arg != '!')
704890277Sobrien	    not_arg = 0;
704990277Sobrien	  else
705090277Sobrien	    {
705190277Sobrien	      not_arg = 1;
705290277Sobrien	      ++this_arg;
705390277Sobrien	    }
705490277Sobrien
705590277Sobrien	  ok = used_arg (this_arg, p - this_arg);
705690277Sobrien	  if (not_arg)
705790277Sobrien	    ok = ! ok;
705890277Sobrien
705990277Sobrien	  if (*p == ' ')
706090277Sobrien	    ++p;
706190277Sobrien	}
706290277Sobrien
706390277Sobrien      if (ok)
706490277Sobrien	return;
706590277Sobrien
706690277Sobrien      ++p;
706790277Sobrien    }
706890277Sobrien
7069104763Skan  first = 1;
707090277Sobrien  p = multilib_select;
707190277Sobrien  while (*p != '\0')
707290277Sobrien    {
707390277Sobrien      /* Ignore newlines.  */
707490277Sobrien      if (*p == '\n')
707590277Sobrien	{
707690277Sobrien	  ++p;
707790277Sobrien	  continue;
707890277Sobrien	}
707990277Sobrien
708018334Speter      /* Get the initial path.  */
708118334Speter      this_path = p;
708218334Speter      while (*p != ' ')
708318334Speter	{
708418334Speter	  if (*p == '\0')
708518334Speter	    abort ();
708618334Speter	  ++p;
708718334Speter	}
708818334Speter      this_path_len = p - this_path;
708918334Speter
709018334Speter      /* Check the arguments.  */
709118334Speter      ok = 1;
7092104763Skan      ndfltok = 1;
709318334Speter      ++p;
709418334Speter      while (*p != ';')
709518334Speter	{
709618334Speter	  if (*p == '\0')
709718334Speter	    abort ();
709818334Speter
709918334Speter	  if (! ok)
710018334Speter	    {
710118334Speter	      ++p;
710218334Speter	      continue;
710318334Speter	    }
710418334Speter
710518334Speter	  this_arg = p;
710618334Speter	  while (*p != ' ' && *p != ';')
710718334Speter	    {
710818334Speter	      if (*p == '\0')
710918334Speter		abort ();
711018334Speter	      ++p;
711118334Speter	    }
711218334Speter
711318334Speter	  if (*this_arg != '!')
711418334Speter	    not_arg = 0;
711518334Speter	  else
711618334Speter	    {
711718334Speter	      not_arg = 1;
711818334Speter	      ++this_arg;
711918334Speter	    }
712018334Speter
712118334Speter	  /* If this is a default argument, we can just ignore it.
712218334Speter	     This is true even if this_arg begins with '!'.  Beginning
712318334Speter	     with '!' does not mean that this argument is necessarily
712418334Speter	     inappropriate for this library: it merely means that
712518334Speter	     there is a more specific library which uses this
712618334Speter	     argument.  If this argument is a default, we need not
712718334Speter	     consider that more specific library.  */
7128104763Skan	  ok = used_arg (this_arg, p - this_arg);
7129104763Skan	  if (not_arg)
7130104763Skan	    ok = ! ok;
713118334Speter
7132104763Skan	  if (! ok)
7133104763Skan	    ndfltok = 0;
7134104763Skan
7135104763Skan	  if (default_arg (this_arg, p - this_arg))
7136104763Skan	    ok = 1;
7137104763Skan
713818334Speter	  if (*p == ' ')
713918334Speter	    ++p;
714018334Speter	}
714118334Speter
7142104763Skan      if (ok && first)
714318334Speter	{
714418334Speter	  if (this_path_len != 1
714518334Speter	      || this_path[0] != '.')
714618334Speter	    {
714790277Sobrien	      char *new_multilib_dir = xmalloc (this_path_len + 1);
7148104763Skan	      char *q;
7149104763Skan
715052520Sobrien	      strncpy (new_multilib_dir, this_path, this_path_len);
715152520Sobrien	      new_multilib_dir[this_path_len] = '\0';
7152104763Skan	      q = strchr (new_multilib_dir, ':');
7153104763Skan	      if (q != NULL)
7154104763Skan		*q = '\0';
715552520Sobrien	      multilib_dir = new_multilib_dir;
715618334Speter	    }
7157104763Skan	  first = 0;
715818334Speter	}
715918334Speter
7160104763Skan      if (ndfltok)
7161104763Skan	{
7162104763Skan	  const char *q = this_path, *end = this_path + this_path_len;
7163104763Skan
7164104763Skan	  while (q < end && *q != ':')
7165104763Skan	    q++;
7166104763Skan	  if (q < end)
7167104763Skan	    {
7168104763Skan	      char *new_multilib_os_dir = xmalloc (end - q);
7169104763Skan	      memcpy (new_multilib_os_dir, q + 1, end - q - 1);
7170104763Skan	      new_multilib_os_dir[end - q - 1] = '\0';
7171104763Skan	      multilib_os_dir = new_multilib_os_dir;
7172104763Skan	      break;
7173104763Skan	    }
7174104763Skan	}
7175104763Skan
717618334Speter      ++p;
717790277Sobrien    }
7178104763Skan
7179104763Skan  if (multilib_dir == NULL && multilib_os_dir != NULL
7180104763Skan      && strcmp (multilib_os_dir, ".") == 0)
7181104763Skan    {
7182104763Skan      free ((char *) multilib_os_dir);
7183104763Skan      multilib_os_dir = NULL;
7184104763Skan    }
7185104763Skan  else if (multilib_dir != NULL && multilib_os_dir == NULL)
7186104763Skan    multilib_os_dir = multilib_dir;
718718334Speter}
718818334Speter
718918334Speter/* Print out the multiple library subdirectory selection
719018334Speter   information.  This prints out a series of lines.  Each line looks
719118334Speter   like SUBDIRECTORY;@OPTION@OPTION, with as many options as is
719218334Speter   required.  Only the desired options are printed out, the negative
719318334Speter   matches.  The options are print without a leading dash.  There are
719418334Speter   no spaces to make it easy to use the information in the shell.
719518334Speter   Each subdirectory is printed only once.  This assumes the ordering
719690277Sobrien   generated by the genmultilib script. Also, we leave out ones that match
719790277Sobrien   the exclusions.  */
719818334Speter
719918334Speterstatic void
7200132733Skanprint_multilib_info (void)
720118334Speter{
720290277Sobrien  const char *p = multilib_select;
720390277Sobrien  const char *last_path = 0, *this_path;
720418334Speter  int skip;
720590277Sobrien  unsigned int last_path_len = 0;
720618334Speter
720718334Speter  while (*p != '\0')
720818334Speter    {
720990277Sobrien      skip = 0;
721018334Speter      /* Ignore newlines.  */
721118334Speter      if (*p == '\n')
721218334Speter	{
721318334Speter	  ++p;
721418334Speter	  continue;
721518334Speter	}
721618334Speter
721718334Speter      /* Get the initial path.  */
721818334Speter      this_path = p;
721918334Speter      while (*p != ' ')
722018334Speter	{
722118334Speter	  if (*p == '\0')
722218334Speter	    abort ();
722318334Speter	  ++p;
722418334Speter	}
722518334Speter
7226104763Skan      /* When --disable-multilib was used but target defines
7227104763Skan	 MULTILIB_OSDIRNAMES, entries starting with .: are there just
7228104763Skan	 to find multilib_os_dir, so skip them from output.  */
7229104763Skan      if (this_path[0] == '.' && this_path[1] == ':')
7230104763Skan	skip = 1;
7231104763Skan
723290277Sobrien      /* Check for matches with the multilib_exclusions. We don't bother
723390277Sobrien         with the '!' in either list. If any of the exclusion rules match
723490277Sobrien         all of its options with the select rule, we skip it.  */
723590277Sobrien      {
723690277Sobrien	const char *e = multilib_exclusions;
723790277Sobrien	const char *this_arg;
723818334Speter
723990277Sobrien	while (*e != '\0')
724090277Sobrien	  {
724190277Sobrien	    int m = 1;
724290277Sobrien	    /* Ignore newlines.  */
724390277Sobrien	    if (*e == '\n')
724490277Sobrien	      {
724590277Sobrien		++e;
724690277Sobrien		continue;
724790277Sobrien	      }
724818334Speter
724990277Sobrien	    /* Check the arguments.  */
725090277Sobrien	    while (*e != ';')
725190277Sobrien	      {
725290277Sobrien		const char *q;
725390277Sobrien		int mp = 0;
725490277Sobrien
725590277Sobrien		if (*e == '\0')
725690277Sobrien		  abort ();
725790277Sobrien
725890277Sobrien		if (! m)
725990277Sobrien		  {
726090277Sobrien		    ++e;
726190277Sobrien		    continue;
726290277Sobrien		  }
726390277Sobrien
726490277Sobrien		this_arg = e;
726590277Sobrien
726690277Sobrien		while (*e != ' ' && *e != ';')
726790277Sobrien		  {
726890277Sobrien		    if (*e == '\0')
726990277Sobrien		      abort ();
727090277Sobrien		    ++e;
727190277Sobrien		  }
727290277Sobrien
727390277Sobrien		q = p + 1;
727490277Sobrien		while (*q != ';')
727590277Sobrien		  {
727690277Sobrien		    const char *arg;
727790277Sobrien		    int len = e - this_arg;
727890277Sobrien
727990277Sobrien		    if (*q == '\0')
728090277Sobrien		      abort ();
728190277Sobrien
728290277Sobrien		    arg = q;
728390277Sobrien
728490277Sobrien		    while (*q != ' ' && *q != ';')
728590277Sobrien		      {
728690277Sobrien			if (*q == '\0')
728790277Sobrien			  abort ();
728890277Sobrien			++q;
728990277Sobrien		      }
729090277Sobrien
729190277Sobrien		    if (! strncmp (arg, this_arg, (len < q - arg) ? q - arg : len) ||
729290277Sobrien			default_arg (this_arg, e - this_arg))
729390277Sobrien		      {
729490277Sobrien			mp = 1;
729590277Sobrien			break;
729690277Sobrien		      }
729790277Sobrien
729890277Sobrien		    if (*q == ' ')
729990277Sobrien		      ++q;
730090277Sobrien		  }
730190277Sobrien
730290277Sobrien		if (! mp)
730390277Sobrien		  m = 0;
730490277Sobrien
730590277Sobrien		if (*e == ' ')
730690277Sobrien		  ++e;
730790277Sobrien	      }
730890277Sobrien
730990277Sobrien	    if (m)
731090277Sobrien	      {
731190277Sobrien		skip = 1;
731290277Sobrien		break;
731390277Sobrien	      }
731490277Sobrien
731590277Sobrien	    if (*e != '\0')
731690277Sobrien	      ++e;
731790277Sobrien	  }
731890277Sobrien      }
731990277Sobrien
732090277Sobrien      if (! skip)
732190277Sobrien	{
732290277Sobrien	  /* If this is a duplicate, skip it.  */
732390277Sobrien	  skip = (last_path != 0 && (unsigned int) (p - this_path) == last_path_len
732490277Sobrien		  && ! strncmp (last_path, this_path, last_path_len));
732590277Sobrien
732690277Sobrien	  last_path = this_path;
732790277Sobrien	  last_path_len = p - this_path;
732890277Sobrien	}
732990277Sobrien
733018334Speter      /* If this directory requires any default arguments, we can skip
733118334Speter	 it.  We will already have printed a directory identical to
733218334Speter	 this one which does not require that default argument.  */
733318334Speter      if (! skip)
733418334Speter	{
733590277Sobrien	  const char *q;
733618334Speter
733718334Speter	  q = p + 1;
733818334Speter	  while (*q != ';')
733918334Speter	    {
734090277Sobrien	      const char *arg;
734118334Speter
734218334Speter	      if (*q == '\0')
734318334Speter		abort ();
734418334Speter
734518334Speter	      if (*q == '!')
734618334Speter		arg = NULL;
734718334Speter	      else
734818334Speter		arg = q;
734918334Speter
735018334Speter	      while (*q != ' ' && *q != ';')
735118334Speter		{
735218334Speter		  if (*q == '\0')
735318334Speter		    abort ();
735418334Speter		  ++q;
735518334Speter		}
735618334Speter
735718334Speter	      if (arg != NULL
735818334Speter		  && default_arg (arg, q - arg))
735918334Speter		{
736018334Speter		  skip = 1;
736118334Speter		  break;
736218334Speter		}
736318334Speter
736418334Speter	      if (*q == ' ')
736518334Speter		++q;
736618334Speter	    }
736718334Speter	}
736818334Speter
736918334Speter      if (! skip)
737018334Speter	{
737190277Sobrien	  const char *p1;
737218334Speter
7373104763Skan	  for (p1 = last_path; p1 < p && *p1 != ':'; p1++)
737418334Speter	    putchar (*p1);
737518334Speter	  putchar (';');
737618334Speter	}
737718334Speter
737818334Speter      ++p;
737918334Speter      while (*p != ';')
738018334Speter	{
738118334Speter	  int use_arg;
738218334Speter
738318334Speter	  if (*p == '\0')
738418334Speter	    abort ();
738518334Speter
738618334Speter	  if (skip)
738718334Speter	    {
738818334Speter	      ++p;
738918334Speter	      continue;
739018334Speter	    }
739118334Speter
739218334Speter	  use_arg = *p != '!';
739318334Speter
739418334Speter	  if (use_arg)
739518334Speter	    putchar ('@');
739618334Speter
739718334Speter	  while (*p != ' ' && *p != ';')
739818334Speter	    {
739918334Speter	      if (*p == '\0')
740018334Speter		abort ();
740118334Speter	      if (use_arg)
740218334Speter		putchar (*p);
740318334Speter	      ++p;
740418334Speter	    }
740518334Speter
740618334Speter	  if (*p == ' ')
740718334Speter	    ++p;
740818334Speter	}
740918334Speter
741018334Speter      if (! skip)
741150599Sobrien	{
741290277Sobrien	  /* If there are extra options, print them now.  */
741350599Sobrien	  if (multilib_extra && *multilib_extra)
741450599Sobrien	    {
741550599Sobrien	      int print_at = TRUE;
741690277Sobrien	      const char *q;
741718334Speter
741850599Sobrien	      for (q = multilib_extra; *q != '\0'; q++)
741950599Sobrien		{
742050599Sobrien		  if (*q == ' ')
742150599Sobrien		    print_at = TRUE;
742250599Sobrien		  else
742350599Sobrien		    {
742450599Sobrien		      if (print_at)
742550599Sobrien			putchar ('@');
742650599Sobrien		      putchar (*q);
742750599Sobrien		      print_at = FALSE;
742850599Sobrien		    }
742950599Sobrien		}
743050599Sobrien	    }
743190277Sobrien
743250599Sobrien	  putchar ('\n');
743350599Sobrien	}
743450599Sobrien
743518334Speter      ++p;
743618334Speter    }
743718334Speter}
7438117413Skan
7439117413Skan/* if-exists built-in spec function.
7440117413Skan
7441117413Skan   Checks to see if the file specified by the absolute pathname in
7442117413Skan   ARGS exists.  Returns that pathname if found.
7443117413Skan
7444117413Skan   The usual use for this function is to check for a library file
7445117413Skan   (whose name has been expanded with %s).  */
7446117413Skan
7447117413Skanstatic const char *
7448132733Skanif_exists_spec_function (int argc, const char **argv)
7449117413Skan{
7450117413Skan  /* Must have only one argument.  */
7451132733Skan  if (argc == 1 && IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
7452117413Skan    return argv[0];
7453117413Skan
7454117413Skan  return NULL;
7455117413Skan}
7456117413Skan
7457117413Skan/* if-exists-else built-in spec function.
7458117413Skan
7459117413Skan   This is like if-exists, but takes an additional argument which
7460117413Skan   is returned if the first argument does not exist.  */
7461117413Skan
7462117413Skanstatic const char *
7463132733Skanif_exists_else_spec_function (int argc, const char **argv)
7464117413Skan{
7465117413Skan  /* Must have exactly two arguments.  */
7466117413Skan  if (argc != 2)
7467117413Skan    return NULL;
7468117413Skan
7469132733Skan  if (IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
7470117413Skan    return argv[0];
7471117413Skan
7472117413Skan  return argv[1];
7473117413Skan}
7474