gcc.c revision 161660
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.
4161660Skan   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
5161660Skan   Inc.
618334Speter
790277SobrienThis file is part of GCC.
818334Speter
990277SobrienGCC is free software; you can redistribute it and/or modify it under
1090277Sobrienthe terms of the GNU General Public License as published by the Free
1190277SobrienSoftware Foundation; either version 2, or (at your option) any later
1290277Sobrienversion.
1318334Speter
1490277SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1590277SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1690277SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1790277Sobrienfor more details.
1818334Speter
1918334SpeterYou should have received a copy of the GNU General Public License
2090277Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
2190277SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
2290277Sobrien02111-1307, USA.
2318334Speter
2418334SpeterThis paragraph is here to try to keep Sun CC from dying.
2518334SpeterThe number of chars here seems crucial!!!!  */
2618334Speter
2751232Sbde/* $FreeBSD: head/contrib/gcc/gcc.c 161660 2006-08-26 21:37:21Z kan $ */
2851232Sbde
2918334Speter/* This program is the user interface to the C compiler and possibly to
3018334Speterother compilers.  It is used because compilation is a complicated procedure
3118334Speterwhich involves running several programs and passing temporary files between
3218334Speterthem, forwarding the users switches to those programs selectively,
3318334Speterand deleting the temporary files at the end.
3418334Speter
3518334SpeterCC recognizes how to compile each input file by suffixes in the file names.
3618334SpeterOnce it knows which kind of compilation to perform, the procedure for
3718334Spetercompilation is specified by a string called a "spec".  */
3890277Sobrien
3990277Sobrien/* A Short Introduction to Adding a Command-Line Option.
4090277Sobrien
4190277Sobrien   Before adding a command-line option, consider if it is really
4290277Sobrien   necessary.  Each additional command-line option adds complexity and
4390277Sobrien   is difficult to remove in subsequent versions.
4490277Sobrien
4590277Sobrien   In the following, consider adding the command-line argument
4690277Sobrien   `--bar'.
4790277Sobrien
4890277Sobrien   1. Each command-line option is specified in the specs file.  The
4990277Sobrien   notation is described below in the comment entitled "The Specs
5090277Sobrien   Language".  Read it.
5190277Sobrien
5290277Sobrien   2. In this file, add an entry to "option_map" equating the long
5390277Sobrien   `--' argument version and any shorter, single letter version.  Read
5490277Sobrien   the comments in the declaration of "struct option_map" for an
5590277Sobrien   explanation.  Do not omit the first `-'.
5690277Sobrien
5790277Sobrien   3. Look in the "specs" file to determine which program or option
5890277Sobrien   list should be given the argument, e.g., "cc1_options".  Add the
5990277Sobrien   appropriate syntax for the shorter option version to the
6090277Sobrien   corresponding "const char *" entry in this file.  Omit the first
6190277Sobrien   `-' from the option.  For example, use `-bar', rather than `--bar'.
6290277Sobrien
6390277Sobrien   4. If the argument takes an argument, e.g., `--baz argument1',
6490277Sobrien   modify either DEFAULT_SWITCH_TAKES_ARG or
6590277Sobrien   DEFAULT_WORD_SWITCH_TAKES_ARG in this file.  Omit the first `-'
6690277Sobrien   from `--baz'.
6790277Sobrien
6890277Sobrien   5. Document the option in this file's display_help().  If the
6990277Sobrien   option is passed to a subprogram, modify its corresponding
7090277Sobrien   function, e.g., cppinit.c:print_help() or toplev.c:display_help(),
7190277Sobrien   instead.
7290277Sobrien
7390277Sobrien   6. Compile and test.  Make sure that your new specs file is being
7490277Sobrien   read.  For example, use a debugger to investigate the value of
7590277Sobrien   "specs_file" in main().  */
7690277Sobrien
7750599Sobrien#include "config.h"
7850599Sobrien#include "system.h"
79132733Skan#include "coretypes.h"
80132733Skan#include "multilib.h" /* before tm.h */
81132733Skan#include "tm.h"
8250599Sobrien#include <signal.h>
8390277Sobrien#if ! defined( SIGCHLD ) && defined( SIGCLD )
8490277Sobrien#  define SIGCHLD SIGCLD
8590277Sobrien#endif
8650599Sobrien#include "obstack.h"
8752520Sobrien#include "intl.h"
8852520Sobrien#include "prefix.h"
8990277Sobrien#include "gcc.h"
9090277Sobrien#include "flags.h"
9118334Speter
9290277Sobrien#ifdef HAVE_SYS_RESOURCE_H
9390277Sobrien#include <sys/resource.h>
9418334Speter#endif
9590277Sobrien#if defined (HAVE_DECL_GETRUSAGE) && !HAVE_DECL_GETRUSAGE
96132733Skanextern int getrusage (int, struct rusage *);
9790277Sobrien#endif
9818334Speter
9990277Sobrien/* By default there is no special suffix for target executables.  */
10090277Sobrien/* FIXME: when autoconf is fixed, remove the host check - dj */
10190277Sobrien#if defined(TARGET_EXECUTABLE_SUFFIX) && defined(HOST_EXECUTABLE_SUFFIX)
10290277Sobrien#define HAVE_TARGET_EXECUTABLE_SUFFIX
10318334Speter#endif
10418334Speter
10590277Sobrien/* By default there is no special suffix for host executables.  */
10690277Sobrien#ifdef HOST_EXECUTABLE_SUFFIX
10790277Sobrien#define HAVE_HOST_EXECUTABLE_SUFFIX
10818334Speter#else
10990277Sobrien#define HOST_EXECUTABLE_SUFFIX ""
11018334Speter#endif
11118334Speter
11290277Sobrien/* By default, the suffix for target object files is ".o".  */
11390277Sobrien#ifdef TARGET_OBJECT_SUFFIX
11490277Sobrien#define HAVE_TARGET_OBJECT_SUFFIX
11590277Sobrien#else
11690277Sobrien#define TARGET_OBJECT_SUFFIX ".o"
11718334Speter#endif
11818334Speter
11990277Sobrienstatic const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
12052520Sobrien
12190277Sobrien/* Most every one is fine with LIBRARY_PATH.  For some, it conflicts.  */
12290277Sobrien#ifndef LIBRARY_PATH_ENV
12390277Sobrien#define LIBRARY_PATH_ENV "LIBRARY_PATH"
12490277Sobrien#endif
12590277Sobrien
12650599Sobrien#ifndef HAVE_KILL
12750599Sobrien#define kill(p,s) raise(s)
12818334Speter#endif
12918334Speter
13018334Speter/* If a stage of compilation returns an exit status >= 1,
13118334Speter   compilation of that file ceases.  */
13218334Speter
13318334Speter#define MIN_FATAL_STATUS 1
13418334Speter
13590277Sobrien/* Flag set by cppspec.c to 1.  */
13690277Sobrienint is_cpp_driver;
13790277Sobrien
13890277Sobrien/* Flag saying to pass the greatest exit code returned by a sub-process
13990277Sobrien   to the calling program.  */
14090277Sobrienstatic int pass_exit_codes;
14190277Sobrien
14290277Sobrien/* Definition of string containing the arguments given to configure.  */
14390277Sobrien#include "configargs.h"
14490277Sobrien
14518334Speter/* Flag saying to print the directories gcc will search through looking for
14618334Speter   programs, libraries, etc.  */
14718334Speter
14818334Speterstatic int print_search_dirs;
14918334Speter
15018334Speter/* Flag saying to print the full filename of this file
15118334Speter   as found through our usual search mechanism.  */
15218334Speter
15352520Sobrienstatic const char *print_file_name = NULL;
15418334Speter
15550599Sobrien/* As print_file_name, but search for executable file.  */
15618334Speter
15752520Sobrienstatic const char *print_prog_name = NULL;
15818334Speter
15918334Speter/* Flag saying to print the relative path we'd use to
16018334Speter   find libgcc.a given the current compiler flags.  */
16118334Speter
16218334Speterstatic int print_multi_directory;
16318334Speter
164104763Skan/* Flag saying to print the relative path we'd use to
165104763Skan   find OS libraries given the current compiler flags.  */
166104763Skan
167104763Skanstatic int print_multi_os_directory;
168104763Skan
16918334Speter/* Flag saying to print the list of subdirectories and
17018334Speter   compiler flags used to select them in a standard form.  */
17118334Speter
17218334Speterstatic int print_multi_lib;
17318334Speter
17450599Sobrien/* Flag saying to print the command line options understood by gcc and its
17550599Sobrien   sub-processes.  */
17650599Sobrien
17750599Sobrienstatic int print_help_list;
17850599Sobrien
17918334Speter/* Flag indicating whether we should print the command and arguments */
18018334Speter
18118334Speterstatic int verbose_flag;
18218334Speter
18390277Sobrien/* Flag indicating whether we should ONLY print the command and
18490277Sobrien   arguments (like verbose_flag) without executing the command.
18590277Sobrien   Displayed arguments are quoted so that the generated command
18690277Sobrien   line is suitable for execution.  This is intended for use in
18790277Sobrien   shell scripts to capture the driver-generated command line.  */
18890277Sobrienstatic int verbose_only_flag;
18990277Sobrien
19090277Sobrien/* Flag indicating to print target specific command line options.  */
19190277Sobrien
19290277Sobrienstatic int target_help_flag;
19390277Sobrien
19490277Sobrien/* Flag indicating whether we should report subprocess execution times
19590277Sobrien   (if this is supported by the system - see pexecute.c).  */
19690277Sobrien
19790277Sobrienstatic int report_times;
19890277Sobrien
199132733Skan/* Nonzero means place this string before uses of /, so that include
200132733Skan   and library files can be found in an alternate location.  */
201132733Skan
202132733Skan#ifdef TARGET_SYSTEM_ROOT
203132733Skanstatic const char *target_system_root = TARGET_SYSTEM_ROOT;
204132733Skan#else
205132733Skanstatic const char *target_system_root = 0;
206132733Skan#endif
207132733Skan
208132733Skan/* Nonzero means pass the updated target_system_root to the compiler.  */
209132733Skan
210132733Skanstatic int target_system_root_changed;
211132733Skan
212132733Skan/* Nonzero means append this string to target_system_root.  */
213132733Skan
214132733Skanstatic const char *target_sysroot_suffix = 0;
215132733Skan
216132733Skan/* Nonzero means append this string to target_system_root for headers.  */
217132733Skan
218132733Skanstatic const char *target_sysroot_hdrs_suffix = 0;
219132733Skan
22018334Speter/* Nonzero means write "temp" files in source directory
22118334Speter   and use the source file's name in them, and don't delete them.  */
22218334Speter
22318334Speterstatic int save_temps_flag;
22418334Speter
225132733Skan/* Nonzero means use pipes to communicate between subprocesses.
226132733Skan   Overridden by either of the above two flags.  */
227132733Skan
228132733Skanstatic int use_pipes;
229132733Skan
23018334Speter/* The compiler version.  */
23118334Speter
23290277Sobrienstatic const char *compiler_version;
23318334Speter
23418334Speter/* The target version specified with -V */
23518334Speter
236117413Skanstatic const char *const spec_version = DEFAULT_TARGET_VERSION;
23718334Speter
23818334Speter/* The target machine specified with -b.  */
23918334Speter
24052520Sobrienstatic const char *spec_machine = DEFAULT_TARGET_MACHINE;
24118334Speter
24218334Speter/* Nonzero if cross-compiling.
24318334Speter   When -b is used, the value comes from the `specs' file.  */
24418334Speter
24518334Speter#ifdef CROSS_COMPILE
24690277Sobrienstatic const char *cross_compile = "1";
24718334Speter#else
24890277Sobrienstatic const char *cross_compile = "0";
24918334Speter#endif
25018334Speter
25190277Sobrien#ifdef MODIFY_TARGET_NAME
25290277Sobrien
25390277Sobrien/* Information on how to alter the target name based on a command-line
25490277Sobrien   switch.  The only case we support now is simply appending or deleting a
25590277Sobrien   string to or from the end of the first part of the configuration name.  */
25690277Sobrien
25790277Sobrienstatic const struct modify_target
25890277Sobrien{
25990277Sobrien  const char *const sw;
26090277Sobrien  const enum add_del {ADD, DELETE} add_del;
26190277Sobrien  const char *const str;
26290277Sobrien}
26390277Sobrienmodify_target[] = MODIFY_TARGET_NAME;
26490277Sobrien#endif
265117413Skan
26618334Speter/* The number of errors that have occurred; the link phase will not be
267117413Skan   run if this is nonzero.  */
26818334Speterstatic int error_count = 0;
26918334Speter
27090277Sobrien/* Greatest exit code of sub-processes that has been encountered up to
27190277Sobrien   now.  */
27290277Sobrienstatic int greatest_status = 1;
27390277Sobrien
27418334Speter/* This is the obstack which we use to allocate many strings.  */
27518334Speter
27618334Speterstatic struct obstack obstack;
27718334Speter
27818334Speter/* This is the obstack to build an environment variable to pass to
27918334Speter   collect2 that describes all of the relevant switches of what to
28018334Speter   pass the compiler in building the list of pointers to constructors
28118334Speter   and destructors.  */
28218334Speter
28318334Speterstatic struct obstack collect_obstack;
28418334Speter
28590277Sobrien/* These structs are used to collect resource usage information for
28690277Sobrien   subprocesses.  */
28790277Sobrien#ifdef HAVE_GETRUSAGE
28890277Sobrienstatic struct rusage rus, prus;
28990277Sobrien#endif
29018334Speter
29118334Speter/* Forward declaration for prototypes.  */
29218334Speterstruct path_prefix;
29318334Speter
294132733Skanstatic void init_spec (void);
295132733Skanstatic void store_arg (const char *, int, int);
296132733Skanstatic char *load_specs (const char *);
297132733Skanstatic void read_specs (const char *, int);
298132733Skanstatic void set_spec (const char *, const char *);
299132733Skanstatic struct compiler *lookup_compiler (const char *, size_t, const char *);
300132733Skanstatic char *build_search_list (struct path_prefix *, const char *, int);
301132733Skanstatic void putenv_from_prefixes (struct path_prefix *, const char *);
302132733Skanstatic int access_check (const char *, int);
303132733Skanstatic char *find_a_file (struct path_prefix *, const char *, int, int);
304132733Skanstatic void add_prefix (struct path_prefix *, const char *, const char *,
305132733Skan			int, int, int *, int);
306132733Skanstatic void add_sysrooted_prefix (struct path_prefix *, const char *,
307132733Skan				  const char *, int, int, int *, int);
308132733Skanstatic void translate_options (int *, const char *const **);
309132733Skanstatic char *skip_whitespace (char *);
310132733Skanstatic void delete_if_ordinary (const char *);
311132733Skanstatic void delete_temp_files (void);
312132733Skanstatic void delete_failure_queue (void);
313132733Skanstatic void clear_failure_queue (void);
314132733Skanstatic int check_live_switch (int, int);
315132733Skanstatic const char *handle_braces (const char *);
316132733Skanstatic inline bool input_suffix_matches (const char *, const char *);
317132733Skanstatic inline bool switch_matches (const char *, const char *, int);
318132733Skanstatic inline void mark_matching_switches (const char *, const char *, int);
319132733Skanstatic inline void process_marked_switches (void);
320132733Skanstatic const char *process_brace_body (const char *, const char *, const char *, int, int);
321132733Skanstatic const struct spec_function *lookup_spec_function (const char *);
322132733Skanstatic const char *eval_spec_function (const char *, const char *);
323132733Skanstatic const char *handle_spec_function (const char *);
324132733Skanstatic char *save_string (const char *, int);
325132733Skanstatic void set_collect_gcc_options (void);
326132733Skanstatic int do_spec_1 (const char *, int, const char *);
327132733Skanstatic int do_spec_2 (const char *);
328132733Skanstatic void do_option_spec (const char *, const char *);
329132733Skanstatic void do_self_spec (const char *);
330132733Skanstatic const char *find_file (const char *);
331132733Skanstatic int is_directory (const char *, const char *, int);
332132733Skanstatic const char *validate_switches (const char *);
333132733Skanstatic void validate_all_switches (void);
334132733Skanstatic inline void validate_switches_from_spec (const char *);
335132733Skanstatic void give_switch (int, int);
336132733Skanstatic int used_arg (const char *, int);
337132733Skanstatic int default_arg (const char *, int);
338132733Skanstatic void set_multilib_dir (void);
339132733Skanstatic void print_multilib_info (void);
340132733Skanstatic void perror_with_name (const char *);
341132733Skanstatic void pfatal_pexecute (const char *, const char *) ATTRIBUTE_NORETURN;
342132733Skanstatic void notice (const char *, ...) ATTRIBUTE_PRINTF_1;
343132733Skanstatic void display_help (void);
344132733Skanstatic void add_preprocessor_option (const char *, int);
345132733Skanstatic void add_assembler_option (const char *, int);
346132733Skanstatic void add_linker_option (const char *, int);
347132733Skanstatic void process_command (int, const char **);
348132733Skanstatic int execute (void);
349132733Skanstatic void alloc_args (void);
350132733Skanstatic void clear_args (void);
351132733Skanstatic void fatal_error (int);
35290277Sobrien#ifdef ENABLE_SHARED_LIBGCC
353132733Skanstatic void init_gcc_specs (struct obstack *, const char *, const char *,
354132733Skan			    const char *);
35590277Sobrien#endif
35690277Sobrien#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
357132733Skanstatic const char *convert_filename (const char *, int, int);
35890277Sobrien#endif
359117413Skan
360132733Skanstatic const char *if_exists_spec_function (int, const char **);
361132733Skanstatic const char *if_exists_else_spec_function (int, const char **);
36290277Sobrien
36390277Sobrien/* The Specs Language
36418334Speter
36590277SobrienSpecs are strings containing lines, each of which (if not blank)
36618334Speteris made up of a program name, and arguments separated by spaces.
36718334SpeterThe program name must be exact and start from root, since no path
36818334Speteris searched and it is unreliable to depend on the current working directory.
36918334SpeterRedirection of input or output is not supported; the subprograms must
37018334Speteraccept filenames saying what files to read and write.
37118334Speter
37218334SpeterIn addition, the specs can contain %-sequences to substitute variable text
37318334Speteror for conditional text.  Here is a table of all defined %-sequences.
37418334SpeterNote that spaces are not generated automatically around the results of
37518334Speterexpanding these sequences; therefore, you can concatenate them together
37618334Speteror with constant text in a single argument.
37718334Speter
37818334Speter %%	substitute one % into the program name or argument.
37918334Speter %i     substitute the name of the input file being processed.
38018334Speter %b     substitute the basename of the input file being processed.
38118334Speter	This is the substring up to (and not including) the last period
38218334Speter	and not including the directory.
38390277Sobrien %B	same as %b, but include the file suffix (text after the last period).
38450599Sobrien %gSUFFIX
38550599Sobrien	substitute a file name that has suffix SUFFIX and is chosen
38650599Sobrien	once per compilation, and mark the argument a la %d.  To reduce
38750599Sobrien	exposure to denial-of-service attacks, the file name is now
38850599Sobrien	chosen in a way that is hard to predict even when previously
38950599Sobrien	chosen file names are known.  For example, `%g.s ... %g.o ... %g.s'
39050599Sobrien	might turn into `ccUVUUAU.s ccXYAXZ12.o ccUVUUAU.s'.  SUFFIX matches
39190277Sobrien	the regexp "[.A-Za-z]*%O"; "%O" is treated exactly as if it
39290277Sobrien	had been pre-processed.  Previously, %g was simply substituted
39390277Sobrien	with a file name chosen once per compilation, without regard
39490277Sobrien	to any appended suffix (which was therefore treated just like
39590277Sobrien	ordinary text), making such attacks more likely to succeed.
396132733Skan %|SUFFIX
397132733Skan	like %g, but if -pipe is in effect, expands simply to "-".
398132733Skan %mSUFFIX
399132733Skan        like %g, but if -pipe is in effect, expands to nothing.  (We have both
400132733Skan	%| and %m to accommodate differences between system assemblers; see
401132733Skan	the AS_NEEDS_DASH_FOR_PIPED_INPUT target macro.)
40250599Sobrien %uSUFFIX
40350599Sobrien	like %g, but generates a new temporary file name even if %uSUFFIX
40450599Sobrien	was already seen.
40550599Sobrien %USUFFIX
40650599Sobrien	substitutes the last file name generated with %uSUFFIX, generating a
40750599Sobrien	new one if there is no such last file name.  In the absence of any
40850599Sobrien	%uSUFFIX, this is just like %gSUFFIX, except they don't share
40950599Sobrien	the same suffix "space", so `%g.s ... %U.s ... %g.s ... %U.s'
41050599Sobrien	would involve the generation of two distinct file names, one
41150599Sobrien	for each `%g.s' and another for each `%U.s'.  Previously, %U was
41250599Sobrien	simply substituted with a file name chosen for the previous %u,
41350599Sobrien	without regard to any appended suffix.
41490277Sobrien %jSUFFIX
41590277Sobrien        substitutes the name of the HOST_BIT_BUCKET, if any, and if it is
41690277Sobrien        writable, and if save-temps is off; otherwise, substitute the name
41790277Sobrien        of a temporary file, just like %u.  This temporary file is not
41890277Sobrien        meant for communication between processes, but rather as a junk
41990277Sobrien        disposal mechanism.
42090277Sobrien %.SUFFIX
42190277Sobrien        substitutes .SUFFIX for the suffixes of a matched switch's args when
42290277Sobrien        it is subsequently output with %*. SUFFIX is terminated by the next
42390277Sobrien        space or %.
42418334Speter %d	marks the argument containing or following the %d as a
42518334Speter	temporary file name, so that that file will be deleted if CC exits
42618334Speter	successfully.  Unlike %g, this contributes no text to the argument.
42718334Speter %w	marks the argument containing or following the %w as the
42818334Speter	"output file" of this compilation.  This puts the argument
42918334Speter	into the sequence of arguments that %o will substitute later.
430132733Skan %V	indicates that this compilation produces no "output file".
43118334Speter %W{...}
43218334Speter	like %{...} but mark last argument supplied within
43318334Speter	as a file to be deleted on failure.
43418334Speter %o	substitutes the names of all the output files, with spaces
43518334Speter	automatically placed around them.  You should write spaces
43618334Speter	around the %o as well or the results are undefined.
43718334Speter	%o is for use in the specs for running the linker.
43818334Speter	Input files whose names have no recognized suffix are not compiled
43918334Speter	at all, but they are included among the output files, so they will
44018334Speter	be linked.
44150599Sobrien %O	substitutes the suffix for object files.  Note that this is
44290277Sobrien        handled specially when it immediately follows %g, %u, or %U
44390277Sobrien	(with or without a suffix argument) because of the need for
44490277Sobrien	those to form complete file names.  The handling is such that
44590277Sobrien	%O is treated exactly as if it had already been substituted,
44690277Sobrien	except that %g, %u, and %U do not currently support additional
44790277Sobrien	SUFFIX characters following %O as they would following, for
44890277Sobrien	example, `.o'.
449132733Skan %I	Substitute any of -iprefix (made from GCC_EXEC_PREFIX), -isysroot
450132733Skan	(made from TARGET_SYSTEM_ROOT), and -isystem (made from COMPILER_PATH
451132733Skan	and -B options) as necessary.
45218334Speter %s     current argument is the name of a library or startup file of some sort.
45318334Speter        Search for that file in a standard list of directories
45418334Speter	and substitute the full name found.
45518334Speter %eSTR  Print STR as an error message.  STR is terminated by a newline.
45618334Speter        Use this when inconsistent options are detected.
457117413Skan %nSTR  Print STR as a notice.  STR is terminated by a newline.
45818334Speter %x{OPTION}	Accumulate an option for %X.
45918334Speter %X	Output the accumulated linker options specified by compilations.
46018334Speter %Y	Output the accumulated assembler options specified by compilations.
46118334Speter %Z	Output the accumulated preprocessor options specified by compilations.
46218334Speter %a     process ASM_SPEC as a spec.
46318334Speter        This allows config.h to specify part of the spec for running as.
46418334Speter %A	process ASM_FINAL_SPEC as a spec.  A capital A is actually
46518334Speter	used here.  This can be used to run a post-processor after the
46650599Sobrien	assembler has done its job.
46718334Speter %D	Dump out a -L option for each directory in startfile_prefixes.
46818334Speter	If multilib_dir is set, extra entries are generated with it affixed.
46918334Speter %l     process LINK_SPEC as a spec.
47018334Speter %L     process LIB_SPEC as a spec.
47118334Speter %G     process LIBGCC_SPEC as a spec.
47290277Sobrien %M     output multilib_dir with directory separators replaced with "_";
47390277Sobrien	if multilib_dir is not set or is ".", output "".
47418334Speter %S     process STARTFILE_SPEC as a spec.  A capital S is actually used here.
47518334Speter %E     process ENDFILE_SPEC as a spec.  A capital E is actually used here.
47690277Sobrien %C     process CPP_SPEC as a spec.
47718334Speter %1	process CC1_SPEC as a spec.
47818334Speter %2	process CC1PLUS_SPEC as a spec.
47918334Speter %*	substitute the variable part of a matched option.  (See below.)
48018334Speter	Note that each comma in the substituted string is replaced by
48118334Speter	a single space.
482132733Skan %<S    remove all occurrences of -S from the command line.
483132733Skan        Note - this command is position dependent.  % commands in the
484132733Skan        spec string before this one will see -S, % commands in the
485132733Skan        spec string after this one will not.
486132733Skan %<S*	remove all occurrences of all switches beginning with -S from the
487132733Skan        command line.
488117413Skan %:function(args)
489117413Skan	Call the named function FUNCTION, passing it ARGS.  ARGS is
490117413Skan	first processed as a nested spec string, then split into an
491117413Skan	argument vector in the usual fashion.  The function returns
492117413Skan	a string which is processed as if it had appeared literally
493117413Skan	as part of the current spec.
49418334Speter %{S}   substitutes the -S switch, if that switch was given to CC.
49518334Speter	If that switch was not specified, this substitutes nothing.
49618334Speter	Here S is a metasyntactic variable.
49718334Speter %{S*}  substitutes all the switches specified to CC whose names start
49890277Sobrien	with -S.  This is used for -o, -I, etc; switches that take
49918334Speter	arguments.  CC considers `-o foo' as being one switch whose
50018334Speter	name starts with `o'.  %{o*} would substitute this text,
50118334Speter	including the space; thus, two arguments would be generated.
50290277Sobrien %{S*&T*} likewise, but preserve order of S and T options (the order
503132733Skan	of S and T in the spec is not significant).  Can be any number
504132733Skan	of ampersand-separated variables; for each the wild card is
505132733Skan	optional.  Useful for CPP as %{D*&U*&A*}.
506132733Skan
507132733Skan %{S:X}   substitutes X, if the -S switch was given to CC.
508132733Skan %{!S:X}  substitutes X, if the -S switch was NOT given to CC.
509132733Skan %{S*:X}  substitutes X if one or more switches whose names start
510132733Skan          with -S was given to CC.  Normally X is substituted only
511132733Skan          once, no matter how many such switches appeared.  However,
512132733Skan          if %* appears somewhere in X, then X will be substituted
513132733Skan          once for each matching switch, with the %* replaced by the
514132733Skan          part of that switch that matched the '*'.
515132733Skan %{.S:X}  substitutes X, if processing a file with suffix S.
516132733Skan %{!.S:X} substitutes X, if NOT processing a file with suffix S.
517132733Skan
518132733Skan %{S|T:X} substitutes X if either -S or -T was given to CC.  This may be
519132733Skan	  combined with !, ., and * as above binding stronger than the OR.
520132733Skan	  If %* appears in X, all of the alternatives must be starred, and
521132733Skan	  only the first matching alternative is substituted.
522132733Skan %{S:X;   if S was given to CC, substitutes X;
523132733Skan   T:Y;   else if T was given to CC, substitutes Y;
524132733Skan    :D}   else substitutes D.  There can be as many clauses as you need.
525132733Skan          This may be combined with ., !, |, and * as above.
526132733Skan
52718334Speter %(Spec) processes a specification defined in a specs file as *Spec:
52818334Speter %[Spec] as above, but put __ around -D arguments
52918334Speter
530132733SkanThe conditional text X in a %{S:X} or similar construct may contain
53118334Speterother nested % constructs or spaces, or even newlines.  They are
532132733Skanprocessed as usual, as described above.  Trailing white space in X is
533132733Skanignored.  White space may also appear anywhere on the left side of the
534132733Skancolon in these constructs, except between . or * and the corresponding
535132733Skanword.
53618334Speter
53718334SpeterThe -O, -f, -m, and -W switches are handled specifically in these
53818334Speterconstructs.  If another value of -O or the negated form of a -f, -m, or
53918334Speter-W switch is found later in the command line, the earlier switch
54018334Spetervalue is ignored, except with {S*} where S is just one letter; this
54118334Speterpasses all matching options.
54218334Speter
54350599SobrienThe character | at the beginning of the predicate text is used to indicate
54450599Sobrienthat a command should be piped to the following command, but only if -pipe
54550599Sobrienis specified.
54618334Speter
54718334SpeterNote that it is built into CC which switches take arguments and which
54818334Speterdo not.  You might think it would be useful to generalize this to
54918334Speterallow each compiler's spec to say which switches take arguments.  But
55018334Speterthis cannot be done in a consistent fashion.  CC cannot even decide
55118334Speterwhich input files have been specified without knowing which switches
55218334Spetertake arguments, and it must know which input files to compile in order
55318334Speterto tell which compilers to run.
55418334Speter
55518334SpeterCC also knows implicitly that arguments starting in `-l' are to be
55618334Spetertreated as compiler output files, and passed to the linker in their
55718334Speterproper position among the other output files.  */
55818334Speter
55996285Sobrien/* Define the macros used for specs %a, %l, %L, %S, %C, %1.  */
56018334Speter
56118334Speter/* config.h can define ASM_SPEC to provide extra args to the assembler
56218334Speter   or extra switch-translations.  */
56318334Speter#ifndef ASM_SPEC
56418334Speter#define ASM_SPEC ""
56518334Speter#endif
56618334Speter
56718334Speter/* config.h can define ASM_FINAL_SPEC to run a post processor after
56818334Speter   the assembler has run.  */
56918334Speter#ifndef ASM_FINAL_SPEC
57018334Speter#define ASM_FINAL_SPEC ""
57118334Speter#endif
57218334Speter
57318334Speter/* config.h can define CPP_SPEC to provide extra args to the C preprocessor
57418334Speter   or extra switch-translations.  */
57518334Speter#ifndef CPP_SPEC
57618334Speter#define CPP_SPEC ""
57718334Speter#endif
57818334Speter
57918334Speter/* config.h can define CC1_SPEC to provide extra args to cc1 and cc1plus
58018334Speter   or extra switch-translations.  */
58118334Speter#ifndef CC1_SPEC
58218334Speter#define CC1_SPEC ""
58318334Speter#endif
58418334Speter
58518334Speter/* config.h can define CC1PLUS_SPEC to provide extra args to cc1plus
58618334Speter   or extra switch-translations.  */
58718334Speter#ifndef CC1PLUS_SPEC
58818334Speter#define CC1PLUS_SPEC ""
58918334Speter#endif
59018334Speter
59118334Speter/* config.h can define LINK_SPEC to provide extra args to the linker
59218334Speter   or extra switch-translations.  */
59318334Speter#ifndef LINK_SPEC
59418334Speter#define LINK_SPEC ""
59518334Speter#endif
59618334Speter
59718334Speter/* config.h can define LIB_SPEC to override the default libraries.  */
59818334Speter#ifndef LIB_SPEC
59918334Speter#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
60018334Speter#endif
60118334Speter
60218334Speter/* config.h can define LIBGCC_SPEC to override how and when libgcc.a is
60318334Speter   included.  */
60418334Speter#ifndef LIBGCC_SPEC
60518334Speter#if defined(LINK_LIBGCC_SPECIAL) || defined(LINK_LIBGCC_SPECIAL_1)
60618334Speter/* Have gcc do the search for libgcc.a.  */
60750599Sobrien#define LIBGCC_SPEC "libgcc.a%s"
60818334Speter#else
60950599Sobrien#define LIBGCC_SPEC "-lgcc"
61018334Speter#endif
61118334Speter#endif
61218334Speter
61318334Speter/* config.h can define STARTFILE_SPEC to override the default crt0 files.  */
61418334Speter#ifndef STARTFILE_SPEC
61518334Speter#define STARTFILE_SPEC  \
61618334Speter  "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}"
61718334Speter#endif
61818334Speter
61950599Sobrien/* config.h can define SWITCHES_NEED_SPACES to control which options
62050599Sobrien   require spaces between the option and the argument.  */
62118334Speter#ifndef SWITCHES_NEED_SPACES
62218334Speter#define SWITCHES_NEED_SPACES ""
62318334Speter#endif
62418334Speter
62518334Speter/* config.h can define ENDFILE_SPEC to override the default crtn files.  */
62618334Speter#ifndef ENDFILE_SPEC
62718334Speter#define ENDFILE_SPEC ""
62818334Speter#endif
62918334Speter
63050599Sobrien#ifndef LINKER_NAME
63150599Sobrien#define LINKER_NAME "collect2"
63218334Speter#endif
63318334Speter
63490277Sobrien/* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g'
63590277Sobrien   to the assembler.  */
63690277Sobrien#ifndef ASM_DEBUG_SPEC
63790277Sobrien# if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \
63890277Sobrien     && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
63990277Sobrien#  define ASM_DEBUG_SPEC					\
64090277Sobrien      (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG			\
64190277Sobrien       ? "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}"	\
64290277Sobrien       : "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}")
64390277Sobrien# else
64490277Sobrien#  if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
64590277Sobrien#   define ASM_DEBUG_SPEC "%{g*:--gstabs}"
64690277Sobrien#  endif
64790277Sobrien#  if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG)
64890277Sobrien#   define ASM_DEBUG_SPEC "%{g*:--gdwarf2}"
64990277Sobrien#  endif
65090277Sobrien# endif
65190277Sobrien#endif
65290277Sobrien#ifndef ASM_DEBUG_SPEC
65390277Sobrien# define ASM_DEBUG_SPEC ""
65490277Sobrien#endif
65518334Speter
65690277Sobrien/* Here is the spec for running the linker, after compiling all files.  */
65790277Sobrien
65896285Sobrien/* This is overridable by the target in case they need to specify the
65996285Sobrien   -lgcc and -lc order specially, yet not require them to override all
66096285Sobrien   of LINK_COMMAND_SPEC.  */
66196285Sobrien#ifndef LINK_GCC_C_SEQUENCE_SPEC
66296285Sobrien#define LINK_GCC_C_SEQUENCE_SPEC "%G %L %G"
66396285Sobrien#endif
66496285Sobrien
665132733Skan#ifndef LINK_PIE_SPEC
666132733Skan#ifdef HAVE_LD_PIE
667132733Skan#define LINK_PIE_SPEC "%{pie:-pie} "
668132733Skan#else
669132733Skan#define LINK_PIE_SPEC "%{pie:} "
670132733Skan#endif
671132733Skan#endif
672132733Skan
67390277Sobrien/* -u* was put back because both BSD and SysV seem to support it.  */
67490277Sobrien/* %{static:} simply prevents an error message if the target machine
67590277Sobrien   doesn't handle -static.  */
67690277Sobrien/* We want %{T*} after %{L*} and %D so that it can be used to specify linker
67790277Sobrien   scripts which exist in user specified directories, or in standard
67890277Sobrien   directories.  */
67990277Sobrien#ifndef LINK_COMMAND_SPEC
68090277Sobrien#define LINK_COMMAND_SPEC "\
68190277Sobrien%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
682132733Skan    %(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
683132733Skan    %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
684132733Skan    %{static:} %{L*} %(link_libgcc) %o %{fprofile-arcs|fprofile-generate:-lgcov}\
685132733Skan    %{!nostdlib:%{!nodefaultlibs:%(link_gcc_c_sequence)}}\
68690277Sobrien    %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
68790277Sobrien#endif
68890277Sobrien
68990277Sobrien#ifndef LINK_LIBGCC_SPEC
69090277Sobrien# ifdef LINK_LIBGCC_SPECIAL
69190277Sobrien/* Don't generate -L options for startfile prefix list.  */
69290277Sobrien#  define LINK_LIBGCC_SPEC ""
69390277Sobrien# else
69490277Sobrien/* Do generate them.  */
69590277Sobrien#  define LINK_LIBGCC_SPEC "%D"
69690277Sobrien# endif
69790277Sobrien#endif
69890277Sobrien
699117413Skan#ifndef STARTFILE_PREFIX_SPEC
700117413Skan# define STARTFILE_PREFIX_SPEC ""
701117413Skan#endif
702117413Skan
703132733Skan#ifndef SYSROOT_SUFFIX_SPEC
704132733Skan# define SYSROOT_SUFFIX_SPEC ""
705132733Skan#endif
706132733Skan
707132733Skan#ifndef SYSROOT_HEADERS_SUFFIX_SPEC
708132733Skan# define SYSROOT_HEADERS_SUFFIX_SPEC ""
709132733Skan#endif
710132733Skan
711117413Skanstatic const char *asm_debug;
71290277Sobrienstatic const char *cpp_spec = CPP_SPEC;
71390277Sobrienstatic const char *cc1_spec = CC1_SPEC;
71490277Sobrienstatic const char *cc1plus_spec = CC1PLUS_SPEC;
71596285Sobrienstatic const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC;
71690277Sobrienstatic const char *asm_spec = ASM_SPEC;
71790277Sobrienstatic const char *asm_final_spec = ASM_FINAL_SPEC;
71890277Sobrienstatic const char *link_spec = LINK_SPEC;
71990277Sobrienstatic const char *lib_spec = LIB_SPEC;
72090277Sobrienstatic const char *libgcc_spec = LIBGCC_SPEC;
72190277Sobrienstatic const char *endfile_spec = ENDFILE_SPEC;
72290277Sobrienstatic const char *startfile_spec = STARTFILE_SPEC;
72390277Sobrienstatic const char *switches_need_spaces = SWITCHES_NEED_SPACES;
72490277Sobrienstatic const char *linker_name_spec = LINKER_NAME;
72590277Sobrienstatic const char *link_command_spec = LINK_COMMAND_SPEC;
72690277Sobrienstatic const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
727117413Skanstatic const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC;
728132733Skanstatic const char *sysroot_suffix_spec = SYSROOT_SUFFIX_SPEC;
729132733Skanstatic const char *sysroot_hdrs_suffix_spec = SYSROOT_HEADERS_SUFFIX_SPEC;
73090277Sobrien
73190277Sobrien/* Standard options to cpp, cc1, and as, to reduce duplication in specs.
73290277Sobrien   There should be no need to override these in target dependent files,
73390277Sobrien   but we need to copy them to the specs file so that newer versions
73490277Sobrien   of the GCC driver can correctly drive older tool chains with the
73590277Sobrien   appropriate -B options.  */
73690277Sobrien
737117413Skan/* When cpplib handles traditional preprocessing, get rid of this, and
738117413Skan   call cc1 (or cc1obj in objc/lang-specs.h) from the main specs so
739117413Skan   that we default the front end language better.  */
74090277Sobrienstatic const char *trad_capable_cpp =
741117413Skan"cc1 -E %{traditional|ftraditional|traditional-cpp:-traditional-cpp}";
74290277Sobrien
743107594Sobrien/* We don't wrap .d files in %W{} since a missing .d file, and
744107594Sobrien   therefore no dependency entry, confuses make into thinking a .o
745107594Sobrien   file that happens to exist is up-to-date.  */
74690277Sobrienstatic const char *cpp_unique_options =
747132733Skan"%{C|CC:%{!E:%eGCC does not support -C or -CC without -E}}\
748117413Skan %{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*} %{P} %I\
749107594Sobrien %{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\
750107594Sobrien %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\
751107594Sobrien %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\
75296285Sobrien %{!E:%{!M:%{!MM:%{MD|MMD:%{o*:-MQ %*}}}}}\
753146908Skan %{remap} %{g3:-dD} %{H} %C %{D*&U*&A*} %{i*} %Z %i\
75496285Sobrien %{E|M|MM:%W{o*}}";
75590277Sobrien
75690277Sobrien/* This contains cpp options which are common with cc1_options and are passed
757117413Skan   only when preprocessing only to avoid duplication.  We pass the cc1 spec
758117413Skan   options to the preprocessor so that it the cc1 spec may manipulate
759117413Skan   options used to set target flags.  Those special target flags settings may
760117413Skan   in turn cause preprocessor symbols to be defined specially.  */
76190277Sobrienstatic const char *cpp_options =
762146908Skan"%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w}\
763146908Skan %{f*} %{g*:%{!g0:%{!fno-working-directory:-fworking-directory}}} %{O*}\
764146908Skan %{undef}";
76590277Sobrien
766117413Skan/* This contains cpp options which are not passed when the preprocessor
767117413Skan   output will be used by another program.  */
768117413Skanstatic const char *cpp_debug_options = "%{d*}";
769117413Skan
77090277Sobrien/* NB: This is shared amongst all front-ends.  */
77190277Sobrienstatic const char *cc1_options =
77290277Sobrien"%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
77390277Sobrien %1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\
774132733Skan %{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}%{!c:%{!S:-auxbase %b}}\
775146908Skan %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs}\
776117413Skan %{v:-version} %{pg:-p} %{p} %{f*} %{undef}\
77790277Sobrien %{Qn:-fno-ident} %{--help:--help}\
77890277Sobrien %{--target-help:--target-help}\
77990277Sobrien %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\
78090277Sobrien %{fsyntax-only:-o %j} %{-param*}";
78190277Sobrien
78290277Sobrienstatic const char *asm_options =
78390277Sobrien"%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
78490277Sobrien
78590277Sobrienstatic const char *invoke_as =
786132733Skan#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
787132733Skan"%{!S:-o %|.s |\n as %(asm_options) %|.s %A }";
788132733Skan#else
789132733Skan"%{!S:-o %|.s |\n as %(asm_options) %m.s %A }";
790132733Skan#endif
79190277Sobrien
79250599Sobrien/* Some compilers have limits on line lengths, and the multilib_select
79350599Sobrien   and/or multilib_matches strings can be very long, so we build them at
79450599Sobrien   run time.  */
79550599Sobrienstatic struct obstack multilib_obstack;
79690277Sobrienstatic const char *multilib_select;
79790277Sobrienstatic const char *multilib_matches;
79890277Sobrienstatic const char *multilib_defaults;
79990277Sobrienstatic const char *multilib_exclusions;
80050599Sobrien
80150599Sobrien/* Check whether a particular argument is a default argument.  */
80250599Sobrien
80350599Sobrien#ifndef MULTILIB_DEFAULTS
80450599Sobrien#define MULTILIB_DEFAULTS { "" }
80550599Sobrien#endif
80650599Sobrien
80790277Sobrienstatic const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
80850599Sobrien
809117413Skan#ifndef DRIVER_SELF_SPECS
810117413Skan#define DRIVER_SELF_SPECS ""
811117413Skan#endif
812117413Skan
813117413Skanstatic const char *const driver_self_specs[] = { DRIVER_SELF_SPECS };
814117413Skan
815132733Skan#ifndef OPTION_DEFAULT_SPECS
816132733Skan#define OPTION_DEFAULT_SPECS { "", "" }
817132733Skan#endif
818132733Skan
819132733Skanstruct default_spec
820132733Skan{
821132733Skan  const char *name;
822132733Skan  const char *spec;
823132733Skan};
824132733Skan
825132733Skanstatic const struct default_spec
826132733Skan  option_default_specs[] = { OPTION_DEFAULT_SPECS };
827132733Skan
82890277Sobrienstruct user_specs
82990277Sobrien{
83050599Sobrien  struct user_specs *next;
83152520Sobrien  const char *filename;
83250599Sobrien};
83350599Sobrien
83450599Sobrienstatic struct user_specs *user_specs_head, *user_specs_tail;
83550599Sobrien
83650599Sobrien#ifndef SWITCH_TAKES_ARG
83750599Sobrien#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
83818334Speter#endif
83918334Speter
84018334Speter#ifndef WORD_SWITCH_TAKES_ARG
84118334Speter#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
84218334Speter#endif
84318334Speter
84490277Sobrien#ifdef HAVE_TARGET_EXECUTABLE_SUFFIX
84550599Sobrien/* This defines which switches stop a full compilation.  */
84650599Sobrien#define DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) \
84750599Sobrien  ((CHAR) == 'c' || (CHAR) == 'S')
84850599Sobrien
84950599Sobrien#ifndef SWITCH_CURTAILS_COMPILATION
85050599Sobrien#define SWITCH_CURTAILS_COMPILATION(CHAR) \
85150599Sobrien  DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR)
85250599Sobrien#endif
85350599Sobrien#endif
85450599Sobrien
85518334Speter/* Record the mapping from file suffixes for compilation specs.  */
85618334Speter
85718334Speterstruct compiler
85818334Speter{
85952520Sobrien  const char *suffix;		/* Use this compiler for input files
86018334Speter				   whose names end in this suffix.  */
86118334Speter
86290277Sobrien  const char *spec;		/* To use this compiler, run this spec.  */
86390277Sobrien
86490277Sobrien  const char *cpp_spec;         /* If non-NULL, substitute this spec
86590277Sobrien				   for `%C', rather than the usual
86690277Sobrien				   cpp_spec.  */
86718334Speter};
86818334Speter
86918334Speter/* Pointer to a vector of `struct compiler' that gives the spec for
87018334Speter   compiling a file, based on its suffix.
87118334Speter   A file that does not end in any of these suffixes will be passed
87218334Speter   unchanged to the loader and nothing else will be done to it.
87318334Speter
87418334Speter   An entry containing two 0s is used to terminate the vector.
87518334Speter
87618334Speter   If multiple entries match a file, the last matching one is used.  */
87718334Speter
87818334Speterstatic struct compiler *compilers;
87918334Speter
88018334Speter/* Number of entries in `compilers', not counting the null terminator.  */
88118334Speter
88218334Speterstatic int n_compilers;
88318334Speter
88418334Speter/* The default list of file name suffixes and their compilation specs.  */
88518334Speter
88690277Sobrienstatic const struct compiler default_compilers[] =
88718334Speter{
88850599Sobrien  /* Add lists of suffixes of known languages here.  If those languages
88950599Sobrien     were not present when we built the driver, we will hit these copies
89050599Sobrien     and be given a more meaningful error than "file not used since
89150599Sobrien     linking is not done".  */
89290277Sobrien  {".m",  "#Objective-C", 0}, {".mi",  "#Objective-C", 0},
89390277Sobrien  {".cc", "#C++", 0}, {".cxx", "#C++", 0}, {".cpp", "#C++", 0},
89490277Sobrien  {".cp", "#C++", 0}, {".c++", "#C++", 0}, {".C", "#C++", 0},
895132733Skan  {".CPP", "#C++", 0}, {".ii", "#C++", 0},
89690277Sobrien  {".ads", "#Ada", 0}, {".adb", "#Ada", 0},
89790277Sobrien  {".f", "#Fortran", 0}, {".for", "#Fortran", 0}, {".fpp", "#Fortran", 0},
89890277Sobrien  {".F", "#Fortran", 0}, {".FOR", "#Fortran", 0}, {".FPP", "#Fortran", 0},
89990277Sobrien  {".r", "#Ratfor", 0},
90090277Sobrien  {".p", "#Pascal", 0}, {".pas", "#Pascal", 0},
90190277Sobrien  {".java", "#Java", 0}, {".class", "#Java", 0},
90290277Sobrien  {".zip", "#Java", 0}, {".jar", "#Java", 0},
90350599Sobrien  /* Next come the entries for C.  */
90490277Sobrien  {".c", "@c", 0},
90518334Speter  {"@c",
90690277Sobrien   /* cc1 has an integrated ISO C preprocessor.  We should invoke the
907117413Skan      external preprocessor if -save-temps is given.  */
908117413Skan     "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
90990277Sobrien      %{!E:%{!M:%{!MM:\
910117413Skan          %{traditional|ftraditional:\
911117413Skan%eGNU C no longer supports -traditional without -E}\
912117413Skan	  %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
913132733Skan		%(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\
914132733Skan		    cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \
915132733Skan			%(cc1_options)}\
916117413Skan	  %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
917117413Skan		cc1 %(cpp_unique_options) %(cc1_options)}}}\
91890277Sobrien        %{!fsyntax-only:%(invoke_as)}}}}", 0},
91918334Speter  {"-",
920146908Skan   "%{!E:%e-E or -x required when input is from standard input}\
921117413Skan    %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 0},
92290277Sobrien  {".h", "@c-header", 0},
92318334Speter  {"@c-header",
924132733Skan   /* cc1 has an integrated ISO C preprocessor.  We should invoke the
925132733Skan      external preprocessor if -save-temps is given.  */
926132733Skan     "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
927132733Skan      %{!E:%{!M:%{!MM:\
928132733Skan	  %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
929132733Skan		%(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\
930132733Skan		    cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \
931132733Skan			%(cc1_options)\
932132733Skan                        -o %g.s %{!o*:--output-pch=%i.gch}\
933132733Skan                        %W{o*:--output-pch=%*}%V}\
934132733Skan	  %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
935132733Skan		cc1 %(cpp_unique_options) %(cc1_options)\
936132733Skan                    -o %g.s %{!o*:--output-pch=%i.gch}\
937132733Skan                    %W{o*:--output-pch=%*}%V}}}}}}", 0},
93890277Sobrien  {".i", "@cpp-output", 0},
93918334Speter  {"@cpp-output",
94090277Sobrien   "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0},
94190277Sobrien  {".s", "@assembler", 0},
94218334Speter  {"@assembler",
94390277Sobrien   "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0},
94490277Sobrien  {".S", "@assembler-with-cpp", 0},
94518334Speter  {"@assembler-with-cpp",
946132733Skan#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
94790277Sobrien   "%(trad_capable_cpp) -lang-asm %(cpp_options)\
948117413Skan      %{E|M|MM:%(cpp_debug_options)}\
949132733Skan      %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
950132733Skan       as %(asm_debug) %(asm_options) %|.s %A }}}}"
951132733Skan#else
952132733Skan   "%(trad_capable_cpp) -lang-asm %(cpp_options)\
953132733Skan      %{E|M|MM:%(cpp_debug_options)}\
954132733Skan      %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
955132733Skan       as %(asm_debug) %(asm_options) %m.s %A }}}}"
956132733Skan#endif
957132733Skan   , 0},
958132733Skan
95918334Speter#include "specs.h"
960132733Skan  /* Mark end of table.  */
96190277Sobrien  {0, 0, 0}
96218334Speter};
96318334Speter
96418334Speter/* Number of elements in default_compilers, not counting the terminator.  */
96518334Speter
966117413Skanstatic const int n_default_compilers = ARRAY_SIZE (default_compilers) - 1;
96718334Speter
96818334Speter/* A vector of options to give to the linker.
96918334Speter   These options are accumulated by %x,
97018334Speter   and substituted into the linker command with %X.  */
97118334Speterstatic int n_linker_options;
97218334Speterstatic char **linker_options;
97318334Speter
97418334Speter/* A vector of options to give to the assembler.
97518334Speter   These options are accumulated by -Wa,
97618334Speter   and substituted into the assembler command with %Y.  */
97718334Speterstatic int n_assembler_options;
97818334Speterstatic char **assembler_options;
97918334Speter
98018334Speter/* A vector of options to give to the preprocessor.
98118334Speter   These options are accumulated by -Wp,
98218334Speter   and substituted into the preprocessor command with %Z.  */
98318334Speterstatic int n_preprocessor_options;
98418334Speterstatic char **preprocessor_options;
98518334Speter
98618334Speter/* Define how to map long options into short ones.  */
98718334Speter
98818334Speter/* This structure describes one mapping.  */
98918334Speterstruct option_map
99018334Speter{
99118334Speter  /* The long option's name.  */
99290277Sobrien  const char *const name;
99318334Speter  /* The equivalent short option.  */
99490277Sobrien  const char *const equivalent;
99518334Speter  /* Argument info.  A string of flag chars; NULL equals no options.
99618334Speter     a => argument required.
99718334Speter     o => argument optional.
99818334Speter     j => join argument to equivalent, making one word.
99918334Speter     * => require other text after NAME as an argument.  */
100090277Sobrien  const char *const arg_info;
100118334Speter};
100218334Speter
100318334Speter/* This is the table of mappings.  Mappings are tried sequentially
100418334Speter   for each option encountered; the first one that matches, wins.  */
100518334Speter
100690277Sobrienstatic const struct option_map option_map[] =
100718334Speter {
100818334Speter   {"--all-warnings", "-Wall", 0},
100918334Speter   {"--ansi", "-ansi", 0},
101018334Speter   {"--assemble", "-S", 0},
101118334Speter   {"--assert", "-A", "a"},
101252520Sobrien   {"--classpath", "-fclasspath=", "aj"},
101396285Sobrien   {"--bootclasspath", "-fbootclasspath=", "aj"},
101496285Sobrien   {"--CLASSPATH", "-fclasspath=", "aj"},
101518334Speter   {"--comments", "-C", 0},
1016117413Skan   {"--comments-in-macros", "-CC", 0},
101718334Speter   {"--compile", "-c", 0},
101818334Speter   {"--debug", "-g", "oj"},
101950599Sobrien   {"--define-macro", "-D", "aj"},
102018334Speter   {"--dependencies", "-M", 0},
102118334Speter   {"--dump", "-d", "a"},
102218334Speter   {"--dumpbase", "-dumpbase", "a"},
102318334Speter   {"--entry", "-e", 0},
102418334Speter   {"--extra-warnings", "-W", 0},
102518334Speter   {"--for-assembler", "-Wa", "a"},
102618334Speter   {"--for-linker", "-Xlinker", "a"},
102718334Speter   {"--force-link", "-u", "a"},
102818334Speter   {"--imacros", "-imacros", "a"},
102918334Speter   {"--include", "-include", "a"},
103018334Speter   {"--include-barrier", "-I-", 0},
103150599Sobrien   {"--include-directory", "-I", "aj"},
103218334Speter   {"--include-directory-after", "-idirafter", "a"},
103318334Speter   {"--include-prefix", "-iprefix", "a"},
103418334Speter   {"--include-with-prefix", "-iwithprefix", "a"},
103518334Speter   {"--include-with-prefix-before", "-iwithprefixbefore", "a"},
103618334Speter   {"--include-with-prefix-after", "-iwithprefix", "a"},
103718334Speter   {"--language", "-x", "a"},
103818334Speter   {"--library-directory", "-L", "a"},
103918334Speter   {"--machine", "-m", "aj"},
104018334Speter   {"--machine-", "-m", "*j"},
104196285Sobrien   {"--no-integrated-cpp", "-no-integrated-cpp", 0},
104218334Speter   {"--no-line-commands", "-P", 0},
104318334Speter   {"--no-precompiled-includes", "-noprecomp", 0},
104418334Speter   {"--no-standard-includes", "-nostdinc", 0},
104518334Speter   {"--no-standard-libraries", "-nostdlib", 0},
104618334Speter   {"--no-warnings", "-w", 0},
104718334Speter   {"--optimize", "-O", "oj"},
104818334Speter   {"--output", "-o", "a"},
104952520Sobrien   {"--output-class-directory", "-foutput-class-dir=", "ja"},
105090277Sobrien   {"--param", "--param", "a"},
105118334Speter   {"--pedantic", "-pedantic", 0},
105218334Speter   {"--pedantic-errors", "-pedantic-errors", 0},
1053132733Skan   {"--pie", "-pie", 0},
105418334Speter   {"--pipe", "-pipe", 0},
105518334Speter   {"--prefix", "-B", "a"},
105618334Speter   {"--preprocess", "-E", 0},
105718334Speter   {"--print-search-dirs", "-print-search-dirs", 0},
105818334Speter   {"--print-file-name", "-print-file-name=", "aj"},
105918334Speter   {"--print-libgcc-file-name", "-print-libgcc-file-name", 0},
106018334Speter   {"--print-missing-file-dependencies", "-MG", 0},
106118334Speter   {"--print-multi-lib", "-print-multi-lib", 0},
106218334Speter   {"--print-multi-directory", "-print-multi-directory", 0},
1063104763Skan   {"--print-multi-os-directory", "-print-multi-os-directory", 0},
106418334Speter   {"--print-prog-name", "-print-prog-name=", "aj"},
106518334Speter   {"--profile", "-p", 0},
106618334Speter   {"--profile-blocks", "-a", 0},
106718334Speter   {"--quiet", "-q", 0},
106896285Sobrien   {"--resource", "-fcompile-resource=", "aj"},
106918334Speter   {"--save-temps", "-save-temps", 0},
107018334Speter   {"--shared", "-shared", 0},
107118334Speter   {"--silent", "-q", 0},
107250599Sobrien   {"--specs", "-specs=", "aj"},
107318334Speter   {"--static", "-static", 0},
107452520Sobrien   {"--std", "-std=", "aj"},
107518334Speter   {"--symbolic", "-symbolic", 0},
107690277Sobrien   {"--time", "-time", 0},
107718334Speter   {"--trace-includes", "-H", 0},
107818334Speter   {"--traditional", "-traditional", 0},
107918334Speter   {"--traditional-cpp", "-traditional-cpp", 0},
108018334Speter   {"--trigraphs", "-trigraphs", 0},
108150599Sobrien   {"--undefine-macro", "-U", "aj"},
108218334Speter   {"--user-dependencies", "-MM", 0},
108318334Speter   {"--verbose", "-v", 0},
108418334Speter   {"--warn-", "-W", "*j"},
108518334Speter   {"--write-dependencies", "-MD", 0},
108618334Speter   {"--write-user-dependencies", "-MMD", 0},
108718334Speter   {"--", "-f", "*j"}
108818334Speter };
108918334Speter
109090277Sobrien
109190277Sobrien#ifdef TARGET_OPTION_TRANSLATE_TABLE
109290277Sobrienstatic const struct {
109390277Sobrien  const char *const option_found;
109490277Sobrien  const char *const replacements;
109590277Sobrien} target_option_translations[] =
109690277Sobrien{
109790277Sobrien  TARGET_OPTION_TRANSLATE_TABLE,
109890277Sobrien  { 0, 0 }
109990277Sobrien};
110090277Sobrien#endif
110190277Sobrien
110218334Speter/* Translate the options described by *ARGCP and *ARGVP.
110318334Speter   Make a new vector and store it back in *ARGVP,
110418334Speter   and store its length in *ARGVC.  */
110518334Speter
110618334Speterstatic void
1107132733Skantranslate_options (int *argcp, const char *const **argvp)
110818334Speter{
110952520Sobrien  int i;
111018334Speter  int argc = *argcp;
111190277Sobrien  const char *const *argv = *argvp;
111290277Sobrien  int newvsize = (argc + 2) * 2 * sizeof (const char *);
1113132733Skan  const char **newv = xmalloc (newvsize);
111418334Speter  int newindex = 0;
111518334Speter
111618334Speter  i = 0;
111718334Speter  newv[newindex++] = argv[i++];
111818334Speter
111918334Speter  while (i < argc)
112018334Speter    {
112190277Sobrien#ifdef TARGET_OPTION_TRANSLATE_TABLE
112290277Sobrien      int tott_idx;
112390277Sobrien
112490277Sobrien      for (tott_idx = 0;
112590277Sobrien	   target_option_translations[tott_idx].option_found;
112690277Sobrien	   tott_idx++)
112790277Sobrien	{
112890277Sobrien	  if (strcmp (target_option_translations[tott_idx].option_found,
112990277Sobrien		      argv[i]) == 0)
113090277Sobrien	    {
113190277Sobrien	      int spaces = 1;
113290277Sobrien	      const char *sp;
113390277Sobrien	      char *np;
113490277Sobrien
113590277Sobrien	      for (sp = target_option_translations[tott_idx].replacements;
113690277Sobrien		   *sp; sp++)
113790277Sobrien		{
113890277Sobrien		  if (*sp == ' ')
113990277Sobrien		    spaces ++;
114090277Sobrien		}
114190277Sobrien
114290277Sobrien	      newvsize += spaces * sizeof (const char *);
1143132733Skan	      newv =  xrealloc (newv, newvsize);
114490277Sobrien
114590277Sobrien	      sp = target_option_translations[tott_idx].replacements;
114690277Sobrien	      np = xstrdup (sp);
114790277Sobrien
114890277Sobrien	      while (1)
114990277Sobrien		{
115090277Sobrien		  while (*np == ' ')
115190277Sobrien		    np++;
115290277Sobrien		  if (*np == 0)
115390277Sobrien		    break;
115490277Sobrien		  newv[newindex++] = np;
115590277Sobrien		  while (*np != ' ' && *np)
115690277Sobrien		    np++;
115790277Sobrien		  if (*np == 0)
115890277Sobrien		    break;
115990277Sobrien		  *np++ = 0;
116090277Sobrien		}
116190277Sobrien
116290277Sobrien	      i ++;
116390277Sobrien	      break;
116490277Sobrien	    }
116590277Sobrien	}
116690277Sobrien      if (target_option_translations[tott_idx].option_found)
116790277Sobrien	continue;
116890277Sobrien#endif
116990277Sobrien
117018334Speter      /* Translate -- options.  */
117118334Speter      if (argv[i][0] == '-' && argv[i][1] == '-')
117218334Speter	{
117352520Sobrien	  size_t j;
117418334Speter	  /* Find a mapping that applies to this option.  */
117590277Sobrien	  for (j = 0; j < ARRAY_SIZE (option_map); j++)
117618334Speter	    {
117750599Sobrien	      size_t optlen = strlen (option_map[j].name);
117850599Sobrien	      size_t arglen = strlen (argv[i]);
117950599Sobrien	      size_t complen = arglen > optlen ? optlen : arglen;
118052520Sobrien	      const char *arginfo = option_map[j].arg_info;
118118334Speter
118218334Speter	      if (arginfo == 0)
118318334Speter		arginfo = "";
118418334Speter
118518334Speter	      if (!strncmp (argv[i], option_map[j].name, complen))
118618334Speter		{
118752520Sobrien		  const char *arg = 0;
118818334Speter
118918334Speter		  if (arglen < optlen)
119018334Speter		    {
119152520Sobrien		      size_t k;
119290277Sobrien		      for (k = j + 1; k < ARRAY_SIZE (option_map); k++)
119318334Speter			if (strlen (option_map[k].name) >= arglen
119418334Speter			    && !strncmp (argv[i], option_map[k].name, arglen))
119518334Speter			  {
119690277Sobrien			    error ("ambiguous abbreviation %s", argv[i]);
119718334Speter			    break;
119818334Speter			  }
119918334Speter
120090277Sobrien		      if (k != ARRAY_SIZE (option_map))
120118334Speter			break;
120218334Speter		    }
120318334Speter
120418334Speter		  if (arglen > optlen)
120518334Speter		    {
120618334Speter		      /* If the option has an argument, accept that.  */
120718334Speter		      if (argv[i][optlen] == '=')
120818334Speter			arg = argv[i] + optlen + 1;
120918334Speter
121018334Speter		      /* If this mapping requires extra text at end of name,
121118334Speter			 accept that as "argument".  */
121290277Sobrien		      else if (strchr (arginfo, '*') != 0)
121318334Speter			arg = argv[i] + optlen;
121418334Speter
121518334Speter		      /* Otherwise, extra text at end means mismatch.
121618334Speter			 Try other mappings.  */
121718334Speter		      else
121818334Speter			continue;
121918334Speter		    }
122018334Speter
122190277Sobrien		  else if (strchr (arginfo, '*') != 0)
122218334Speter		    {
122390277Sobrien		      error ("incomplete `%s' option", option_map[j].name);
122418334Speter		      break;
122518334Speter		    }
122618334Speter
122718334Speter		  /* Handle arguments.  */
122890277Sobrien		  if (strchr (arginfo, 'a') != 0)
122918334Speter		    {
123018334Speter		      if (arg == 0)
123118334Speter			{
123218334Speter			  if (i + 1 == argc)
123318334Speter			    {
123490277Sobrien			      error ("missing argument to `%s' option",
123518334Speter				     option_map[j].name);
123618334Speter			      break;
123718334Speter			    }
123818334Speter
123918334Speter			  arg = argv[++i];
124018334Speter			}
124118334Speter		    }
124290277Sobrien		  else if (strchr (arginfo, '*') != 0)
124318334Speter		    ;
124490277Sobrien		  else if (strchr (arginfo, 'o') == 0)
124518334Speter		    {
124618334Speter		      if (arg != 0)
124790277Sobrien			error ("extraneous argument to `%s' option",
124818334Speter			       option_map[j].name);
124918334Speter		      arg = 0;
125018334Speter		    }
125118334Speter
125218334Speter		  /* Store the translation as one argv elt or as two.  */
125390277Sobrien		  if (arg != 0 && strchr (arginfo, 'j') != 0)
125450599Sobrien		    newv[newindex++] = concat (option_map[j].equivalent, arg,
125590277Sobrien					       NULL);
125618334Speter		  else if (arg != 0)
125718334Speter		    {
125818334Speter		      newv[newindex++] = option_map[j].equivalent;
125918334Speter		      newv[newindex++] = arg;
126018334Speter		    }
126118334Speter		  else
126218334Speter		    newv[newindex++] = option_map[j].equivalent;
126318334Speter
126418334Speter		  break;
126518334Speter		}
126618334Speter	    }
126718334Speter	  i++;
126818334Speter	}
126918334Speter
127018334Speter      /* Handle old-fashioned options--just copy them through,
127118334Speter	 with their arguments.  */
127218334Speter      else if (argv[i][0] == '-')
127318334Speter	{
127452520Sobrien	  const char *p = argv[i] + 1;
127518334Speter	  int c = *p;
127618334Speter	  int nskip = 1;
127718334Speter
127818334Speter	  if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
127918334Speter	    nskip += SWITCH_TAKES_ARG (c) - (p[1] != 0);
128018334Speter	  else if (WORD_SWITCH_TAKES_ARG (p))
128118334Speter	    nskip += WORD_SWITCH_TAKES_ARG (p);
1282117413Skan	  else if ((c == 'B' || c == 'b' || c == 'x')
128318334Speter		   && p[1] == 0)
128418334Speter	    nskip += 1;
128518334Speter	  else if (! strcmp (p, "Xlinker"))
128618334Speter	    nskip += 1;
1287132733Skan	  else if (! strcmp (p, "Xpreprocessor"))
1288132733Skan	    nskip += 1;
1289132733Skan	  else if (! strcmp (p, "Xassembler"))
1290132733Skan	    nskip += 1;
129118334Speter
129218334Speter	  /* Watch out for an option at the end of the command line that
129318334Speter	     is missing arguments, and avoid skipping past the end of the
129418334Speter	     command line.  */
129518334Speter	  if (nskip + i > argc)
129618334Speter	    nskip = argc - i;
129718334Speter
129818334Speter	  while (nskip > 0)
129918334Speter	    {
130018334Speter	      newv[newindex++] = argv[i++];
130118334Speter	      nskip--;
130218334Speter	    }
130318334Speter	}
130418334Speter      else
130518334Speter	/* Ordinary operands, or +e options.  */
130618334Speter	newv[newindex++] = argv[i++];
130718334Speter    }
130818334Speter
130918334Speter  newv[newindex] = 0;
131018334Speter
131118334Speter  *argvp = newv;
131218334Speter  *argcp = newindex;
131318334Speter}
131418334Speter
131518334Speterstatic char *
1316132733Skanskip_whitespace (char *p)
131718334Speter{
131818334Speter  while (1)
131918334Speter    {
132018334Speter      /* A fully-blank line is a delimiter in the SPEC file and shouldn't
132118334Speter	 be considered whitespace.  */
132218334Speter      if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n')
132318334Speter	return p + 1;
132418334Speter      else if (*p == '\n' || *p == ' ' || *p == '\t')
132518334Speter	p++;
132618334Speter      else if (*p == '#')
132718334Speter	{
132890277Sobrien	  while (*p != '\n')
132990277Sobrien	    p++;
133018334Speter	  p++;
133118334Speter	}
133218334Speter      else
133318334Speter	break;
133418334Speter    }
133518334Speter
133618334Speter  return p;
133718334Speter}
133890277Sobrien/* Structures to keep track of prefixes to try when looking for files.  */
133990277Sobrien
134090277Sobrienstruct prefix_list
134190277Sobrien{
134290277Sobrien  const char *prefix;	      /* String to prepend to the path.  */
134390277Sobrien  struct prefix_list *next;   /* Next in linked list.  */
134490277Sobrien  int require_machine_suffix; /* Don't use without machine_suffix.  */
134590277Sobrien  /* 2 means try both machine_suffix and just_machine_suffix.  */
134690277Sobrien  int *used_flag_ptr;	      /* 1 if a file was found with this prefix.  */
1347104763Skan  int priority;		      /* Sort key - priority within list.  */
1348104763Skan  int os_multilib;	      /* 1 if OS multilib scheme should be used,
1349104763Skan				 0 for GCC multilib scheme.  */
135090277Sobrien};
135190277Sobrien
135290277Sobrienstruct path_prefix
135390277Sobrien{
135490277Sobrien  struct prefix_list *plist;  /* List of prefixes to try */
135590277Sobrien  int max_len;                /* Max length of a prefix in PLIST */
135690277Sobrien  const char *name;           /* Name of this list (used in config stuff) */
135790277Sobrien};
135890277Sobrien
135990277Sobrien/* List of prefixes to try when looking for executables.  */
136090277Sobrien
136190277Sobrienstatic struct path_prefix exec_prefixes = { 0, 0, "exec" };
136290277Sobrien
136390277Sobrien/* List of prefixes to try when looking for startup (crt0) files.  */
136490277Sobrien
136590277Sobrienstatic struct path_prefix startfile_prefixes = { 0, 0, "startfile" };
136690277Sobrien
136790277Sobrien/* List of prefixes to try when looking for include files.  */
136890277Sobrien
136990277Sobrienstatic struct path_prefix include_prefixes = { 0, 0, "include" };
137090277Sobrien
137190277Sobrien/* Suffix to attach to directories searched for commands.
137290277Sobrien   This looks like `MACHINE/VERSION/'.  */
137390277Sobrien
137490277Sobrienstatic const char *machine_suffix = 0;
137590277Sobrien
137690277Sobrien/* Suffix to attach to directories searched for commands.
137790277Sobrien   This is just `MACHINE/'.  */
137890277Sobrien
137990277Sobrienstatic const char *just_machine_suffix = 0;
138090277Sobrien
138190277Sobrien/* Adjusted value of GCC_EXEC_PREFIX envvar.  */
138290277Sobrien
138390277Sobrienstatic const char *gcc_exec_prefix;
138490277Sobrien
1385132733Skan/* Adjusted value of standard_libexec_prefix.  */
1386132733Skan
1387132733Skanstatic const char *gcc_libexec_prefix;
1388132733Skan
138990277Sobrien/* Default prefixes to attach to command names.  */
139090277Sobrien
139190277Sobrien#ifdef CROSS_COMPILE  /* Don't use these prefixes for a cross compiler.  */
139290277Sobrien#undef MD_EXEC_PREFIX
139390277Sobrien#undef MD_STARTFILE_PREFIX
139490277Sobrien#undef MD_STARTFILE_PREFIX_1
139590277Sobrien#endif
139690277Sobrien
139790277Sobrien/* If no prefixes defined, use the null string, which will disable them.  */
139890277Sobrien#ifndef MD_EXEC_PREFIX
139990277Sobrien#define MD_EXEC_PREFIX ""
140090277Sobrien#endif
140190277Sobrien#ifndef MD_STARTFILE_PREFIX
140290277Sobrien#define MD_STARTFILE_PREFIX ""
140390277Sobrien#endif
140490277Sobrien#ifndef MD_STARTFILE_PREFIX_1
140590277Sobrien#define MD_STARTFILE_PREFIX_1 ""
140690277Sobrien#endif
140790277Sobrien
140890277Sobrienstatic const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX;
1409132733Skanstatic const char *const standard_exec_prefix_1 = "/usr/libexec/gcc/";
1410132733Skanstatic const char *const standard_exec_prefix_2 = "/usr/lib/gcc/";
141190277Sobrienstatic const char *md_exec_prefix = MD_EXEC_PREFIX;
141290277Sobrien
141390277Sobrienstatic const char *md_startfile_prefix = MD_STARTFILE_PREFIX;
141490277Sobrienstatic const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
141590277Sobrienstatic const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
141690277Sobrienstatic const char *const standard_startfile_prefix_1 = "/lib/";
141790277Sobrienstatic const char *const standard_startfile_prefix_2 = "/usr/lib/";
141890277Sobrien
141990277Sobrienstatic const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
142090277Sobrienstatic const char *tooldir_prefix;
142190277Sobrien
142296736Sru#ifndef FREEBSD_NATIVE
142390277Sobrienstatic const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
142496736Sru#endif	/* not FREEBSD_NATIVE */
142590277Sobrien
1426132733Skanstatic const char *standard_libexec_prefix = STANDARD_LIBEXEC_PREFIX;
1427132733Skan
142890277Sobrien/* Subdirectory to use for locating libraries.  Set by
142990277Sobrien   set_multilib_dir based on the compilation options.  */
143090277Sobrien
143190277Sobrienstatic const char *multilib_dir;
1432104763Skan
1433104763Skan/* Subdirectory to use for locating libraries in OS conventions.  Set by
1434104763Skan   set_multilib_dir based on the compilation options.  */
1435104763Skan
1436104763Skanstatic const char *multilib_os_dir;
143718334Speter
143850599Sobrien/* Structure to keep track of the specs that have been defined so far.
143950599Sobrien   These are accessed using %(specname) or %[specname] in a compiler
144050599Sobrien   or link spec.  */
144118334Speter
144218334Speterstruct spec_list
144318334Speter{
144450599Sobrien				/* The following 2 fields must be first */
144550599Sobrien				/* to allow EXTRA_SPECS to be initialized */
144690277Sobrien  const char *name;		/* name of the spec.  */
144790277Sobrien  const char *ptr;		/* available ptr if no static pointer */
144850599Sobrien
144950599Sobrien				/* The following fields are not initialized */
145050599Sobrien				/* by EXTRA_SPECS */
145190277Sobrien  const char **ptr_spec;	/* pointer to the spec itself.  */
145250599Sobrien  struct spec_list *next;	/* Next spec in linked list.  */
145350599Sobrien  int name_len;			/* length of the name */
145450599Sobrien  int alloc_p;			/* whether string was allocated */
145518334Speter};
145618334Speter
145750599Sobrien#define INIT_STATIC_SPEC(NAME,PTR) \
145890277Sobrien{ NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, 0 }
145918334Speter
146090277Sobrien/* List of statically defined specs.  */
146190277Sobrienstatic struct spec_list static_specs[] =
146290277Sobrien{
146350599Sobrien  INIT_STATIC_SPEC ("asm",			&asm_spec),
146490277Sobrien  INIT_STATIC_SPEC ("asm_debug",		&asm_debug),
146550599Sobrien  INIT_STATIC_SPEC ("asm_final",		&asm_final_spec),
146690277Sobrien  INIT_STATIC_SPEC ("asm_options",		&asm_options),
146790277Sobrien  INIT_STATIC_SPEC ("invoke_as",		&invoke_as),
146850599Sobrien  INIT_STATIC_SPEC ("cpp",			&cpp_spec),
146990277Sobrien  INIT_STATIC_SPEC ("cpp_options",		&cpp_options),
1470117413Skan  INIT_STATIC_SPEC ("cpp_debug_options",	&cpp_debug_options),
147190277Sobrien  INIT_STATIC_SPEC ("cpp_unique_options",	&cpp_unique_options),
147290277Sobrien  INIT_STATIC_SPEC ("trad_capable_cpp",		&trad_capable_cpp),
147350599Sobrien  INIT_STATIC_SPEC ("cc1",			&cc1_spec),
147490277Sobrien  INIT_STATIC_SPEC ("cc1_options",		&cc1_options),
147550599Sobrien  INIT_STATIC_SPEC ("cc1plus",			&cc1plus_spec),
147696285Sobrien  INIT_STATIC_SPEC ("link_gcc_c_sequence",	&link_gcc_c_sequence_spec),
147750599Sobrien  INIT_STATIC_SPEC ("endfile",			&endfile_spec),
147850599Sobrien  INIT_STATIC_SPEC ("link",			&link_spec),
147950599Sobrien  INIT_STATIC_SPEC ("lib",			&lib_spec),
148050599Sobrien  INIT_STATIC_SPEC ("libgcc",			&libgcc_spec),
148150599Sobrien  INIT_STATIC_SPEC ("startfile",		&startfile_spec),
148250599Sobrien  INIT_STATIC_SPEC ("switches_need_spaces",	&switches_need_spaces),
148350599Sobrien  INIT_STATIC_SPEC ("cross_compile",		&cross_compile),
148450599Sobrien  INIT_STATIC_SPEC ("version",			&compiler_version),
148550599Sobrien  INIT_STATIC_SPEC ("multilib",			&multilib_select),
148650599Sobrien  INIT_STATIC_SPEC ("multilib_defaults",	&multilib_defaults),
148750599Sobrien  INIT_STATIC_SPEC ("multilib_extra",		&multilib_extra),
148850599Sobrien  INIT_STATIC_SPEC ("multilib_matches",		&multilib_matches),
148990277Sobrien  INIT_STATIC_SPEC ("multilib_exclusions",	&multilib_exclusions),
1490104763Skan  INIT_STATIC_SPEC ("multilib_options",		&multilib_options),
149150599Sobrien  INIT_STATIC_SPEC ("linker",			&linker_name_spec),
149290277Sobrien  INIT_STATIC_SPEC ("link_libgcc",		&link_libgcc_spec),
149390277Sobrien  INIT_STATIC_SPEC ("md_exec_prefix",		&md_exec_prefix),
149490277Sobrien  INIT_STATIC_SPEC ("md_startfile_prefix",	&md_startfile_prefix),
149590277Sobrien  INIT_STATIC_SPEC ("md_startfile_prefix_1",	&md_startfile_prefix_1),
1496117413Skan  INIT_STATIC_SPEC ("startfile_prefix_spec",	&startfile_prefix_spec),
1497132733Skan  INIT_STATIC_SPEC ("sysroot_suffix_spec",	&sysroot_suffix_spec),
1498132733Skan  INIT_STATIC_SPEC ("sysroot_hdrs_suffix_spec",	&sysroot_hdrs_suffix_spec),
149950599Sobrien};
150050599Sobrien
150150599Sobrien#ifdef EXTRA_SPECS		/* additional specs needed */
150252520Sobrien/* Structure to keep track of just the first two args of a spec_list.
150390277Sobrien   That is all that the EXTRA_SPECS macro gives us.  */
150452520Sobrienstruct spec_list_1
150552520Sobrien{
150690277Sobrien  const char *const name;
150790277Sobrien  const char *const ptr;
150852520Sobrien};
150952520Sobrien
151090277Sobrienstatic const struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
151190277Sobrienstatic struct spec_list *extra_specs = (struct spec_list *) 0;
151250599Sobrien#endif
151350599Sobrien
151450599Sobrien/* List of dynamically allocates specs that have been defined so far.  */
151550599Sobrien
151690277Sobrienstatic struct spec_list *specs = (struct spec_list *) 0;
151790277Sobrien
1518117413Skan/* List of static spec functions.  */
1519117413Skan
1520117413Skanstatic const struct spec_function static_spec_functions[] =
1521117413Skan{
1522117413Skan  { "if-exists",		if_exists_spec_function },
1523117413Skan  { "if-exists-else",		if_exists_else_spec_function },
1524117413Skan  { 0, 0 }
1525117413Skan};
1526117413Skan
1527117413Skanstatic int processing_spec_function;
1528117413Skan
152990277Sobrien/* Add appropriate libgcc specs to OBSTACK, taking into account
153090277Sobrien   various permutations of -shared-libgcc, -shared, and such.  */
153150599Sobrien
153290277Sobrien#ifdef ENABLE_SHARED_LIBGCC
153390277Sobrienstatic void
1534132733Skaninit_gcc_specs (struct obstack *obstack, const char *shared_name,
1535132733Skan		const char *static_name, const char *eh_name)
153690277Sobrien{
153796285Sobrien  char *buf;
153890277Sobrien
153996285Sobrien  buf = concat ("%{static|static-libgcc:", static_name, " ", eh_name,
154096285Sobrien		"}%{!static:%{!static-libgcc:",
1541132733Skan#ifdef HAVE_LD_AS_NEEDED
1542132733Skan		"%{!shared-libgcc:", static_name,
1543132733Skan		" --as-needed ", shared_name, " --no-as-needed}"
1544132733Skan		"%{shared-libgcc:", shared_name, "%{!shared: ", static_name,
1545132733Skan		"}",
1546132733Skan#else
154796285Sobrien		"%{!shared:%{!shared-libgcc:", static_name, " ",
154896285Sobrien		eh_name, "}%{shared-libgcc:", shared_name, " ",
154996285Sobrien		static_name, "}}%{shared:",
155090277Sobrien#ifdef LINK_EH_SPEC
155196285Sobrien		"%{shared-libgcc:", shared_name,
155296285Sobrien		"}%{!shared-libgcc:", static_name, "}",
155390277Sobrien#else
155496285Sobrien		shared_name,
155590277Sobrien#endif
1556132733Skan#endif
155796285Sobrien		"}}}", NULL);
155896285Sobrien
155996285Sobrien  obstack_grow (obstack, buf, strlen (buf));
156096285Sobrien  free (buf);
156190277Sobrien}
156290277Sobrien#endif /* ENABLE_SHARED_LIBGCC */
156390277Sobrien
156450599Sobrien/* Initialize the specs lookup routines.  */
156550599Sobrien
156650599Sobrienstatic void
1567132733Skaninit_spec (void)
156850599Sobrien{
156990277Sobrien  struct spec_list *next = (struct spec_list *) 0;
157090277Sobrien  struct spec_list *sl   = (struct spec_list *) 0;
157150599Sobrien  int i;
157250599Sobrien
157350599Sobrien  if (specs)
157490277Sobrien    return;			/* Already initialized.  */
157550599Sobrien
157650599Sobrien  if (verbose_flag)
157790277Sobrien    notice ("Using built-in specs.\n");
157850599Sobrien
157950599Sobrien#ifdef EXTRA_SPECS
1580132733Skan  extra_specs = xcalloc (sizeof (struct spec_list),
1581132733Skan			 ARRAY_SIZE (extra_specs_1));
158290277Sobrien
158390277Sobrien  for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--)
158450599Sobrien    {
158550599Sobrien      sl = &extra_specs[i];
158652520Sobrien      sl->name = extra_specs_1[i].name;
158752520Sobrien      sl->ptr = extra_specs_1[i].ptr;
158850599Sobrien      sl->next = next;
158950599Sobrien      sl->name_len = strlen (sl->name);
159050599Sobrien      sl->ptr_spec = &sl->ptr;
159150599Sobrien      next = sl;
159250599Sobrien    }
159350599Sobrien#endif
159450599Sobrien
1595117413Skan  /* Initialize here, not in definition.  The IRIX 6 O32 cc sometimes chokes
1596117413Skan     on ?: in file-scope variable initializations.  */
1597117413Skan  asm_debug = ASM_DEBUG_SPEC;
1598117413Skan
159990277Sobrien  for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
160050599Sobrien    {
160150599Sobrien      sl = &static_specs[i];
160250599Sobrien      sl->next = next;
160350599Sobrien      next = sl;
160450599Sobrien    }
160550599Sobrien
160690277Sobrien#ifdef ENABLE_SHARED_LIBGCC
160790277Sobrien  /* ??? If neither -shared-libgcc nor --static-libgcc was
160890277Sobrien     seen, then we should be making an educated guess.  Some proposed
160990277Sobrien     heuristics for ELF include:
161090277Sobrien
161190277Sobrien	(1) If "-Wl,--export-dynamic", then it's a fair bet that the
161290277Sobrien	    program will be doing dynamic loading, which will likely
161390277Sobrien	    need the shared libgcc.
161490277Sobrien
161590277Sobrien	(2) If "-ldl", then it's also a fair bet that we're doing
161690277Sobrien	    dynamic loading.
161790277Sobrien
161890277Sobrien	(3) For each ET_DYN we're linking against (either through -lfoo
161990277Sobrien	    or /some/path/foo.so), check to see whether it or one of
162090277Sobrien	    its dependencies depends on a shared libgcc.
162190277Sobrien
162290277Sobrien	(4) If "-shared"
162390277Sobrien
162490277Sobrien	    If the runtime is fixed to look for program headers instead
162590277Sobrien	    of calling __register_frame_info at all, for each object,
162690277Sobrien	    use the shared libgcc if any EH symbol referenced.
162790277Sobrien
162890277Sobrien	    If crtstuff is fixed to not invoke __register_frame_info
162990277Sobrien	    automatically, for each object, use the shared libgcc if
163090277Sobrien	    any non-empty unwind section found.
163190277Sobrien
163290277Sobrien     Doing any of this probably requires invoking an external program to
163390277Sobrien     do the actual object file scanning.  */
163490277Sobrien  {
163590277Sobrien    const char *p = libgcc_spec;
163690277Sobrien    int in_sep = 1;
1637117413Skan
163890277Sobrien    /* Transform the extant libgcc_spec into one that uses the shared libgcc
163990277Sobrien       when given the proper command line arguments.  */
164090277Sobrien    while (*p)
164190277Sobrien      {
1642117413Skan	if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0)
164390277Sobrien	  {
164490277Sobrien	    init_gcc_specs (&obstack,
164590277Sobrien#ifdef NO_SHARED_LIBGCC_MULTILIB
164690277Sobrien			    "-lgcc_s"
164790277Sobrien#else
164890277Sobrien			    "-lgcc_s%M"
164990277Sobrien#endif
1650146908Skan#ifdef USE_LIBUNWIND_EXCEPTIONS
1651146908Skan			    " -lunwind"
1652146908Skan#endif
1653132733Skan			    ,
1654132733Skan			    "-lgcc",
1655132733Skan			    "-lgcc_eh"
1656122197Skan#ifdef USE_LIBUNWIND_EXCEPTIONS
1657146908Skan# ifdef HAVE_LD_STATIC_DYNAMIC
1658146908Skan			    " %{!static:-Bstatic} -lunwind %{!static:-Bdynamic}"
1659146908Skan# else
1660122197Skan			    " -lunwind"
1661146908Skan# endif
1662122197Skan#endif
1663132733Skan			    );
1664132733Skan
166590277Sobrien	    p += 5;
166690277Sobrien	    in_sep = 0;
166790277Sobrien	  }
166890277Sobrien	else if (in_sep && *p == 'l' && strncmp (p, "libgcc.a%s", 10) == 0)
166990277Sobrien	  {
167090277Sobrien	    /* Ug.  We don't know shared library extensions.  Hope that
167190277Sobrien	       systems that use this form don't do shared libraries.  */
167290277Sobrien	    init_gcc_specs (&obstack,
167390277Sobrien#ifdef NO_SHARED_LIBGCC_MULTILIB
167490277Sobrien			    "-lgcc_s"
167590277Sobrien#else
167690277Sobrien			    "-lgcc_s%M"
167790277Sobrien#endif
167890277Sobrien			    ,
167990277Sobrien			    "libgcc.a%s",
1680132733Skan			    "libgcc_eh.a%s"
1681132733Skan#ifdef USE_LIBUNWIND_EXCEPTIONS
1682132733Skan			    " -lunwind"
1683132733Skan#endif
1684132733Skan			    );
168590277Sobrien	    p += 10;
168690277Sobrien	    in_sep = 0;
168790277Sobrien	  }
168890277Sobrien	else
168990277Sobrien	  {
169090277Sobrien	    obstack_1grow (&obstack, *p);
169190277Sobrien	    in_sep = (*p == ' ');
169290277Sobrien	    p += 1;
169390277Sobrien	  }
169490277Sobrien      }
169590277Sobrien
169690277Sobrien    obstack_1grow (&obstack, '\0');
169790277Sobrien    libgcc_spec = obstack_finish (&obstack);
169890277Sobrien  }
169990277Sobrien#endif
170090277Sobrien#ifdef USE_AS_TRADITIONAL_FORMAT
170190277Sobrien  /* Prepend "--traditional-format" to whatever asm_spec we had before.  */
170290277Sobrien  {
170390277Sobrien    static const char tf[] = "--traditional-format ";
170490277Sobrien    obstack_grow (&obstack, tf, sizeof(tf) - 1);
170590277Sobrien    obstack_grow0 (&obstack, asm_spec, strlen (asm_spec));
170690277Sobrien    asm_spec = obstack_finish (&obstack);
170790277Sobrien  }
170890277Sobrien#endif
170990277Sobrien#ifdef LINK_EH_SPEC
171090277Sobrien  /* Prepend LINK_EH_SPEC to whatever link_spec we had before.  */
171190277Sobrien  obstack_grow (&obstack, LINK_EH_SPEC, sizeof(LINK_EH_SPEC) - 1);
171290277Sobrien  obstack_grow0 (&obstack, link_spec, strlen (link_spec));
171390277Sobrien  link_spec = obstack_finish (&obstack);
171490277Sobrien#endif
171590277Sobrien
171650599Sobrien  specs = sl;
171750599Sobrien}
171850599Sobrien
171918334Speter/* Change the value of spec NAME to SPEC.  If SPEC is empty, then the spec is
172018334Speter   removed; If the spec starts with a + then SPEC is added to the end of the
172150599Sobrien   current spec.  */
172218334Speter
172318334Speterstatic void
1724132733Skanset_spec (const char *name, const char *spec)
172518334Speter{
172618334Speter  struct spec_list *sl;
172790277Sobrien  const char *old_spec;
172850599Sobrien  int name_len = strlen (name);
172950599Sobrien  int i;
173018334Speter
173190277Sobrien  /* If this is the first call, initialize the statically allocated specs.  */
173250599Sobrien  if (!specs)
173350599Sobrien    {
173490277Sobrien      struct spec_list *next = (struct spec_list *) 0;
173590277Sobrien      for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
173650599Sobrien	{
173750599Sobrien	  sl = &static_specs[i];
173850599Sobrien	  sl->next = next;
173950599Sobrien	  next = sl;
174050599Sobrien	}
174150599Sobrien      specs = sl;
174250599Sobrien    }
174350599Sobrien
174490277Sobrien  /* See if the spec already exists.  */
174518334Speter  for (sl = specs; sl; sl = sl->next)
174650599Sobrien    if (name_len == sl->name_len && !strcmp (sl->name, name))
174718334Speter      break;
174818334Speter
174918334Speter  if (!sl)
175018334Speter    {
175190277Sobrien      /* Not found - make it.  */
1752132733Skan      sl = xmalloc (sizeof (struct spec_list));
175390277Sobrien      sl->name = xstrdup (name);
175450599Sobrien      sl->name_len = name_len;
175550599Sobrien      sl->ptr_spec = &sl->ptr;
175650599Sobrien      sl->alloc_p = 0;
175750599Sobrien      *(sl->ptr_spec) = "";
175818334Speter      sl->next = specs;
175918334Speter      specs = sl;
176018334Speter    }
176118334Speter
176250599Sobrien  old_spec = *(sl->ptr_spec);
176352520Sobrien  *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1]))
176490277Sobrien		     ? concat (old_spec, spec + 1, NULL)
176590277Sobrien		     : xstrdup (spec));
176618334Speter
176750599Sobrien#ifdef DEBUG_SPECS
176850599Sobrien  if (verbose_flag)
176952520Sobrien    notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
177050599Sobrien#endif
177150599Sobrien
177290277Sobrien  /* Free the old spec.  */
177350599Sobrien  if (old_spec && sl->alloc_p)
1774132733Skan    free ((void *) old_spec);
177550599Sobrien
177650599Sobrien  sl->alloc_p = 1;
177718334Speter}
177818334Speter
177918334Speter/* Accumulate a command (program name and args), and run it.  */
178018334Speter
178118334Speter/* Vector of pointers to arguments in the current line of specifications.  */
178218334Speter
178390277Sobrienstatic const char **argbuf;
178418334Speter
178518334Speter/* Number of elements allocated in argbuf.  */
178618334Speter
178718334Speterstatic int argbuf_length;
178818334Speter
178918334Speter/* Number of elements in argbuf currently in use (containing args).  */
179018334Speter
179118334Speterstatic int argbuf_index;
179218334Speter
179390277Sobrien/* This is the list of suffixes and codes (%g/%u/%U/%j) and the associated
179490277Sobrien   temp file.  If the HOST_BIT_BUCKET is used for %j, no entry is made for
179590277Sobrien   it here.  */
179650599Sobrien
179718334Speterstatic struct temp_name {
179852520Sobrien  const char *suffix;	/* suffix associated with the code.  */
179918334Speter  int length;		/* strlen (suffix).  */
180018334Speter  int unique;		/* Indicates whether %g or %u/%U was used.  */
180152520Sobrien  const char *filename;	/* associated filename.  */
180218334Speter  int filename_length;	/* strlen (filename).  */
180318334Speter  struct temp_name *next;
180418334Speter} *temp_names;
180518334Speter
180618334Speter/* Number of commands executed so far.  */
180718334Speter
180818334Speterstatic int execution_count;
180918334Speter
181018334Speter/* Number of commands that exited with a signal.  */
181118334Speter
181218334Speterstatic int signal_count;
181318334Speter
181418334Speter/* Name with which this program was invoked.  */
181518334Speter
181652520Sobrienstatic const char *programname;
181718334Speter
1818117413Skan/* Allocate the argument vector.  */
1819117413Skan
1820117413Skanstatic void
1821132733Skanalloc_args (void)
1822117413Skan{
1823117413Skan  argbuf_length = 10;
1824132733Skan  argbuf = xmalloc (argbuf_length * sizeof (const char *));
1825117413Skan}
1826117413Skan
182718334Speter/* Clear out the vector of arguments (after a command is executed).  */
182818334Speter
182918334Speterstatic void
1830132733Skanclear_args (void)
183118334Speter{
183218334Speter  argbuf_index = 0;
183318334Speter}
183418334Speter
183518334Speter/* Add one argument to the vector at the end.
183618334Speter   This is done when a space is seen or at the end of the line.
183718334Speter   If DELETE_ALWAYS is nonzero, the arg is a filename
183818334Speter    and the file should be deleted eventually.
183918334Speter   If DELETE_FAILURE is nonzero, the arg is a filename
184018334Speter    and the file should be deleted if this compilation fails.  */
184118334Speter
184218334Speterstatic void
1843132733Skanstore_arg (const char *arg, int delete_always, int delete_failure)
184418334Speter{
184518334Speter  if (argbuf_index + 1 == argbuf_length)
1846132733Skan    argbuf = xrealloc (argbuf, (argbuf_length *= 2) * sizeof (const char *));
184718334Speter
184818334Speter  argbuf[argbuf_index++] = arg;
184918334Speter  argbuf[argbuf_index] = 0;
185018334Speter
185118334Speter  if (delete_always || delete_failure)
185218334Speter    record_temp_file (arg, delete_always, delete_failure);
185318334Speter}
185418334Speter
185590277Sobrien/* Load specs from a file name named FILENAME, replacing occurrences of
185690277Sobrien   various different types of line-endings, \r\n, \n\r and just \r, with
185790277Sobrien   a single \n.  */
185850599Sobrien
185990277Sobrienstatic char *
1860132733Skanload_specs (const char *filename)
186150599Sobrien{
186250599Sobrien  int desc;
186350599Sobrien  int readlen;
186450599Sobrien  struct stat statbuf;
186550599Sobrien  char *buffer;
186690277Sobrien  char *buffer_p;
186790277Sobrien  char *specs;
186890277Sobrien  char *specs_p;
186950599Sobrien
187050599Sobrien  if (verbose_flag)
187152520Sobrien    notice ("Reading specs from %s\n", filename);
187250599Sobrien
187350599Sobrien  /* Open and stat the file.  */
187450599Sobrien  desc = open (filename, O_RDONLY, 0);
187550599Sobrien  if (desc < 0)
187650599Sobrien    pfatal_with_name (filename);
187750599Sobrien  if (stat (filename, &statbuf) < 0)
187850599Sobrien    pfatal_with_name (filename);
187950599Sobrien
188050599Sobrien  /* Read contents of file into BUFFER.  */
188150599Sobrien  buffer = xmalloc ((unsigned) statbuf.st_size + 1);
188250599Sobrien  readlen = read (desc, buffer, (unsigned) statbuf.st_size);
188350599Sobrien  if (readlen < 0)
188450599Sobrien    pfatal_with_name (filename);
188550599Sobrien  buffer[readlen] = 0;
188650599Sobrien  close (desc);
188750599Sobrien
188890277Sobrien  specs = xmalloc (readlen + 1);
188990277Sobrien  specs_p = specs;
189090277Sobrien  for (buffer_p = buffer; buffer_p && *buffer_p; buffer_p++)
189190277Sobrien    {
189290277Sobrien      int skip = 0;
189390277Sobrien      char c = *buffer_p;
189490277Sobrien      if (c == '\r')
189590277Sobrien	{
189690277Sobrien	  if (buffer_p > buffer && *(buffer_p - 1) == '\n')	/* \n\r */
189790277Sobrien	    skip = 1;
189890277Sobrien	  else if (*(buffer_p + 1) == '\n')			/* \r\n */
189990277Sobrien	    skip = 1;
190090277Sobrien	  else							/* \r */
190190277Sobrien	    c = '\n';
190290277Sobrien	}
190390277Sobrien      if (! skip)
190490277Sobrien	*specs_p++ = c;
190590277Sobrien    }
190690277Sobrien  *specs_p = '\0';
190790277Sobrien
190890277Sobrien  free (buffer);
190990277Sobrien  return (specs);
191090277Sobrien}
191190277Sobrien
191290277Sobrien/* Read compilation specs from a file named FILENAME,
191390277Sobrien   replacing the default ones.
191490277Sobrien
191590277Sobrien   A suffix which starts with `*' is a definition for
191690277Sobrien   one of the machine-specific sub-specs.  The "suffix" should be
191796285Sobrien   *asm, *cc1, *cpp, *link, *startfile, etc.
191890277Sobrien   The corresponding spec is stored in asm_spec, etc.,
191990277Sobrien   rather than in the `compilers' vector.
192090277Sobrien
192190277Sobrien   Anything invalid in the file is a fatal error.  */
192290277Sobrien
192390277Sobrienstatic void
1924132733Skanread_specs (const char *filename, int main_p)
192590277Sobrien{
192690277Sobrien  char *buffer;
192790277Sobrien  char *p;
192890277Sobrien
192990277Sobrien  buffer = load_specs (filename);
193090277Sobrien
193150599Sobrien  /* Scan BUFFER for specs, putting them in the vector.  */
193250599Sobrien  p = buffer;
193350599Sobrien  while (1)
193450599Sobrien    {
193550599Sobrien      char *suffix;
193650599Sobrien      char *spec;
193750599Sobrien      char *in, *out, *p1, *p2, *p3;
193850599Sobrien
193950599Sobrien      /* Advance P in BUFFER to the next nonblank nocomment line.  */
194050599Sobrien      p = skip_whitespace (p);
194150599Sobrien      if (*p == 0)
194250599Sobrien	break;
194350599Sobrien
194450599Sobrien      /* Is this a special command that starts with '%'? */
194550599Sobrien      /* Don't allow this for the main specs file, since it would
194650599Sobrien	 encourage people to overwrite it.  */
194750599Sobrien      if (*p == '%' && !main_p)
194850599Sobrien	{
194950599Sobrien	  p1 = p;
195050599Sobrien	  while (*p && *p != '\n')
195150599Sobrien	    p++;
195250599Sobrien
195390277Sobrien	  /* Skip '\n'.  */
195490277Sobrien	  p++;
195550599Sobrien
195690277Sobrien	  if (!strncmp (p1, "%include", sizeof ("%include") - 1)
195750599Sobrien	      && (p1[sizeof "%include" - 1] == ' '
195850599Sobrien		  || p1[sizeof "%include" - 1] == '\t'))
195950599Sobrien	    {
196050599Sobrien	      char *new_filename;
196150599Sobrien
196250599Sobrien	      p1 += sizeof ("%include");
196350599Sobrien	      while (*p1 == ' ' || *p1 == '\t')
196450599Sobrien		p1++;
196550599Sobrien
196650599Sobrien	      if (*p1++ != '<' || p[-2] != '>')
196752520Sobrien		fatal ("specs %%include syntax malformed after %ld characters",
196852520Sobrien		       (long) (p1 - buffer + 1));
196950599Sobrien
197050599Sobrien	      p[-2] = '\0';
1971104763Skan	      new_filename = find_a_file (&startfile_prefixes, p1, R_OK, 0);
197250599Sobrien	      read_specs (new_filename ? new_filename : p1, FALSE);
197350599Sobrien	      continue;
197450599Sobrien	    }
197550599Sobrien	  else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1)
197650599Sobrien		   && (p1[sizeof "%include_noerr" - 1] == ' '
197750599Sobrien		       || p1[sizeof "%include_noerr" - 1] == '\t'))
197850599Sobrien	    {
197950599Sobrien	      char *new_filename;
198050599Sobrien
198150599Sobrien	      p1 += sizeof "%include_noerr";
198290277Sobrien	      while (*p1 == ' ' || *p1 == '\t')
198390277Sobrien		p1++;
198450599Sobrien
198550599Sobrien	      if (*p1++ != '<' || p[-2] != '>')
198652520Sobrien		fatal ("specs %%include syntax malformed after %ld characters",
198752520Sobrien		       (long) (p1 - buffer + 1));
198850599Sobrien
198950599Sobrien	      p[-2] = '\0';
1990104763Skan	      new_filename = find_a_file (&startfile_prefixes, p1, R_OK, 0);
199150599Sobrien	      if (new_filename)
199250599Sobrien		read_specs (new_filename, FALSE);
199350599Sobrien	      else if (verbose_flag)
199490277Sobrien		notice ("could not find specs file %s\n", p1);
199550599Sobrien	      continue;
199650599Sobrien	    }
199750599Sobrien	  else if (!strncmp (p1, "%rename", sizeof "%rename" - 1)
199850599Sobrien		   && (p1[sizeof "%rename" - 1] == ' '
199950599Sobrien		       || p1[sizeof "%rename" - 1] == '\t'))
200050599Sobrien	    {
200150599Sobrien	      int name_len;
200250599Sobrien	      struct spec_list *sl;
2003117413Skan	      struct spec_list *newsl;
200450599Sobrien
2005117413Skan	      /* Get original name.  */
200650599Sobrien	      p1 += sizeof "%rename";
200750599Sobrien	      while (*p1 == ' ' || *p1 == '\t')
200850599Sobrien		p1++;
200950599Sobrien
201090277Sobrien	      if (! ISALPHA ((unsigned char) *p1))
201152520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
201252520Sobrien		       (long) (p1 - buffer));
201350599Sobrien
201450599Sobrien	      p2 = p1;
201590277Sobrien	      while (*p2 && !ISSPACE ((unsigned char) *p2))
201650599Sobrien		p2++;
201750599Sobrien
201850599Sobrien	      if (*p2 != ' ' && *p2 != '\t')
201952520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
202052520Sobrien		       (long) (p2 - buffer));
202150599Sobrien
202250599Sobrien	      name_len = p2 - p1;
202350599Sobrien	      *p2++ = '\0';
202450599Sobrien	      while (*p2 == ' ' || *p2 == '\t')
202550599Sobrien		p2++;
202650599Sobrien
202790277Sobrien	      if (! ISALPHA ((unsigned char) *p2))
202852520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
202952520Sobrien		       (long) (p2 - buffer));
203050599Sobrien
203190277Sobrien	      /* Get new spec name.  */
203250599Sobrien	      p3 = p2;
203390277Sobrien	      while (*p3 && !ISSPACE ((unsigned char) *p3))
203450599Sobrien		p3++;
203550599Sobrien
203690277Sobrien	      if (p3 != p - 1)
203752520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
203852520Sobrien		       (long) (p3 - buffer));
203950599Sobrien	      *p3 = '\0';
204050599Sobrien
204150599Sobrien	      for (sl = specs; sl; sl = sl->next)
204250599Sobrien		if (name_len == sl->name_len && !strcmp (sl->name, p1))
204350599Sobrien		  break;
204450599Sobrien
204550599Sobrien	      if (!sl)
204650599Sobrien		fatal ("specs %s spec was not found to be renamed", p1);
204750599Sobrien
204850599Sobrien	      if (strcmp (p1, p2) == 0)
204950599Sobrien		continue;
205050599Sobrien
2051117413Skan	      for (newsl = specs; newsl; newsl = newsl->next)
2052117413Skan		if (strcmp (newsl->name, p2) == 0)
2053117413Skan		  fatal ("%s: attempt to rename spec '%s' to already defined spec '%s'",
2054117413Skan		    filename, p1, p2);
2055117413Skan
205650599Sobrien	      if (verbose_flag)
205750599Sobrien		{
205852520Sobrien		  notice ("rename spec %s to %s\n", p1, p2);
205950599Sobrien#ifdef DEBUG_SPECS
206052520Sobrien		  notice ("spec is '%s'\n\n", *(sl->ptr_spec));
206150599Sobrien#endif
206250599Sobrien		}
206350599Sobrien
206450599Sobrien	      set_spec (p2, *(sl->ptr_spec));
206550599Sobrien	      if (sl->alloc_p)
2066132733Skan		free ((void *) *(sl->ptr_spec));
206750599Sobrien
206850599Sobrien	      *(sl->ptr_spec) = "";
206950599Sobrien	      sl->alloc_p = 0;
207050599Sobrien	      continue;
207150599Sobrien	    }
207250599Sobrien	  else
207352520Sobrien	    fatal ("specs unknown %% command after %ld characters",
207452520Sobrien		   (long) (p1 - buffer));
207550599Sobrien	}
207650599Sobrien
207750599Sobrien      /* Find the colon that should end the suffix.  */
207850599Sobrien      p1 = p;
207950599Sobrien      while (*p1 && *p1 != ':' && *p1 != '\n')
208050599Sobrien	p1++;
208150599Sobrien
208250599Sobrien      /* The colon shouldn't be missing.  */
208350599Sobrien      if (*p1 != ':')
208452520Sobrien	fatal ("specs file malformed after %ld characters",
208552520Sobrien	       (long) (p1 - buffer));
208650599Sobrien
208750599Sobrien      /* Skip back over trailing whitespace.  */
208850599Sobrien      p2 = p1;
208950599Sobrien      while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t'))
209050599Sobrien	p2--;
209150599Sobrien
209250599Sobrien      /* Copy the suffix to a string.  */
209350599Sobrien      suffix = save_string (p, p2 - p);
209450599Sobrien      /* Find the next line.  */
209550599Sobrien      p = skip_whitespace (p1 + 1);
209650599Sobrien      if (p[1] == 0)
209752520Sobrien	fatal ("specs file malformed after %ld characters",
209852520Sobrien	       (long) (p - buffer));
209950599Sobrien
210050599Sobrien      p1 = p;
210150599Sobrien      /* Find next blank line or end of string.  */
210250599Sobrien      while (*p1 && !(*p1 == '\n' && (p1[1] == '\n' || p1[1] == '\0')))
210350599Sobrien	p1++;
210450599Sobrien
210550599Sobrien      /* Specs end at the blank line and do not include the newline.  */
210650599Sobrien      spec = save_string (p, p1 - p);
210750599Sobrien      p = p1;
210850599Sobrien
210950599Sobrien      /* Delete backslash-newline sequences from the spec.  */
211050599Sobrien      in = spec;
211150599Sobrien      out = spec;
211250599Sobrien      while (*in != 0)
211350599Sobrien	{
211450599Sobrien	  if (in[0] == '\\' && in[1] == '\n')
211550599Sobrien	    in += 2;
211650599Sobrien	  else if (in[0] == '#')
211750599Sobrien	    while (*in && *in != '\n')
211850599Sobrien	      in++;
211950599Sobrien
212050599Sobrien	  else
212150599Sobrien	    *out++ = *in++;
212250599Sobrien	}
212350599Sobrien      *out = 0;
212450599Sobrien
212550599Sobrien      if (suffix[0] == '*')
212650599Sobrien	{
212750599Sobrien	  if (! strcmp (suffix, "*link_command"))
212850599Sobrien	    link_command_spec = spec;
212950599Sobrien	  else
213050599Sobrien	    set_spec (suffix + 1, spec);
213150599Sobrien	}
213250599Sobrien      else
213350599Sobrien	{
213450599Sobrien	  /* Add this pair to the vector.  */
213550599Sobrien	  compilers
2136132733Skan	    = xrealloc (compilers,
2137132733Skan			(n_compilers + 2) * sizeof (struct compiler));
213850599Sobrien
213950599Sobrien	  compilers[n_compilers].suffix = suffix;
214090277Sobrien	  compilers[n_compilers].spec = spec;
214150599Sobrien	  n_compilers++;
214290277Sobrien	  memset (&compilers[n_compilers], 0, sizeof compilers[n_compilers]);
214350599Sobrien	}
214450599Sobrien
214550599Sobrien      if (*suffix == 0)
214650599Sobrien	link_command_spec = spec;
214750599Sobrien    }
214850599Sobrien
214950599Sobrien  if (link_command_spec == 0)
215050599Sobrien    fatal ("spec file has no spec for linking");
215150599Sobrien}
215250599Sobrien
215318334Speter/* Record the names of temporary files we tell compilers to write,
215418334Speter   and delete them at the end of the run.  */
215518334Speter
215618334Speter/* This is the common prefix we use to make temp file names.
215718334Speter   It is chosen once for each run of this program.
215890277Sobrien   It is substituted into a spec by %g or %j.
215918334Speter   Thus, all temp file names contain this prefix.
216018334Speter   In practice, all temp file names start with this prefix.
216118334Speter
216218334Speter   This prefix comes from the envvar TMPDIR if it is defined;
216318334Speter   otherwise, from the P_tmpdir macro if that is defined;
216450599Sobrien   otherwise, in /usr/tmp or /tmp;
216550599Sobrien   or finally the current directory if all else fails.  */
216618334Speter
216752520Sobrienstatic const char *temp_filename;
216818334Speter
216918334Speter/* Length of the prefix.  */
217018334Speter
217118334Speterstatic int temp_filename_length;
217218334Speter
217318334Speter/* Define the list of temporary files to delete.  */
217418334Speter
217518334Speterstruct temp_file
217618334Speter{
217752520Sobrien  const char *name;
217818334Speter  struct temp_file *next;
217918334Speter};
218018334Speter
218118334Speter/* Queue of files to delete on success or failure of compilation.  */
218218334Speterstatic struct temp_file *always_delete_queue;
218318334Speter/* Queue of files to delete on failure of compilation.  */
218418334Speterstatic struct temp_file *failure_delete_queue;
218518334Speter
218618334Speter/* Record FILENAME as a file to be deleted automatically.
218718334Speter   ALWAYS_DELETE nonzero means delete it if all compilation succeeds;
218818334Speter   otherwise delete it in any case.
218918334Speter   FAIL_DELETE nonzero means delete it if a compilation step fails;
219018334Speter   otherwise delete it in any case.  */
219118334Speter
219290277Sobrienvoid
2193132733Skanrecord_temp_file (const char *filename, int always_delete, int fail_delete)
219418334Speter{
219590277Sobrien  char *const name = xstrdup (filename);
219618334Speter
219718334Speter  if (always_delete)
219818334Speter    {
219990277Sobrien      struct temp_file *temp;
220018334Speter      for (temp = always_delete_queue; temp; temp = temp->next)
220118334Speter	if (! strcmp (name, temp->name))
220218334Speter	  goto already1;
220350599Sobrien
2204132733Skan      temp = xmalloc (sizeof (struct temp_file));
220518334Speter      temp->next = always_delete_queue;
220618334Speter      temp->name = name;
220718334Speter      always_delete_queue = temp;
220850599Sobrien
220918334Speter    already1:;
221018334Speter    }
221118334Speter
221218334Speter  if (fail_delete)
221318334Speter    {
221490277Sobrien      struct temp_file *temp;
221518334Speter      for (temp = failure_delete_queue; temp; temp = temp->next)
221618334Speter	if (! strcmp (name, temp->name))
221718334Speter	  goto already2;
221850599Sobrien
2219132733Skan      temp = xmalloc (sizeof (struct temp_file));
222018334Speter      temp->next = failure_delete_queue;
222118334Speter      temp->name = name;
222218334Speter      failure_delete_queue = temp;
222350599Sobrien
222418334Speter    already2:;
222518334Speter    }
222618334Speter}
222718334Speter
222818334Speter/* Delete all the temporary files whose names we previously recorded.  */
222918334Speter
223018334Speterstatic void
2231132733Skandelete_if_ordinary (const char *name)
223218334Speter{
223318334Speter  struct stat st;
223418334Speter#ifdef DEBUG
223518334Speter  int i, c;
223618334Speter
223718334Speter  printf ("Delete %s? (y or n) ", name);
223818334Speter  fflush (stdout);
223918334Speter  i = getchar ();
224018334Speter  if (i != '\n')
224150599Sobrien    while ((c = getchar ()) != '\n' && c != EOF)
224250599Sobrien      ;
224350599Sobrien
224418334Speter  if (i == 'y' || i == 'Y')
224518334Speter#endif /* DEBUG */
224618334Speter    if (stat (name, &st) >= 0 && S_ISREG (st.st_mode))
224718334Speter      if (unlink (name) < 0)
224818334Speter	if (verbose_flag)
224918334Speter	  perror_with_name (name);
225018334Speter}
225118334Speter
225218334Speterstatic void
2253132733Skandelete_temp_files (void)
225418334Speter{
225590277Sobrien  struct temp_file *temp;
225618334Speter
225718334Speter  for (temp = always_delete_queue; temp; temp = temp->next)
225818334Speter    delete_if_ordinary (temp->name);
225918334Speter  always_delete_queue = 0;
226018334Speter}
226118334Speter
226218334Speter/* Delete all the files to be deleted on error.  */
226318334Speter
226418334Speterstatic void
2265132733Skandelete_failure_queue (void)
226618334Speter{
226790277Sobrien  struct temp_file *temp;
226818334Speter
226918334Speter  for (temp = failure_delete_queue; temp; temp = temp->next)
227018334Speter    delete_if_ordinary (temp->name);
227118334Speter}
227218334Speter
227318334Speterstatic void
2274132733Skanclear_failure_queue (void)
227518334Speter{
227618334Speter  failure_delete_queue = 0;
227718334Speter}
227818334Speter
227918334Speter/* Build a list of search directories from PATHS.
228018334Speter   PREFIX is a string to prepend to the list.
2281117413Skan   If CHECK_DIR_P is nonzero we ensure the directory exists.
228218334Speter   This is used mostly by putenv_from_prefixes so we use `collect_obstack'.
228318334Speter   It is also used by the --print-search-dirs flag.  */
228418334Speter
228518334Speterstatic char *
2286132733Skanbuild_search_list (struct path_prefix *paths, const char *prefix,
2287132733Skan		   int check_dir_p)
228818334Speter{
228918334Speter  int suffix_len = (machine_suffix) ? strlen (machine_suffix) : 0;
229018334Speter  int just_suffix_len
229118334Speter    = (just_machine_suffix) ? strlen (just_machine_suffix) : 0;
229218334Speter  int first_time = TRUE;
229318334Speter  struct prefix_list *pprefix;
229418334Speter
229518334Speter  obstack_grow (&collect_obstack, prefix, strlen (prefix));
229690277Sobrien  obstack_1grow (&collect_obstack, '=');
229718334Speter
229818334Speter  for (pprefix = paths->plist; pprefix != 0; pprefix = pprefix->next)
229918334Speter    {
230018334Speter      int len = strlen (pprefix->prefix);
230118334Speter
230218334Speter      if (machine_suffix
230350599Sobrien	  && (! check_dir_p
230418334Speter	      || is_directory (pprefix->prefix, machine_suffix, 0)))
230518334Speter	{
230618334Speter	  if (!first_time)
230718334Speter	    obstack_1grow (&collect_obstack, PATH_SEPARATOR);
230890277Sobrien
230918334Speter	  first_time = FALSE;
231018334Speter	  obstack_grow (&collect_obstack, pprefix->prefix, len);
231118334Speter	  obstack_grow (&collect_obstack, machine_suffix, suffix_len);
231218334Speter	}
231318334Speter
231418334Speter      if (just_machine_suffix
231518334Speter	  && pprefix->require_machine_suffix == 2
231650599Sobrien	  && (! check_dir_p
231718334Speter	      || is_directory (pprefix->prefix, just_machine_suffix, 0)))
231818334Speter	{
231950599Sobrien	  if (! first_time)
232018334Speter	    obstack_1grow (&collect_obstack, PATH_SEPARATOR);
232190277Sobrien
232218334Speter	  first_time = FALSE;
232318334Speter	  obstack_grow (&collect_obstack, pprefix->prefix, len);
232418334Speter	  obstack_grow (&collect_obstack, just_machine_suffix,
232518334Speter			just_suffix_len);
232618334Speter	}
232718334Speter
232850599Sobrien      if (! pprefix->require_machine_suffix)
232918334Speter	{
233050599Sobrien	  if (! first_time)
233118334Speter	    obstack_1grow (&collect_obstack, PATH_SEPARATOR);
233218334Speter
233318334Speter	  first_time = FALSE;
233418334Speter	  obstack_grow (&collect_obstack, pprefix->prefix, len);
233518334Speter	}
233618334Speter    }
233750599Sobrien
233818334Speter  obstack_1grow (&collect_obstack, '\0');
233918334Speter  return obstack_finish (&collect_obstack);
234018334Speter}
234118334Speter
234250599Sobrien/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
234350599Sobrien   for collect.  */
234418334Speter
234518334Speterstatic void
2346132733Skanputenv_from_prefixes (struct path_prefix *paths, const char *env_var)
234718334Speter{
234818334Speter  putenv (build_search_list (paths, env_var, 1));
234918334Speter}
235018334Speter
235190277Sobrien/* Check whether NAME can be accessed in MODE.  This is like access,
235290277Sobrien   except that it never considers directories to be executable.  */
235390277Sobrien
235490277Sobrienstatic int
2355132733Skanaccess_check (const char *name, int mode)
235690277Sobrien{
235790277Sobrien  if (mode == X_OK)
235890277Sobrien    {
235990277Sobrien      struct stat st;
236090277Sobrien
236190277Sobrien      if (stat (name, &st) < 0
236290277Sobrien	  || S_ISDIR (st.st_mode))
236390277Sobrien	return -1;
236490277Sobrien    }
236590277Sobrien
236690277Sobrien  return access (name, mode);
236790277Sobrien}
236890277Sobrien
236918334Speter/* Search for NAME using the prefix list PREFIXES.  MODE is passed to
237018334Speter   access to check permissions.
237150599Sobrien   Return 0 if not found, otherwise return its name, allocated with malloc.  */
237218334Speter
237318334Speterstatic char *
2374132733Skanfind_a_file (struct path_prefix *pprefix, const char *name, int mode,
2375132733Skan	     int multilib)
237618334Speter{
237718334Speter  char *temp;
237890277Sobrien  const char *const file_suffix =
237990277Sobrien    ((mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : "");
238018334Speter  struct prefix_list *pl;
238118334Speter  int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1;
2382104763Skan  const char *multilib_name, *multilib_os_name;
238318334Speter
238452520Sobrien#ifdef DEFAULT_ASSEMBLER
238590277Sobrien  if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0)
238690277Sobrien    return xstrdup (DEFAULT_ASSEMBLER);
238752520Sobrien#endif
238852520Sobrien
238952520Sobrien#ifdef DEFAULT_LINKER
239090277Sobrien  if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0)
239190277Sobrien    return xstrdup (DEFAULT_LINKER);
239252520Sobrien#endif
239352520Sobrien
239418334Speter  if (machine_suffix)
239518334Speter    len += strlen (machine_suffix);
239618334Speter
2397104763Skan  multilib_name = name;
2398104763Skan  multilib_os_name = name;
2399104763Skan  if (multilib && multilib_os_dir)
2400104763Skan    {
2401104763Skan      int len1 = multilib_dir ? strlen (multilib_dir) + 1 : 0;
2402104763Skan      int len2 = strlen (multilib_os_dir) + 1;
2403104763Skan
2404104763Skan      len += len1 > len2 ? len1 : len2;
2405104763Skan      if (multilib_dir)
2406104763Skan	multilib_name = ACONCAT ((multilib_dir, dir_separator_str, name,
2407104763Skan				  NULL));
2408104763Skan      if (strcmp (multilib_os_dir, ".") != 0)
2409104763Skan	multilib_os_name = ACONCAT ((multilib_os_dir, dir_separator_str, name,
2410104763Skan				    NULL));
2411104763Skan    }
2412104763Skan
241318334Speter  temp = xmalloc (len);
241418334Speter
241518334Speter  /* Determine the filename to execute (special case for absolute paths).  */
241618334Speter
2417132733Skan  if (IS_ABSOLUTE_PATH (name))
241818334Speter    {
241952520Sobrien      if (access (name, mode) == 0)
242018334Speter	{
242118334Speter	  strcpy (temp, name);
242218334Speter	  return temp;
242318334Speter	}
242418334Speter    }
242518334Speter  else
242618334Speter    for (pl = pprefix->plist; pl; pl = pl->next)
242718334Speter      {
2428104763Skan	const char *this_name
2429104763Skan	  = pl->os_multilib ? multilib_os_name : multilib_name;
2430104763Skan
243118334Speter	if (machine_suffix)
243218334Speter	  {
243318334Speter	    /* Some systems have a suffix for executable files.
243418334Speter	       So try appending that first.  */
243518334Speter	    if (file_suffix[0] != 0)
243618334Speter	      {
243718334Speter		strcpy (temp, pl->prefix);
243818334Speter		strcat (temp, machine_suffix);
2439104763Skan		strcat (temp, multilib_name);
244018334Speter		strcat (temp, file_suffix);
244190277Sobrien		if (access_check (temp, mode) == 0)
244218334Speter		  {
244318334Speter		    if (pl->used_flag_ptr != 0)
244418334Speter		      *pl->used_flag_ptr = 1;
244518334Speter		    return temp;
244618334Speter		  }
244718334Speter	      }
244818334Speter
2449104763Skan	    /* Now try just the multilib_name.  */
245018334Speter	    strcpy (temp, pl->prefix);
245118334Speter	    strcat (temp, machine_suffix);
2452104763Skan	    strcat (temp, multilib_name);
245390277Sobrien	    if (access_check (temp, mode) == 0)
245418334Speter	      {
245518334Speter		if (pl->used_flag_ptr != 0)
245618334Speter		  *pl->used_flag_ptr = 1;
245718334Speter		return temp;
245818334Speter	      }
245918334Speter	  }
246018334Speter
246118334Speter	/* Certain prefixes are tried with just the machine type,
246218334Speter	   not the version.  This is used for finding as, ld, etc.  */
246318334Speter	if (just_machine_suffix && pl->require_machine_suffix == 2)
246418334Speter	  {
246518334Speter	    /* Some systems have a suffix for executable files.
246618334Speter	       So try appending that first.  */
246718334Speter	    if (file_suffix[0] != 0)
246818334Speter	      {
246918334Speter		strcpy (temp, pl->prefix);
247018334Speter		strcat (temp, just_machine_suffix);
2471104763Skan		strcat (temp, multilib_name);
247218334Speter		strcat (temp, file_suffix);
247390277Sobrien		if (access_check (temp, mode) == 0)
247418334Speter		  {
247518334Speter		    if (pl->used_flag_ptr != 0)
247618334Speter		      *pl->used_flag_ptr = 1;
247718334Speter		    return temp;
247818334Speter		  }
247918334Speter	      }
248018334Speter
248118334Speter	    strcpy (temp, pl->prefix);
248218334Speter	    strcat (temp, just_machine_suffix);
2483104763Skan	    strcat (temp, multilib_name);
248490277Sobrien	    if (access_check (temp, mode) == 0)
248518334Speter	      {
248618334Speter		if (pl->used_flag_ptr != 0)
248718334Speter		  *pl->used_flag_ptr = 1;
248818334Speter		return temp;
248918334Speter	      }
249018334Speter	  }
249118334Speter
249218334Speter	/* Certain prefixes can't be used without the machine suffix
249318334Speter	   when the machine or version is explicitly specified.  */
249450599Sobrien	if (! pl->require_machine_suffix)
249518334Speter	  {
249618334Speter	    /* Some systems have a suffix for executable files.
249718334Speter	       So try appending that first.  */
249818334Speter	    if (file_suffix[0] != 0)
249918334Speter	      {
250018334Speter		strcpy (temp, pl->prefix);
2501104763Skan		strcat (temp, this_name);
250218334Speter		strcat (temp, file_suffix);
250390277Sobrien		if (access_check (temp, mode) == 0)
250418334Speter		  {
250518334Speter		    if (pl->used_flag_ptr != 0)
250618334Speter		      *pl->used_flag_ptr = 1;
250718334Speter		    return temp;
250818334Speter		  }
250918334Speter	      }
251018334Speter
251118334Speter	    strcpy (temp, pl->prefix);
2512104763Skan	    strcat (temp, this_name);
251390277Sobrien	    if (access_check (temp, mode) == 0)
251418334Speter	      {
251518334Speter		if (pl->used_flag_ptr != 0)
251618334Speter		  *pl->used_flag_ptr = 1;
251718334Speter		return temp;
251818334Speter	      }
251918334Speter	  }
252018334Speter      }
252118334Speter
252218334Speter  free (temp);
252318334Speter  return 0;
252418334Speter}
252518334Speter
252690277Sobrien/* Ranking of prefixes in the sort list. -B prefixes are put before
252790277Sobrien   all others.  */
252818334Speter
252990277Sobrienenum path_prefix_priority
253090277Sobrien{
253190277Sobrien  PREFIX_PRIORITY_B_OPT,
253290277Sobrien  PREFIX_PRIORITY_LAST
253390277Sobrien};
253490277Sobrien
2535132733Skan/* Add an entry for PREFIX in PLIST.  The PLIST is kept in ascending
253690277Sobrien   order according to PRIORITY.  Within each PRIORITY, new entries are
253790277Sobrien   appended.
253890277Sobrien
253918334Speter   If WARN is nonzero, we will warn if no file is found
254018334Speter   through this prefix.  WARN should point to an int
254118334Speter   which will be set to 1 if this entry is used.
254218334Speter
254350599Sobrien   COMPONENT is the value to be passed to update_path.
254450599Sobrien
254518334Speter   REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without
254618334Speter   the complete value of machine_suffix.
254718334Speter   2 means try both machine_suffix and just_machine_suffix.  */
254818334Speter
254918334Speterstatic void
2550132733Skanadd_prefix (struct path_prefix *pprefix, const char *prefix,
2551132733Skan	    const char *component, /* enum prefix_priority */ int priority,
2552132733Skan	    int require_machine_suffix, int *warn, int os_multilib)
255318334Speter{
255418334Speter  struct prefix_list *pl, **prev;
255518334Speter  int len;
255618334Speter
255790277Sobrien  for (prev = &pprefix->plist;
255890277Sobrien       (*prev) != NULL && (*prev)->priority <= priority;
255990277Sobrien       prev = &(*prev)->next)
256090277Sobrien    ;
256118334Speter
2562132733Skan  /* Keep track of the longest prefix.  */
256318334Speter
256450599Sobrien  prefix = update_path (prefix, component);
256518334Speter  len = strlen (prefix);
256618334Speter  if (len > pprefix->max_len)
256718334Speter    pprefix->max_len = len;
256818334Speter
2569132733Skan  pl = xmalloc (sizeof (struct prefix_list));
257090277Sobrien  pl->prefix = prefix;
257118334Speter  pl->require_machine_suffix = require_machine_suffix;
257218334Speter  pl->used_flag_ptr = warn;
257390277Sobrien  pl->priority = priority;
2574104763Skan  pl->os_multilib = os_multilib;
257518334Speter  if (warn)
257618334Speter    *warn = 0;
257718334Speter
2578132733Skan  /* Insert after PREV.  */
257990277Sobrien  pl->next = (*prev);
258090277Sobrien  (*prev) = pl;
258118334Speter}
2582132733Skan
2583132733Skan/* Same as add_prefix, but prepending target_system_root to prefix.  */
2584132733Skanstatic void
2585132733Skanadd_sysrooted_prefix (struct path_prefix *pprefix, const char *prefix,
2586132733Skan		      const char *component,
2587132733Skan		      /* enum prefix_priority */ int priority,
2588132733Skan		      int require_machine_suffix, int *warn, int os_multilib)
2589132733Skan{
2590132733Skan  if (!IS_ABSOLUTE_PATH (prefix))
2591132733Skan    abort ();
2592132733Skan
2593132733Skan  if (target_system_root)
2594132733Skan    {
2595132733Skan      if (target_sysroot_suffix)
2596132733Skan	  prefix = concat (target_sysroot_suffix, prefix, NULL);
2597132733Skan      prefix = concat (target_system_root, prefix, NULL);
2598132733Skan
2599132733Skan      /* We have to override this because GCC's notion of sysroot
2600132733Skan	 moves along with GCC.  */
2601132733Skan      component = "GCC";
2602132733Skan    }
2603132733Skan
2604132733Skan  add_prefix (pprefix, prefix, component, priority,
2605132733Skan	      require_machine_suffix, warn, os_multilib);
2606132733Skan}
260718334Speter
260818334Speter/* Execute the command specified by the arguments on the current line of spec.
260918334Speter   When using pipes, this includes several piped-together commands
261018334Speter   with `|' between them.
261118334Speter
261218334Speter   Return 0 if successful, -1 if failed.  */
261318334Speter
261418334Speterstatic int
2615132733Skanexecute (void)
261618334Speter{
261718334Speter  int i;
261818334Speter  int n_commands;		/* # of command.  */
261918334Speter  char *string;
262018334Speter  struct command
262190277Sobrien  {
262290277Sobrien    const char *prog;		/* program name.  */
262390277Sobrien    const char **argv;		/* vector of args.  */
262490277Sobrien    int pid;			/* pid of process for this command.  */
262590277Sobrien  };
262618334Speter
262718334Speter  struct command *commands;	/* each command buffer with above info.  */
262818334Speter
2629117413Skan  if (processing_spec_function)
2630117413Skan    abort ();
2631117413Skan
263218334Speter  /* Count # of piped commands.  */
263318334Speter  for (n_commands = 1, i = 0; i < argbuf_index; i++)
263418334Speter    if (strcmp (argbuf[i], "|") == 0)
263518334Speter      n_commands++;
263618334Speter
263718334Speter  /* Get storage for each command.  */
2638132733Skan  commands = alloca (n_commands * sizeof (struct command));
263918334Speter
264018334Speter  /* Split argbuf into its separate piped processes,
264118334Speter     and record info about each one.
264218334Speter     Also search for the programs that are to be run.  */
264318334Speter
264418334Speter  commands[0].prog = argbuf[0]; /* first command.  */
264518334Speter  commands[0].argv = &argbuf[0];
2646104763Skan  string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, 0);
264750599Sobrien
264818334Speter  if (string)
264918334Speter    commands[0].argv[0] = string;
265018334Speter
265118334Speter  for (n_commands = 1, i = 0; i < argbuf_index; i++)
265218334Speter    if (strcmp (argbuf[i], "|") == 0)
265318334Speter      {				/* each command.  */
265452520Sobrien#if defined (__MSDOS__) || defined (OS2) || defined (VMS)
265590277Sobrien	fatal ("-pipe not supported");
265618334Speter#endif
265718334Speter	argbuf[i] = 0;	/* termination of command args.  */
265818334Speter	commands[n_commands].prog = argbuf[i + 1];
265918334Speter	commands[n_commands].argv = &argbuf[i + 1];
2660104763Skan	string = find_a_file (&exec_prefixes, commands[n_commands].prog,
2661104763Skan			      X_OK, 0);
266218334Speter	if (string)
266318334Speter	  commands[n_commands].argv[0] = string;
266418334Speter	n_commands++;
266518334Speter      }
266618334Speter
266718334Speter  argbuf[argbuf_index] = 0;
266818334Speter
266918334Speter  /* If -v, print what we are about to do, and maybe query.  */
267018334Speter
267118334Speter  if (verbose_flag)
267218334Speter    {
267350599Sobrien      /* For help listings, put a blank line between sub-processes.  */
267450599Sobrien      if (print_help_list)
267550599Sobrien	fputc ('\n', stderr);
267690277Sobrien
267718334Speter      /* Print each piped command as a separate line.  */
267890277Sobrien      for (i = 0; i < n_commands; i++)
267918334Speter	{
268090277Sobrien	  const char *const *j;
268118334Speter
2682117413Skan	  if (verbose_only_flag)
2683117413Skan	    {
268490277Sobrien	      for (j = commands[i].argv; *j; j++)
268590277Sobrien		{
268690277Sobrien		  const char *p;
268790277Sobrien		  fprintf (stderr, " \"");
268890277Sobrien		  for (p = *j; *p; ++p)
268990277Sobrien		    {
269090277Sobrien		      if (*p == '"' || *p == '\\' || *p == '$')
269190277Sobrien			fputc ('\\', stderr);
269290277Sobrien		      fputc (*p, stderr);
269390277Sobrien		    }
269490277Sobrien		  fputc ('"', stderr);
269590277Sobrien		}
2696117413Skan	    }
2697117413Skan	  else
269890277Sobrien	    for (j = commands[i].argv; *j; j++)
269990277Sobrien	      fprintf (stderr, " %s", *j);
270018334Speter
270118334Speter	  /* Print a pipe symbol after all but the last command.  */
270218334Speter	  if (i + 1 != n_commands)
270318334Speter	    fprintf (stderr, " |");
270418334Speter	  fprintf (stderr, "\n");
270518334Speter	}
270618334Speter      fflush (stderr);
270790277Sobrien      if (verbose_only_flag != 0)
2708132733Skan        {
2709132733Skan	  /* verbose_only_flag should act as if the spec was
2710132733Skan	     executed, so increment execution_count before
2711132733Skan	     returning.  This prevents spurious warnings about
2712132733Skan	     unused linker input files, etc.  */
2713132733Skan	  execution_count++;
2714132733Skan	  return 0;
2715132733Skan        }
271618334Speter#ifdef DEBUG
271752520Sobrien      notice ("\nGo ahead? (y or n) ");
271818334Speter      fflush (stderr);
271918334Speter      i = getchar ();
272018334Speter      if (i != '\n')
272150599Sobrien	while (getchar () != '\n')
272250599Sobrien	  ;
272350599Sobrien
272418334Speter      if (i != 'y' && i != 'Y')
272518334Speter	return 0;
272618334Speter#endif /* DEBUG */
272718334Speter    }
272818334Speter
2729117413Skan#ifdef ENABLE_VALGRIND_CHECKING
2730132733Skan  /* Run the each command through valgrind.  To simplify prepending the
2731117413Skan     path to valgrind and the option "-q" (for quiet operation unless
2732117413Skan     something triggers), we allocate a separate argv array.  */
2733117413Skan
2734117413Skan  for (i = 0; i < n_commands; i++)
2735117413Skan    {
2736117413Skan      const char **argv;
2737117413Skan      int argc;
2738117413Skan      int j;
2739117413Skan
2740117413Skan      for (argc = 0; commands[i].argv[argc] != NULL; argc++)
2741117413Skan	;
2742117413Skan
2743117413Skan      argv = alloca ((argc + 3) * sizeof (char *));
2744117413Skan
2745117413Skan      argv[0] = VALGRIND_PATH;
2746117413Skan      argv[1] = "-q";
2747117413Skan      for (j = 2; j < argc + 2; j++)
2748117413Skan	argv[j] = commands[i].argv[j - 2];
2749117413Skan      argv[j] = NULL;
2750117413Skan
2751117413Skan      commands[i].argv = argv;
2752117413Skan      commands[i].prog = argv[0];
2753117413Skan    }
2754117413Skan#endif
2755117413Skan
275618334Speter  /* Run each piped subprocess.  */
275718334Speter
275818334Speter  for (i = 0; i < n_commands; i++)
275918334Speter    {
276050599Sobrien      char *errmsg_fmt, *errmsg_arg;
276190277Sobrien      const char *string = commands[i].argv[0];
276218334Speter
276390277Sobrien      /* For some bizarre reason, the second argument of execvp() is
276490277Sobrien	 char *const *, not const char *const *.  */
276590277Sobrien      commands[i].pid = pexecute (string, (char *const *) commands[i].argv,
276650599Sobrien				  programname, temp_filename,
276750599Sobrien				  &errmsg_fmt, &errmsg_arg,
276850599Sobrien				  ((i == 0 ? PEXECUTE_FIRST : 0)
276950599Sobrien				   | (i + 1 == n_commands ? PEXECUTE_LAST : 0)
277050599Sobrien				   | (string == commands[i].prog
277150599Sobrien				      ? PEXECUTE_SEARCH : 0)
277250599Sobrien				   | (verbose_flag ? PEXECUTE_VERBOSE : 0)));
277318334Speter
277450599Sobrien      if (commands[i].pid == -1)
277550599Sobrien	pfatal_pexecute (errmsg_fmt, errmsg_arg);
277650599Sobrien
277718334Speter      if (string != commands[i].prog)
2778132733Skan	free ((void *) string);
277918334Speter    }
278018334Speter
278118334Speter  execution_count++;
278218334Speter
278318334Speter  /* Wait for all the subprocesses to finish.
278418334Speter     We don't care what order they finish in;
278518334Speter     we know that N_COMMANDS waits will get them all.
278618334Speter     Ignore subprocesses that we don't know about,
278718334Speter     since they can be spawned by the process that exec'ed us.  */
278818334Speter
278918334Speter  {
279018334Speter    int ret_code = 0;
279190277Sobrien#ifdef HAVE_GETRUSAGE
279290277Sobrien    struct timeval d;
279390277Sobrien    double ut = 0.0, st = 0.0;
279490277Sobrien#endif
279518334Speter
279690277Sobrien    for (i = 0; i < n_commands;)
279718334Speter      {
279818334Speter	int j;
279918334Speter	int status;
280018334Speter	int pid;
280118334Speter
280250599Sobrien	pid = pwait (commands[i].pid, &status, 0);
280318334Speter	if (pid < 0)
280418334Speter	  abort ();
280518334Speter
280690277Sobrien#ifdef HAVE_GETRUSAGE
280790277Sobrien	if (report_times)
280890277Sobrien	  {
280990277Sobrien	    /* getrusage returns the total resource usage of all children
281090277Sobrien	       up to now.  Copy the previous values into prus, get the
281190277Sobrien	       current statistics, then take the difference.  */
281290277Sobrien
281390277Sobrien	    prus = rus;
281490277Sobrien	    getrusage (RUSAGE_CHILDREN, &rus);
281590277Sobrien	    d.tv_sec = rus.ru_utime.tv_sec - prus.ru_utime.tv_sec;
281690277Sobrien	    d.tv_usec = rus.ru_utime.tv_usec - prus.ru_utime.tv_usec;
281790277Sobrien	    ut = (double) d.tv_sec + (double) d.tv_usec / 1.0e6;
281890277Sobrien
281990277Sobrien	    d.tv_sec = rus.ru_stime.tv_sec - prus.ru_stime.tv_sec;
282090277Sobrien	    d.tv_usec = rus.ru_stime.tv_usec - prus.ru_stime.tv_usec;
282190277Sobrien	    st = (double) d.tv_sec + (double) d.tv_usec / 1.0e6;
282290277Sobrien	  }
282390277Sobrien#endif
282490277Sobrien
282518334Speter	for (j = 0; j < n_commands; j++)
282618334Speter	  if (commands[j].pid == pid)
282718334Speter	    {
282818334Speter	      i++;
282990277Sobrien	      if (WIFSIGNALED (status))
283018334Speter		{
283190277Sobrien#ifdef SIGPIPE
283290277Sobrien		  /* SIGPIPE is a special case.  It happens in -pipe mode
283390277Sobrien		     when the compiler dies before the preprocessor is
283490277Sobrien		     done, or the assembler dies before the compiler is
283590277Sobrien		     done.  There's generally been an error already, and
283690277Sobrien		     this is just fallout.  So don't generate another error
283790277Sobrien		     unless we would otherwise have succeeded.  */
283890277Sobrien		  if (WTERMSIG (status) == SIGPIPE
283990277Sobrien		      && (signal_count || greatest_status >= MIN_FATAL_STATUS))
284090277Sobrien		    ;
284190277Sobrien		  else
284290277Sobrien#endif
284390277Sobrien		    fatal ("\
284490277SobrienInternal error: %s (program %s)\n\
284590277SobrienPlease submit a full bug report.\n\
284690277SobrienSee %s for instructions.",
284790277Sobrien			   strsignal (WTERMSIG (status)), commands[j].prog,
2848117413Skan			   bug_report_url);
284990277Sobrien		  signal_count++;
285090277Sobrien		  ret_code = -1;
285118334Speter		}
285290277Sobrien	      else if (WIFEXITED (status)
285390277Sobrien		       && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
285490277Sobrien		{
285590277Sobrien		  if (WEXITSTATUS (status) > greatest_status)
285690277Sobrien		    greatest_status = WEXITSTATUS (status);
285790277Sobrien		  ret_code = -1;
285890277Sobrien		}
285990277Sobrien#ifdef HAVE_GETRUSAGE
286090277Sobrien	      if (report_times && ut + st != 0)
286190277Sobrien		notice ("# %s %.2f %.2f\n", commands[j].prog, ut, st);
286290277Sobrien#endif
286318334Speter	      break;
286418334Speter	    }
286518334Speter      }
286618334Speter    return ret_code;
286718334Speter  }
286818334Speter}
286918334Speter
287018334Speter/* Find all the switches given to us
287118334Speter   and make a vector describing them.
287218334Speter   The elements of the vector are strings, one per switch given.
287318334Speter   If a switch uses following arguments, then the `part1' field
287418334Speter   is the switch itself and the `args' field
287518334Speter   is a null-terminated vector containing the following arguments.
287690277Sobrien   The `live_cond' field is:
287790277Sobrien   0 when initialized
287890277Sobrien   1 if the switch is true in a conditional spec,
287990277Sobrien   -1 if false (overridden by a later switch)
2880132733Skan   -2 if this switch should be ignored (used in %<S)
288152520Sobrien   The `validated' field is nonzero if any spec has looked at this switch;
288218334Speter   if it remains zero at the end of the run, it must be meaningless.  */
288318334Speter
288490277Sobrien#define SWITCH_OK       0
288590277Sobrien#define SWITCH_FALSE   -1
288690277Sobrien#define SWITCH_IGNORE  -2
288790277Sobrien#define SWITCH_LIVE     1
288890277Sobrien
288918334Speterstruct switchstr
289018334Speter{
289152520Sobrien  const char *part1;
289290277Sobrien  const char **args;
289318334Speter  int live_cond;
289490277Sobrien  unsigned char validated;
289590277Sobrien  unsigned char ordering;
289618334Speter};
289718334Speter
289818334Speterstatic struct switchstr *switches;
289918334Speter
290018334Speterstatic int n_switches;
290118334Speter
290218334Speterstruct infile
290318334Speter{
290452520Sobrien  const char *name;
290552520Sobrien  const char *language;
290618334Speter};
290718334Speter
290818334Speter/* Also a vector of input files specified.  */
290918334Speter
291018334Speterstatic struct infile *infiles;
291118334Speter
291290277Sobrienint n_infiles;
291318334Speter
2914132733Skan/* True if multiple input files are being compiled to a single
2915132733Skan   assembly file.  */
2916132733Skan
2917132733Skanstatic bool combine_inputs;
2918132733Skan
291952520Sobrien/* This counts the number of libraries added by lang_specific_driver, so that
292050599Sobrien   we can tell if there were any user supplied any files or libraries.  */
292150599Sobrien
292250599Sobrienstatic int added_libraries;
292350599Sobrien
292418334Speter/* And a vector of corresponding output files is made up later.  */
292518334Speter
292690277Sobrienconst char **outfiles;
292718334Speter
292850599Sobrien/* Used to track if none of the -B paths are used.  */
292950599Sobrienstatic int warn_B;
293050599Sobrien
293150599Sobrien/* Gives value to pass as "warn" to add_prefix for standard prefixes.  */
293250599Sobrienstatic int *warn_std_ptr = 0;
293350599Sobrien
293490277Sobrien#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
293550599Sobrien
293650599Sobrien/* Convert NAME to a new name if it is the standard suffix.  DO_EXE
293790277Sobrien   is true if we should look for an executable suffix.  DO_OBJ
293890277Sobrien   is true if we should look for an object suffix.  */
293950599Sobrien
294090277Sobrienstatic const char *
2941132733Skanconvert_filename (const char *name, int do_exe ATTRIBUTE_UNUSED,
2942132733Skan		  int do_obj ATTRIBUTE_UNUSED)
294350599Sobrien{
294490277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
294550599Sobrien  int i;
294690277Sobrien#endif
294752520Sobrien  int len;
294850599Sobrien
294952520Sobrien  if (name == NULL)
295052520Sobrien    return NULL;
295190277Sobrien
295252520Sobrien  len = strlen (name);
295352520Sobrien
295490277Sobrien#ifdef HAVE_TARGET_OBJECT_SUFFIX
295590277Sobrien  /* Convert x.o to x.obj if TARGET_OBJECT_SUFFIX is ".obj".  */
295690277Sobrien  if (do_obj && len > 2
295750599Sobrien      && name[len - 2] == '.'
295850599Sobrien      && name[len - 1] == 'o')
295950599Sobrien    {
296050599Sobrien      obstack_grow (&obstack, name, len - 2);
296190277Sobrien      obstack_grow0 (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
296250599Sobrien      name = obstack_finish (&obstack);
296350599Sobrien    }
296450599Sobrien#endif
296550599Sobrien
296690277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
296750599Sobrien  /* If there is no filetype, make it the executable suffix (which includes
296850599Sobrien     the ".").  But don't get confused if we have just "-o".  */
296990277Sobrien  if (! do_exe || TARGET_EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-'))
297050599Sobrien    return name;
297150599Sobrien
297250599Sobrien  for (i = len - 1; i >= 0; i--)
297352520Sobrien    if (IS_DIR_SEPARATOR (name[i]))
297450599Sobrien      break;
297550599Sobrien
297650599Sobrien  for (i++; i < len; i++)
297750599Sobrien    if (name[i] == '.')
297850599Sobrien      return name;
297950599Sobrien
298050599Sobrien  obstack_grow (&obstack, name, len);
298190277Sobrien  obstack_grow0 (&obstack, TARGET_EXECUTABLE_SUFFIX,
298290277Sobrien		 strlen (TARGET_EXECUTABLE_SUFFIX));
298350599Sobrien  name = obstack_finish (&obstack);
298450599Sobrien#endif
298550599Sobrien
298650599Sobrien  return name;
298750599Sobrien}
298850599Sobrien#endif
298950599Sobrien
299050599Sobrien/* Display the command line switches accepted by gcc.  */
299150599Sobrienstatic void
2992132733Skandisplay_help (void)
299350599Sobrien{
299490277Sobrien  printf (_("Usage: %s [options] file...\n"), programname);
299590277Sobrien  fputs (_("Options:\n"), stdout);
299650599Sobrien
299790277Sobrien  fputs (_("  -pass-exit-codes         Exit with highest error code from a phase\n"), stdout);
299890277Sobrien  fputs (_("  --help                   Display this information\n"), stdout);
299990277Sobrien  fputs (_("  --target-help            Display target specific command line options\n"), stdout);
300050599Sobrien  if (! verbose_flag)
300190277Sobrien    fputs (_("  (Use '-v --help' to display command line options of sub-processes)\n"), stdout);
300290277Sobrien  fputs (_("  -dumpspecs               Display all of the built in spec strings\n"), stdout);
300390277Sobrien  fputs (_("  -dumpversion             Display the version of the compiler\n"), stdout);
300490277Sobrien  fputs (_("  -dumpmachine             Display the compiler's target processor\n"), stdout);
300590277Sobrien  fputs (_("  -print-search-dirs       Display the directories in the compiler's search path\n"), stdout);
300690277Sobrien  fputs (_("  -print-libgcc-file-name  Display the name of the compiler's companion library\n"), stdout);
300790277Sobrien  fputs (_("  -print-file-name=<lib>   Display the full path to library <lib>\n"), stdout);
300890277Sobrien  fputs (_("  -print-prog-name=<prog>  Display the full path to compiler component <prog>\n"), stdout);
300990277Sobrien  fputs (_("  -print-multi-directory   Display the root directory for versions of libgcc\n"), stdout);
301090277Sobrien  fputs (_("\
301190277Sobrien  -print-multi-lib         Display the mapping between command line options and\n\
301290277Sobrien                           multiple library search directories\n"), stdout);
3013104763Skan  fputs (_("  -print-multi-os-directory Display the relative path to OS libraries\n"), stdout);
301490277Sobrien  fputs (_("  -Wa,<options>            Pass comma-separated <options> on to the assembler\n"), stdout);
301590277Sobrien  fputs (_("  -Wp,<options>            Pass comma-separated <options> on to the preprocessor\n"), stdout);
301690277Sobrien  fputs (_("  -Wl,<options>            Pass comma-separated <options> on to the linker\n"), stdout);
3017132733Skan  fputs (_("  -Xassembler <arg>        Pass <arg> on to the assembler\n"), stdout);
3018132733Skan  fputs (_("  -Xpreprocessor <arg>     Pass <arg> on to the preprocessor\n"), stdout);
301990277Sobrien  fputs (_("  -Xlinker <arg>           Pass <arg> on to the linker\n"), stdout);
302090277Sobrien  fputs (_("  -save-temps              Do not delete intermediate files\n"), stdout);
302190277Sobrien  fputs (_("  -pipe                    Use pipes rather than intermediate files\n"), stdout);
302290277Sobrien  fputs (_("  -time                    Time the execution of each subprocess\n"), stdout);
302390277Sobrien  fputs (_("  -specs=<file>            Override built-in specs with the contents of <file>\n"), stdout);
302490277Sobrien  fputs (_("  -std=<standard>          Assume that the input sources are for <standard>\n"), stdout);
302590277Sobrien  fputs (_("  -B <directory>           Add <directory> to the compiler's search paths\n"), stdout);
302690277Sobrien  fputs (_("  -b <machine>             Run gcc for target <machine>, if installed\n"), stdout);
302790277Sobrien  fputs (_("  -V <version>             Run gcc version number <version>, if installed\n"), stdout);
302890277Sobrien  fputs (_("  -v                       Display the programs invoked by the compiler\n"), stdout);
302990277Sobrien  fputs (_("  -###                     Like -v but options quoted and commands not executed\n"), stdout);
303090277Sobrien  fputs (_("  -E                       Preprocess only; do not compile, assemble or link\n"), stdout);
303190277Sobrien  fputs (_("  -S                       Compile only; do not assemble or link\n"), stdout);
303290277Sobrien  fputs (_("  -c                       Compile and assemble, but do not link\n"), stdout);
303390277Sobrien  fputs (_("  -o <file>                Place the output into <file>\n"), stdout);
303490277Sobrien  fputs (_("\
303590277Sobrien  -x <language>            Specify the language of the following input files\n\
3036117413Skan                           Permissible languages include: c c++ assembler none\n\
303790277Sobrien                           'none' means revert to the default behavior of\n\
303890277Sobrien                           guessing the language based on the file's extension\n\
303990277Sobrien"), stdout);
304050599Sobrien
304190277Sobrien  printf (_("\
304290277Sobrien\nOptions starting with -g, -f, -m, -O, -W, or --param are automatically\n\
304390277Sobrien passed on to the various sub-processes invoked by %s.  In order to pass\n\
304490277Sobrien other options on to these processes the -W<letter> options must be used.\n\
304590277Sobrien"), programname);
304650599Sobrien
304750599Sobrien  /* The rest of the options are displayed by invocations of the various
304850599Sobrien     sub-processes.  */
304950599Sobrien}
305050599Sobrien
305190277Sobrienstatic void
3052132733Skanadd_preprocessor_option (const char *option, int len)
305390277Sobrien{
305452520Sobrien  n_preprocessor_options++;
305590277Sobrien
305652520Sobrien  if (! preprocessor_options)
3057132733Skan    preprocessor_options = xmalloc (n_preprocessor_options * sizeof (char *));
305852520Sobrien  else
3059132733Skan    preprocessor_options = xrealloc (preprocessor_options,
3060132733Skan				     n_preprocessor_options * sizeof (char *));
306190277Sobrien
306252520Sobrien  preprocessor_options [n_preprocessor_options - 1] =
306352520Sobrien    save_string (option, len);
306450599Sobrien}
306590277Sobrien
306690277Sobrienstatic void
3067132733Skanadd_assembler_option (const char *option, int len)
306852520Sobrien{
306952520Sobrien  n_assembler_options++;
307052520Sobrien
307152520Sobrien  if (! assembler_options)
3072132733Skan    assembler_options = xmalloc (n_assembler_options * sizeof (char *));
307352520Sobrien  else
3074132733Skan    assembler_options = xrealloc (assembler_options,
3075132733Skan				  n_assembler_options * sizeof (char *));
307652520Sobrien
307752520Sobrien  assembler_options [n_assembler_options - 1] = save_string (option, len);
307850599Sobrien}
307990277Sobrien
308090277Sobrienstatic void
3081132733Skanadd_linker_option (const char *option, int len)
308252520Sobrien{
308352520Sobrien  n_linker_options++;
308452520Sobrien
308552520Sobrien  if (! linker_options)
3086132733Skan    linker_options = xmalloc (n_linker_options * sizeof (char *));
308752520Sobrien  else
3088132733Skan    linker_options = xrealloc (linker_options,
3089132733Skan			       n_linker_options * sizeof (char *));
309052520Sobrien
309152520Sobrien  linker_options [n_linker_options - 1] = save_string (option, len);
309250599Sobrien}
309350599Sobrien
309418334Speter/* Create the vector `switches' and its contents.
309518334Speter   Store its length in `n_switches'.  */
309618334Speter
309718334Speterstatic void
3098132733Skanprocess_command (int argc, const char **argv)
309918334Speter{
310090277Sobrien  int i;
310152520Sobrien  const char *temp;
310252520Sobrien  char *temp1;
310390277Sobrien  const char *spec_lang = 0;
310418334Speter  int last_language_n_infiles;
310550599Sobrien  int have_c = 0;
310650599Sobrien  int have_o = 0;
310750599Sobrien  int lang_n_infiles = 0;
310890277Sobrien#ifdef MODIFY_TARGET_NAME
310990277Sobrien  int is_modify_target_name;
311090277Sobrien  int j;
311190277Sobrien#endif
311218334Speter
3113117413Skan  GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
311418334Speter
311518334Speter  n_switches = 0;
311618334Speter  n_infiles = 0;
311750599Sobrien  added_libraries = 0;
311818334Speter
311918334Speter  /* Figure compiler version from version string.  */
312018334Speter
312190277Sobrien  compiler_version = temp1 = xstrdup (version_string);
312290277Sobrien
312352520Sobrien  for (; *temp1; ++temp1)
312418334Speter    {
312552520Sobrien      if (*temp1 == ' ')
312618334Speter	{
312752520Sobrien	  *temp1 = '\0';
312818334Speter	  break;
312918334Speter	}
313018334Speter    }
313118334Speter
3132117413Skan  /* If there is a -V or -b option (or both), process it now, before
3133117413Skan     trying to interpret the rest of the command line.  */
3134117413Skan  if (argc > 1 && argv[1][0] == '-'
3135117413Skan      && (argv[1][1] == 'V' || argv[1][1] == 'b'))
3136117413Skan    {
3137117413Skan      const char *new_version = DEFAULT_TARGET_VERSION;
3138117413Skan      const char *new_machine = DEFAULT_TARGET_MACHINE;
3139117413Skan      const char *progname = argv[0];
3140117413Skan      char **new_argv;
3141117413Skan      char *new_argv0;
3142117413Skan      int baselen;
3143132733Skan
3144117413Skan      while (argc > 1 && argv[1][0] == '-'
3145117413Skan	     && (argv[1][1] == 'V' || argv[1][1] == 'b'))
3146117413Skan	{
3147117413Skan	  char opt = argv[1][1];
3148117413Skan	  const char *arg;
3149117413Skan	  if (argv[1][2] != '\0')
3150117413Skan	    {
3151117413Skan	      arg = argv[1] + 2;
3152117413Skan	      argc -= 1;
3153117413Skan	      argv += 1;
3154117413Skan	    }
3155117413Skan	  else if (argc > 2)
3156117413Skan	    {
3157117413Skan	      arg = argv[2];
3158117413Skan	      argc -= 2;
3159117413Skan	      argv += 2;
3160117413Skan	    }
3161117413Skan	  else
3162117413Skan	    fatal ("`-%c' option must have argument", opt);
3163117413Skan	  if (opt == 'V')
3164117413Skan	    new_version = arg;
3165117413Skan	  else
3166117413Skan	    new_machine = arg;
3167117413Skan	}
3168117413Skan
3169117413Skan      for (baselen = strlen (progname); baselen > 0; baselen--)
3170117413Skan	if (IS_DIR_SEPARATOR (progname[baselen-1]))
3171117413Skan	  break;
3172132733Skan      new_argv0 = xmemdup (progname, baselen,
3173117413Skan			   baselen + concat_length (new_version, new_machine,
3174117413Skan						    "-gcc-", NULL) + 1);
3175117413Skan      strcpy (new_argv0 + baselen, new_machine);
3176117413Skan      strcat (new_argv0, "-gcc-");
3177117413Skan      strcat (new_argv0, new_version);
3178117413Skan
3179117413Skan      new_argv = xmemdup (argv, (argc + 1) * sizeof (argv[0]),
3180117413Skan			  (argc + 1) * sizeof (argv[0]));
3181117413Skan      new_argv[0] = new_argv0;
3182117413Skan
3183117413Skan      execvp (new_argv0, new_argv);
3184117413Skan      fatal ("couldn't run `%s': %s", new_argv0, xstrerror (errno));
3185117413Skan    }
3186117413Skan
318790277Sobrien  /* Set up the default search paths.  If there is no GCC_EXEC_PREFIX,
318890277Sobrien     see if we can create it from the pathname specified in argv[0].  */
318918334Speter
3190132733Skan  gcc_libexec_prefix = standard_libexec_prefix;
319196736Sru#ifndef FREEBSD_NATIVE
319290277Sobrien#ifndef VMS
319390277Sobrien  /* FIXME: make_relative_prefix doesn't yet work for VMS.  */
319490277Sobrien  if (!gcc_exec_prefix)
319590277Sobrien    {
319690277Sobrien      gcc_exec_prefix = make_relative_prefix (argv[0], standard_bindir_prefix,
319790277Sobrien					      standard_exec_prefix);
3198132733Skan      gcc_libexec_prefix = make_relative_prefix (argv[0],
3199132733Skan						 standard_bindir_prefix,
3200132733Skan						 standard_libexec_prefix);
320190277Sobrien      if (gcc_exec_prefix)
320290277Sobrien	putenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL));
320390277Sobrien    }
3204132733Skan  else
3205132733Skan    gcc_libexec_prefix = make_relative_prefix (gcc_exec_prefix,
3206132733Skan					       standard_exec_prefix,
3207132733Skan					       standard_libexec_prefix);
3208132733Skan#else
320990277Sobrien#endif
321096736Sru#endif	/* not FREEBSD_NATIVE */
321190277Sobrien
321218334Speter  if (gcc_exec_prefix)
321318334Speter    {
321450599Sobrien      int len = strlen (gcc_exec_prefix);
321590277Sobrien
3216132733Skan      if (len > (int) sizeof ("/lib/gcc/") - 1
321752520Sobrien	  && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1])))
321850599Sobrien	{
3219132733Skan	  temp = gcc_exec_prefix + len - sizeof ("/lib/gcc/") + 1;
322052520Sobrien	  if (IS_DIR_SEPARATOR (*temp)
322190277Sobrien	      && strncmp (temp + 1, "lib", 3) == 0
322252520Sobrien	      && IS_DIR_SEPARATOR (temp[4])
3223132733Skan	      && strncmp (temp + 5, "gcc", 3) == 0)
3224132733Skan	    len -= sizeof ("/lib/gcc/") - 1;
322550599Sobrien	}
322650599Sobrien
322750599Sobrien      set_std_prefix (gcc_exec_prefix, len);
3228132733Skan      add_prefix (&exec_prefixes, gcc_libexec_prefix, "GCC",
3229104763Skan		  PREFIX_PRIORITY_LAST, 0, NULL, 0);
323090277Sobrien      add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC",
3231104763Skan		  PREFIX_PRIORITY_LAST, 0, NULL, 0);
323218334Speter    }
323318334Speter
323418334Speter  /* COMPILER_PATH and LIBRARY_PATH have values
323518334Speter     that are lists of directory names with colons.  */
323618334Speter
3237117413Skan  GET_ENVIRONMENT (temp, "COMPILER_PATH");
323818334Speter  if (temp)
323918334Speter    {
324052520Sobrien      const char *startp, *endp;
3241132733Skan      char *nstore = alloca (strlen (temp) + 3);
324218334Speter
324318334Speter      startp = endp = temp;
324418334Speter      while (1)
324518334Speter	{
324618334Speter	  if (*endp == PATH_SEPARATOR || *endp == 0)
324718334Speter	    {
324890277Sobrien	      strncpy (nstore, startp, endp - startp);
324918334Speter	      if (endp == startp)
325090277Sobrien		strcpy (nstore, concat (".", dir_separator_str, NULL));
325152520Sobrien	      else if (!IS_DIR_SEPARATOR (endp[-1]))
325218334Speter		{
325390277Sobrien		  nstore[endp - startp] = DIR_SEPARATOR;
325490277Sobrien		  nstore[endp - startp + 1] = 0;
325518334Speter		}
325618334Speter	      else
325790277Sobrien		nstore[endp - startp] = 0;
325890277Sobrien	      add_prefix (&exec_prefixes, nstore, 0,
3259104763Skan			  PREFIX_PRIORITY_LAST, 0, NULL, 0);
326050599Sobrien	      add_prefix (&include_prefixes,
326190277Sobrien			  concat (nstore, "include", NULL),
3262104763Skan			  0, PREFIX_PRIORITY_LAST, 0, NULL, 0);
326318334Speter	      if (*endp == 0)
326418334Speter		break;
326518334Speter	      endp = startp = endp + 1;
326618334Speter	    }
326718334Speter	  else
326818334Speter	    endp++;
326918334Speter	}
327018334Speter    }
327118334Speter
3272117413Skan  GET_ENVIRONMENT (temp, LIBRARY_PATH_ENV);
327391651Sobrien  if (temp && *cross_compile == '0')
327418334Speter    {
327552520Sobrien      const char *startp, *endp;
3276132733Skan      char *nstore = alloca (strlen (temp) + 3);
327718334Speter
327818334Speter      startp = endp = temp;
327918334Speter      while (1)
328018334Speter	{
328118334Speter	  if (*endp == PATH_SEPARATOR || *endp == 0)
328218334Speter	    {
328390277Sobrien	      strncpy (nstore, startp, endp - startp);
328418334Speter	      if (endp == startp)
328590277Sobrien		strcpy (nstore, concat (".", dir_separator_str, NULL));
328652520Sobrien	      else if (!IS_DIR_SEPARATOR (endp[-1]))
328718334Speter		{
328890277Sobrien		  nstore[endp - startp] = DIR_SEPARATOR;
328990277Sobrien		  nstore[endp - startp + 1] = 0;
329018334Speter		}
329118334Speter	      else
329290277Sobrien		nstore[endp - startp] = 0;
329390277Sobrien	      add_prefix (&startfile_prefixes, nstore, NULL,
3294104763Skan			  PREFIX_PRIORITY_LAST, 0, NULL, 1);
329518334Speter	      if (*endp == 0)
329618334Speter		break;
329718334Speter	      endp = startp = endp + 1;
329818334Speter	    }
329918334Speter	  else
330018334Speter	    endp++;
330118334Speter	}
330218334Speter    }
330318334Speter
330418334Speter  /* Use LPATH like LIBRARY_PATH (for the CMU build program).  */
3305117413Skan  GET_ENVIRONMENT (temp, "LPATH");
330650599Sobrien  if (temp && *cross_compile == '0')
330718334Speter    {
330852520Sobrien      const char *startp, *endp;
3309132733Skan      char *nstore = alloca (strlen (temp) + 3);
331018334Speter
331118334Speter      startp = endp = temp;
331218334Speter      while (1)
331318334Speter	{
331418334Speter	  if (*endp == PATH_SEPARATOR || *endp == 0)
331518334Speter	    {
331690277Sobrien	      strncpy (nstore, startp, endp - startp);
331718334Speter	      if (endp == startp)
331890277Sobrien		strcpy (nstore, concat (".", dir_separator_str, NULL));
331952520Sobrien	      else if (!IS_DIR_SEPARATOR (endp[-1]))
332018334Speter		{
332190277Sobrien		  nstore[endp - startp] = DIR_SEPARATOR;
332290277Sobrien		  nstore[endp - startp + 1] = 0;
332318334Speter		}
332418334Speter	      else
332590277Sobrien		nstore[endp - startp] = 0;
332690277Sobrien	      add_prefix (&startfile_prefixes, nstore, NULL,
3327104763Skan			  PREFIX_PRIORITY_LAST, 0, NULL, 1);
332818334Speter	      if (*endp == 0)
332918334Speter		break;
333018334Speter	      endp = startp = endp + 1;
333118334Speter	    }
333218334Speter	  else
333318334Speter	    endp++;
333418334Speter	}
333518334Speter    }
333618334Speter
333777389Sobrien  /* Options specified as if they appeared on the command line.  */
333877389Sobrien  temp = getenv ("GCC_OPTIONS");
333977389Sobrien  if ((temp) && (strlen (temp) > 0))
334077389Sobrien    {
334177389Sobrien      int len;
334277389Sobrien      int optc = 1;
334377389Sobrien      int new_argc;
3344110024Sobrien      const char **new_argv;
334577389Sobrien      char *envopts;
334677389Sobrien
334777389Sobrien      while (isspace (*temp))
334877389Sobrien	temp++;
334977389Sobrien      len = strlen (temp);
335077389Sobrien      envopts = (char *) xmalloc (len + 1);
335177389Sobrien      strcpy (envopts, temp);
335277389Sobrien
335377389Sobrien      for (i = 0; i < (len - 1); i++)
335477389Sobrien	if ((isspace (envopts[i])) && ! (isspace (envopts[i+1])))
335577389Sobrien	  optc++;
335677389Sobrien
3357110024Sobrien      new_argv = (const char **) alloca ((optc + argc) * sizeof(char *));
335877389Sobrien
335977389Sobrien      for (i = 0, new_argc = 1; new_argc <= optc; new_argc++)
336077389Sobrien	{
336177389Sobrien	  while (isspace (envopts[i]))
336277389Sobrien	    i++;
336377389Sobrien	  new_argv[new_argc] = envopts + i;
336477389Sobrien	  while (!isspace (envopts[i]) && (envopts[i] != '\0'))
336577389Sobrien	    i++;
336677389Sobrien	  envopts[i++] = '\0';
336777389Sobrien	}
336877389Sobrien      for (i = 1; i < argc; i++)
336977389Sobrien	new_argv[new_argc++] = argv[i];
337077389Sobrien
337177389Sobrien      argv = new_argv;
337277389Sobrien      argc = new_argc;
337377389Sobrien    }
337477389Sobrien
337518334Speter  /* Convert new-style -- options to old-style.  */
3376132733Skan  translate_options (&argc, (const char *const **) &argv);
337718334Speter
337850599Sobrien  /* Do language-specific adjustment/addition of flags.  */
3379132733Skan  lang_specific_driver (&argc, (const char *const **) &argv, &added_libraries);
338050599Sobrien
338118334Speter  /* Scan argv twice.  Here, the first time, just count how many switches
338218334Speter     there will be in their vector, and how many input files in theirs.
338318334Speter     Here we also parse the switches that cc itself uses (e.g. -v).  */
338418334Speter
338518334Speter  for (i = 1; i < argc; i++)
338618334Speter    {
338718334Speter      if (! strcmp (argv[i], "-dumpspecs"))
338818334Speter	{
338950599Sobrien	  struct spec_list *sl;
339050599Sobrien	  init_spec ();
339150599Sobrien	  for (sl = specs; sl; sl = sl->next)
339250599Sobrien	    printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec));
339390277Sobrien	  if (link_command_spec)
339490277Sobrien	    printf ("*link_command:\n%s\n\n", link_command_spec);
339518334Speter	  exit (0);
339618334Speter	}
339718334Speter      else if (! strcmp (argv[i], "-dumpversion"))
339818334Speter	{
339950599Sobrien	  printf ("%s\n", spec_version);
340018334Speter	  exit (0);
340118334Speter	}
340218334Speter      else if (! strcmp (argv[i], "-dumpmachine"))
340318334Speter	{
340418334Speter	  printf ("%s\n", spec_machine);
340590277Sobrien	  exit (0);
340618334Speter	}
340790277Sobrien      else if (strcmp (argv[i], "-fversion") == 0)
340890277Sobrien	{
340990277Sobrien	  /* translate_options () has turned --version into -fversion.  */
341090277Sobrien	  printf (_("%s (GCC) %s\n"), programname, version_string);
3411161660Skan	  printf ("Copyright %s 2006 Free Software Foundation, Inc.\n",
3412132733Skan		  _("(C)"));
341390277Sobrien	  fputs (_("This is free software; see the source for copying conditions.  There is NO\n\
341490277Sobrienwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
341590277Sobrien		 stdout);
341690277Sobrien	  exit (0);
341790277Sobrien	}
341850599Sobrien      else if (strcmp (argv[i], "-fhelp") == 0)
341950599Sobrien	{
342050599Sobrien	  /* translate_options () has turned --help into -fhelp.  */
342150599Sobrien	  print_help_list = 1;
342250599Sobrien
342350599Sobrien	  /* We will be passing a dummy file on to the sub-processes.  */
342450599Sobrien	  n_infiles++;
342550599Sobrien	  n_switches++;
342690277Sobrien
342790277Sobrien	  /* CPP driver cannot obtain switch from cc1_options.  */
342890277Sobrien	  if (is_cpp_driver)
342990277Sobrien	    add_preprocessor_option ("--help", 6);
343050599Sobrien	  add_assembler_option ("--help", 6);
343150599Sobrien	  add_linker_option ("--help", 6);
343250599Sobrien	}
343390277Sobrien      else if (strcmp (argv[i], "-ftarget-help") == 0)
3434117413Skan	{
3435117413Skan	  /* translate_options() has turned --target-help into -ftarget-help.  */
3436117413Skan	  target_help_flag = 1;
343790277Sobrien
3438117413Skan	  /* We will be passing a dummy file on to the sub-processes.  */
3439117413Skan	  n_infiles++;
3440117413Skan	  n_switches++;
344190277Sobrien
344290277Sobrien	  /* CPP driver cannot obtain switch from cc1_options.  */
344390277Sobrien	  if (is_cpp_driver)
344490277Sobrien	    add_preprocessor_option ("--target-help", 13);
3445117413Skan	  add_assembler_option ("--target-help", 13);
3446117413Skan	  add_linker_option ("--target-help", 13);
3447117413Skan	}
344890277Sobrien      else if (! strcmp (argv[i], "-pass-exit-codes"))
344990277Sobrien	{
345090277Sobrien	  pass_exit_codes = 1;
345190277Sobrien	  n_switches++;
345290277Sobrien	}
345318334Speter      else if (! strcmp (argv[i], "-print-search-dirs"))
345418334Speter	print_search_dirs = 1;
345518334Speter      else if (! strcmp (argv[i], "-print-libgcc-file-name"))
345618334Speter	print_file_name = "libgcc.a";
345718334Speter      else if (! strncmp (argv[i], "-print-file-name=", 17))
345818334Speter	print_file_name = argv[i] + 17;
345918334Speter      else if (! strncmp (argv[i], "-print-prog-name=", 17))
346018334Speter	print_prog_name = argv[i] + 17;
346118334Speter      else if (! strcmp (argv[i], "-print-multi-lib"))
346218334Speter	print_multi_lib = 1;
346318334Speter      else if (! strcmp (argv[i], "-print-multi-directory"))
346418334Speter	print_multi_directory = 1;
3465104763Skan      else if (! strcmp (argv[i], "-print-multi-os-directory"))
3466104763Skan	print_multi_os_directory = 1;
346718334Speter      else if (! strncmp (argv[i], "-Wa,", 4))
346818334Speter	{
346918334Speter	  int prev, j;
347018334Speter	  /* Pass the rest of this option to the assembler.  */
347118334Speter
347218334Speter	  /* Split the argument at commas.  */
347318334Speter	  prev = 4;
347418334Speter	  for (j = 4; argv[i][j]; j++)
347518334Speter	    if (argv[i][j] == ',')
347618334Speter	      {
347750599Sobrien		add_assembler_option (argv[i] + prev, j - prev);
347818334Speter		prev = j + 1;
347918334Speter	      }
348090277Sobrien
348118334Speter	  /* Record the part after the last comma.  */
348250599Sobrien	  add_assembler_option (argv[i] + prev, j - prev);
348318334Speter	}
348418334Speter      else if (! strncmp (argv[i], "-Wp,", 4))
348518334Speter	{
348618334Speter	  int prev, j;
348718334Speter	  /* Pass the rest of this option to the preprocessor.  */
348818334Speter
348918334Speter	  /* Split the argument at commas.  */
349018334Speter	  prev = 4;
349118334Speter	  for (j = 4; argv[i][j]; j++)
349218334Speter	    if (argv[i][j] == ',')
349318334Speter	      {
349450599Sobrien		add_preprocessor_option (argv[i] + prev, j - prev);
349518334Speter		prev = j + 1;
349618334Speter	      }
349790277Sobrien
349818334Speter	  /* Record the part after the last comma.  */
349950599Sobrien	  add_preprocessor_option (argv[i] + prev, j - prev);
350018334Speter	}
350118334Speter      else if (argv[i][0] == '+' && argv[i][1] == 'e')
350218334Speter	/* The +e options to the C++ front-end.  */
350318334Speter	n_switches++;
350418334Speter      else if (strncmp (argv[i], "-Wl,", 4) == 0)
350518334Speter	{
350618334Speter	  int j;
350718334Speter	  /* Split the argument at commas.  */
350818334Speter	  for (j = 3; argv[i][j]; j++)
350918334Speter	    n_infiles += (argv[i][j] == ',');
351018334Speter	}
351118334Speter      else if (strcmp (argv[i], "-Xlinker") == 0)
351218334Speter	{
351318334Speter	  if (i + 1 == argc)
351418334Speter	    fatal ("argument to `-Xlinker' is missing");
351518334Speter
351618334Speter	  n_infiles++;
351718334Speter	  i++;
351818334Speter	}
3519132733Skan      else if (strcmp (argv[i], "-Xpreprocessor") == 0)
3520132733Skan	{
3521132733Skan	  if (i + 1 == argc)
3522132733Skan	    fatal ("argument to `-Xpreprocessor' is missing");
3523132733Skan
3524132733Skan	  add_preprocessor_option (argv[i+1], strlen (argv[i+1]));
3525132733Skan	}
3526132733Skan      else if (strcmp (argv[i], "-Xassembler") == 0)
3527132733Skan	{
3528132733Skan	  if (i + 1 == argc)
3529132733Skan	    fatal ("argument to `-Xassembler' is missing");
3530132733Skan
3531132733Skan	  add_assembler_option (argv[i+1], strlen (argv[i+1]));
3532132733Skan	}
353377389Sobrien      else if (strcmp (argv[i], "-l") == 0)
353477389Sobrien	{
353577389Sobrien	  if (i + 1 == argc)
353677389Sobrien	    fatal ("argument to `-l' is missing");
353777389Sobrien
353877389Sobrien	  n_infiles++;
353977389Sobrien	  i++;
354077389Sobrien	}
354118334Speter      else if (strncmp (argv[i], "-l", 2) == 0)
354218334Speter	n_infiles++;
354350599Sobrien      else if (strcmp (argv[i], "-save-temps") == 0)
354450599Sobrien	{
354550599Sobrien	  save_temps_flag = 1;
354650599Sobrien	  n_switches++;
354750599Sobrien	}
354850599Sobrien      else if (strcmp (argv[i], "-specs") == 0)
354950599Sobrien	{
3550132733Skan	  struct user_specs *user = xmalloc (sizeof (struct user_specs));
355150599Sobrien	  if (++i >= argc)
355250599Sobrien	    fatal ("argument to `-specs' is missing");
355350599Sobrien
355490277Sobrien	  user->next = (struct user_specs *) 0;
355550599Sobrien	  user->filename = argv[i];
355650599Sobrien	  if (user_specs_tail)
355750599Sobrien	    user_specs_tail->next = user;
355850599Sobrien	  else
355950599Sobrien	    user_specs_head = user;
356050599Sobrien	  user_specs_tail = user;
356150599Sobrien	}
356250599Sobrien      else if (strncmp (argv[i], "-specs=", 7) == 0)
356350599Sobrien	{
3564132733Skan	  struct user_specs *user = xmalloc (sizeof (struct user_specs));
356550599Sobrien	  if (strlen (argv[i]) == 7)
356650599Sobrien	    fatal ("argument to `-specs=' is missing");
356750599Sobrien
356890277Sobrien	  user->next = (struct user_specs *) 0;
356990277Sobrien	  user->filename = argv[i] + 7;
357050599Sobrien	  if (user_specs_tail)
357150599Sobrien	    user_specs_tail->next = user;
357250599Sobrien	  else
357350599Sobrien	    user_specs_head = user;
357450599Sobrien	  user_specs_tail = user;
357550599Sobrien	}
357690277Sobrien      else if (strcmp (argv[i], "-time") == 0)
357790277Sobrien	report_times = 1;
3578132733Skan      else if (strcmp (argv[i], "-pipe") == 0)
3579132733Skan	{
3580132733Skan	  /* -pipe has to go into the switches array as well as
3581132733Skan	     setting a flag.  */
3582132733Skan	  use_pipes = 1;
3583132733Skan	  n_switches++;
3584132733Skan	}
358590277Sobrien      else if (strcmp (argv[i], "-###") == 0)
358690277Sobrien	{
358790277Sobrien	  /* This is similar to -v except that there is no execution
358890277Sobrien	     of the commands and the echoed arguments are quoted.  It
358990277Sobrien	     is intended for use in shell scripts to capture the
359090277Sobrien	     driver-generated command line.  */
359190277Sobrien	  verbose_only_flag++;
359290277Sobrien	  verbose_flag++;
359390277Sobrien	}
359418334Speter      else if (argv[i][0] == '-' && argv[i][1] != 0)
359518334Speter	{
359690277Sobrien	  const char *p = &argv[i][1];
359790277Sobrien	  int c = *p;
359818334Speter
359918334Speter	  switch (c)
360018334Speter	    {
360118334Speter	    case 'b':
3602117413Skan	    case 'V':
3603117413Skan	      fatal ("`-%c' must come at the start of the command line", c);
360418334Speter	      break;
360518334Speter
360618334Speter	    case 'B':
360718334Speter	      {
360890277Sobrien		const char *value;
360990277Sobrien		int len;
361090277Sobrien
361118334Speter		if (p[1] == 0 && i + 1 == argc)
361218334Speter		  fatal ("argument to `-B' is missing");
361318334Speter		if (p[1] == 0)
361418334Speter		  value = argv[++i];
361518334Speter		else
361618334Speter		  value = p + 1;
361718334Speter
361890277Sobrien		len = strlen (value);
361990277Sobrien
362090277Sobrien		/* Catch the case where the user has forgotten to append a
362190277Sobrien		   directory separator to the path.  Note, they may be using
362290277Sobrien		   -B to add an executable name prefix, eg "i386-elf-", in
362390277Sobrien		   order to distinguish between multiple installations of
362490277Sobrien		   GCC in the same directory.  Hence we must check to see
362590277Sobrien		   if appending a directory separator actually makes a
362690277Sobrien		   valid directory name.  */
362790277Sobrien		if (! IS_DIR_SEPARATOR (value [len - 1])
362890277Sobrien		    && is_directory (value, "", 0))
362990277Sobrien		  {
363090277Sobrien		    char *tmp = xmalloc (len + 2);
363190277Sobrien		    strcpy (tmp, value);
363290277Sobrien		    tmp[len] = DIR_SEPARATOR;
363390277Sobrien		    tmp[++ len] = 0;
363490277Sobrien		    value = tmp;
363590277Sobrien		  }
3636117413Skan
363790277Sobrien		/* As a kludge, if the arg is "[foo/]stageN/", just
363890277Sobrien		   add "[foo/]include" to the include prefix.  */
363990277Sobrien		if ((len == 7
364090277Sobrien		     || (len > 7
364190277Sobrien			 && (IS_DIR_SEPARATOR (value[len - 8]))))
364290277Sobrien		    && strncmp (value + len - 7, "stage", 5) == 0
364390277Sobrien		    && ISDIGIT (value[len - 2])
364490277Sobrien		    && (IS_DIR_SEPARATOR (value[len - 1])))
364590277Sobrien		  {
364690277Sobrien		    if (len == 7)
364790277Sobrien		      add_prefix (&include_prefixes, "include", NULL,
3648104763Skan				  PREFIX_PRIORITY_B_OPT, 0, NULL, 0);
364990277Sobrien		    else
365090277Sobrien		      {
365190277Sobrien			char * string = xmalloc (len + 1);
365290277Sobrien
365390277Sobrien			strncpy (string, value, len - 7);
365490277Sobrien			strcpy (string + len - 7, "include");
365590277Sobrien			add_prefix (&include_prefixes, string, NULL,
3656104763Skan				    PREFIX_PRIORITY_B_OPT, 0, NULL, 0);
365790277Sobrien		      }
365890277Sobrien		  }
365990277Sobrien
366090277Sobrien		add_prefix (&exec_prefixes, value, NULL,
3661104763Skan			    PREFIX_PRIORITY_B_OPT, 0, &warn_B, 0);
366290277Sobrien		add_prefix (&startfile_prefixes, value, NULL,
3663104763Skan			    PREFIX_PRIORITY_B_OPT, 0, &warn_B, 0);
366490277Sobrien		add_prefix (&include_prefixes, concat (value, "include", NULL),
3665104763Skan			    NULL, PREFIX_PRIORITY_B_OPT, 0, NULL, 0);
366690277Sobrien		n_switches++;
366718334Speter	      }
366818334Speter	      break;
366918334Speter
367018334Speter	    case 'v':	/* Print our subcommands and print versions.  */
367118334Speter	      n_switches++;
367218334Speter	      /* If they do anything other than exactly `-v', don't set
367318334Speter		 verbose_flag; rather, continue on to give the error.  */
367418334Speter	      if (p[1] != 0)
367518334Speter		break;
367618334Speter	      verbose_flag++;
367718334Speter	      break;
367818334Speter
367950599Sobrien	    case 'S':
368050599Sobrien	    case 'c':
368150599Sobrien	      if (p[1] == 0)
368218334Speter		{
368350599Sobrien		  have_c = 1;
368418334Speter		  n_switches++;
368518334Speter		  break;
368618334Speter		}
368750599Sobrien	      goto normal_switch;
368850599Sobrien
368950599Sobrien	    case 'o':
369050599Sobrien	      have_o = 1;
369190277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
369250599Sobrien	      if (! have_c)
369350599Sobrien		{
369450599Sobrien		  int skip;
369590277Sobrien
369650599Sobrien		  /* Forward scan, just in case -S or -c is specified
369750599Sobrien		     after -o.  */
369850599Sobrien		  int j = i + 1;
369950599Sobrien		  if (p[1] == 0)
370050599Sobrien		    ++j;
370150599Sobrien		  while (j < argc)
370250599Sobrien		    {
370350599Sobrien		      if (argv[j][0] == '-')
370450599Sobrien			{
370550599Sobrien			  if (SWITCH_CURTAILS_COMPILATION (argv[j][1])
370650599Sobrien			      && argv[j][2] == 0)
370750599Sobrien			    {
370850599Sobrien			      have_c = 1;
370950599Sobrien			      break;
371050599Sobrien			    }
371190277Sobrien			  else if ((skip = SWITCH_TAKES_ARG (argv[j][1])))
371250599Sobrien			    j += skip - (argv[j][2] != 0);
371390277Sobrien			  else if ((skip = WORD_SWITCH_TAKES_ARG (argv[j] + 1)))
371450599Sobrien			    j += skip;
371550599Sobrien			}
371650599Sobrien		      j++;
371750599Sobrien		    }
371850599Sobrien		}
371950599Sobrien#endif
372090277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX)
372150599Sobrien	      if (p[1] == 0)
372290277Sobrien		argv[i + 1] = convert_filename (argv[i + 1], ! have_c, 0);
372350599Sobrien	      else
372490277Sobrien		argv[i] = convert_filename (argv[i], ! have_c, 0);
372550599Sobrien#endif
372650599Sobrien	      goto normal_switch;
372750599Sobrien
372818334Speter	    default:
372950599Sobrien	    normal_switch:
373090277Sobrien
373190277Sobrien#ifdef MODIFY_TARGET_NAME
373290277Sobrien	      is_modify_target_name = 0;
373390277Sobrien
3734117413Skan	      for (j = 0; j < ARRAY_SIZE (modify_target); j++)
373590277Sobrien		if (! strcmp (argv[i], modify_target[j].sw))
373690277Sobrien		  {
3737132733Skan		    char *new_name = xmalloc (strlen (modify_target[j].str)
3738132733Skan					      + strlen (spec_machine));
373990277Sobrien		    const char *p, *r;
374090277Sobrien		    char *q;
374190277Sobrien		    int made_addition = 0;
374290277Sobrien
374390277Sobrien		    is_modify_target_name = 1;
374490277Sobrien		    for (p = spec_machine, q = new_name; *p != 0; )
374590277Sobrien		      {
374690277Sobrien			if (modify_target[j].add_del == DELETE
374790277Sobrien			    && (! strncmp (q, modify_target[j].str,
374890277Sobrien					   strlen (modify_target[j].str))))
374990277Sobrien			  p += strlen (modify_target[j].str);
375090277Sobrien			else if (modify_target[j].add_del == ADD
375190277Sobrien				 && ! made_addition && *p == '-')
375290277Sobrien			  {
375390277Sobrien			    for (r = modify_target[j].str; *r != 0; )
375490277Sobrien			      *q++ = *r++;
375590277Sobrien			    made_addition = 1;
375690277Sobrien			  }
375790277Sobrien
375890277Sobrien			*q++ = *p++;
375990277Sobrien		      }
376090277Sobrien
376190277Sobrien		    spec_machine = new_name;
376290277Sobrien		  }
376390277Sobrien
376490277Sobrien	      if (is_modify_target_name)
376590277Sobrien		break;
3766117413Skan#endif
376790277Sobrien
376818334Speter	      n_switches++;
376918334Speter
377018334Speter	      if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
377118334Speter		i += SWITCH_TAKES_ARG (c) - (p[1] != 0);
377218334Speter	      else if (WORD_SWITCH_TAKES_ARG (p))
377318334Speter		i += WORD_SWITCH_TAKES_ARG (p);
377418334Speter	    }
377518334Speter	}
377618334Speter      else
377750599Sobrien	{
377850599Sobrien	  n_infiles++;
377950599Sobrien	  lang_n_infiles++;
378050599Sobrien	}
378118334Speter    }
378218334Speter
3783132733Skan  combine_inputs = (have_c && have_o && lang_n_infiles > 1);
378450599Sobrien
3785132733Skan  if ((save_temps_flag || report_times) && use_pipes)
3786132733Skan    {
3787132733Skan      /* -save-temps overrides -pipe, so that temp files are produced */
3788132733Skan      if (save_temps_flag)
3789132733Skan	error ("warning: -pipe ignored because -save-temps specified");
3790132733Skan      /* -time overrides -pipe because we can't get correct stats when
3791132733Skan	 multiple children are running at once.  */
3792132733Skan      else if (report_times)
3793132733Skan	error ("warning: -pipe ignored because -time specified");
3794132733Skan
3795132733Skan      use_pipes = 0;
3796132733Skan    }
3797132733Skan
379818334Speter  /* Set up the search paths before we go looking for config files.  */
379918334Speter
380018334Speter  /* These come before the md prefixes so that we will find gcc's subcommands
380118334Speter     (such as cpp) rather than those of the host system.  */
380218334Speter  /* Use 2 as fourth arg meaning try just the machine as a suffix,
380318334Speter     as well as trying the machine and the version.  */
380418346Speter#ifdef FREEBSD_NATIVE
3805104953Sobrien      add_prefix (&exec_prefixes, PREFIX"/bin/", "BINUTILS",
3806122632Skan		  PREFIX_PRIORITY_LAST, 0, warn_std_ptr, 0);
380791561Sobrien#endif	/* FREEBSD_NATIVE */
380818334Speter#ifndef OS2
3809132733Skan  add_prefix (&exec_prefixes, standard_libexec_prefix, "GCC",
3810104763Skan	      PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0);
3811132733Skan  add_prefix (&exec_prefixes, standard_libexec_prefix, "BINUTILS",
3812132733Skan	      PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0);
3813132733Skan#ifndef FREEBSD_NATIVE
381450599Sobrien  add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS",
3815104763Skan	      PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0);
381650599Sobrien  add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS",
3817104763Skan	      PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0);
3818132733Skan  add_prefix (&exec_prefixes, standard_exec_prefix_2, "BINUTILS",
3819132733Skan	      PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0);
3820132733Skan#endif	/* FREEBSD_NATIVE */
382118334Speter#endif
382218334Speter
382391578Sobrien#ifndef FREEBSD_NATIVE
382450599Sobrien  add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS",
3825104763Skan	      PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0);
3826132733Skan  add_prefix (&startfile_prefixes, standard_exec_prefix_2, "BINUTILS",
3827104763Skan	      PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0);
382891561Sobrien#endif	/* not FREEBSD_NATIVE */
382918334Speter
383090277Sobrien  tooldir_prefix = concat (tooldir_base_prefix, spec_machine,
383190277Sobrien			   dir_separator_str, NULL);
383218334Speter
383318334Speter  /* If tooldir is relative, base it on exec_prefixes.  A relative
383418334Speter     tooldir lets us move the installed tree as a unit.
383518334Speter
383618334Speter     If GCC_EXEC_PREFIX is defined, then we want to add two relative
383718334Speter     directories, so that we can search both the user specified directory
383818334Speter     and the standard place.  */
383918334Speter
3840132733Skan  if (!IS_ABSOLUTE_PATH (tooldir_prefix))
384118334Speter    {
384218334Speter      if (gcc_exec_prefix)
384318334Speter	{
384418334Speter	  char *gcc_exec_tooldir_prefix
384550599Sobrien	    = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
384690277Sobrien		      spec_version, dir_separator_str, tooldir_prefix, NULL);
384718334Speter
384818334Speter	  add_prefix (&exec_prefixes,
384990277Sobrien		      concat (gcc_exec_tooldir_prefix, "bin",
385090277Sobrien			      dir_separator_str, NULL),
3851104763Skan		      NULL, PREFIX_PRIORITY_LAST, 0, NULL, 0);
385218334Speter	  add_prefix (&startfile_prefixes,
385390277Sobrien		      concat (gcc_exec_tooldir_prefix, "lib",
385490277Sobrien			      dir_separator_str, NULL),
3855104763Skan		      NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1);
385618334Speter	}
385718334Speter
385850599Sobrien      tooldir_prefix = concat (standard_exec_prefix, spec_machine,
385990277Sobrien			       dir_separator_str, spec_version,
386090277Sobrien			       dir_separator_str, tooldir_prefix, NULL);
386118334Speter    }
386218334Speter
386318346Speter#ifndef FREEBSD_NATIVE
386490277Sobrien  add_prefix (&exec_prefixes,
386590277Sobrien	      concat (tooldir_prefix, "bin", dir_separator_str, NULL),
3866104763Skan	      "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 0);
386718334Speter  add_prefix (&startfile_prefixes,
386890277Sobrien	      concat (tooldir_prefix, "lib", dir_separator_str, NULL),
3869104763Skan	      "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1);
3870132733Skan
3871132733Skan#if defined(TARGET_SYSTEM_ROOT_RELOCATABLE) && !defined(VMS)
3872132733Skan  /* If the normal TARGET_SYSTEM_ROOT is inside of $exec_prefix,
3873132733Skan     then consider it to relocate with the rest of the GCC installation
3874132733Skan     if GCC_EXEC_PREFIX is set.
3875132733Skan     ``make_relative_prefix'' is not compiled for VMS, so don't call it.  */
3876132733Skan  if (target_system_root && gcc_exec_prefix)
3877132733Skan    {
3878132733Skan      char *tmp_prefix = make_relative_prefix (argv[0],
3879132733Skan					       standard_bindir_prefix,
3880132733Skan					       target_system_root);
3881132733Skan      if (tmp_prefix && access_check (tmp_prefix, F_OK) == 0)
3882132733Skan	{
3883132733Skan	  target_system_root = tmp_prefix;
3884132733Skan	  target_system_root_changed = 1;
3885132733Skan	}
3886132733Skan    }
3887132733Skan#endif
388818346Speter#endif /* FREEBSD_NATIVE */
388918334Speter
389018334Speter  /* More prefixes are enabled in main, after we read the specs file
389118334Speter     and determine whether this is cross-compilation or not.  */
389218334Speter
389318334Speter  /* Then create the space for the vectors and scan again.  */
389418334Speter
3895132733Skan  switches = xmalloc ((n_switches + 1) * sizeof (struct switchstr));
3896132733Skan  infiles = xmalloc ((n_infiles + 1) * sizeof (struct infile));
389718334Speter  n_switches = 0;
389818334Speter  n_infiles = 0;
389918334Speter  last_language_n_infiles = -1;
390018334Speter
390118334Speter  /* This, time, copy the text of each switch and store a pointer
390218334Speter     to the copy in the vector of switches.
390318334Speter     Store all the infiles in their vector.  */
390418334Speter
390518334Speter  for (i = 1; i < argc; i++)
390618334Speter    {
390718334Speter      /* Just skip the switches that were handled by the preceding loop.  */
390890277Sobrien#ifdef MODIFY_TARGET_NAME
390990277Sobrien      is_modify_target_name = 0;
391090277Sobrien
3911117413Skan      for (j = 0; j < ARRAY_SIZE (modify_target); j++)
391290277Sobrien	if (! strcmp (argv[i], modify_target[j].sw))
391390277Sobrien	  is_modify_target_name = 1;
391490277Sobrien
391590277Sobrien      if (is_modify_target_name)
391690277Sobrien	;
391790277Sobrien      else
391890277Sobrien#endif
391918334Speter      if (! strncmp (argv[i], "-Wa,", 4))
392018334Speter	;
392118334Speter      else if (! strncmp (argv[i], "-Wp,", 4))
392218334Speter	;
392390277Sobrien      else if (! strcmp (argv[i], "-pass-exit-codes"))
392490277Sobrien	;
392518334Speter      else if (! strcmp (argv[i], "-print-search-dirs"))
392618334Speter	;
392718334Speter      else if (! strcmp (argv[i], "-print-libgcc-file-name"))
392818334Speter	;
392918334Speter      else if (! strncmp (argv[i], "-print-file-name=", 17))
393018334Speter	;
393118334Speter      else if (! strncmp (argv[i], "-print-prog-name=", 17))
393218334Speter	;
393318334Speter      else if (! strcmp (argv[i], "-print-multi-lib"))
393418334Speter	;
393518334Speter      else if (! strcmp (argv[i], "-print-multi-directory"))
393618334Speter	;
3937104763Skan      else if (! strcmp (argv[i], "-print-multi-os-directory"))
3938104763Skan	;
393990277Sobrien      else if (! strcmp (argv[i], "-ftarget-help"))
394090277Sobrien	;
394190277Sobrien      else if (! strcmp (argv[i], "-fhelp"))
394290277Sobrien	;
394318334Speter      else if (argv[i][0] == '+' && argv[i][1] == 'e')
394418334Speter	{
394518334Speter	  /* Compensate for the +e options to the C++ front-end;
394618334Speter	     they're there simply for cfront call-compatibility.  We do
394718334Speter	     some magic in default_compilers to pass them down properly.
394818334Speter	     Note we deliberately start at the `+' here, to avoid passing
394918334Speter	     -e0 or -e1 down into the linker.  */
395018334Speter	  switches[n_switches].part1 = &argv[i][0];
395118334Speter	  switches[n_switches].args = 0;
395290277Sobrien	  switches[n_switches].live_cond = SWITCH_OK;
395352520Sobrien	  switches[n_switches].validated = 0;
395418334Speter	  n_switches++;
395518334Speter	}
395618334Speter      else if (strncmp (argv[i], "-Wl,", 4) == 0)
395718334Speter	{
395818334Speter	  int prev, j;
395918334Speter	  /* Split the argument at commas.  */
396018334Speter	  prev = 4;
396118334Speter	  for (j = 4; argv[i][j]; j++)
396218334Speter	    if (argv[i][j] == ',')
396318334Speter	      {
396450599Sobrien		infiles[n_infiles].language = "*";
396518334Speter		infiles[n_infiles++].name
396618334Speter		  = save_string (argv[i] + prev, j - prev);
396718334Speter		prev = j + 1;
396818334Speter	      }
396918334Speter	  /* Record the part after the last comma.  */
397050599Sobrien	  infiles[n_infiles].language = "*";
397118334Speter	  infiles[n_infiles++].name = argv[i] + prev;
397218334Speter	}
397318334Speter      else if (strcmp (argv[i], "-Xlinker") == 0)
397418334Speter	{
397550599Sobrien	  infiles[n_infiles].language = "*";
397618334Speter	  infiles[n_infiles++].name = argv[++i];
397718334Speter	}
3978132733Skan      else if (strcmp (argv[i], "-Xassembler") == 0)
3979132733Skan	{
3980132733Skan	  infiles[n_infiles].language = "*";
3981132733Skan	  infiles[n_infiles++].name = argv[++i];
3982132733Skan	}
3983132733Skan      else if (strcmp (argv[i], "-Xpreprocessor") == 0)
3984132733Skan	{
3985132733Skan	  infiles[n_infiles].language = "*";
3986132733Skan	  infiles[n_infiles++].name = argv[++i];
3987132733Skan	}
398877389Sobrien      else if (strcmp (argv[i], "-l") == 0)
398977389Sobrien	{ /* POSIX allows separation of -l and the lib arg;
399077389Sobrien	     canonicalize by concatenating -l with its arg */
399177389Sobrien	  infiles[n_infiles].language = "*";
399277389Sobrien	  infiles[n_infiles++].name = concat ("-l", argv[++i], NULL);
399377389Sobrien	}
399418334Speter      else if (strncmp (argv[i], "-l", 2) == 0)
399518334Speter	{
399650599Sobrien	  infiles[n_infiles].language = "*";
399718334Speter	  infiles[n_infiles++].name = argv[i];
399818334Speter	}
399950599Sobrien      else if (strcmp (argv[i], "-specs") == 0)
400050599Sobrien	i++;
400150599Sobrien      else if (strncmp (argv[i], "-specs=", 7) == 0)
400250599Sobrien	;
400390277Sobrien      else if (strcmp (argv[i], "-time") == 0)
400490277Sobrien	;
400590277Sobrien      else if (strcmp (argv[i], "-###") == 0)
400690277Sobrien	;
400718334Speter      else if (argv[i][0] == '-' && argv[i][1] != 0)
400818334Speter	{
400990277Sobrien	  const char *p = &argv[i][1];
401090277Sobrien	  int c = *p;
401118334Speter
401218334Speter	  if (c == 'x')
401318334Speter	    {
401418334Speter	      if (p[1] == 0 && i + 1 == argc)
401518334Speter		fatal ("argument to `-x' is missing");
401618334Speter	      if (p[1] == 0)
401718334Speter		spec_lang = argv[++i];
401818334Speter	      else
401918334Speter		spec_lang = p + 1;
402018334Speter	      if (! strcmp (spec_lang, "none"))
402118334Speter		/* Suppress the warning if -xnone comes after the last input
402218334Speter		   file, because alternate command interfaces like g++ might
402318334Speter		   find it useful to place -xnone after each input file.  */
402418334Speter		spec_lang = 0;
402518334Speter	      else
402618334Speter		last_language_n_infiles = n_infiles;
402718334Speter	      continue;
402818334Speter	    }
402918334Speter	  switches[n_switches].part1 = p;
403018334Speter	  /* Deal with option arguments in separate argv elements.  */
403118334Speter	  if ((SWITCH_TAKES_ARG (c) > (p[1] != 0))
403218334Speter	      || WORD_SWITCH_TAKES_ARG (p))
403318334Speter	    {
403418334Speter	      int j = 0;
403518334Speter	      int n_args = WORD_SWITCH_TAKES_ARG (p);
403618334Speter
403718334Speter	      if (n_args == 0)
403818334Speter		{
403918334Speter		  /* Count only the option arguments in separate argv elements.  */
404018334Speter		  n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0);
404118334Speter		}
404218334Speter	      if (i + n_args >= argc)
404318334Speter		fatal ("argument to `-%s' is missing", p);
404418334Speter	      switches[n_switches].args
4045132733Skan		= xmalloc ((n_args + 1) * sizeof(const char *));
404618334Speter	      while (j < n_args)
404718334Speter		switches[n_switches].args[j++] = argv[++i];
404818334Speter	      /* Null-terminate the vector.  */
404918334Speter	      switches[n_switches].args[j] = 0;
405018334Speter	    }
405190277Sobrien	  else if (strchr (switches_need_spaces, c))
405218334Speter	    {
405350599Sobrien	      /* On some systems, ld cannot handle some options without
405450599Sobrien		 a space.  So split the option from its argument.  */
4055132733Skan	      char *part1 = xmalloc (2);
405650599Sobrien	      part1[0] = c;
405750599Sobrien	      part1[1] = '\0';
405890277Sobrien
405950599Sobrien	      switches[n_switches].part1 = part1;
4060132733Skan	      switches[n_switches].args = xmalloc (2 * sizeof (const char *));
406190277Sobrien	      switches[n_switches].args[0] = xstrdup (p+1);
406218334Speter	      switches[n_switches].args[1] = 0;
406318334Speter	    }
406418334Speter	  else
406518334Speter	    switches[n_switches].args = 0;
406618334Speter
406790277Sobrien	  switches[n_switches].live_cond = SWITCH_OK;
406852520Sobrien	  switches[n_switches].validated = 0;
406990277Sobrien	  switches[n_switches].ordering = 0;
4070132733Skan	  /* These are always valid, since gcc.c itself understands them.  */
407190277Sobrien	  if (!strcmp (p, "save-temps")
407290277Sobrien	      || !strcmp (p, "static-libgcc")
4073132733Skan	      || !strcmp (p, "shared-libgcc")
4074132733Skan	      || !strcmp (p, "pipe"))
407552520Sobrien	    switches[n_switches].validated = 1;
407690277Sobrien	  else
407790277Sobrien	    {
407890277Sobrien	      char ch = switches[n_switches].part1[0];
4079117413Skan	      if (ch == 'B')
408090277Sobrien		switches[n_switches].validated = 1;
408190277Sobrien	    }
408218334Speter	  n_switches++;
408318334Speter	}
408418334Speter      else
408518334Speter	{
408690277Sobrien#ifdef HAVE_TARGET_OBJECT_SUFFIX
408790277Sobrien	  argv[i] = convert_filename (argv[i], 0, access (argv[i], F_OK));
408818334Speter#endif
408918334Speter
409090277Sobrien	  if (strcmp (argv[i], "-") != 0 && access (argv[i], F_OK) < 0)
409118334Speter	    {
409218334Speter	      perror_with_name (argv[i]);
409318334Speter	      error_count++;
409418334Speter	    }
409518334Speter	  else
409618334Speter	    {
409718334Speter	      infiles[n_infiles].language = spec_lang;
409818334Speter	      infiles[n_infiles++].name = argv[i];
409918334Speter	    }
410018334Speter	}
410118334Speter    }
410218334Speter
410318334Speter  if (n_infiles == last_language_n_infiles && spec_lang != 0)
410490277Sobrien    error ("warning: `-x %s' after last input file has no effect", spec_lang);
410518334Speter
410690277Sobrien  /* Ensure we only invoke each subprocess once.  */
410790277Sobrien  if (target_help_flag || print_help_list)
410890277Sobrien    {
410990277Sobrien      n_infiles = 1;
411090277Sobrien
411190277Sobrien      /* Create a dummy input file, so that we can pass --target-help on to
411290277Sobrien	 the various sub-processes.  */
411390277Sobrien      infiles[0].language = "c";
411490277Sobrien      infiles[0].name   = "help-dummy";
411590277Sobrien
411690277Sobrien      if (target_help_flag)
411790277Sobrien	{
411890277Sobrien	  switches[n_switches].part1     = "--target-help";
411990277Sobrien	  switches[n_switches].args      = 0;
412090277Sobrien	  switches[n_switches].live_cond = SWITCH_OK;
412190277Sobrien	  switches[n_switches].validated = 0;
412290277Sobrien
412390277Sobrien	  n_switches++;
412490277Sobrien	}
412590277Sobrien
412690277Sobrien      if (print_help_list)
412790277Sobrien	{
412890277Sobrien	  switches[n_switches].part1     = "--help";
412990277Sobrien	  switches[n_switches].args      = 0;
413090277Sobrien	  switches[n_switches].live_cond = SWITCH_OK;
413190277Sobrien	  switches[n_switches].validated = 0;
413290277Sobrien
413390277Sobrien	  n_switches++;
413490277Sobrien	}
413590277Sobrien    }
413690277Sobrien
413718334Speter  switches[n_switches].part1 = 0;
413818334Speter  infiles[n_infiles].name = 0;
413918334Speter}
414090277Sobrien
4141132733Skan/* Store switches not filtered out by %<S in spec in COLLECT_GCC_OPTIONS
414290277Sobrien   and place that in the environment.  */
414390277Sobrien
414490277Sobrienstatic void
4145132733Skanset_collect_gcc_options (void)
414690277Sobrien{
414790277Sobrien  int i;
414890277Sobrien  int first_time;
414990277Sobrien
415090277Sobrien  /* Build COLLECT_GCC_OPTIONS to have all of the options specified to
415190277Sobrien     the compiler.  */
415290277Sobrien  obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
415390277Sobrien		sizeof ("COLLECT_GCC_OPTIONS=") - 1);
415490277Sobrien
415590277Sobrien  first_time = TRUE;
415690277Sobrien  for (i = 0; (int) i < n_switches; i++)
415790277Sobrien    {
415890277Sobrien      const char *const *args;
415990277Sobrien      const char *p, *q;
416090277Sobrien      if (!first_time)
416190277Sobrien	obstack_grow (&collect_obstack, " ", 1);
416290277Sobrien
416390277Sobrien      first_time = FALSE;
416490277Sobrien
416590277Sobrien      /* Ignore elided switches.  */
416690277Sobrien      if (switches[i].live_cond == SWITCH_IGNORE)
416790277Sobrien	continue;
416890277Sobrien
416990277Sobrien      obstack_grow (&collect_obstack, "'-", 2);
417090277Sobrien      q = switches[i].part1;
417190277Sobrien      while ((p = strchr (q, '\'')))
417290277Sobrien	{
417390277Sobrien	  obstack_grow (&collect_obstack, q, p - q);
417490277Sobrien	  obstack_grow (&collect_obstack, "'\\''", 4);
417590277Sobrien	  q = ++p;
417690277Sobrien	}
417790277Sobrien      obstack_grow (&collect_obstack, q, strlen (q));
417890277Sobrien      obstack_grow (&collect_obstack, "'", 1);
417990277Sobrien
418090277Sobrien      for (args = switches[i].args; args && *args; args++)
418190277Sobrien	{
418290277Sobrien	  obstack_grow (&collect_obstack, " '", 2);
418390277Sobrien	  q = *args;
418490277Sobrien	  while ((p = strchr (q, '\'')))
418590277Sobrien	    {
418690277Sobrien	      obstack_grow (&collect_obstack, q, p - q);
418790277Sobrien	      obstack_grow (&collect_obstack, "'\\''", 4);
418890277Sobrien	      q = ++p;
418990277Sobrien	    }
419090277Sobrien	  obstack_grow (&collect_obstack, q, strlen (q));
419190277Sobrien	  obstack_grow (&collect_obstack, "'", 1);
419290277Sobrien	}
419390277Sobrien    }
419490277Sobrien  obstack_grow (&collect_obstack, "\0", 1);
419590277Sobrien  putenv (obstack_finish (&collect_obstack));
419690277Sobrien}
419718334Speter
419818334Speter/* Process a spec string, accumulating and running commands.  */
419918334Speter
420018334Speter/* These variables describe the input file name.
420118334Speter   input_file_number is the index on outfiles of this file,
420218334Speter   so that the output file name can be stored for later use by %o.
420318334Speter   input_basename is the start of the part of the input file
420418334Speter   sans all directory names, and basename_length is the number
420518334Speter   of characters starting there excluding the suffix .c or whatever.  */
420618334Speter
4207132733Skanstatic const char *input_filename;
420818334Speterstatic int input_file_number;
420950599Sobriensize_t input_filename_length;
421018334Speterstatic int basename_length;
421190277Sobrienstatic int suffixed_basename_length;
421252520Sobrienstatic const char *input_basename;
421352520Sobrienstatic const char *input_suffix;
421490277Sobrienstatic struct stat input_stat;
421590277Sobrienstatic int input_stat_set;
421618334Speter
421790277Sobrien/* The compiler used to process the current input file.  */
421890277Sobrienstatic struct compiler *input_file_compiler;
421990277Sobrien
422018334Speter/* These are variables used within do_spec and do_spec_1.  */
422118334Speter
422218334Speter/* Nonzero if an arg has been started and not yet terminated
422318334Speter   (with space, tab or newline).  */
422418334Speterstatic int arg_going;
422518334Speter
422618334Speter/* Nonzero means %d or %g has been seen; the next arg to be terminated
422718334Speter   is a temporary file name.  */
422818334Speterstatic int delete_this_arg;
422918334Speter
423018334Speter/* Nonzero means %w has been seen; the next arg to be terminated
423118334Speter   is the output file name of this compilation.  */
423218334Speterstatic int this_is_output_file;
423318334Speter
423418334Speter/* Nonzero means %s has been seen; the next arg to be terminated
423518334Speter   is the name of a library file and we should try the standard
423618334Speter   search dirs for it.  */
423718334Speterstatic int this_is_library_file;
423818334Speter
423918334Speter/* Nonzero means that the input of this command is coming from a pipe.  */
424018334Speterstatic int input_from_pipe;
424118334Speter
424290277Sobrien/* Nonnull means substitute this for any suffix when outputting a switches
424390277Sobrien   arguments.  */
424490277Sobrienstatic const char *suffix_subst;
424590277Sobrien
424618334Speter/* Process the spec SPEC and run the commands specified therein.
424718334Speter   Returns 0 if the spec is successfully processed; -1 if failed.  */
424818334Speter
424950599Sobrienint
4250132733Skando_spec (const char *spec)
425118334Speter{
425218334Speter  int value;
425318334Speter
4254117413Skan  value = do_spec_2 (spec);
425518334Speter
425618334Speter  /* Force out any unfinished command.
425718334Speter     If -pipe, this forces out the last command if it ended in `|'.  */
425818334Speter  if (value == 0)
425918334Speter    {
426018334Speter      if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
426118334Speter	argbuf_index--;
426218334Speter
426390277Sobrien      set_collect_gcc_options ();
426490277Sobrien
426518334Speter      if (argbuf_index > 0)
426618334Speter	value = execute ();
426718334Speter    }
426818334Speter
426918334Speter  return value;
427018334Speter}
427118334Speter
4272117413Skanstatic int
4273132733Skando_spec_2 (const char *spec)
4274117413Skan{
4275132733Skan  const char *string;
4276132733Skan  int result;
4277132733Skan
4278117413Skan  clear_args ();
4279117413Skan  arg_going = 0;
4280117413Skan  delete_this_arg = 0;
4281117413Skan  this_is_output_file = 0;
4282117413Skan  this_is_library_file = 0;
4283117413Skan  input_from_pipe = 0;
4284117413Skan  suffix_subst = NULL;
4285117413Skan
4286132733Skan  result = do_spec_1 (spec, 0, NULL);
4287132733Skan
4288132733Skan  /* End any pending argument.  */
4289132733Skan  if (arg_going)
4290132733Skan    {
4291132733Skan      obstack_1grow (&obstack, 0);
4292132733Skan      string = obstack_finish (&obstack);
4293132733Skan      if (this_is_library_file)
4294132733Skan	string = find_file (string);
4295132733Skan      store_arg (string, delete_this_arg, this_is_output_file);
4296132733Skan      if (this_is_output_file)
4297132733Skan	outfiles[input_file_number] = string;
4298132733Skan      arg_going = 0;
4299132733Skan    }
4300132733Skan
4301132733Skan  return result;
4302117413Skan}
4303117413Skan
4304117413Skan
4305117413Skan/* Process the given spec string and add any new options to the end
4306117413Skan   of the switches/n_switches array.  */
4307117413Skan
4308117413Skanstatic void
4309132733Skando_option_spec (const char *name, const char *spec)
4310117413Skan{
4311132733Skan  unsigned int i, value_count, value_len;
4312132733Skan  const char *p, *q, *value;
4313132733Skan  char *tmp_spec, *tmp_spec_p;
4314132733Skan
4315132733Skan  if (configure_default_options[0].name == NULL)
4316132733Skan    return;
4317132733Skan
4318132733Skan  for (i = 0; i < ARRAY_SIZE (configure_default_options); i++)
4319132733Skan    if (strcmp (configure_default_options[i].name, name) == 0)
4320132733Skan      break;
4321132733Skan  if (i == ARRAY_SIZE (configure_default_options))
4322132733Skan    return;
4323132733Skan
4324132733Skan  value = configure_default_options[i].value;
4325132733Skan  value_len = strlen (value);
4326132733Skan
4327132733Skan  /* Compute the size of the final spec.  */
4328132733Skan  value_count = 0;
4329132733Skan  p = spec;
4330132733Skan  while ((p = strstr (p, "%(VALUE)")) != NULL)
4331132733Skan    {
4332132733Skan      p ++;
4333132733Skan      value_count ++;
4334132733Skan    }
4335132733Skan
4336132733Skan  /* Replace each %(VALUE) by the specified value.  */
4337132733Skan  tmp_spec = alloca (strlen (spec) + 1
4338132733Skan		     + value_count * (value_len - strlen ("%(VALUE)")));
4339132733Skan  tmp_spec_p = tmp_spec;
4340132733Skan  q = spec;
4341132733Skan  while ((p = strstr (q, "%(VALUE)")) != NULL)
4342132733Skan    {
4343132733Skan      memcpy (tmp_spec_p, q, p - q);
4344132733Skan      tmp_spec_p = tmp_spec_p + (p - q);
4345132733Skan      memcpy (tmp_spec_p, value, value_len);
4346132733Skan      tmp_spec_p += value_len;
4347132733Skan      q = p + strlen ("%(VALUE)");
4348132733Skan    }
4349132733Skan  strcpy (tmp_spec_p, q);
4350132733Skan
4351132733Skan  do_self_spec (tmp_spec);
4352132733Skan}
4353132733Skan
4354132733Skan/* Process the given spec string and add any new options to the end
4355132733Skan   of the switches/n_switches array.  */
4356132733Skan
4357132733Skanstatic void
4358132733Skando_self_spec (const char *spec)
4359132733Skan{
4360117413Skan  do_spec_2 (spec);
4361117413Skan  do_spec_1 (" ", 0, NULL);
4362117413Skan
4363117413Skan  if (argbuf_index > 0)
4364117413Skan    {
4365117413Skan      int i, first;
4366117413Skan
4367117413Skan      first = n_switches;
4368117413Skan      n_switches += argbuf_index;
4369117413Skan      switches = xrealloc (switches,
4370117413Skan			   sizeof (struct switchstr) * (n_switches + 1));
4371117413Skan
4372117413Skan      switches[n_switches] = switches[first];
4373117413Skan      for (i = 0; i < argbuf_index; i++)
4374117413Skan	{
4375117413Skan	  struct switchstr *sw;
4376117413Skan
4377117413Skan	  /* Each switch should start with '-'.  */
4378117413Skan	  if (argbuf[i][0] != '-')
4379117413Skan	    abort ();
4380117413Skan
4381117413Skan	  sw = &switches[i + first];
4382117413Skan	  sw->part1 = &argbuf[i][1];
4383117413Skan	  sw->args = 0;
4384117413Skan	  sw->live_cond = SWITCH_OK;
4385117413Skan	  sw->validated = 0;
4386117413Skan	  sw->ordering = 0;
4387117413Skan	}
4388117413Skan    }
4389117413Skan}
4390117413Skan
439118334Speter/* Process the sub-spec SPEC as a portion of a larger spec.
439218334Speter   This is like processing a whole spec except that we do
439318334Speter   not initialize at the beginning and we do not supply a
439418334Speter   newline by default at the end.
439518334Speter   INSWITCH nonzero means don't process %-sequences in SPEC;
439618334Speter   in this case, % is treated as an ordinary character.
439718334Speter   This is used while substituting switches.
439818334Speter   INSWITCH nonzero also causes SPC not to terminate an argument.
439918334Speter
440018334Speter   Value is zero unless a line was finished
440118334Speter   and the command on that line reported an error.  */
440218334Speter
440318334Speterstatic int
4404132733Skando_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
440518334Speter{
440690277Sobrien  const char *p = spec;
440790277Sobrien  int c;
440818334Speter  int i;
440952520Sobrien  const char *string;
441018334Speter  int value;
441118334Speter
441250599Sobrien  while ((c = *p++))
441318334Speter    /* If substituting a switch, treat all chars like letters.
441418334Speter       Otherwise, NL, SPC, TAB and % are special.  */
441518334Speter    switch (inswitch ? 'a' : c)
441618334Speter      {
441718334Speter      case '\n':
441818334Speter	/* End of line: finish any pending argument,
441918334Speter	   then run the pending command if one has been started.  */
442018334Speter	if (arg_going)
442118334Speter	  {
442218334Speter	    obstack_1grow (&obstack, 0);
442318334Speter	    string = obstack_finish (&obstack);
442418334Speter	    if (this_is_library_file)
442518334Speter	      string = find_file (string);
442618334Speter	    store_arg (string, delete_this_arg, this_is_output_file);
442718334Speter	    if (this_is_output_file)
442818334Speter	      outfiles[input_file_number] = string;
442918334Speter	  }
443018334Speter	arg_going = 0;
443118334Speter
443218334Speter	if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
443318334Speter	  {
443418334Speter	    /* A `|' before the newline means use a pipe here,
443518334Speter	       but only if -pipe was specified.
443618334Speter	       Otherwise, execute now and don't pass the `|' as an arg.  */
4437132733Skan	    if (use_pipes)
443818334Speter	      {
443918334Speter		input_from_pipe = 1;
444018334Speter		break;
444118334Speter	      }
444218334Speter	    else
444318334Speter	      argbuf_index--;
444418334Speter	  }
444518334Speter
444690277Sobrien	set_collect_gcc_options ();
444790277Sobrien
444818334Speter	if (argbuf_index > 0)
444918334Speter	  {
445018334Speter	    value = execute ();
445118334Speter	    if (value)
445218334Speter	      return value;
445318334Speter	  }
445418334Speter	/* Reinitialize for a new command, and for a new argument.  */
445518334Speter	clear_args ();
445618334Speter	arg_going = 0;
445718334Speter	delete_this_arg = 0;
445818334Speter	this_is_output_file = 0;
445918334Speter	this_is_library_file = 0;
446018334Speter	input_from_pipe = 0;
446118334Speter	break;
446218334Speter
446318334Speter      case '|':
446418334Speter	/* End any pending argument.  */
446518334Speter	if (arg_going)
446618334Speter	  {
446718334Speter	    obstack_1grow (&obstack, 0);
446818334Speter	    string = obstack_finish (&obstack);
446918334Speter	    if (this_is_library_file)
447018334Speter	      string = find_file (string);
447118334Speter	    store_arg (string, delete_this_arg, this_is_output_file);
447218334Speter	    if (this_is_output_file)
447318334Speter	      outfiles[input_file_number] = string;
447418334Speter	  }
447518334Speter
447618334Speter	/* Use pipe */
447718334Speter	obstack_1grow (&obstack, c);
447818334Speter	arg_going = 1;
447918334Speter	break;
448018334Speter
448118334Speter      case '\t':
448218334Speter      case ' ':
448318334Speter	/* Space or tab ends an argument if one is pending.  */
448418334Speter	if (arg_going)
448518334Speter	  {
448618334Speter	    obstack_1grow (&obstack, 0);
448718334Speter	    string = obstack_finish (&obstack);
448818334Speter	    if (this_is_library_file)
448918334Speter	      string = find_file (string);
449018334Speter	    store_arg (string, delete_this_arg, this_is_output_file);
449118334Speter	    if (this_is_output_file)
449218334Speter	      outfiles[input_file_number] = string;
449318334Speter	  }
449418334Speter	/* Reinitialize for a new argument.  */
449518334Speter	arg_going = 0;
449618334Speter	delete_this_arg = 0;
449718334Speter	this_is_output_file = 0;
449818334Speter	this_is_library_file = 0;
449918334Speter	break;
450018334Speter
450118334Speter      case '%':
450218334Speter	switch (c = *p++)
450318334Speter	  {
450418334Speter	  case 0:
450590277Sobrien	    fatal ("invalid specification!  Bug in cc");
450618334Speter
450718334Speter	  case 'b':
450818334Speter	    obstack_grow (&obstack, input_basename, basename_length);
450918334Speter	    arg_going = 1;
451018334Speter	    break;
451118334Speter
451290277Sobrien	  case 'B':
451390277Sobrien	    obstack_grow (&obstack, input_basename, suffixed_basename_length);
451490277Sobrien	    arg_going = 1;
451590277Sobrien	    break;
451690277Sobrien
451718334Speter	  case 'd':
451818334Speter	    delete_this_arg = 2;
451918334Speter	    break;
452018334Speter
452118334Speter	  /* Dump out the directories specified with LIBRARY_PATH,
452218334Speter	     followed by the absolute directories
452318334Speter	     that we search for startfiles.  */
452418334Speter	  case 'D':
452518334Speter	    {
452618334Speter	      struct prefix_list *pl = startfile_prefixes.plist;
452750599Sobrien	      size_t bufsize = 100;
4528132733Skan	      char *buffer = xmalloc (bufsize);
452918334Speter	      int idx;
453018334Speter
453118334Speter	      for (; pl; pl = pl->next)
453218334Speter		{
453318334Speter#ifdef RELATIVE_PREFIX_NOT_LINKDIR
453418334Speter		  /* Used on systems which record the specified -L dirs
453518334Speter		     and use them to search for dynamic linking.  */
453618334Speter		  /* Relative directories always come from -B,
453718334Speter		     and it is better not to use them for searching
453890277Sobrien		     at run time.  In particular, stage1 loses.  */
4539132733Skan		  if (!IS_ABSOLUTE_PATH (pl->prefix))
454018334Speter		    continue;
454118334Speter#endif
454218334Speter		  /* Try subdirectory if there is one.  */
4543104763Skan		  if (multilib_dir != NULL
4544104763Skan		      || (pl->os_multilib && multilib_os_dir != NULL))
454518334Speter		    {
4546104763Skan		      const char *multi_dir;
4547104763Skan
4548104763Skan		      multi_dir = pl->os_multilib ? multilib_os_dir
4549104763Skan						  : multilib_dir;
4550104763Skan		      if (machine_suffix && multilib_dir)
455118334Speter			{
455218334Speter			  if (strlen (pl->prefix) + strlen (machine_suffix)
455318334Speter			      >= bufsize)
455418334Speter			    bufsize = (strlen (pl->prefix)
455518334Speter				       + strlen (machine_suffix)) * 2 + 1;
4556132733Skan			  buffer = xrealloc (buffer, bufsize);
455718334Speter			  strcpy (buffer, pl->prefix);
455818334Speter			  strcat (buffer, machine_suffix);
455918334Speter			  if (is_directory (buffer, multilib_dir, 1))
456018334Speter			    {
456190277Sobrien			      do_spec_1 ("-L", 0, NULL);
456218334Speter#ifdef SPACE_AFTER_L_OPTION
456390277Sobrien			      do_spec_1 (" ", 0, NULL);
456418334Speter#endif
456590277Sobrien			      do_spec_1 (buffer, 1, NULL);
456690277Sobrien			      do_spec_1 (multilib_dir, 1, NULL);
456718334Speter			      /* Make this a separate argument.  */
456890277Sobrien			      do_spec_1 (" ", 0, NULL);
456918334Speter			    }
457018334Speter			}
457118334Speter		      if (!pl->require_machine_suffix)
457218334Speter			{
4573104763Skan			  if (is_directory (pl->prefix, multi_dir, 1))
457418334Speter			    {
457590277Sobrien			      do_spec_1 ("-L", 0, NULL);
457618334Speter#ifdef SPACE_AFTER_L_OPTION
457790277Sobrien			      do_spec_1 (" ", 0, NULL);
457818334Speter#endif
457990277Sobrien			      do_spec_1 (pl->prefix, 1, NULL);
4580104763Skan			      do_spec_1 (multi_dir, 1, NULL);
458118334Speter			      /* Make this a separate argument.  */
458290277Sobrien			      do_spec_1 (" ", 0, NULL);
458318334Speter			    }
458418334Speter			}
458518334Speter		    }
458618334Speter		  if (machine_suffix)
458718334Speter		    {
458818334Speter		      if (is_directory (pl->prefix, machine_suffix, 1))
458918334Speter			{
459090277Sobrien			  do_spec_1 ("-L", 0, NULL);
459118334Speter#ifdef SPACE_AFTER_L_OPTION
459290277Sobrien			  do_spec_1 (" ", 0, NULL);
459318334Speter#endif
459490277Sobrien			  do_spec_1 (pl->prefix, 1, NULL);
459518334Speter			  /* Remove slash from machine_suffix.  */
459618334Speter			  if (strlen (machine_suffix) >= bufsize)
459718334Speter			    bufsize = strlen (machine_suffix) * 2 + 1;
4598132733Skan			  buffer = xrealloc (buffer, bufsize);
459918334Speter			  strcpy (buffer, machine_suffix);
460018334Speter			  idx = strlen (buffer);
460152520Sobrien			  if (IS_DIR_SEPARATOR (buffer[idx - 1]))
460218334Speter			    buffer[idx - 1] = 0;
460390277Sobrien			  do_spec_1 (buffer, 1, NULL);
460418334Speter			  /* Make this a separate argument.  */
460590277Sobrien			  do_spec_1 (" ", 0, NULL);
460618334Speter			}
460718334Speter		    }
460818334Speter		  if (!pl->require_machine_suffix)
460918334Speter		    {
461018334Speter		      if (is_directory (pl->prefix, "", 1))
461118334Speter			{
461290277Sobrien			  do_spec_1 ("-L", 0, NULL);
461318334Speter#ifdef SPACE_AFTER_L_OPTION
461490277Sobrien			  do_spec_1 (" ", 0, NULL);
461518334Speter#endif
461618334Speter			  /* Remove slash from pl->prefix.  */
461718334Speter			  if (strlen (pl->prefix) >= bufsize)
461818334Speter			    bufsize = strlen (pl->prefix) * 2 + 1;
4619132733Skan			  buffer = xrealloc (buffer, bufsize);
462018334Speter			  strcpy (buffer, pl->prefix);
462118334Speter			  idx = strlen (buffer);
462252520Sobrien			  if (IS_DIR_SEPARATOR (buffer[idx - 1]))
462318334Speter			    buffer[idx - 1] = 0;
462490277Sobrien			  do_spec_1 (buffer, 1, NULL);
462518334Speter			  /* Make this a separate argument.  */
462690277Sobrien			  do_spec_1 (" ", 0, NULL);
462718334Speter			}
462818334Speter		    }
462918334Speter		}
463018334Speter	      free (buffer);
463118334Speter	    }
463218334Speter	    break;
463318334Speter
463418334Speter	  case 'e':
463552520Sobrien	    /* %efoo means report an error with `foo' as error message
463618334Speter	       and don't execute any more commands for this file.  */
463718334Speter	    {
463852520Sobrien	      const char *q = p;
463918334Speter	      char *buf;
464090277Sobrien	      while (*p != 0 && *p != '\n')
464190277Sobrien		p++;
4642132733Skan	      buf = alloca (p - q + 1);
464318334Speter	      strncpy (buf, q, p - q);
464418334Speter	      buf[p - q] = 0;
464590277Sobrien	      error ("%s", buf);
464618334Speter	      return -1;
464718334Speter	    }
464818334Speter	    break;
464990277Sobrien	  case 'n':
4650117413Skan	    /* %nfoo means report a notice with `foo' on stderr.  */
465190277Sobrien	    {
465290277Sobrien	      const char *q = p;
465390277Sobrien	      char *buf;
465490277Sobrien	      while (*p != 0 && *p != '\n')
465590277Sobrien		p++;
4656132733Skan	      buf = alloca (p - q + 1);
465790277Sobrien	      strncpy (buf, q, p - q);
465890277Sobrien	      buf[p - q] = 0;
465990277Sobrien	      notice ("%s\n", buf);
466090277Sobrien	      if (*p)
466190277Sobrien		p++;
466290277Sobrien	    }
466390277Sobrien	    break;
466418334Speter
466590277Sobrien	  case 'j':
466690277Sobrien	    {
466790277Sobrien	      struct stat st;
466890277Sobrien
4669132733Skan	      /* If save_temps_flag is off, and the HOST_BIT_BUCKET is
4670132733Skan		 defined, and it is not a directory, and it is
4671132733Skan		 writable, use it.  Otherwise, treat this like any
4672132733Skan		 other temporary file.  */
467390277Sobrien
467490277Sobrien	      if ((!save_temps_flag)
467590277Sobrien		  && (stat (HOST_BIT_BUCKET, &st) == 0) && (!S_ISDIR (st.st_mode))
467690277Sobrien		  && (access (HOST_BIT_BUCKET, W_OK) == 0))
467790277Sobrien		{
467890277Sobrien		  obstack_grow (&obstack, HOST_BIT_BUCKET,
467990277Sobrien				strlen (HOST_BIT_BUCKET));
468090277Sobrien		  delete_this_arg = 0;
468190277Sobrien		  arg_going = 1;
468290277Sobrien		  break;
468390277Sobrien		}
468490277Sobrien	    }
4685132733Skan	    goto create_temp_file;
4686132733Skan	  case '|':
4687132733Skan	    if (use_pipes)
4688132733Skan	      {
4689132733Skan		obstack_1grow (&obstack, '-');
4690132733Skan		delete_this_arg = 0;
4691132733Skan		arg_going = 1;
4692132733Skan
4693132733Skan		/* consume suffix */
4694132733Skan		while (*p == '.' || ISALPHA ((unsigned char) *p))
4695132733Skan		  p++;
4696132733Skan		if (p[0] == '%' && p[1] == 'O')
4697132733Skan		  p += 2;
4698132733Skan
4699132733Skan		break;
4700132733Skan	      }
4701132733Skan	    goto create_temp_file;
4702132733Skan	  case 'm':
4703132733Skan	    if (use_pipes)
4704132733Skan	      {
4705132733Skan		/* consume suffix */
4706132733Skan		while (*p == '.' || ISALPHA ((unsigned char) *p))
4707132733Skan		  p++;
4708132733Skan		if (p[0] == '%' && p[1] == 'O')
4709132733Skan		  p += 2;
4710132733Skan
4711132733Skan		break;
4712132733Skan	      }
4713132733Skan	    goto create_temp_file;
471418334Speter	  case 'g':
471518334Speter	  case 'u':
471618334Speter	  case 'U':
4717132733Skan	  create_temp_file:
471818334Speter	      {
471918334Speter		struct temp_name *t;
472050599Sobrien		int suffix_length;
472152520Sobrien		const char *suffix = p;
472290277Sobrien		char *saved_suffix = NULL;
472318334Speter
472490277Sobrien		while (*p == '.' || ISALPHA ((unsigned char) *p))
472590277Sobrien		  p++;
472690277Sobrien		suffix_length = p - suffix;
472750599Sobrien		if (p[0] == '%' && p[1] == 'O')
472850599Sobrien		  {
472950599Sobrien		    p += 2;
473050599Sobrien		    /* We don't support extra suffix characters after %O.  */
473190277Sobrien		    if (*p == '.' || ISALPHA ((unsigned char) *p))
473250599Sobrien		      abort ();
473390277Sobrien		    if (suffix_length == 0)
473490277Sobrien		      suffix = TARGET_OBJECT_SUFFIX;
473590277Sobrien		    else
473690277Sobrien		      {
473790277Sobrien			saved_suffix
4738132733Skan			  = xmalloc (suffix_length
4739132733Skan				     + strlen (TARGET_OBJECT_SUFFIX));
474090277Sobrien			strncpy (saved_suffix, suffix, suffix_length);
474190277Sobrien			strcpy (saved_suffix + suffix_length,
474290277Sobrien				TARGET_OBJECT_SUFFIX);
474390277Sobrien		      }
474490277Sobrien		    suffix_length += strlen (TARGET_OBJECT_SUFFIX);
474550599Sobrien		  }
4746117413Skan
474790277Sobrien		/* If the input_filename has the same suffix specified
474890277Sobrien		   for the %g, %u, or %U, and -save-temps is specified,
474990277Sobrien		   we could end up using that file as an intermediate
475090277Sobrien		   thus clobbering the user's source file (.e.g.,
475190277Sobrien		   gcc -save-temps foo.s would clobber foo.s with the
475290277Sobrien		   output of cpp0).  So check for this condition and
475390277Sobrien		   generate a temp file as the intermediate.  */
4754117413Skan
475590277Sobrien		if (save_temps_flag)
475650599Sobrien		  {
475790277Sobrien		    temp_filename_length = basename_length + suffix_length;
475890277Sobrien		    temp_filename = alloca (temp_filename_length + 1);
475990277Sobrien		    strncpy ((char *) temp_filename, input_basename, basename_length);
476090277Sobrien		    strncpy ((char *) temp_filename + basename_length, suffix,
4761132733Skan			     suffix_length);
476290277Sobrien		    *((char *) temp_filename + temp_filename_length) = '\0';
476390277Sobrien		    if (strcmp (temp_filename, input_filename) != 0)
476490277Sobrien		      {
4765132733Skan			struct stat st_temp;
4766117413Skan
4767132733Skan			/* Note, set_input() resets input_stat_set to 0.  */
4768132733Skan			if (input_stat_set == 0)
4769132733Skan			  {
4770132733Skan			    input_stat_set = stat (input_filename, &input_stat);
4771132733Skan			    if (input_stat_set >= 0)
4772132733Skan			      input_stat_set = 1;
4773132733Skan			  }
4774117413Skan
4775132733Skan			/* If we have the stat for the input_filename
4776132733Skan			   and we can do the stat for the temp_filename
4777132733Skan			   then the they could still refer to the same
4778132733Skan			   file if st_dev/st_ino's are the same.  */
4779117413Skan
478090277Sobrien			if (input_stat_set != 1
478190277Sobrien			    || stat (temp_filename, &st_temp) < 0
478290277Sobrien			    || input_stat.st_dev != st_temp.st_dev
478390277Sobrien			    || input_stat.st_ino != st_temp.st_ino)
4784117413Skan			  {
478590277Sobrien			    temp_filename = save_string (temp_filename,
478690277Sobrien							 temp_filename_length + 1);
478790277Sobrien			    obstack_grow (&obstack, temp_filename,
4788132733Skan						    temp_filename_length);
478990277Sobrien			    arg_going = 1;
4790117413Skan			    delete_this_arg = 0;
479190277Sobrien			    break;
479290277Sobrien			  }
479390277Sobrien		      }
479450599Sobrien		  }
479550599Sobrien
479618334Speter		/* See if we already have an association of %g/%u/%U and
479718334Speter		   suffix.  */
479818334Speter		for (t = temp_names; t; t = t->next)
479950599Sobrien		  if (t->length == suffix_length
480050599Sobrien		      && strncmp (t->suffix, suffix, suffix_length) == 0
4801132733Skan		      && t->unique == (c == 'u' || c == 'U' || c == 'j'))
480218334Speter		    break;
480318334Speter
480490277Sobrien		/* Make a new association if needed.  %u and %j
480590277Sobrien		   require one.  */
480690277Sobrien		if (t == 0 || c == 'u' || c == 'j')
480718334Speter		  {
480818334Speter		    if (t == 0)
480918334Speter		      {
4810132733Skan			t = xmalloc (sizeof (struct temp_name));
481118334Speter			t->next = temp_names;
481218334Speter			temp_names = t;
481318334Speter		      }
481450599Sobrien		    t->length = suffix_length;
481590277Sobrien		    if (saved_suffix)
481690277Sobrien		      {
481790277Sobrien			t->suffix = saved_suffix;
481890277Sobrien			saved_suffix = NULL;
481990277Sobrien		      }
482090277Sobrien		    else
482190277Sobrien		      t->suffix = save_string (suffix, suffix_length);
4822132733Skan		    t->unique = (c == 'u' || c == 'U' || c == 'j');
482350599Sobrien		    temp_filename = make_temp_file (t->suffix);
482450599Sobrien		    temp_filename_length = strlen (temp_filename);
482518334Speter		    t->filename = temp_filename;
482618334Speter		    t->filename_length = temp_filename_length;
482718334Speter		  }
482818334Speter
482990277Sobrien		if (saved_suffix)
483090277Sobrien		  free (saved_suffix);
483190277Sobrien
483218334Speter		obstack_grow (&obstack, t->filename, t->filename_length);
483318334Speter		delete_this_arg = 1;
483418334Speter	      }
483518334Speter	    arg_going = 1;
483618334Speter	    break;
483718334Speter
483818334Speter	  case 'i':
4839132733Skan	    if (combine_inputs)
4840132733Skan	      {
4841132733Skan		for (i = 0; (int) i < n_infiles; i++)
4842132733Skan		  store_arg (infiles[i].name, 0, 0);
4843132733Skan	      }
4844132733Skan	    else
4845132733Skan	      {
4846132733Skan		obstack_grow (&obstack, input_filename, input_filename_length);
4847132733Skan		arg_going = 1;
4848132733Skan	      }
484918334Speter	    break;
485018334Speter
485118334Speter	  case 'I':
485218334Speter	    {
485318334Speter	      struct prefix_list *pl = include_prefixes.plist;
485418334Speter
485518334Speter	      if (gcc_exec_prefix)
485618334Speter		{
485790277Sobrien		  do_spec_1 ("-iprefix", 1, NULL);
485818334Speter		  /* Make this a separate argument.  */
485990277Sobrien		  do_spec_1 (" ", 0, NULL);
486090277Sobrien		  do_spec_1 (gcc_exec_prefix, 1, NULL);
486190277Sobrien		  do_spec_1 (" ", 0, NULL);
486218334Speter		}
486318334Speter
4864132733Skan	      if (target_system_root_changed ||
4865132733Skan		  (target_system_root && target_sysroot_hdrs_suffix))
4866132733Skan		{
4867132733Skan		  do_spec_1 ("-isysroot", 1, NULL);
4868132733Skan		  /* Make this a separate argument.  */
4869132733Skan		  do_spec_1 (" ", 0, NULL);
4870132733Skan		  do_spec_1 (target_system_root, 1, NULL);
4871132733Skan		  if (target_sysroot_hdrs_suffix)
4872132733Skan		    do_spec_1 (target_sysroot_hdrs_suffix, 1, NULL);
4873132733Skan		  do_spec_1 (" ", 0, NULL);
4874132733Skan		}
4875132733Skan
487618334Speter	      for (; pl; pl = pl->next)
487718334Speter		{
487890277Sobrien		  do_spec_1 ("-isystem", 1, NULL);
487918334Speter		  /* Make this a separate argument.  */
488090277Sobrien		  do_spec_1 (" ", 0, NULL);
488190277Sobrien		  do_spec_1 (pl->prefix, 1, NULL);
488290277Sobrien		  do_spec_1 (" ", 0, NULL);
488318334Speter		}
488418334Speter	    }
488518334Speter	    break;
488618334Speter
488718334Speter	  case 'o':
488852520Sobrien	    {
488952520Sobrien	      int max = n_infiles;
489052520Sobrien	      max += lang_specific_extra_outfiles;
489118334Speter
489252520Sobrien	      for (i = 0; i < max; i++)
489352520Sobrien		if (outfiles[i])
489452520Sobrien		  store_arg (outfiles[i], 0, 0);
489552520Sobrien	      break;
489652520Sobrien	    }
489752520Sobrien
489818334Speter	  case 'O':
489990277Sobrien	    obstack_grow (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
490018334Speter	    arg_going = 1;
490118334Speter	    break;
490218334Speter
490318334Speter	  case 's':
490418334Speter	    this_is_library_file = 1;
490518334Speter	    break;
490618334Speter
4907132733Skan	  case 'V':
4908132733Skan	    outfiles[input_file_number] = NULL;
4909132733Skan	    break;
4910132733Skan
491118334Speter	  case 'w':
491218334Speter	    this_is_output_file = 1;
491318334Speter	    break;
491418334Speter
491518334Speter	  case 'W':
491618334Speter	    {
491750599Sobrien	      int cur_index = argbuf_index;
491818334Speter	      /* Handle the {...} following the %W.  */
491918334Speter	      if (*p != '{')
492018334Speter		abort ();
492118334Speter	      p = handle_braces (p + 1);
492218334Speter	      if (p == 0)
492318334Speter		return -1;
4924132733Skan	      /* End any pending argument.  */
4925132733Skan	      if (arg_going)
4926132733Skan		{
4927132733Skan		  obstack_1grow (&obstack, 0);
4928132733Skan		  string = obstack_finish (&obstack);
4929132733Skan		  if (this_is_library_file)
4930132733Skan		    string = find_file (string);
4931132733Skan		  store_arg (string, delete_this_arg, this_is_output_file);
4932132733Skan		  if (this_is_output_file)
4933132733Skan		    outfiles[input_file_number] = string;
4934132733Skan		  arg_going = 0;
4935132733Skan		}
493618334Speter	      /* If any args were output, mark the last one for deletion
493718334Speter		 on failure.  */
493850599Sobrien	      if (argbuf_index != cur_index)
493918334Speter		record_temp_file (argbuf[argbuf_index - 1], 0, 1);
494018334Speter	      break;
494118334Speter	    }
494218334Speter
494318334Speter	  /* %x{OPTION} records OPTION for %X to output.  */
494418334Speter	  case 'x':
494518334Speter	    {
494652520Sobrien	      const char *p1 = p;
494718334Speter	      char *string;
494818334Speter
494918334Speter	      /* Skip past the option value and make a copy.  */
495018334Speter	      if (*p != '{')
495118334Speter		abort ();
495218334Speter	      while (*p++ != '}')
495318334Speter		;
495418334Speter	      string = save_string (p1 + 1, p - p1 - 2);
495518334Speter
495618334Speter	      /* See if we already recorded this option.  */
495718334Speter	      for (i = 0; i < n_linker_options; i++)
495818334Speter		if (! strcmp (string, linker_options[i]))
495918334Speter		  {
496018334Speter		    free (string);
496118334Speter		    return 0;
496218334Speter		  }
496318334Speter
496418334Speter	      /* This option is new; add it.  */
496550599Sobrien	      add_linker_option (string, strlen (string));
496618334Speter	    }
496718334Speter	    break;
496818334Speter
496918334Speter	  /* Dump out the options accumulated previously using %x.  */
497018334Speter	  case 'X':
497118334Speter	    for (i = 0; i < n_linker_options; i++)
497218334Speter	      {
497390277Sobrien		do_spec_1 (linker_options[i], 1, NULL);
497418334Speter		/* Make each accumulated option a separate argument.  */
497590277Sobrien		do_spec_1 (" ", 0, NULL);
497618334Speter	      }
497718334Speter	    break;
497818334Speter
497918334Speter	  /* Dump out the options accumulated previously using -Wa,.  */
498018334Speter	  case 'Y':
498118334Speter	    for (i = 0; i < n_assembler_options; i++)
498218334Speter	      {
498390277Sobrien		do_spec_1 (assembler_options[i], 1, NULL);
498418334Speter		/* Make each accumulated option a separate argument.  */
498590277Sobrien		do_spec_1 (" ", 0, NULL);
498618334Speter	      }
498718334Speter	    break;
498818334Speter
498918334Speter	  /* Dump out the options accumulated previously using -Wp,.  */
499018334Speter	  case 'Z':
499118334Speter	    for (i = 0; i < n_preprocessor_options; i++)
499218334Speter	      {
499390277Sobrien		do_spec_1 (preprocessor_options[i], 1, NULL);
499418334Speter		/* Make each accumulated option a separate argument.  */
499590277Sobrien		do_spec_1 (" ", 0, NULL);
499618334Speter	      }
499718334Speter	    break;
499818334Speter
499918334Speter	    /* Here are digits and numbers that just process
500018334Speter	       a certain constant string as a spec.  */
500118334Speter
500218334Speter	  case '1':
500390277Sobrien	    value = do_spec_1 (cc1_spec, 0, NULL);
500418334Speter	    if (value != 0)
500518334Speter	      return value;
500618334Speter	    break;
500718334Speter
500818334Speter	  case '2':
500990277Sobrien	    value = do_spec_1 (cc1plus_spec, 0, NULL);
501018334Speter	    if (value != 0)
501118334Speter	      return value;
501218334Speter	    break;
501318334Speter
501418334Speter	  case 'a':
501590277Sobrien	    value = do_spec_1 (asm_spec, 0, NULL);
501618334Speter	    if (value != 0)
501718334Speter	      return value;
501818334Speter	    break;
501918334Speter
502018334Speter	  case 'A':
502190277Sobrien	    value = do_spec_1 (asm_final_spec, 0, NULL);
502218334Speter	    if (value != 0)
502318334Speter	      return value;
502418334Speter	    break;
502518334Speter
502618334Speter	  case 'C':
502790277Sobrien	    {
502890277Sobrien	      const char *const spec
5029117413Skan		= (input_file_compiler->cpp_spec
5030117413Skan		   ? input_file_compiler->cpp_spec
503190277Sobrien		   : cpp_spec);
503290277Sobrien	      value = do_spec_1 (spec, 0, NULL);
503390277Sobrien	      if (value != 0)
503490277Sobrien		return value;
503590277Sobrien	    }
503618334Speter	    break;
503718334Speter
503818334Speter	  case 'E':
503990277Sobrien	    value = do_spec_1 (endfile_spec, 0, NULL);
504018334Speter	    if (value != 0)
504118334Speter	      return value;
504218334Speter	    break;
504318334Speter
504418334Speter	  case 'l':
504590277Sobrien	    value = do_spec_1 (link_spec, 0, NULL);
504618334Speter	    if (value != 0)
504718334Speter	      return value;
504818334Speter	    break;
504918334Speter
505018334Speter	  case 'L':
505190277Sobrien	    value = do_spec_1 (lib_spec, 0, NULL);
505218334Speter	    if (value != 0)
505318334Speter	      return value;
505418334Speter	    break;
505518334Speter
505618334Speter	  case 'G':
505790277Sobrien	    value = do_spec_1 (libgcc_spec, 0, NULL);
505818334Speter	    if (value != 0)
505918334Speter	      return value;
506018334Speter	    break;
506118334Speter
506290277Sobrien	  case 'M':
506390277Sobrien	    if (multilib_dir && strcmp (multilib_dir, ".") != 0)
506490277Sobrien	      {
506590277Sobrien		char *p;
506690277Sobrien		const char *q;
506790277Sobrien		size_t len;
506890277Sobrien
506990277Sobrien		len = strlen (multilib_dir);
507090277Sobrien		obstack_blank (&obstack, len + 1);
507190277Sobrien		p = obstack_next_free (&obstack) - (len + 1);
507290277Sobrien
507390277Sobrien		*p++ = '_';
507490277Sobrien		for (q = multilib_dir; *q ; ++q, ++p)
507590277Sobrien		  *p = (IS_DIR_SEPARATOR (*q) ? '_' : *q);
507690277Sobrien	      }
507790277Sobrien	    break;
507890277Sobrien
5079132733Skan	  case 'R':
5080132733Skan	    /* We assume there is a directory
5081132733Skan	       separator at the end of this string.  */
5082132733Skan	    if (target_system_root)
5083132733Skan	      {
5084132733Skan	        obstack_grow (&obstack, target_system_root,
5085132733Skan			      strlen (target_system_root));
5086132733Skan		if (target_sysroot_suffix)
5087132733Skan		  obstack_grow (&obstack, target_sysroot_suffix,
5088132733Skan				strlen (target_sysroot_suffix));
5089132733Skan	      }
509018334Speter	    break;
509118334Speter
509218334Speter	  case 'S':
509390277Sobrien	    value = do_spec_1 (startfile_spec, 0, NULL);
509418334Speter	    if (value != 0)
509518334Speter	      return value;
509618334Speter	    break;
509718334Speter
509818334Speter	    /* Here we define characters other than letters and digits.  */
509918334Speter
510018334Speter	  case '{':
510118334Speter	    p = handle_braces (p);
510218334Speter	    if (p == 0)
510318334Speter	      return -1;
510418334Speter	    break;
510518334Speter
5106117413Skan	  case ':':
5107117413Skan	    p = handle_spec_function (p);
5108117413Skan	    if (p == 0)
5109117413Skan	      return -1;
5110117413Skan	    break;
5111117413Skan
511218334Speter	  case '%':
511318334Speter	    obstack_1grow (&obstack, '%');
511418334Speter	    break;
511518334Speter
5116117413Skan	  case '.':
5117117413Skan	    {
5118117413Skan	      unsigned len = 0;
511990277Sobrien
5120117413Skan	      while (p[len] && p[len] != ' ' && p[len] != '%')
5121117413Skan		len++;
5122117413Skan	      suffix_subst = save_string (p - 1, len + 1);
5123117413Skan	      p += len;
5124117413Skan	    }
512590277Sobrien	   break;
5126117413Skan
5127132733Skan	   /* Henceforth ignore the option(s) matching the pattern
5128132733Skan	      after the %<.  */
5129132733Skan	  case '<':
5130132733Skan	    {
5131132733Skan	      unsigned len = 0;
5132132733Skan	      int have_wildcard = 0;
5133132733Skan	      int i;
5134132733Skan
5135132733Skan	      while (p[len] && p[len] != ' ' && p[len] != '\t')
5136132733Skan		len++;
5137132733Skan
5138132733Skan	      if (p[len-1] == '*')
5139132733Skan		have_wildcard = 1;
5140132733Skan
5141132733Skan	      for (i = 0; i < n_switches; i++)
5142132733Skan		if (!strncmp (switches[i].part1, p, len - have_wildcard)
5143132733Skan		    && (have_wildcard || switches[i].part1[len] == '\0'))
5144132733Skan		  {
5145132733Skan		    switches[i].live_cond = SWITCH_IGNORE;
5146132733Skan		    switches[i].validated = 1;
5147132733Skan		  }
5148132733Skan
5149132733Skan	      p += len;
5150132733Skan	    }
5151132733Skan	    break;
5152132733Skan
515318334Speter	  case '*':
515490277Sobrien	    if (soft_matched_part)
515590277Sobrien	      {
515690277Sobrien		do_spec_1 (soft_matched_part, 1, NULL);
515790277Sobrien		do_spec_1 (" ", 0, NULL);
515890277Sobrien	      }
515990277Sobrien	    else
516090277Sobrien	      /* Catch the case where a spec string contains something like
516190277Sobrien		 '%{foo:%*}'.  ie there is no * in the pattern on the left
516290277Sobrien		 hand side of the :.  */
516390277Sobrien	      error ("spec failure: '%%*' has not been initialized by pattern match");
516418334Speter	    break;
516518334Speter
516618334Speter	    /* Process a string found as the value of a spec given by name.
516718334Speter	       This feature allows individual machine descriptions
516818334Speter	       to add and use their own specs.
516918334Speter	       %[...] modifies -D options the way %P does;
517018334Speter	       %(...) uses the spec unmodified.  */
517150599Sobrien	  case '[':
517290277Sobrien	    error ("warning: use of obsolete %%[ operator in specs");
517318334Speter	  case '(':
517418334Speter	    {
517552520Sobrien	      const char *name = p;
517618334Speter	      struct spec_list *sl;
517718334Speter	      int len;
517818334Speter
517918334Speter	      /* The string after the S/P is the name of a spec that is to be
518050599Sobrien		 processed.  */
518118334Speter	      while (*p && *p != ')' && *p != ']')
518218334Speter		p++;
518318334Speter
518490277Sobrien	      /* See if it's in the list.  */
518518334Speter	      for (len = p - name, sl = specs; sl; sl = sl->next)
518650599Sobrien		if (sl->name_len == len && !strncmp (sl->name, name, len))
518718334Speter		  {
518850599Sobrien		    name = *(sl->ptr_spec);
518950599Sobrien#ifdef DEBUG_SPECS
519052520Sobrien		    notice ("Processing spec %c%s%c, which is '%s'\n",
519152520Sobrien			    c, sl->name, (c == '(') ? ')' : ']', name);
519250599Sobrien#endif
519318334Speter		    break;
519418334Speter		  }
519518334Speter
519618334Speter	      if (sl)
519718334Speter		{
519818334Speter		  if (c == '(')
519918334Speter		    {
520090277Sobrien		      value = do_spec_1 (name, 0, NULL);
520118334Speter		      if (value != 0)
520218334Speter			return value;
520318334Speter		    }
520418334Speter		  else
520518334Speter		    {
5206132733Skan		      char *x = alloca (strlen (name) * 2 + 1);
520718334Speter		      char *buf = x;
520852520Sobrien		      const char *y = name;
520950599Sobrien		      int flag = 0;
521018334Speter
521118334Speter		      /* Copy all of NAME into BUF, but put __ after
521290277Sobrien			 every -D and at the end of each arg.  */
521318334Speter		      while (1)
521418334Speter			{
521518334Speter			  if (! strncmp (y, "-D", 2))
521618334Speter			    {
521718334Speter			      *x++ = '-';
521818334Speter			      *x++ = 'D';
521918334Speter			      *x++ = '_';
522018334Speter			      *x++ = '_';
522118334Speter			      y += 2;
522250599Sobrien			      flag = 1;
522350599Sobrien			      continue;
522418334Speter			    }
522590277Sobrien			  else if (flag
522690277Sobrien				   && (*y == ' ' || *y == '\t' || *y == '='
522790277Sobrien				       || *y == '}' || *y == 0))
522818334Speter			    {
522918334Speter			      *x++ = '_';
523018334Speter			      *x++ = '_';
523150599Sobrien			      flag = 0;
523218334Speter			    }
523390277Sobrien			  if (*y == 0)
523450599Sobrien			    break;
523518334Speter			  else
523618334Speter			    *x++ = *y++;
523718334Speter			}
523818334Speter		      *x = 0;
523918334Speter
524090277Sobrien		      value = do_spec_1 (buf, 0, NULL);
524118334Speter		      if (value != 0)
524218334Speter			return value;
524318334Speter		    }
524418334Speter		}
524518334Speter
524618334Speter	      /* Discard the closing paren or bracket.  */
524718334Speter	      if (*p)
524818334Speter		p++;
524918334Speter	    }
525018334Speter	    break;
525118334Speter
525218334Speter	  default:
525390277Sobrien	    error ("spec failure: unrecognized spec option '%c'", c);
525490277Sobrien	    break;
525518334Speter	  }
525618334Speter	break;
525718334Speter
525818334Speter      case '\\':
525918334Speter	/* Backslash: treat next character as ordinary.  */
526018334Speter	c = *p++;
526118334Speter
5262132733Skan	/* Fall through.  */
526318334Speter      default:
526418334Speter	/* Ordinary character: put it into the current argument.  */
526518334Speter	obstack_1grow (&obstack, c);
526618334Speter	arg_going = 1;
526718334Speter      }
526818334Speter
5269117413Skan  /* End of string.  If we are processing a spec function, we need to
5270117413Skan     end any pending argument.  */
5271117413Skan  if (processing_spec_function && arg_going)
5272117413Skan    {
5273117413Skan      obstack_1grow (&obstack, 0);
5274117413Skan      string = obstack_finish (&obstack);
5275117413Skan      if (this_is_library_file)
5276117413Skan        string = find_file (string);
5277117413Skan      store_arg (string, delete_this_arg, this_is_output_file);
5278117413Skan      if (this_is_output_file)
5279117413Skan        outfiles[input_file_number] = string;
5280117413Skan      arg_going = 0;
5281117413Skan    }
5282117413Skan
528390277Sobrien  return 0;
528418334Speter}
528518334Speter
5286117413Skan/* Look up a spec function.  */
5287117413Skan
5288117413Skanstatic const struct spec_function *
5289132733Skanlookup_spec_function (const char *name)
5290117413Skan{
5291117413Skan  static const struct spec_function * const spec_function_tables[] =
5292117413Skan  {
5293117413Skan    static_spec_functions,
5294117413Skan    lang_specific_spec_functions,
5295117413Skan  };
5296117413Skan  const struct spec_function *sf;
5297117413Skan  unsigned int i;
5298117413Skan
5299117413Skan  for (i = 0; i < ARRAY_SIZE (spec_function_tables); i++)
5300117413Skan    {
5301117413Skan      for (sf = spec_function_tables[i]; sf->name != NULL; sf++)
5302117413Skan	if (strcmp (sf->name, name) == 0)
5303117413Skan	  return sf;
5304117413Skan    }
5305117413Skan
5306117413Skan  return NULL;
5307117413Skan}
5308117413Skan
5309117413Skan/* Evaluate a spec function.  */
5310117413Skan
5311117413Skanstatic const char *
5312132733Skaneval_spec_function (const char *func, const char *args)
5313117413Skan{
5314117413Skan  const struct spec_function *sf;
5315117413Skan  const char *funcval;
5316117413Skan
5317117413Skan  /* Saved spec processing context.  */
5318117413Skan  int save_argbuf_index;
5319117413Skan  int save_argbuf_length;
5320117413Skan  const char **save_argbuf;
5321117413Skan
5322117413Skan  int save_arg_going;
5323117413Skan  int save_delete_this_arg;
5324117413Skan  int save_this_is_output_file;
5325117413Skan  int save_this_is_library_file;
5326117413Skan  int save_input_from_pipe;
5327117413Skan  const char *save_suffix_subst;
5328117413Skan
5329117413Skan
5330117413Skan  sf = lookup_spec_function (func);
5331117413Skan  if (sf == NULL)
5332117413Skan    fatal ("unknown spec function `%s'", func);
5333117413Skan
5334117413Skan  /* Push the spec processing context.  */
5335117413Skan  save_argbuf_index = argbuf_index;
5336117413Skan  save_argbuf_length = argbuf_length;
5337117413Skan  save_argbuf = argbuf;
5338117413Skan
5339117413Skan  save_arg_going = arg_going;
5340117413Skan  save_delete_this_arg = delete_this_arg;
5341117413Skan  save_this_is_output_file = this_is_output_file;
5342117413Skan  save_this_is_library_file = this_is_library_file;
5343117413Skan  save_input_from_pipe = input_from_pipe;
5344117413Skan  save_suffix_subst = suffix_subst;
5345117413Skan
5346117413Skan  /* Create a new spec processing context, and build the function
5347117413Skan     arguments.  */
5348117413Skan
5349117413Skan  alloc_args ();
5350117413Skan  if (do_spec_2 (args) < 0)
5351117413Skan    fatal ("error in args to spec function `%s'", func);
5352117413Skan
5353117413Skan  /* argbuf_index is an index for the next argument to be inserted, and
5354117413Skan     so contains the count of the args already inserted.  */
5355117413Skan
5356117413Skan  funcval = (*sf->func) (argbuf_index, argbuf);
5357117413Skan
5358117413Skan  /* Pop the spec processing context.  */
5359117413Skan  argbuf_index = save_argbuf_index;
5360117413Skan  argbuf_length = save_argbuf_length;
5361117413Skan  free (argbuf);
5362117413Skan  argbuf = save_argbuf;
5363117413Skan
5364117413Skan  arg_going = save_arg_going;
5365117413Skan  delete_this_arg = save_delete_this_arg;
5366117413Skan  this_is_output_file = save_this_is_output_file;
5367117413Skan  this_is_library_file = save_this_is_library_file;
5368117413Skan  input_from_pipe = save_input_from_pipe;
5369117413Skan  suffix_subst = save_suffix_subst;
5370117413Skan
5371117413Skan  return funcval;
5372117413Skan}
5373117413Skan
5374117413Skan/* Handle a spec function call of the form:
5375117413Skan
5376117413Skan   %:function(args)
5377117413Skan
5378117413Skan   ARGS is processed as a spec in a separate context and split into an
5379117413Skan   argument vector in the normal fashion.  The function returns a string
5380117413Skan   containing a spec which we then process in the caller's context, or
5381117413Skan   NULL if no processing is required.  */
5382117413Skan
5383117413Skanstatic const char *
5384132733Skanhandle_spec_function (const char *p)
5385117413Skan{
5386117413Skan  char *func, *args;
5387117413Skan  const char *endp, *funcval;
5388117413Skan  int count;
5389117413Skan
5390117413Skan  processing_spec_function++;
5391117413Skan
5392117413Skan  /* Get the function name.  */
5393117413Skan  for (endp = p; *endp != '\0'; endp++)
5394117413Skan    {
5395117413Skan      if (*endp == '(')		/* ) */
5396117413Skan        break;
5397117413Skan      /* Only allow [A-Za-z0-9], -, and _ in function names.  */
5398117413Skan      if (!ISALNUM (*endp) && !(*endp == '-' || *endp == '_'))
5399117413Skan	fatal ("malformed spec function name");
5400117413Skan    }
5401117413Skan  if (*endp != '(')		/* ) */
5402117413Skan    fatal ("no arguments for spec function");
5403117413Skan  func = save_string (p, endp - p);
5404117413Skan  p = ++endp;
5405117413Skan
5406117413Skan  /* Get the arguments.  */
5407117413Skan  for (count = 0; *endp != '\0'; endp++)
5408117413Skan    {
5409117413Skan      /* ( */
5410117413Skan      if (*endp == ')')
5411117413Skan	{
5412117413Skan	  if (count == 0)
5413117413Skan	    break;
5414117413Skan	  count--;
5415117413Skan	}
5416117413Skan      else if (*endp == '(')	/* ) */
5417117413Skan	count++;
5418117413Skan    }
5419117413Skan  /* ( */
5420117413Skan  if (*endp != ')')
5421117413Skan    fatal ("malformed spec function arguments");
5422117413Skan  args = save_string (p, endp - p);
5423117413Skan  p = ++endp;
5424117413Skan
5425117413Skan  /* p now points to just past the end of the spec function expression.  */
5426117413Skan
5427117413Skan  funcval = eval_spec_function (func, args);
5428117413Skan  if (funcval != NULL && do_spec_1 (funcval, 0, NULL) < 0)
5429117413Skan    p = NULL;
5430117413Skan
5431117413Skan  free (func);
5432117413Skan  free (args);
5433117413Skan
5434117413Skan  processing_spec_function--;
5435117413Skan
5436117413Skan  return p;
5437117413Skan}
5438117413Skan
5439132733Skan/* Inline subroutine of handle_braces.  Returns true if the current
5440132733Skan   input suffix matches the atom bracketed by ATOM and END_ATOM.  */
5441132733Skanstatic inline bool
5442132733Skaninput_suffix_matches (const char *atom, const char *end_atom)
5443132733Skan{
5444132733Skan  return (input_suffix
5445132733Skan	  && !strncmp (input_suffix, atom, end_atom - atom)
5446132733Skan	  && input_suffix[end_atom - atom] == '\0');
5447132733Skan}
544818334Speter
5449132733Skan/* Inline subroutine of handle_braces.  Returns true if a switch
5450132733Skan   matching the atom bracketed by ATOM and END_ATOM appeared on the
5451132733Skan   command line.  */
5452132733Skanstatic inline bool
5453132733Skanswitch_matches (const char *atom, const char *end_atom, int starred)
545418334Speter{
5455132733Skan  int i;
5456132733Skan  int len = end_atom - atom;
5457132733Skan  int plen = starred ? len : -1;
545818334Speter
5459132733Skan  for (i = 0; i < n_switches; i++)
5460132733Skan    if (!strncmp (switches[i].part1, atom, len)
5461132733Skan	&& (starred || switches[i].part1[len] == '\0')
5462132733Skan	&& check_live_switch (i, plen))
5463132733Skan      return true;
546450599Sobrien
5465132733Skan  return false;
5466132733Skan}
546718334Speter
5468132733Skan/* Inline subroutine of handle_braces.  Mark all of the switches which
5469132733Skan   match ATOM (extends to END_ATOM; STARRED indicates whether there
5470132733Skan   was a star after the atom) for later processing.  */
5471132733Skanstatic inline void
5472132733Skanmark_matching_switches (const char *atom, const char *end_atom, int starred)
5473132733Skan{
5474132733Skan  int i;
5475132733Skan  int len = end_atom - atom;
5476132733Skan  int plen = starred ? len : -1;
547790277Sobrien
5478132733Skan  for (i = 0; i < n_switches; i++)
5479132733Skan    if (!strncmp (switches[i].part1, atom, len)
5480132733Skan	&& (starred || switches[i].part1[len] == '\0')
5481132733Skan	&& check_live_switch (i, plen))
5482132733Skan      switches[i].ordering = 1;
5483132733Skan}
548450599Sobrien
5485132733Skan/* Inline subroutine of handle_braces.  Process all the currently
5486132733Skan   marked switches through give_switch, and clear the marks.  */
5487132733Skanstatic inline void
5488132733Skanprocess_marked_switches (void)
5489132733Skan{
5490132733Skan  int i;
549118334Speter
5492132733Skan  for (i = 0; i < n_switches; i++)
5493132733Skan    if (switches[i].ordering == 1)
5494132733Skan      {
5495132733Skan	switches[i].ordering = 0;
5496132733Skan	give_switch (i, 0);
5497132733Skan      }
5498132733Skan}
549918334Speter
5500132733Skan/* Handle a %{ ... } construct.  P points just inside the leading {.
5501132733Skan   Returns a pointer one past the end of the brace block, or 0
5502132733Skan   if we call do_spec_1 and that returns -1.  */
550318334Speter
5504132733Skanstatic const char *
5505132733Skanhandle_braces (const char *p)
5506132733Skan{
5507132733Skan  const char *atom, *end_atom;
5508132733Skan  const char *d_atom = NULL, *d_end_atom = NULL;
550990277Sobrien
5510132733Skan  bool a_is_suffix;
5511132733Skan  bool a_is_starred;
5512132733Skan  bool a_is_negated;
5513132733Skan  bool a_matched;
551450599Sobrien
5515132733Skan  bool a_must_be_last = false;
5516132733Skan  bool ordered_set    = false;
5517132733Skan  bool disjunct_set   = false;
5518132733Skan  bool disj_matched   = false;
5519132733Skan  bool disj_starred   = true;
5520132733Skan  bool n_way_choice   = false;
5521132733Skan  bool n_way_matched  = false;
552250599Sobrien
5523132733Skan#define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0)
5524132733Skan
5525132733Skan  do
552618334Speter    {
5527132733Skan      if (a_must_be_last)
5528132733Skan	abort ();
552950599Sobrien
5530132733Skan      /* Scan one "atom" (S in the description above of %{}, possibly
5531132733Skan	 with !, ., or * modifiers).  */
5532132733Skan      a_matched = a_is_suffix = a_is_starred = a_is_negated = false;
553390277Sobrien
5534132733Skan      SKIP_WHITE();
5535132733Skan      if (*p == '!')
5536132733Skan	p++, a_is_negated = true;
553718334Speter
5538132733Skan      SKIP_WHITE();
5539132733Skan      if (*p == '.')
5540132733Skan	p++, a_is_suffix = true;
554118334Speter
5542132733Skan      atom = p;
5543132733Skan      while (ISIDNUM(*p) || *p == '-' || *p == '+' || *p == '='
5544132733Skan	     || *p == ',' || *p == '.' || *p == '@')
5545132733Skan	p++;
5546132733Skan      end_atom = p;
554718334Speter
5548132733Skan      if (*p == '*')
5549132733Skan	p++, a_is_starred = 1;
555090277Sobrien
5551132733Skan      SKIP_WHITE();
5552132733Skan      if (*p == '&' || *p == '}')
5553132733Skan	{
5554132733Skan	  /* Substitute the switch(es) indicated by the current atom.  */
5555132733Skan	  ordered_set = true;
5556132733Skan	  if (disjunct_set || n_way_choice || a_is_negated || a_is_suffix
5557132733Skan	      || atom == end_atom)
5558132733Skan	    abort ();
555918334Speter
5560132733Skan	  mark_matching_switches (atom, end_atom, a_is_starred);
5561132733Skan
5562132733Skan	  if (*p == '}')
5563132733Skan	    process_marked_switches ();
5564132733Skan	}
5565132733Skan      else if (*p == '|' || *p == ':')
556618334Speter	{
5567132733Skan	  /* Substitute some text if the current atom appears as a switch
5568132733Skan	     or suffix.  */
5569132733Skan	  disjunct_set = true;
5570132733Skan	  if (ordered_set)
5571132733Skan	    abort ();
557218334Speter
5573132733Skan	  if (atom == end_atom)
557418334Speter	    {
5575132733Skan	      if (!n_way_choice || disj_matched || *p == '|'
5576132733Skan		  || a_is_negated || a_is_suffix || a_is_starred)
5577132733Skan		abort ();
5578132733Skan
5579132733Skan	      /* An empty term may appear as the last choice of an
5580132733Skan		 N-way choice set; it means "otherwise".  */
5581132733Skan	      a_must_be_last = true;
5582132733Skan	      disj_matched = !n_way_matched;
5583132733Skan	      disj_starred = false;
558418334Speter	    }
5585132733Skan	  else
558618334Speter	    {
5587132733Skan	       if (a_is_suffix && a_is_starred)
5588132733Skan		 abort ();
558918334Speter
5590132733Skan	       if (!a_is_starred)
5591132733Skan		 disj_starred = false;
559218334Speter
5593132733Skan	       /* Don't bother testing this atom if we already have a
5594132733Skan                  match.  */
5595132733Skan	       if (!disj_matched && !n_way_matched)
5596132733Skan		 {
5597132733Skan		   if (a_is_suffix)
5598132733Skan		     a_matched = input_suffix_matches (atom, end_atom);
5599132733Skan		   else
5600132733Skan		     a_matched = switch_matches (atom, end_atom, a_is_starred);
560118334Speter
5602132733Skan		   if (a_matched != a_is_negated)
5603132733Skan		     {
5604132733Skan		       disj_matched = true;
5605132733Skan		       d_atom = atom;
5606132733Skan		       d_end_atom = end_atom;
5607132733Skan		     }
5608132733Skan		 }
560918334Speter	    }
561018334Speter
5611132733Skan	  if (*p == ':')
561218334Speter	    {
5613132733Skan	      /* Found the body, that is, the text to substitute if the
5614132733Skan		 current disjunction matches.  */
5615132733Skan	      p = process_brace_body (p + 1, d_atom, d_end_atom, disj_starred,
5616132733Skan				      disj_matched && !n_way_matched);
5617132733Skan	      if (p == 0)
5618132733Skan		return 0;
561918334Speter
5620132733Skan	      /* If we have an N-way choice, reset state for the next
5621132733Skan		 disjunction.  */
5622132733Skan	      if (*p == ';')
562318334Speter		{
5624132733Skan		  n_way_choice = true;
5625132733Skan		  n_way_matched |= disj_matched;
5626132733Skan		  disj_matched = false;
5627132733Skan		  disj_starred = true;
5628132733Skan		  d_atom = d_end_atom = NULL;
562918334Speter		}
563018334Speter	    }
563118334Speter	}
563218334Speter      else
5633132733Skan	abort ();
5634132733Skan    }
5635132733Skan  while (*p++ != '}');
563618334Speter
5637132733Skan  return p;
5638132733Skan
5639132733Skan#undef SKIP_WHITE
5640132733Skan}
5641132733Skan
5642132733Skan/* Subroutine of handle_braces.  Scan and process a brace substitution body
5643132733Skan   (X in the description of %{} syntax).  P points one past the colon;
5644132733Skan   ATOM and END_ATOM bracket the first atom which was found to be true
5645132733Skan   (present) in the current disjunction; STARRED indicates whether all
5646132733Skan   the atoms in the current disjunction were starred (for syntax validation);
5647132733Skan   MATCHED indicates whether the disjunction matched or not, and therefore
5648132733Skan   whether or not the body is to be processed through do_spec_1 or just
5649132733Skan   skipped.  Returns a pointer to the closing } or ;, or 0 if do_spec_1
5650132733Skan   returns -1.  */
5651132733Skan
5652132733Skanstatic const char *
5653132733Skanprocess_brace_body (const char *p, const char *atom, const char *end_atom,
5654132733Skan		    int starred, int matched)
5655132733Skan{
5656132733Skan  const char *body, *end_body;
5657132733Skan  unsigned int nesting_level;
5658132733Skan  bool have_subst     = false;
5659132733Skan
5660132733Skan  /* Locate the closing } or ;, honoring nested braces.
5661132733Skan     Trim trailing whitespace.  */
5662132733Skan  body = p;
5663132733Skan  nesting_level = 1;
5664132733Skan  for (;;)
5665132733Skan    {
5666132733Skan      if (*p == '{')
5667132733Skan	nesting_level++;
5668132733Skan      else if (*p == '}')
566918334Speter	{
5670132733Skan	  if (!--nesting_level)
5671132733Skan	    break;
567218334Speter	}
5673132733Skan      else if (*p == ';' && nesting_level == 1)
5674132733Skan	break;
5675132733Skan      else if (*p == '%' && p[1] == '*' && nesting_level == 1)
5676132733Skan	have_subst = true;
5677132733Skan      else if (*p == '\0')
5678132733Skan	abort ();
5679132733Skan      p++;
568018334Speter    }
568118334Speter
5682132733Skan  end_body = p;
5683132733Skan  while (end_body[-1] == ' ' || end_body[-1] == '\t')
5684132733Skan    end_body--;
568550599Sobrien
5686132733Skan  if (have_subst && !starred)
5687132733Skan    abort ();
5688132733Skan
5689132733Skan  if (matched)
569090277Sobrien    {
5691132733Skan      /* Copy the substitution body to permanent storage and execute it.
5692132733Skan	 If have_subst is false, this is a simple matter of running the
5693132733Skan	 body through do_spec_1...  */
5694132733Skan      char *string = save_string (body, end_body - body);
5695132733Skan      if (!have_subst)
5696132733Skan	{
5697132733Skan	  if (do_spec_1 (string, 0, NULL) < 0)
5698132733Skan	    return 0;
5699132733Skan	}
5700132733Skan      else
5701132733Skan	{
5702132733Skan	  /* ... but if have_subst is true, we have to process the
5703132733Skan	     body once for each matching switch, with %* set to the
5704132733Skan	     variant part of the switch.  */
5705132733Skan	  unsigned int hard_match_len = end_atom - atom;
5706132733Skan	  int i;
570790277Sobrien
5708132733Skan	  for (i = 0; i < n_switches; i++)
5709132733Skan	    if (!strncmp (switches[i].part1, atom, hard_match_len)
5710132733Skan		&& check_live_switch (i, hard_match_len))
5711132733Skan	      {
5712132733Skan		if (do_spec_1 (string, 0,
5713132733Skan			       &switches[i].part1[hard_match_len]) < 0)
5714132733Skan		  return 0;
5715132733Skan		/* Pass any arguments this switch has.  */
5716132733Skan		give_switch (i, 1);
5717132733Skan		suffix_subst = NULL;
5718132733Skan	      }
5719132733Skan	}
572090277Sobrien    }
572190277Sobrien
5722132733Skan  return p;
572318334Speter}
572418334Speter
572518334Speter/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch
572618334Speter   on the command line.  PREFIX_LENGTH is the length of XXX in an {XXX*}
572718334Speter   spec, or -1 if either exact match or %* is used.
572818334Speter
572918334Speter   A -O switch is obsoleted by a later -O switch.  A -f, -m, or -W switch
573018334Speter   whose value does not begin with "no-" is obsoleted by the same value
573118334Speter   with the "no-", similarly for a switch with the "no-" prefix.  */
573218334Speter
573318334Speterstatic int
5734132733Skancheck_live_switch (int switchnum, int prefix_length)
573518334Speter{
573652520Sobrien  const char *name = switches[switchnum].part1;
573718334Speter  int i;
573818334Speter
573918334Speter  /* In the common case of {<at-most-one-letter>*}, a negating
574018334Speter     switch would always match, so ignore that case.  We will just
574118334Speter     send the conflicting switches to the compiler phase.  */
574218334Speter  if (prefix_length >= 0 && prefix_length <= 1)
574318334Speter    return 1;
574418334Speter
574518334Speter  /* If we already processed this switch and determined if it was
574618334Speter     live or not, return our past determination.  */
574718334Speter  if (switches[switchnum].live_cond != 0)
574818334Speter    return switches[switchnum].live_cond > 0;
574918334Speter
575018334Speter  /* Now search for duplicate in a manner that depends on the name.  */
575118334Speter  switch (*name)
575218334Speter    {
575318334Speter    case 'O':
575490277Sobrien      for (i = switchnum + 1; i < n_switches; i++)
575590277Sobrien	if (switches[i].part1[0] == 'O')
575690277Sobrien	  {
575790277Sobrien	    switches[switchnum].validated = 1;
575890277Sobrien	    switches[switchnum].live_cond = SWITCH_FALSE;
575990277Sobrien	    return 0;
576090277Sobrien	  }
576118334Speter      break;
576218334Speter
576318334Speter    case 'W':  case 'f':  case 'm':
576418334Speter      if (! strncmp (name + 1, "no-", 3))
576518334Speter	{
576650599Sobrien	  /* We have Xno-YYY, search for XYYY.  */
576718334Speter	  for (i = switchnum + 1; i < n_switches; i++)
576818334Speter	    if (switches[i].part1[0] == name[0]
576918334Speter		&& ! strcmp (&switches[i].part1[1], &name[4]))
577090277Sobrien	      {
577190277Sobrien		switches[switchnum].validated = 1;
577290277Sobrien		switches[switchnum].live_cond = SWITCH_FALSE;
577390277Sobrien		return 0;
577490277Sobrien	      }
577518334Speter	}
577618334Speter      else
577718334Speter	{
577818334Speter	  /* We have XYYY, search for Xno-YYY.  */
577918334Speter	  for (i = switchnum + 1; i < n_switches; i++)
578018334Speter	    if (switches[i].part1[0] == name[0]
578118334Speter		&& switches[i].part1[1] == 'n'
578218334Speter		&& switches[i].part1[2] == 'o'
578318334Speter		&& switches[i].part1[3] == '-'
578418334Speter		&& !strcmp (&switches[i].part1[4], &name[1]))
578590277Sobrien	      {
578690277Sobrien		switches[switchnum].validated = 1;
578790277Sobrien		switches[switchnum].live_cond = SWITCH_FALSE;
578890277Sobrien		return 0;
578990277Sobrien	      }
579018334Speter	}
579118334Speter      break;
579218334Speter    }
579318334Speter
579418334Speter  /* Otherwise the switch is live.  */
579590277Sobrien  switches[switchnum].live_cond = SWITCH_LIVE;
579618334Speter  return 1;
579718334Speter}
579818334Speter
579918334Speter/* Pass a switch to the current accumulating command
580018334Speter   in the same form that we received it.
580118334Speter   SWITCHNUM identifies the switch; it is an index into
580218334Speter   the vector of switches gcc received, which is `switches'.
580318334Speter   This cannot fail since it never finishes a command line.
580418334Speter
5805132733Skan   If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument.  */
580618334Speter
580718334Speterstatic void
5808132733Skangive_switch (int switchnum, int omit_first_word)
580918334Speter{
581090277Sobrien  if (switches[switchnum].live_cond == SWITCH_IGNORE)
581190277Sobrien    return;
581290277Sobrien
581318334Speter  if (!omit_first_word)
581418334Speter    {
581590277Sobrien      do_spec_1 ("-", 0, NULL);
581690277Sobrien      do_spec_1 (switches[switchnum].part1, 1, NULL);
581718334Speter    }
581850599Sobrien
581918334Speter  if (switches[switchnum].args != 0)
582018334Speter    {
582190277Sobrien      const char **p;
582218334Speter      for (p = switches[switchnum].args; *p; p++)
582318334Speter	{
582490277Sobrien	  const char *arg = *p;
582590277Sobrien
5826132733Skan	  do_spec_1 (" ", 0, NULL);
582790277Sobrien	  if (suffix_subst)
582890277Sobrien	    {
582990277Sobrien	      unsigned length = strlen (arg);
583090277Sobrien	      int dot = 0;
583190277Sobrien
583290277Sobrien	      while (length-- && !IS_DIR_SEPARATOR (arg[length]))
583390277Sobrien		if (arg[length] == '.')
583490277Sobrien		  {
583590277Sobrien		    ((char *)arg)[length] = 0;
583690277Sobrien		    dot = 1;
583790277Sobrien		    break;
583890277Sobrien		  }
583990277Sobrien	      do_spec_1 (arg, 1, NULL);
584090277Sobrien	      if (dot)
584190277Sobrien		((char *)arg)[length] = '.';
584290277Sobrien	      do_spec_1 (suffix_subst, 1, NULL);
584390277Sobrien	    }
584490277Sobrien	  else
584590277Sobrien	    do_spec_1 (arg, 1, NULL);
584618334Speter	}
584718334Speter    }
584850599Sobrien
584990277Sobrien  do_spec_1 (" ", 0, NULL);
585052520Sobrien  switches[switchnum].validated = 1;
585118334Speter}
585218334Speter
585318334Speter/* Search for a file named NAME trying various prefixes including the
585418334Speter   user's -B prefix and some standard ones.
585518334Speter   Return the absolute file name found.  If nothing is found, return NAME.  */
585618334Speter
585752520Sobrienstatic const char *
5858132733Skanfind_file (const char *name)
585918334Speter{
586018334Speter  char *newname;
586118334Speter
586218334Speter  /* Try multilib_dir if it is defined.  */
5863104763Skan  if (multilib_os_dir != NULL)
586418334Speter    {
5865104763Skan      newname = find_a_file (&startfile_prefixes, name, R_OK, 1);
586618334Speter
586718334Speter      /* If we don't find it in the multi library dir, then fall
586818334Speter	 through and look for it in the normal places.  */
586918334Speter      if (newname != NULL)
587018334Speter	return newname;
587118334Speter    }
587218334Speter
5873104763Skan  newname = find_a_file (&startfile_prefixes, name, R_OK, 0);
587418334Speter  return newname ? newname : name;
587518334Speter}
587618334Speter
587718334Speter/* Determine whether a directory exists.  If LINKER, return 0 for
587818334Speter   certain fixed names not needed by the linker.  If not LINKER, it is
587918334Speter   only important to return 0 if the host machine has a small ARG_MAX
588018334Speter   limit.  */
588118334Speter
588218334Speterstatic int
5883132733Skanis_directory (const char *path1, const char *path2, int linker)
588418334Speter{
588518334Speter  int len1 = strlen (path1);
588618334Speter  int len2 = strlen (path2);
5887132733Skan  char *path = alloca (3 + len1 + len2);
588818334Speter  char *cp;
588918334Speter  struct stat st;
589018334Speter
589118334Speter#ifndef SMALL_ARG_MAX
589218334Speter  if (! linker)
589318334Speter    return 1;
589418334Speter#endif
589518334Speter
589618334Speter  /* Construct the path from the two parts.  Ensure the string ends with "/.".
589718334Speter     The resulting path will be a directory even if the given path is a
589818334Speter     symbolic link.  */
589952520Sobrien  memcpy (path, path1, len1);
590052520Sobrien  memcpy (path + len1, path2, len2);
590118334Speter  cp = path + len1 + len2;
590252520Sobrien  if (!IS_DIR_SEPARATOR (cp[-1]))
590318334Speter    *cp++ = DIR_SEPARATOR;
590418334Speter  *cp++ = '.';
590518334Speter  *cp = '\0';
590618334Speter
590751232Sbde#ifndef FREEBSD_NATIVE
590818334Speter  /* Exclude directories that the linker is known to search.  */
590918334Speter  if (linker
591018334Speter      && ((cp - path == 6
591190277Sobrien	   && strcmp (path, concat (dir_separator_str, "lib",
591290277Sobrien				    dir_separator_str, ".", NULL)) == 0)
591318334Speter	  || (cp - path == 10
591490277Sobrien	      && strcmp (path, concat (dir_separator_str, "usr",
591590277Sobrien				       dir_separator_str, "lib",
591690277Sobrien				       dir_separator_str, ".", NULL)) == 0)))
591718334Speter    return 0;
591851232Sbde#endif /* FREEBSD_NATIVE */
591918334Speter
592018334Speter  return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
592118334Speter}
592290277Sobrien
592390277Sobrien/* Set up the various global variables to indicate that we're processing
592490277Sobrien   the input file named FILENAME.  */
592590277Sobrien
592690277Sobrienvoid
5927132733Skanset_input (const char *filename)
592890277Sobrien{
592990277Sobrien  const char *p;
593090277Sobrien
593190277Sobrien  input_filename = filename;
593290277Sobrien  input_filename_length = strlen (input_filename);
593390277Sobrien
593490277Sobrien  input_basename = input_filename;
593590277Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM
593690277Sobrien  /* Skip drive name so 'x:foo' is handled properly.  */
593790277Sobrien  if (input_basename[1] == ':')
593890277Sobrien    input_basename += 2;
593990277Sobrien#endif
594090277Sobrien  for (p = input_basename; *p; p++)
594190277Sobrien    if (IS_DIR_SEPARATOR (*p))
594290277Sobrien      input_basename = p + 1;
594390277Sobrien
594490277Sobrien  /* Find a suffix starting with the last period,
594590277Sobrien     and set basename_length to exclude that suffix.  */
594690277Sobrien  basename_length = strlen (input_basename);
594790277Sobrien  suffixed_basename_length = basename_length;
594890277Sobrien  p = input_basename + basename_length;
594990277Sobrien  while (p != input_basename && *p != '.')
595090277Sobrien    --p;
595190277Sobrien  if (*p == '.' && p != input_basename)
595290277Sobrien    {
595390277Sobrien      basename_length = p - input_basename;
595490277Sobrien      input_suffix = p + 1;
595590277Sobrien    }
595690277Sobrien  else
595790277Sobrien    input_suffix = "";
5958117413Skan
595990277Sobrien  /* If a spec for 'g', 'u', or 'U' is seen with -save-temps then
596090277Sobrien     we will need to do a stat on the input_filename.  The
596190277Sobrien     INPUT_STAT_SET signals that the stat is needed.  */
596290277Sobrien  input_stat_set = 0;
596390277Sobrien}
596418334Speter
596518334Speter/* On fatal signals, delete all the temporary files.  */
596618334Speter
596718334Speterstatic void
5968132733Skanfatal_error (int signum)
596918334Speter{
597018334Speter  signal (signum, SIG_DFL);
597118334Speter  delete_failure_queue ();
597218334Speter  delete_temp_files ();
597318334Speter  /* Get the same signal again, this time not handled,
597418334Speter     so its normal effect occurs.  */
597518334Speter  kill (getpid (), signum);
597618334Speter}
597718334Speter
5978132733Skanextern int main (int, const char **);
597990277Sobrien
598018334Speterint
5981132733Skanmain (int argc, const char **argv)
598218334Speter{
598390277Sobrien  size_t i;
598418334Speter  int value;
598518334Speter  int linker_was_run = 0;
5986132733Skan  int num_linker_inputs = 0;
598718334Speter  char *explicit_link_files;
598818334Speter  char *specs_file;
598952520Sobrien  const char *p;
599050599Sobrien  struct user_specs *uptr;
599118334Speter
599218334Speter  p = argv[0] + strlen (argv[0]);
599352520Sobrien  while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
599452520Sobrien    --p;
599518334Speter  programname = p;
599618334Speter
599790277Sobrien  xmalloc_set_program_name (programname);
599890277Sobrien
599990277Sobrien#ifdef GCC_DRIVER_HOST_INITIALIZATION
600090277Sobrien  /* Perform host dependent initialization when needed.  */
600190277Sobrien  GCC_DRIVER_HOST_INITIALIZATION;
600252520Sobrien#endif
600352520Sobrien
600490277Sobrien  gcc_init_libintl ();
600590277Sobrien
600618334Speter  if (signal (SIGINT, SIG_IGN) != SIG_IGN)
600718334Speter    signal (SIGINT, fatal_error);
600818334Speter#ifdef SIGHUP
600918334Speter  if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
601018334Speter    signal (SIGHUP, fatal_error);
601118334Speter#endif
601218334Speter  if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
601318334Speter    signal (SIGTERM, fatal_error);
601418334Speter#ifdef SIGPIPE
601518334Speter  if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
601618334Speter    signal (SIGPIPE, fatal_error);
601718334Speter#endif
601890277Sobrien#ifdef SIGCHLD
601990277Sobrien  /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
602090277Sobrien     receive the signal.  A different setting is inheritable */
602190277Sobrien  signal (SIGCHLD, SIG_DFL);
602290277Sobrien#endif
602318334Speter
6024117413Skan  /* Allocate the argument vector.  */
6025117413Skan  alloc_args ();
602618334Speter
602718334Speter  obstack_init (&obstack);
602818334Speter
602950599Sobrien  /* Build multilib_select, et. al from the separate lines that make up each
603050599Sobrien     multilib selection.  */
603150599Sobrien  {
603290277Sobrien    const char *const *q = multilib_raw;
603350599Sobrien    int need_space;
603450599Sobrien
603550599Sobrien    obstack_init (&multilib_obstack);
603650599Sobrien    while ((p = *q++) != (char *) 0)
603750599Sobrien      obstack_grow (&multilib_obstack, p, strlen (p));
603850599Sobrien
603950599Sobrien    obstack_1grow (&multilib_obstack, 0);
604050599Sobrien    multilib_select = obstack_finish (&multilib_obstack);
604150599Sobrien
604250599Sobrien    q = multilib_matches_raw;
604350599Sobrien    while ((p = *q++) != (char *) 0)
604450599Sobrien      obstack_grow (&multilib_obstack, p, strlen (p));
604550599Sobrien
604650599Sobrien    obstack_1grow (&multilib_obstack, 0);
604750599Sobrien    multilib_matches = obstack_finish (&multilib_obstack);
604850599Sobrien
604990277Sobrien    q = multilib_exclusions_raw;
605090277Sobrien    while ((p = *q++) != (char *) 0)
605190277Sobrien      obstack_grow (&multilib_obstack, p, strlen (p));
605290277Sobrien
605390277Sobrien    obstack_1grow (&multilib_obstack, 0);
605490277Sobrien    multilib_exclusions = obstack_finish (&multilib_obstack);
605590277Sobrien
605650599Sobrien    need_space = FALSE;
605790277Sobrien    for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++)
605850599Sobrien      {
605950599Sobrien	if (need_space)
606050599Sobrien	  obstack_1grow (&multilib_obstack, ' ');
606150599Sobrien	obstack_grow (&multilib_obstack,
606250599Sobrien		      multilib_defaults_raw[i],
606350599Sobrien		      strlen (multilib_defaults_raw[i]));
606450599Sobrien	need_space = TRUE;
606550599Sobrien      }
606650599Sobrien
606750599Sobrien    obstack_1grow (&multilib_obstack, 0);
606850599Sobrien    multilib_defaults = obstack_finish (&multilib_obstack);
606950599Sobrien  }
607050599Sobrien
607118334Speter  /* Set up to remember the pathname of gcc and any options
607218334Speter     needed for collect.  We use argv[0] instead of programname because
607318334Speter     we need the complete pathname.  */
607418334Speter  obstack_init (&collect_obstack);
607590277Sobrien  obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1);
607690277Sobrien  obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1);
607718334Speter  putenv (obstack_finish (&collect_obstack));
607818334Speter
607918334Speter#ifdef INIT_ENVIRONMENT
608018334Speter  /* Set up any other necessary machine specific environment variables.  */
608118334Speter  putenv (INIT_ENVIRONMENT);
608218334Speter#endif
608318334Speter
608418334Speter  /* Make a table of what switches there are (switches, n_switches).
608518334Speter     Make a table of specified input files (infiles, n_infiles).
608618334Speter     Decode switches that are handled locally.  */
608718334Speter
608818334Speter  process_command (argc, argv);
608918334Speter
609018334Speter  /* Initialize the vector of specs to just the default.
609118334Speter     This means one element containing 0s, as a terminator.  */
609218334Speter
6093132733Skan  compilers = xmalloc (sizeof default_compilers);
6094132733Skan  memcpy (compilers, default_compilers, sizeof default_compilers);
609518334Speter  n_compilers = n_default_compilers;
609618334Speter
609718334Speter  /* Read specs from a file if there is one.  */
609818334Speter
609991561Sobrien#ifdef FREEBSD_NATIVE
610091561Sobrien  just_machine_suffix = "";
610191561Sobrien#else	/* FREEBSD_NATIVE */
610250599Sobrien  machine_suffix = concat (spec_machine, dir_separator_str,
610390277Sobrien			   spec_version, dir_separator_str, NULL);
610490277Sobrien  just_machine_suffix = concat (spec_machine, dir_separator_str, NULL);
610550599Sobrien#endif /* FREEBSD_NATIVE */
610618334Speter
6107104763Skan  specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, 0);
610818334Speter  /* Read the specs file unless it is a default one.  */
610918334Speter  if (specs_file != 0 && strcmp (specs_file, "specs"))
611050599Sobrien    read_specs (specs_file, TRUE);
611150599Sobrien  else
611250599Sobrien    init_spec ();
611318334Speter
611450599Sobrien  /* We need to check standard_exec_prefix/just_machine_suffix/specs
611590277Sobrien     for any override of as, ld and libraries.  */
611697902Sobrien  specs_file = (char *) alloca (strlen (FBSD_DATA_PREFIX)
611750599Sobrien				+ strlen (just_machine_suffix)
611850599Sobrien				+ sizeof ("specs"));
611950599Sobrien
612097902Sobrien  strcpy (specs_file, FBSD_DATA_PREFIX);
612150599Sobrien  strcat (specs_file, just_machine_suffix);
612250599Sobrien  strcat (specs_file, "specs");
612350599Sobrien  if (access (specs_file, R_OK) == 0)
612450599Sobrien    read_specs (specs_file, TRUE);
612590277Sobrien
6126132733Skan  /* Process any configure-time defaults specified for the command line
6127132733Skan     options, via OPTION_DEFAULT_SPECS.  */
6128132733Skan  for (i = 0; i < ARRAY_SIZE (option_default_specs); i++)
6129132733Skan    do_option_spec (option_default_specs[i].name,
6130132733Skan		    option_default_specs[i].spec);
6131132733Skan
6132132733Skan  /* Process DRIVER_SELF_SPECS, adding any new options to the end
6133132733Skan     of the command line.  */
6134132733Skan
6135132733Skan  for (i = 0; i < ARRAY_SIZE (driver_self_specs); i++)
6136132733Skan    do_self_spec (driver_self_specs[i]);
6137132733Skan
6138132733Skan  /* If not cross-compiling, look for executables in the standard
6139132733Skan     places.  */
6140132733Skan  if (*cross_compile == '0')
614118334Speter    {
614290277Sobrien      if (*md_exec_prefix)
614390277Sobrien	{
614490277Sobrien	  add_prefix (&exec_prefixes, md_exec_prefix, "GCC",
6145104763Skan		      PREFIX_PRIORITY_LAST, 0, NULL, 0);
614690277Sobrien	}
6147132733Skan    }
614818334Speter
6149132733Skan  /* Process sysroot_suffix_spec.  */
6150132733Skan  if (*sysroot_suffix_spec != 0
6151132733Skan      && do_spec_2 (sysroot_suffix_spec) == 0)
6152132733Skan    {
6153132733Skan      if (argbuf_index > 1)
6154132733Skan        error ("spec failure: more than one arg to SYSROOT_SUFFIX_SPEC.");
6155132733Skan      else if (argbuf_index == 1)
6156132733Skan        target_sysroot_suffix = xstrdup (argbuf[argbuf_index -1]);
6157132733Skan    }
6158132733Skan
6159132733Skan  /* Process sysroot_hdrs_suffix_spec.  */
6160132733Skan  if (*sysroot_hdrs_suffix_spec != 0
6161132733Skan      && do_spec_2 (sysroot_hdrs_suffix_spec) == 0)
6162132733Skan    {
6163132733Skan      if (argbuf_index > 1)
6164132733Skan        error ("spec failure: more than one arg to SYSROOT_HEADERS_SUFFIX_SPEC.");
6165132733Skan      else if (argbuf_index == 1)
6166132733Skan        target_sysroot_hdrs_suffix = xstrdup (argbuf[argbuf_index -1]);
6167132733Skan    }
6168132733Skan
6169132733Skan  /* Look for startfiles in the standard places.  */
6170132733Skan  if (*startfile_prefix_spec != 0
6171132733Skan      && do_spec_2 (startfile_prefix_spec) == 0
6172132733Skan      && do_spec_1 (" ", 0, NULL) == 0)
6173132733Skan    {
6174132733Skan      int ndx;
6175132733Skan      for (ndx = 0; ndx < argbuf_index; ndx++)
6176132733Skan	add_sysrooted_prefix (&startfile_prefixes, argbuf[ndx], "BINUTILS",
6177132733Skan			      PREFIX_PRIORITY_LAST, 0, NULL, 1);
6178132733Skan    }
6179132733Skan  /* We should eventually get rid of all these and stick to
6180132733Skan     startfile_prefix_spec exclusively.  */
6181132733Skan  else if (*cross_compile == '0' || target_system_root)
6182132733Skan    {
6183132733Skan      if (*md_exec_prefix)
6184132733Skan	add_sysrooted_prefix (&startfile_prefixes, md_exec_prefix, "GCC",
6185132733Skan			      PREFIX_PRIORITY_LAST, 0, NULL, 1);
6186132733Skan
618790277Sobrien      if (*md_startfile_prefix)
6188132733Skan	add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix,
6189132733Skan			      "GCC", PREFIX_PRIORITY_LAST, 0, NULL, 1);
619018334Speter
619190277Sobrien      if (*md_startfile_prefix_1)
6192132733Skan	add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix_1,
6193132733Skan			      "GCC", PREFIX_PRIORITY_LAST, 0, NULL, 1);
619418334Speter
619518334Speter      /* If standard_startfile_prefix is relative, base it on
619618334Speter	 standard_exec_prefix.  This lets us move the installed tree
619718334Speter	 as a unit.  If GCC_EXEC_PREFIX is defined, base
6198132733Skan	 standard_startfile_prefix on that as well.
6199132733Skan
6200132733Skan         If the prefix is relative, only search it for native compilers;
6201132733Skan         otherwise we will search a directory containing host libraries.  */
6202132733Skan      if (IS_ABSOLUTE_PATH (standard_startfile_prefix))
6203132733Skan	add_sysrooted_prefix (&startfile_prefixes,
6204132733Skan			      standard_startfile_prefix, "BINUTILS",
6205132733Skan			      PREFIX_PRIORITY_LAST, 0, NULL, 1);
6206132733Skan      else if (*cross_compile == '0')
620718334Speter	{
620818334Speter	  if (gcc_exec_prefix)
620918334Speter	    add_prefix (&startfile_prefixes,
621050599Sobrien			concat (gcc_exec_prefix, machine_suffix,
621190277Sobrien				standard_startfile_prefix, NULL),
6212104763Skan			NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1);
621318334Speter	  add_prefix (&startfile_prefixes,
621450599Sobrien		      concat (standard_exec_prefix,
621550599Sobrien			      machine_suffix,
621690277Sobrien			      standard_startfile_prefix, NULL),
6217104763Skan		      NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1);
621890277Sobrien	}
621918334Speter
622018346Speter#ifndef FREEBSD_NATIVE
6221132733Skan      add_sysrooted_prefix (&startfile_prefixes, standard_startfile_prefix_1,
6222132733Skan			    "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1);
6223132733Skan      add_sysrooted_prefix (&startfile_prefixes, standard_startfile_prefix_2,
6224132733Skan			    "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1);
622591561Sobrien#endif	/* not FREEBSD_NATIVE */
622618334Speter#if 0 /* Can cause surprises, and one can use -B./ instead.  */
622790277Sobrien      add_prefix (&startfile_prefixes, "./", NULL,
6228104763Skan		  PREFIX_PRIORITY_LAST, 1, NULL, 0);
622918334Speter#endif
623018334Speter    }
623118334Speter
623252520Sobrien  /* Process any user specified specs in the order given on the command
623352520Sobrien     line.  */
623452520Sobrien  for (uptr = user_specs_head; uptr; uptr = uptr->next)
623552520Sobrien    {
6236104763Skan      char *filename = find_a_file (&startfile_prefixes, uptr->filename,
6237104763Skan				    R_OK, 0);
623852520Sobrien      read_specs (filename ? filename : uptr->filename, FALSE);
623952520Sobrien    }
624052520Sobrien
624118334Speter  /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake.  */
624218334Speter  if (gcc_exec_prefix)
624390277Sobrien    gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
624490277Sobrien			      spec_version, dir_separator_str, NULL);
624518334Speter
624618334Speter  /* Now we have the specs.
624718334Speter     Set the `valid' bits for switches that match anything in any spec.  */
624818334Speter
624918334Speter  validate_all_switches ();
625018334Speter
625118334Speter  /* Now that we have the switches and the specs, set
625218334Speter     the subdirectory based on the options.  */
625318334Speter  set_multilib_dir ();
625418334Speter
625518334Speter  /* Warn about any switches that no pass was interested in.  */
625618334Speter
625790277Sobrien  for (i = 0; (int) i < n_switches; i++)
625852520Sobrien    if (! switches[i].validated)
625918334Speter      error ("unrecognized option `-%s'", switches[i].part1);
626018334Speter
626118334Speter  /* Obey some of the options.  */
626218334Speter
626318334Speter  if (print_search_dirs)
626418334Speter    {
626590277Sobrien      printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix);
626690277Sobrien      printf (_("programs: %s\n"), build_search_list (&exec_prefixes, "", 0));
626790277Sobrien      printf (_("libraries: %s\n"), build_search_list (&startfile_prefixes, "", 0));
626890277Sobrien      return (0);
626918334Speter    }
627018334Speter
627118334Speter  if (print_file_name)
627218334Speter    {
627318334Speter      printf ("%s\n", find_file (print_file_name));
627490277Sobrien      return (0);
627518334Speter    }
627618334Speter
627718334Speter  if (print_prog_name)
627818334Speter    {
6279104763Skan      char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK, 0);
628018334Speter      printf ("%s\n", (newname ? newname : print_prog_name));
628190277Sobrien      return (0);
628218334Speter    }
628318334Speter
628418334Speter  if (print_multi_lib)
628518334Speter    {
628618334Speter      print_multilib_info ();
628790277Sobrien      return (0);
628818334Speter    }
628918334Speter
629018334Speter  if (print_multi_directory)
629118334Speter    {
629218334Speter      if (multilib_dir == NULL)
629318334Speter	printf (".\n");
629418334Speter      else
629518334Speter	printf ("%s\n", multilib_dir);
629690277Sobrien      return (0);
629718334Speter    }
629818334Speter
6299104763Skan  if (print_multi_os_directory)
6300104763Skan    {
6301104763Skan      if (multilib_os_dir == NULL)
6302104763Skan	printf (".\n");
6303104763Skan      else
6304104763Skan	printf ("%s\n", multilib_os_dir);
6305104763Skan      return (0);
6306104763Skan    }
6307104763Skan
630890277Sobrien  if (target_help_flag)
630990277Sobrien   {
631090277Sobrien      /* Print if any target specific options.  */
631190277Sobrien
631290277Sobrien      /* We do not exit here. Instead we have created a fake input file
631390277Sobrien         called 'target-dummy' which needs to be compiled, and we pass this
631490277Sobrien         on to the various sub-processes, along with the --target-help
631590277Sobrien         switch.  */
631690277Sobrien    }
631790277Sobrien
631850599Sobrien  if (print_help_list)
631950599Sobrien    {
632050599Sobrien      display_help ();
632150599Sobrien
632250599Sobrien      if (! verbose_flag)
632350599Sobrien	{
632490277Sobrien	  printf (_("\nFor bug reporting instructions, please see:\n"));
6325117413Skan	  printf ("%s.\n", bug_report_url);
632690277Sobrien
632790277Sobrien	  return (0);
632850599Sobrien	}
632950599Sobrien
633050599Sobrien      /* We do not exit here.  Instead we have created a fake input file
633150599Sobrien	 called 'help-dummy' which needs to be compiled, and we pass this
633290277Sobrien	 on the various sub-processes, along with the --help switch.  */
633350599Sobrien    }
633490277Sobrien
633518334Speter  if (verbose_flag)
633618334Speter    {
633750599Sobrien      int n;
633890277Sobrien      const char *thrmod;
633950599Sobrien
634090277Sobrien      notice ("Configured with: %s\n", configuration_arguments);
634190277Sobrien
634290277Sobrien#ifdef THREAD_MODEL_SPEC
634390277Sobrien      /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
634490277Sobrien	 but there's no point in doing all this processing just to get
634590277Sobrien	 thread_model back.  */
634690277Sobrien      obstack_init (&obstack);
634790277Sobrien      do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
634890277Sobrien      obstack_1grow (&obstack, '\0');
634990277Sobrien      thrmod = obstack_finish (&obstack);
635090277Sobrien#else
635190277Sobrien      thrmod = thread_model;
635290277Sobrien#endif
635390277Sobrien
635490277Sobrien      notice ("Thread model: %s\n", thrmod);
635590277Sobrien
635650599Sobrien      /* compiler_version is truncated at the first space when initialized
635750599Sobrien	 from version string, so truncate version_string at the first space
635850599Sobrien	 before comparing.  */
635950599Sobrien      for (n = 0; version_string[n]; n++)
636050599Sobrien	if (version_string[n] == ' ')
636150599Sobrien	  break;
636250599Sobrien
636350599Sobrien      if (! strncmp (version_string, compiler_version, n)
636450599Sobrien	  && compiler_version[n] == 0)
636552520Sobrien	notice ("gcc version %s\n", version_string);
636618334Speter      else
636752520Sobrien	notice ("gcc driver version %s executing gcc version %s\n",
636852520Sobrien		version_string, compiler_version);
636918334Speter
637018334Speter      if (n_infiles == 0)
637190277Sobrien	return (0);
637218334Speter    }
637318334Speter
637450599Sobrien  if (n_infiles == added_libraries)
637518346Speter    fatal ("No input files specified");
637618334Speter
637718334Speter  /* Make a place to record the compiler output file names
637818334Speter     that correspond to the input files.  */
637918334Speter
638050599Sobrien  i = n_infiles;
638150599Sobrien  i += lang_specific_extra_outfiles;
6382132733Skan  outfiles = xcalloc (i, sizeof (char *));
638318334Speter
638418334Speter  /* Record which files were specified explicitly as link input.  */
638518334Speter
638690277Sobrien  explicit_link_files = xcalloc (1, n_infiles);
638718334Speter
6388132733Skan  if (combine_inputs)
638918334Speter    {
6390132733Skan       int lang_n_infiles = 0;
6391132733Skan       for (i = 0; (int) i < n_infiles; i++)
6392132733Skan	 {
6393132733Skan	   const char *name = infiles[i].name;
6394132733Skan	   struct compiler *compiler
6395132733Skan	     = lookup_compiler (name, strlen (name), infiles[i].language);
6396132733Skan	   if (compiler == NULL)
6397132733Skan	     error ("%s: linker input file unused because linking not done",
6398132733Skan		    name);
6399132733Skan	   else if (lang_n_infiles > 0 && compiler != input_file_compiler)
6400132733Skan	     fatal ("cannot specify -o with -c or -S and multiple languages");
6401132733Skan	   else
6402132733Skan	     {
6403132733Skan	       lang_n_infiles++;
6404132733Skan	       input_file_compiler = compiler;
6405132733Skan	     }
6406132733Skan	 }
6407132733Skan    }
6408132733Skan
6409132733Skan  for (i = 0; (int) i < (combine_inputs ? 1 : n_infiles); i++)
6410132733Skan    {
641118334Speter      int this_file_error = 0;
641218334Speter
641318334Speter      /* Tell do_spec what to substitute for %i.  */
641418334Speter
641518334Speter      input_file_number = i;
641690277Sobrien      set_input (infiles[i].name);
641718334Speter
641818334Speter      /* Use the same thing in %o, unless cp->spec says otherwise.  */
641918334Speter
642018334Speter      outfiles[i] = input_filename;
642118334Speter
642218334Speter      /* Figure out which compiler from the file's suffix.  */
642318334Speter
6424132733Skan      if (! combine_inputs)
6425132733Skan	input_file_compiler
6426132733Skan	  = lookup_compiler (infiles[i].name, input_filename_length,
6427132733Skan			     infiles[i].language);
6428117413Skan
642990277Sobrien      if (input_file_compiler)
643018334Speter	{
643118334Speter	  /* Ok, we found an applicable compiler.  Run its spec.  */
643218334Speter
643390277Sobrien	  if (input_file_compiler->spec[0] == '#')
643418334Speter	    {
643590277Sobrien	      error ("%s: %s compiler not installed on this system",
643690277Sobrien		     input_filename, &input_file_compiler->spec[1]);
643790277Sobrien	      this_file_error = 1;
643818334Speter	    }
643918334Speter	  else
644090277Sobrien	    {
644190277Sobrien	      value = do_spec (input_file_compiler->spec);
644290277Sobrien	      if (value < 0)
644390277Sobrien		this_file_error = 1;
644490277Sobrien	    }
644518334Speter	}
644618334Speter
644718334Speter      /* If this file's name does not contain a recognized suffix,
644818334Speter	 record it as explicit linker input.  */
644918334Speter
645018334Speter      else
645118334Speter	explicit_link_files[i] = 1;
645218334Speter
645318334Speter      /* Clear the delete-on-failure queue, deleting the files in it
645418334Speter	 if this compilation failed.  */
645518334Speter
645618334Speter      if (this_file_error)
645718334Speter	{
645818334Speter	  delete_failure_queue ();
645918334Speter	  error_count++;
646018334Speter	}
646118334Speter      /* If this compilation succeeded, don't delete those files later.  */
646218334Speter      clear_failure_queue ();
646318334Speter    }
646418334Speter
646590277Sobrien  /* Reset the output file name to the first input file name, for use
646690277Sobrien     with %b in LINK_SPEC on a target that prefers not to emit a.out
646790277Sobrien     by default.  */
646890277Sobrien  if (n_infiles > 0)
646990277Sobrien    set_input (infiles[0].name);
647090277Sobrien
647152520Sobrien  if (error_count == 0)
647252520Sobrien    {
647352520Sobrien      /* Make sure INPUT_FILE_NUMBER points to first available open
647452520Sobrien	 slot.  */
647552520Sobrien      input_file_number = n_infiles;
647652520Sobrien      if (lang_specific_pre_link ())
647752520Sobrien	error_count++;
647852520Sobrien    }
647950599Sobrien
6480132733Skan  /* Determine if there are any linker input files.  */
6481132733Skan  num_linker_inputs = 0;
6482132733Skan  for (i = 0; (int) i < n_infiles; i++)
6483132733Skan    if (explicit_link_files[i] || outfiles[i] != NULL)
6484132733Skan      num_linker_inputs++;
6485132733Skan
648618334Speter  /* Run ld to link all the compiler output files.  */
648718334Speter
6488132733Skan  if (num_linker_inputs > 0 && error_count == 0)
648918334Speter    {
649018334Speter      int tmp = execution_count;
649118334Speter
649290277Sobrien      /* We'll use ld if we can't find collect2.  */
649350599Sobrien      if (! strcmp (linker_name_spec, "collect2"))
649450599Sobrien	{
6495104763Skan	  char *s = find_a_file (&exec_prefixes, "collect2", X_OK, 0);
649650599Sobrien	  if (s == NULL)
649750599Sobrien	    linker_name_spec = "ld";
649850599Sobrien	}
649918334Speter      /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
650018334Speter	 for collect.  */
650190277Sobrien      putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH");
650290277Sobrien      putenv_from_prefixes (&startfile_prefixes, LIBRARY_PATH_ENV);
650318334Speter
650418334Speter      value = do_spec (link_command_spec);
650518334Speter      if (value < 0)
650618334Speter	error_count = 1;
650718334Speter      linker_was_run = (tmp != execution_count);
650818334Speter    }
650918334Speter
651018334Speter  /* If options said don't run linker,
651118334Speter     complain about input files to be given to the linker.  */
651218334Speter
651318334Speter  if (! linker_was_run && error_count == 0)
651490277Sobrien    for (i = 0; (int) i < n_infiles; i++)
651518334Speter      if (explicit_link_files[i])
651690277Sobrien	error ("%s: linker input file unused because linking not done",
651718334Speter	       outfiles[i]);
651818334Speter
651918334Speter  /* Delete some or all of the temporary files we made.  */
652018334Speter
652118334Speter  if (error_count)
652218334Speter    delete_failure_queue ();
652318334Speter  delete_temp_files ();
652418334Speter
652550599Sobrien  if (print_help_list)
652650599Sobrien    {
652790277Sobrien      printf (("\nFor bug reporting instructions, please see:\n"));
6528117413Skan      printf ("%s\n", bug_report_url);
652950599Sobrien    }
653090277Sobrien
653190277Sobrien  return (signal_count != 0 ? 2
653290277Sobrien	  : error_count > 0 ? (pass_exit_codes ? greatest_status : 1)
653390277Sobrien	  : 0);
653418334Speter}
653518334Speter
653618334Speter/* Find the proper compilation spec for the file name NAME,
653718334Speter   whose length is LENGTH.  LANGUAGE is the specified language,
653850599Sobrien   or 0 if this file is to be passed to the linker.  */
653918334Speter
654018334Speterstatic struct compiler *
6541132733Skanlookup_compiler (const char *name, size_t length, const char *language)
654218334Speter{
654318334Speter  struct compiler *cp;
654418334Speter
654590277Sobrien  /* If this was specified by the user to be a linker input, indicate that.  */
654650599Sobrien  if (language != 0 && language[0] == '*')
654750599Sobrien    return 0;
654850599Sobrien
654950599Sobrien  /* Otherwise, look for the language, if one is spec'd.  */
655018334Speter  if (language != 0)
655118334Speter    {
655218334Speter      for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
655350599Sobrien	if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language))
655450599Sobrien	  return cp;
655550599Sobrien
655618334Speter      error ("language %s not recognized", language);
655750599Sobrien      return 0;
655818334Speter    }
655918334Speter
656018334Speter  /* Look for a suffix.  */
656118334Speter  for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
656218334Speter    {
656318334Speter      if (/* The suffix `-' matches only the file name `-'.  */
656418334Speter	  (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
656550599Sobrien	  || (strlen (cp->suffix) < length
656650599Sobrien	      /* See if the suffix matches the end of NAME.  */
656750599Sobrien	      && !strcmp (cp->suffix,
656850599Sobrien			  name + length - strlen (cp->suffix))
656950599Sobrien	 ))
6570117413Skan	break;
657190277Sobrien    }
657250599Sobrien
657390277Sobrien#if defined (OS2) ||defined (HAVE_DOS_BASED_FILE_SYSTEM)
657490277Sobrien  /* look again, but case-insensitively this time.  */
657590277Sobrien  if (cp < compilers)
657690277Sobrien    for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
657790277Sobrien      {
657890277Sobrien	if (/* The suffix `-' matches only the file name `-'.  */
657990277Sobrien	    (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
658090277Sobrien	    || (strlen (cp->suffix) < length
658190277Sobrien		/* See if the suffix matches the end of NAME.  */
658290277Sobrien		&& ((!strcmp (cp->suffix,
658390277Sobrien			     name + length - strlen (cp->suffix))
658490277Sobrien		     || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
658590277Sobrien		    && !strcasecmp (cp->suffix,
658690277Sobrien				    name + length - strlen (cp->suffix)))
658790277Sobrien	   ))
658890277Sobrien	  break;
658990277Sobrien      }
659090277Sobrien#endif
659150599Sobrien
659290277Sobrien  if (cp >= compilers)
659390277Sobrien    {
659490277Sobrien      if (cp->spec[0] != '@')
659590277Sobrien	/* A non-alias entry: return it.  */
659690277Sobrien	return cp;
659790277Sobrien
659890277Sobrien      /* An alias entry maps a suffix to a language.
659990277Sobrien	 Search for the language; pass 0 for NAME and LENGTH
660090277Sobrien	 to avoid infinite recursion if language not found.  */
660190277Sobrien      return lookup_compiler (NULL, 0, cp->spec + 1);
660218334Speter    }
660318334Speter  return 0;
660418334Speter}
660518334Speter
660618334Speterstatic char *
6607132733Skansave_string (const char *s, int len)
660818334Speter{
660990277Sobrien  char *result = xmalloc (len + 1);
661018334Speter
661190277Sobrien  memcpy (result, s, len);
661218334Speter  result[len] = 0;
661318334Speter  return result;
661418334Speter}
661518334Speter
661690277Sobrienvoid
6617132733Skanpfatal_with_name (const char *name)
661818334Speter{
661952520Sobrien  perror_with_name (name);
662052520Sobrien  delete_temp_files ();
662152520Sobrien  exit (1);
662218334Speter}
662318334Speter
662418334Speterstatic void
6625132733Skanperror_with_name (const char *name)
662618334Speter{
662752520Sobrien  error ("%s: %s", name, xstrerror (errno));
662818334Speter}
662918334Speter
663018334Speterstatic void
6631132733Skanpfatal_pexecute (const char *errmsg_fmt, const char *errmsg_arg)
663218334Speter{
663350599Sobrien  if (errmsg_arg)
663450599Sobrien    {
663552520Sobrien      int save_errno = errno;
663652520Sobrien
663750599Sobrien      /* Space for trailing '\0' is in %s.  */
663850599Sobrien      char *msg = xmalloc (strlen (errmsg_fmt) + strlen (errmsg_arg));
663950599Sobrien      sprintf (msg, errmsg_fmt, errmsg_arg);
664050599Sobrien      errmsg_fmt = msg;
664152520Sobrien
664252520Sobrien      errno = save_errno;
664350599Sobrien    }
664450599Sobrien
664552520Sobrien  pfatal_with_name (errmsg_fmt);
664618334Speter}
664718334Speter
6648132733Skan/* Output an error message and exit.  */
664918334Speter
665018334Spetervoid
6651132733Skanfancy_abort (void)
665218334Speter{
665390277Sobrien  fatal ("internal gcc abort");
665418334Speter}
665518334Speter
6656132733Skan/* Output an error message and exit.  */
665718334Speter
665852520Sobrienvoid
6659132733Skanfatal (const char *msgid, ...)
666018334Speter{
6661132733Skan  va_list ap;
666218334Speter
6663132733Skan  va_start (ap, msgid);
6664132733Skan
666518334Speter  fprintf (stderr, "%s: ", programname);
666652520Sobrien  vfprintf (stderr, _(msgid), ap);
6667132733Skan  va_end (ap);
666818334Speter  fprintf (stderr, "\n");
666918334Speter  delete_temp_files ();
667018334Speter  exit (1);
667118334Speter}
667218334Speter
667390277Sobrienvoid
6674132733Skanerror (const char *msgid, ...)
667518334Speter{
6676132733Skan  va_list ap;
667718334Speter
6678132733Skan  va_start (ap, msgid);
667918334Speter  fprintf (stderr, "%s: ", programname);
668052520Sobrien  vfprintf (stderr, _(msgid), ap);
6681132733Skan  va_end (ap);
668218334Speter
668318334Speter  fprintf (stderr, "\n");
668418334Speter}
668552520Sobrien
668652520Sobrienstatic void
6687132733Skannotice (const char *msgid, ...)
668852520Sobrien{
6689132733Skan  va_list ap;
669052520Sobrien
6691132733Skan  va_start (ap, msgid);
669252520Sobrien  vfprintf (stderr, _(msgid), ap);
6693132733Skan  va_end (ap);
669452520Sobrien}
669518334Speter
6696132733Skanstatic inline void
6697132733Skanvalidate_switches_from_spec (const char *spec)
6698132733Skan{
6699132733Skan  const char *p = spec;
6700132733Skan  char c;
6701132733Skan  while ((c = *p++))
6702132733Skan    if (c == '%' && (*p == '{' || *p == '<' || (*p == 'W' && *++p == '{')))
6703132733Skan      /* We have a switch spec.  */
6704132733Skan      p = validate_switches (p + 1);
6705132733Skan}
6706132733Skan
670718334Speterstatic void
6708132733Skanvalidate_all_switches (void)
670918334Speter{
671018334Speter  struct compiler *comp;
671118334Speter  struct spec_list *spec;
671218334Speter
671390277Sobrien  for (comp = compilers; comp->spec; comp++)
6714132733Skan    validate_switches_from_spec (comp->spec);
671518334Speter
671690277Sobrien  /* Look through the linked list of specs read from the specs file.  */
671790277Sobrien  for (spec = specs; spec; spec = spec->next)
6718132733Skan    validate_switches_from_spec (*spec->ptr_spec);
671918334Speter
6720132733Skan  validate_switches_from_spec (link_command_spec);
672118334Speter}
672218334Speter
672318334Speter/* Look at the switch-name that comes after START
672418334Speter   and mark as valid all supplied switches that match it.  */
672518334Speter
6726132733Skanstatic const char *
6727132733Skanvalidate_switches (const char *start)
672818334Speter{
672990277Sobrien  const char *p = start;
6730132733Skan  const char *atom;
6731132733Skan  size_t len;
673290277Sobrien  int i;
6733132733Skan  bool suffix = false;
6734132733Skan  bool starred = false;
673518334Speter
6736132733Skan#define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0)
673718334Speter
673890277Sobriennext_member:
6739132733Skan  SKIP_WHITE ();
6740132733Skan
674118334Speter  if (*p == '!')
6742132733Skan    p++;
674318334Speter
6744132733Skan  SKIP_WHITE ();
674518334Speter  if (*p == '.')
6746132733Skan    suffix = true, p++;
674718334Speter
6748132733Skan  atom = p;
6749132733Skan  while (ISIDNUM (*p) || *p == '-' || *p == '+' || *p == '='
6750132733Skan	 || *p == ',' || *p == '.' || *p == '@')
675190277Sobrien    p++;
6752132733Skan  len = p - atom;
675318334Speter
6754132733Skan  if (*p == '*')
6755132733Skan    starred = true, p++;
6756132733Skan
6757132733Skan  SKIP_WHITE ();
6758132733Skan
6759132733Skan  if (!suffix)
676018334Speter    {
676118334Speter      /* Mark all matching switches as valid.  */
676218334Speter      for (i = 0; i < n_switches; i++)
6763132733Skan	if (!strncmp (switches[i].part1, atom, len)
6764132733Skan	    && (starred || switches[i].part1[len] == 0))
676552520Sobrien	  switches[i].validated = 1;
676618334Speter    }
6767132733Skan
6768132733Skan  if (*p) p++;
6769132733Skan  if (*p && (p[-1] == '|' || p[-1] == '&'))
6770132733Skan    goto next_member;
6771132733Skan
6772132733Skan  if (*p && p[-1] == ':')
677318334Speter    {
6774132733Skan      while (*p && *p != ';' && *p != '}')
677518334Speter	{
6776132733Skan	  if (*p == '%')
6777132733Skan	    {
6778132733Skan	      p++;
6779132733Skan	      if (*p == '{' || *p == '<')
6780132733Skan		p = validate_switches (p+1);
6781132733Skan	      else if (p[0] == 'W' && p[1] == '{')
6782132733Skan		p = validate_switches (p+2);
6783132733Skan	    }
6784132733Skan	  else
6785132733Skan	    p++;
678618334Speter	}
6787132733Skan
6788132733Skan      if (*p) p++;
6789132733Skan      if (*p && p[-1] == ';')
6790132733Skan	goto next_member;
679118334Speter    }
679290277Sobrien
6793132733Skan  return p;
6794132733Skan#undef SKIP_WHITE
679518334Speter}
679618334Speter
6797104763Skanstruct mdswitchstr
6798104763Skan{
6799104763Skan  const char *str;
6800104763Skan  int len;
6801104763Skan};
6802104763Skan
6803104763Skanstatic struct mdswitchstr *mdswitches;
6804104763Skanstatic int n_mdswitches;
6805104763Skan
680650599Sobrien/* Check whether a particular argument was used.  The first time we
680750599Sobrien   canonicalize the switches to keep only the ones we care about.  */
680818334Speter
680918334Speterstatic int
6810132733Skanused_arg (const char *p, int len)
681118334Speter{
681290277Sobrien  struct mswitchstr
681390277Sobrien  {
681490277Sobrien    const char *str;
681590277Sobrien    const char *replace;
681650599Sobrien    int len;
681750599Sobrien    int rep_len;
681850599Sobrien  };
681918334Speter
682050599Sobrien  static struct mswitchstr *mswitches;
682150599Sobrien  static int n_mswitches;
682250599Sobrien  int i, j;
682350599Sobrien
682450599Sobrien  if (!mswitches)
682550599Sobrien    {
682650599Sobrien      struct mswitchstr *matches;
682790277Sobrien      const char *q;
682850599Sobrien      int cnt = 0;
682950599Sobrien
683090277Sobrien      /* Break multilib_matches into the component strings of string
683190277Sobrien         and replacement string.  */
683250599Sobrien      for (q = multilib_matches; *q != '\0'; q++)
683350599Sobrien	if (*q == ';')
683450599Sobrien	  cnt++;
683550599Sobrien
6836132733Skan      matches = alloca ((sizeof (struct mswitchstr)) * cnt);
683750599Sobrien      i = 0;
683850599Sobrien      q = multilib_matches;
683950599Sobrien      while (*q != '\0')
684050599Sobrien	{
684150599Sobrien	  matches[i].str = q;
684250599Sobrien	  while (*q != ' ')
684350599Sobrien	    {
684450599Sobrien	      if (*q == '\0')
684550599Sobrien		abort ();
684650599Sobrien	      q++;
684750599Sobrien	    }
684850599Sobrien	  matches[i].len = q - matches[i].str;
684950599Sobrien
685050599Sobrien	  matches[i].replace = ++q;
685150599Sobrien	  while (*q != ';' && *q != '\0')
685250599Sobrien	    {
685350599Sobrien	      if (*q == ' ')
685450599Sobrien		abort ();
685550599Sobrien	      q++;
685650599Sobrien	    }
685750599Sobrien	  matches[i].rep_len = q - matches[i].replace;
685850599Sobrien	  i++;
685950599Sobrien	  if (*q == ';')
686090277Sobrien	    q++;
686150599Sobrien	}
686250599Sobrien
686350599Sobrien      /* Now build a list of the replacement string for switches that we care
686450599Sobrien	 about.  Make sure we allocate at least one entry.  This prevents
686550599Sobrien	 xmalloc from calling fatal, and prevents us from re-executing this
686650599Sobrien	 block of code.  */
686750599Sobrien      mswitches
6868132733Skan	= xmalloc (sizeof (struct mswitchstr)
6869104763Skan		   * (n_mdswitches + (n_switches ? n_switches : 1)));
687050599Sobrien      for (i = 0; i < n_switches; i++)
687150599Sobrien	{
687250599Sobrien	  int xlen = strlen (switches[i].part1);
687350599Sobrien	  for (j = 0; j < cnt; j++)
687490277Sobrien	    if (xlen == matches[j].len
687590277Sobrien		&& ! strncmp (switches[i].part1, matches[j].str, xlen))
687650599Sobrien	      {
687750599Sobrien		mswitches[n_mswitches].str = matches[j].replace;
687850599Sobrien		mswitches[n_mswitches].len = matches[j].rep_len;
687990277Sobrien		mswitches[n_mswitches].replace = (char *) 0;
688050599Sobrien		mswitches[n_mswitches].rep_len = 0;
688150599Sobrien		n_mswitches++;
688250599Sobrien		break;
688350599Sobrien	      }
688450599Sobrien	}
6885104763Skan
6886104763Skan      /* Add MULTILIB_DEFAULTS switches too, as long as they were not present
6887104763Skan	 on the command line nor any options mutually incompatible with
6888104763Skan	 them.  */
6889104763Skan      for (i = 0; i < n_mdswitches; i++)
6890104763Skan	{
6891104763Skan	  const char *r;
6892104763Skan
6893104763Skan	  for (q = multilib_options; *q != '\0'; q++)
6894104763Skan	    {
6895104763Skan	      while (*q == ' ')
6896104763Skan		q++;
6897104763Skan
6898104763Skan	      r = q;
6899104763Skan	      while (strncmp (q, mdswitches[i].str, mdswitches[i].len) != 0
6900104763Skan		     || strchr (" /", q[mdswitches[i].len]) == NULL)
6901104763Skan		{
6902104763Skan		  while (*q != ' ' && *q != '/' && *q != '\0')
6903104763Skan		    q++;
6904104763Skan		  if (*q != '/')
6905104763Skan		    break;
6906104763Skan		  q++;
6907104763Skan		}
6908104763Skan
6909104763Skan	      if (*q != ' ' && *q != '\0')
6910104763Skan		{
6911104763Skan		  while (*r != ' ' && *r != '\0')
6912104763Skan		    {
6913104763Skan		      q = r;
6914104763Skan		      while (*q != ' ' && *q != '/' && *q != '\0')
6915104763Skan			q++;
6916104763Skan
6917104763Skan		      if (used_arg (r, q - r))
6918104763Skan			break;
6919104763Skan
6920104763Skan		      if (*q != '/')
6921104763Skan			{
6922104763Skan			  mswitches[n_mswitches].str = mdswitches[i].str;
6923104763Skan			  mswitches[n_mswitches].len = mdswitches[i].len;
6924104763Skan			  mswitches[n_mswitches].replace = (char *) 0;
6925104763Skan			  mswitches[n_mswitches].rep_len = 0;
6926104763Skan			  n_mswitches++;
6927104763Skan			  break;
6928104763Skan			}
6929104763Skan
6930104763Skan		      r = q + 1;
6931104763Skan		    }
6932104763Skan		  break;
6933104763Skan		}
6934104763Skan	    }
6935104763Skan	}
693650599Sobrien    }
693750599Sobrien
693850599Sobrien  for (i = 0; i < n_mswitches; i++)
693950599Sobrien    if (len == mswitches[i].len && ! strncmp (p, mswitches[i].str, len))
694018334Speter      return 1;
694150599Sobrien
694218334Speter  return 0;
694318334Speter}
694418334Speter
694518334Speterstatic int
6946132733Skandefault_arg (const char *p, int len)
694718334Speter{
6948104763Skan  int i;
694918334Speter
6950104763Skan  for (i = 0; i < n_mdswitches; i++)
6951104763Skan    if (len == mdswitches[i].len && ! strncmp (p, mdswitches[i].str, len))
6952104763Skan      return 1;
695318334Speter
695418334Speter  return 0;
695518334Speter}
695618334Speter
695790277Sobrien/* Work out the subdirectory to use based on the options. The format of
695890277Sobrien   multilib_select is a list of elements. Each element is a subdirectory
695990277Sobrien   name followed by a list of options followed by a semicolon. The format
696090277Sobrien   of multilib_exclusions is the same, but without the preceding
696190277Sobrien   directory. First gcc will check the exclusions, if none of the options
696290277Sobrien   beginning with an exclamation point are present, and all of the other
696390277Sobrien   options are present, then we will ignore this completely. Passing
696490277Sobrien   that, gcc will consider each multilib_select in turn using the same
696590277Sobrien   rules for matching the options. If a match is found, that subdirectory
696690277Sobrien   will be used.  */
696718334Speter
696818334Speterstatic void
6969132733Skanset_multilib_dir (void)
697018334Speter{
697190277Sobrien  const char *p;
697290277Sobrien  unsigned int this_path_len;
697390277Sobrien  const char *this_path, *this_arg;
6974104763Skan  const char *start, *end;
697518334Speter  int not_arg;
6976104763Skan  int ok, ndfltok, first;
697718334Speter
6978104763Skan  n_mdswitches = 0;
6979104763Skan  start = multilib_defaults;
6980104763Skan  while (*start == ' ' || *start == '\t')
6981104763Skan    start++;
6982104763Skan  while (*start != '\0')
6983104763Skan    {
6984104763Skan      n_mdswitches++;
6985104763Skan      while (*start != ' ' && *start != '\t' && *start != '\0')
6986104763Skan	start++;
6987104763Skan      while (*start == ' ' || *start == '\t')
6988104763Skan        start++;
6989104763Skan    }
6990104763Skan
6991104763Skan  if (n_mdswitches)
6992104763Skan    {
6993104763Skan      int i = 0;
6994104763Skan
6995132733Skan      mdswitches = xmalloc (sizeof (struct mdswitchstr) * n_mdswitches);
6996104763Skan      for (start = multilib_defaults; *start != '\0'; start = end + 1)
6997104763Skan	{
6998104763Skan	  while (*start == ' ' || *start == '\t')
6999104763Skan	    start++;
7000104763Skan
7001104763Skan	  if (*start == '\0')
7002104763Skan	    break;
7003132733Skan
7004104763Skan	  for (end = start + 1;
7005104763Skan	       *end != ' ' && *end != '\t' && *end != '\0'; end++)
7006104763Skan	    ;
7007104763Skan
7008104763Skan	  obstack_grow (&multilib_obstack, start, end - start);
7009104763Skan	  obstack_1grow (&multilib_obstack, 0);
7010104763Skan	  mdswitches[i].str = obstack_finish (&multilib_obstack);
7011104763Skan	  mdswitches[i++].len = end - start;
7012104763Skan
7013104763Skan	  if (*end == '\0')
7014104763Skan	    break;
7015104763Skan	}
7016104763Skan    }
7017104763Skan
701890277Sobrien  p = multilib_exclusions;
701918334Speter  while (*p != '\0')
702018334Speter    {
702118334Speter      /* Ignore newlines.  */
702218334Speter      if (*p == '\n')
702318334Speter	{
702418334Speter	  ++p;
702518334Speter	  continue;
702618334Speter	}
702718334Speter
702890277Sobrien      /* Check the arguments.  */
702990277Sobrien      ok = 1;
703090277Sobrien      while (*p != ';')
703190277Sobrien	{
703290277Sobrien	  if (*p == '\0')
703390277Sobrien	    abort ();
703490277Sobrien
703590277Sobrien	  if (! ok)
703690277Sobrien	    {
703790277Sobrien	      ++p;
703890277Sobrien	      continue;
703990277Sobrien	    }
704090277Sobrien
704190277Sobrien	  this_arg = p;
704290277Sobrien	  while (*p != ' ' && *p != ';')
704390277Sobrien	    {
704490277Sobrien	      if (*p == '\0')
704590277Sobrien		abort ();
704690277Sobrien	      ++p;
704790277Sobrien	    }
704890277Sobrien
704990277Sobrien	  if (*this_arg != '!')
705090277Sobrien	    not_arg = 0;
705190277Sobrien	  else
705290277Sobrien	    {
705390277Sobrien	      not_arg = 1;
705490277Sobrien	      ++this_arg;
705590277Sobrien	    }
705690277Sobrien
705790277Sobrien	  ok = used_arg (this_arg, p - this_arg);
705890277Sobrien	  if (not_arg)
705990277Sobrien	    ok = ! ok;
706090277Sobrien
706190277Sobrien	  if (*p == ' ')
706290277Sobrien	    ++p;
706390277Sobrien	}
706490277Sobrien
706590277Sobrien      if (ok)
706690277Sobrien	return;
706790277Sobrien
706890277Sobrien      ++p;
706990277Sobrien    }
707090277Sobrien
7071104763Skan  first = 1;
707290277Sobrien  p = multilib_select;
707390277Sobrien  while (*p != '\0')
707490277Sobrien    {
707590277Sobrien      /* Ignore newlines.  */
707690277Sobrien      if (*p == '\n')
707790277Sobrien	{
707890277Sobrien	  ++p;
707990277Sobrien	  continue;
708090277Sobrien	}
708190277Sobrien
708218334Speter      /* Get the initial path.  */
708318334Speter      this_path = p;
708418334Speter      while (*p != ' ')
708518334Speter	{
708618334Speter	  if (*p == '\0')
708718334Speter	    abort ();
708818334Speter	  ++p;
708918334Speter	}
709018334Speter      this_path_len = p - this_path;
709118334Speter
709218334Speter      /* Check the arguments.  */
709318334Speter      ok = 1;
7094104763Skan      ndfltok = 1;
709518334Speter      ++p;
709618334Speter      while (*p != ';')
709718334Speter	{
709818334Speter	  if (*p == '\0')
709918334Speter	    abort ();
710018334Speter
710118334Speter	  if (! ok)
710218334Speter	    {
710318334Speter	      ++p;
710418334Speter	      continue;
710518334Speter	    }
710618334Speter
710718334Speter	  this_arg = p;
710818334Speter	  while (*p != ' ' && *p != ';')
710918334Speter	    {
711018334Speter	      if (*p == '\0')
711118334Speter		abort ();
711218334Speter	      ++p;
711318334Speter	    }
711418334Speter
711518334Speter	  if (*this_arg != '!')
711618334Speter	    not_arg = 0;
711718334Speter	  else
711818334Speter	    {
711918334Speter	      not_arg = 1;
712018334Speter	      ++this_arg;
712118334Speter	    }
712218334Speter
712318334Speter	  /* If this is a default argument, we can just ignore it.
712418334Speter	     This is true even if this_arg begins with '!'.  Beginning
712518334Speter	     with '!' does not mean that this argument is necessarily
712618334Speter	     inappropriate for this library: it merely means that
712718334Speter	     there is a more specific library which uses this
712818334Speter	     argument.  If this argument is a default, we need not
712918334Speter	     consider that more specific library.  */
7130104763Skan	  ok = used_arg (this_arg, p - this_arg);
7131104763Skan	  if (not_arg)
7132104763Skan	    ok = ! ok;
713318334Speter
7134104763Skan	  if (! ok)
7135104763Skan	    ndfltok = 0;
7136104763Skan
7137104763Skan	  if (default_arg (this_arg, p - this_arg))
7138104763Skan	    ok = 1;
7139104763Skan
714018334Speter	  if (*p == ' ')
714118334Speter	    ++p;
714218334Speter	}
714318334Speter
7144104763Skan      if (ok && first)
714518334Speter	{
714618334Speter	  if (this_path_len != 1
714718334Speter	      || this_path[0] != '.')
714818334Speter	    {
714990277Sobrien	      char *new_multilib_dir = xmalloc (this_path_len + 1);
7150104763Skan	      char *q;
7151104763Skan
715252520Sobrien	      strncpy (new_multilib_dir, this_path, this_path_len);
715352520Sobrien	      new_multilib_dir[this_path_len] = '\0';
7154104763Skan	      q = strchr (new_multilib_dir, ':');
7155104763Skan	      if (q != NULL)
7156104763Skan		*q = '\0';
715752520Sobrien	      multilib_dir = new_multilib_dir;
715818334Speter	    }
7159104763Skan	  first = 0;
716018334Speter	}
716118334Speter
7162104763Skan      if (ndfltok)
7163104763Skan	{
7164104763Skan	  const char *q = this_path, *end = this_path + this_path_len;
7165104763Skan
7166104763Skan	  while (q < end && *q != ':')
7167104763Skan	    q++;
7168104763Skan	  if (q < end)
7169104763Skan	    {
7170104763Skan	      char *new_multilib_os_dir = xmalloc (end - q);
7171104763Skan	      memcpy (new_multilib_os_dir, q + 1, end - q - 1);
7172104763Skan	      new_multilib_os_dir[end - q - 1] = '\0';
7173104763Skan	      multilib_os_dir = new_multilib_os_dir;
7174104763Skan	      break;
7175104763Skan	    }
7176104763Skan	}
7177104763Skan
717818334Speter      ++p;
717990277Sobrien    }
7180104763Skan
7181104763Skan  if (multilib_dir == NULL && multilib_os_dir != NULL
7182104763Skan      && strcmp (multilib_os_dir, ".") == 0)
7183104763Skan    {
7184104763Skan      free ((char *) multilib_os_dir);
7185104763Skan      multilib_os_dir = NULL;
7186104763Skan    }
7187104763Skan  else if (multilib_dir != NULL && multilib_os_dir == NULL)
7188104763Skan    multilib_os_dir = multilib_dir;
718918334Speter}
719018334Speter
719118334Speter/* Print out the multiple library subdirectory selection
719218334Speter   information.  This prints out a series of lines.  Each line looks
719318334Speter   like SUBDIRECTORY;@OPTION@OPTION, with as many options as is
719418334Speter   required.  Only the desired options are printed out, the negative
719518334Speter   matches.  The options are print without a leading dash.  There are
719618334Speter   no spaces to make it easy to use the information in the shell.
719718334Speter   Each subdirectory is printed only once.  This assumes the ordering
719890277Sobrien   generated by the genmultilib script. Also, we leave out ones that match
719990277Sobrien   the exclusions.  */
720018334Speter
720118334Speterstatic void
7202132733Skanprint_multilib_info (void)
720318334Speter{
720490277Sobrien  const char *p = multilib_select;
720590277Sobrien  const char *last_path = 0, *this_path;
720618334Speter  int skip;
720790277Sobrien  unsigned int last_path_len = 0;
720818334Speter
720918334Speter  while (*p != '\0')
721018334Speter    {
721190277Sobrien      skip = 0;
721218334Speter      /* Ignore newlines.  */
721318334Speter      if (*p == '\n')
721418334Speter	{
721518334Speter	  ++p;
721618334Speter	  continue;
721718334Speter	}
721818334Speter
721918334Speter      /* Get the initial path.  */
722018334Speter      this_path = p;
722118334Speter      while (*p != ' ')
722218334Speter	{
722318334Speter	  if (*p == '\0')
722418334Speter	    abort ();
722518334Speter	  ++p;
722618334Speter	}
722718334Speter
7228104763Skan      /* When --disable-multilib was used but target defines
7229104763Skan	 MULTILIB_OSDIRNAMES, entries starting with .: are there just
7230104763Skan	 to find multilib_os_dir, so skip them from output.  */
7231104763Skan      if (this_path[0] == '.' && this_path[1] == ':')
7232104763Skan	skip = 1;
7233104763Skan
723490277Sobrien      /* Check for matches with the multilib_exclusions. We don't bother
723590277Sobrien         with the '!' in either list. If any of the exclusion rules match
723690277Sobrien         all of its options with the select rule, we skip it.  */
723790277Sobrien      {
723890277Sobrien	const char *e = multilib_exclusions;
723990277Sobrien	const char *this_arg;
724018334Speter
724190277Sobrien	while (*e != '\0')
724290277Sobrien	  {
724390277Sobrien	    int m = 1;
724490277Sobrien	    /* Ignore newlines.  */
724590277Sobrien	    if (*e == '\n')
724690277Sobrien	      {
724790277Sobrien		++e;
724890277Sobrien		continue;
724990277Sobrien	      }
725018334Speter
725190277Sobrien	    /* Check the arguments.  */
725290277Sobrien	    while (*e != ';')
725390277Sobrien	      {
725490277Sobrien		const char *q;
725590277Sobrien		int mp = 0;
725690277Sobrien
725790277Sobrien		if (*e == '\0')
725890277Sobrien		  abort ();
725990277Sobrien
726090277Sobrien		if (! m)
726190277Sobrien		  {
726290277Sobrien		    ++e;
726390277Sobrien		    continue;
726490277Sobrien		  }
726590277Sobrien
726690277Sobrien		this_arg = e;
726790277Sobrien
726890277Sobrien		while (*e != ' ' && *e != ';')
726990277Sobrien		  {
727090277Sobrien		    if (*e == '\0')
727190277Sobrien		      abort ();
727290277Sobrien		    ++e;
727390277Sobrien		  }
727490277Sobrien
727590277Sobrien		q = p + 1;
727690277Sobrien		while (*q != ';')
727790277Sobrien		  {
727890277Sobrien		    const char *arg;
727990277Sobrien		    int len = e - this_arg;
728090277Sobrien
728190277Sobrien		    if (*q == '\0')
728290277Sobrien		      abort ();
728390277Sobrien
728490277Sobrien		    arg = q;
728590277Sobrien
728690277Sobrien		    while (*q != ' ' && *q != ';')
728790277Sobrien		      {
728890277Sobrien			if (*q == '\0')
728990277Sobrien			  abort ();
729090277Sobrien			++q;
729190277Sobrien		      }
729290277Sobrien
729390277Sobrien		    if (! strncmp (arg, this_arg, (len < q - arg) ? q - arg : len) ||
729490277Sobrien			default_arg (this_arg, e - this_arg))
729590277Sobrien		      {
729690277Sobrien			mp = 1;
729790277Sobrien			break;
729890277Sobrien		      }
729990277Sobrien
730090277Sobrien		    if (*q == ' ')
730190277Sobrien		      ++q;
730290277Sobrien		  }
730390277Sobrien
730490277Sobrien		if (! mp)
730590277Sobrien		  m = 0;
730690277Sobrien
730790277Sobrien		if (*e == ' ')
730890277Sobrien		  ++e;
730990277Sobrien	      }
731090277Sobrien
731190277Sobrien	    if (m)
731290277Sobrien	      {
731390277Sobrien		skip = 1;
731490277Sobrien		break;
731590277Sobrien	      }
731690277Sobrien
731790277Sobrien	    if (*e != '\0')
731890277Sobrien	      ++e;
731990277Sobrien	  }
732090277Sobrien      }
732190277Sobrien
732290277Sobrien      if (! skip)
732390277Sobrien	{
732490277Sobrien	  /* If this is a duplicate, skip it.  */
732590277Sobrien	  skip = (last_path != 0 && (unsigned int) (p - this_path) == last_path_len
732690277Sobrien		  && ! strncmp (last_path, this_path, last_path_len));
732790277Sobrien
732890277Sobrien	  last_path = this_path;
732990277Sobrien	  last_path_len = p - this_path;
733090277Sobrien	}
733190277Sobrien
733218334Speter      /* If this directory requires any default arguments, we can skip
733318334Speter	 it.  We will already have printed a directory identical to
733418334Speter	 this one which does not require that default argument.  */
733518334Speter      if (! skip)
733618334Speter	{
733790277Sobrien	  const char *q;
733818334Speter
733918334Speter	  q = p + 1;
734018334Speter	  while (*q != ';')
734118334Speter	    {
734290277Sobrien	      const char *arg;
734318334Speter
734418334Speter	      if (*q == '\0')
734518334Speter		abort ();
734618334Speter
734718334Speter	      if (*q == '!')
734818334Speter		arg = NULL;
734918334Speter	      else
735018334Speter		arg = q;
735118334Speter
735218334Speter	      while (*q != ' ' && *q != ';')
735318334Speter		{
735418334Speter		  if (*q == '\0')
735518334Speter		    abort ();
735618334Speter		  ++q;
735718334Speter		}
735818334Speter
735918334Speter	      if (arg != NULL
736018334Speter		  && default_arg (arg, q - arg))
736118334Speter		{
736218334Speter		  skip = 1;
736318334Speter		  break;
736418334Speter		}
736518334Speter
736618334Speter	      if (*q == ' ')
736718334Speter		++q;
736818334Speter	    }
736918334Speter	}
737018334Speter
737118334Speter      if (! skip)
737218334Speter	{
737390277Sobrien	  const char *p1;
737418334Speter
7375104763Skan	  for (p1 = last_path; p1 < p && *p1 != ':'; p1++)
737618334Speter	    putchar (*p1);
737718334Speter	  putchar (';');
737818334Speter	}
737918334Speter
738018334Speter      ++p;
738118334Speter      while (*p != ';')
738218334Speter	{
738318334Speter	  int use_arg;
738418334Speter
738518334Speter	  if (*p == '\0')
738618334Speter	    abort ();
738718334Speter
738818334Speter	  if (skip)
738918334Speter	    {
739018334Speter	      ++p;
739118334Speter	      continue;
739218334Speter	    }
739318334Speter
739418334Speter	  use_arg = *p != '!';
739518334Speter
739618334Speter	  if (use_arg)
739718334Speter	    putchar ('@');
739818334Speter
739918334Speter	  while (*p != ' ' && *p != ';')
740018334Speter	    {
740118334Speter	      if (*p == '\0')
740218334Speter		abort ();
740318334Speter	      if (use_arg)
740418334Speter		putchar (*p);
740518334Speter	      ++p;
740618334Speter	    }
740718334Speter
740818334Speter	  if (*p == ' ')
740918334Speter	    ++p;
741018334Speter	}
741118334Speter
741218334Speter      if (! skip)
741350599Sobrien	{
741490277Sobrien	  /* If there are extra options, print them now.  */
741550599Sobrien	  if (multilib_extra && *multilib_extra)
741650599Sobrien	    {
741750599Sobrien	      int print_at = TRUE;
741890277Sobrien	      const char *q;
741918334Speter
742050599Sobrien	      for (q = multilib_extra; *q != '\0'; q++)
742150599Sobrien		{
742250599Sobrien		  if (*q == ' ')
742350599Sobrien		    print_at = TRUE;
742450599Sobrien		  else
742550599Sobrien		    {
742650599Sobrien		      if (print_at)
742750599Sobrien			putchar ('@');
742850599Sobrien		      putchar (*q);
742950599Sobrien		      print_at = FALSE;
743050599Sobrien		    }
743150599Sobrien		}
743250599Sobrien	    }
743390277Sobrien
743450599Sobrien	  putchar ('\n');
743550599Sobrien	}
743650599Sobrien
743718334Speter      ++p;
743818334Speter    }
743918334Speter}
7440117413Skan
7441117413Skan/* if-exists built-in spec function.
7442117413Skan
7443117413Skan   Checks to see if the file specified by the absolute pathname in
7444117413Skan   ARGS exists.  Returns that pathname if found.
7445117413Skan
7446117413Skan   The usual use for this function is to check for a library file
7447117413Skan   (whose name has been expanded with %s).  */
7448117413Skan
7449117413Skanstatic const char *
7450132733Skanif_exists_spec_function (int argc, const char **argv)
7451117413Skan{
7452117413Skan  /* Must have only one argument.  */
7453132733Skan  if (argc == 1 && IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
7454117413Skan    return argv[0];
7455117413Skan
7456117413Skan  return NULL;
7457117413Skan}
7458117413Skan
7459117413Skan/* if-exists-else built-in spec function.
7460117413Skan
7461117413Skan   This is like if-exists, but takes an additional argument which
7462117413Skan   is returned if the first argument does not exist.  */
7463117413Skan
7464117413Skanstatic const char *
7465132733Skanif_exists_else_spec_function (int argc, const char **argv)
7466117413Skan{
7467117413Skan  /* Must have exactly two arguments.  */
7468117413Skan  if (argc != 2)
7469117413Skan    return NULL;
7470117413Skan
7471132733Skan  if (IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
7472117413Skan    return argv[0];
7473117413Skan
7474117413Skan  return argv[1];
7475117413Skan}
7476