118334Speter/* Compiler driver program that can handle many languages.
290277Sobrien   Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3161660Skan   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
4161660Skan   Inc.
518334Speter
690277SobrienThis file is part of GCC.
718334Speter
890277SobrienGCC is free software; you can redistribute it and/or modify it under
990277Sobrienthe terms of the GNU General Public License as published by the Free
1090277SobrienSoftware Foundation; either version 2, or (at your option) any later
1190277Sobrienversion.
1218334Speter
1390277SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1490277SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1590277SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1690277Sobrienfor more details.
1718334Speter
1818334SpeterYou should have received a copy of the GNU General Public License
1990277Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
20169704SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21169704Skan02110-1301, USA.
2218334Speter
2318334SpeterThis paragraph is here to try to keep Sun CC from dying.
2418334SpeterThe number of chars here seems crucial!!!!  */
2518334Speter
2651232Sbde/* $FreeBSD$ */
2751232Sbde
2818334Speter/* This program is the user interface to the C compiler and possibly to
2918334Speterother compilers.  It is used because compilation is a complicated procedure
3018334Speterwhich involves running several programs and passing temporary files between
3118334Speterthem, forwarding the users switches to those programs selectively,
3218334Speterand deleting the temporary files at the end.
3318334Speter
3418334SpeterCC recognizes how to compile each input file by suffixes in the file names.
3518334SpeterOnce it knows which kind of compilation to perform, the procedure for
3618334Spetercompilation is specified by a string called a "spec".  */
3790277Sobrien
3890277Sobrien/* A Short Introduction to Adding a Command-Line Option.
3990277Sobrien
4090277Sobrien   Before adding a command-line option, consider if it is really
4190277Sobrien   necessary.  Each additional command-line option adds complexity and
4290277Sobrien   is difficult to remove in subsequent versions.
4390277Sobrien
4490277Sobrien   In the following, consider adding the command-line argument
4590277Sobrien   `--bar'.
4690277Sobrien
4790277Sobrien   1. Each command-line option is specified in the specs file.  The
4890277Sobrien   notation is described below in the comment entitled "The Specs
4990277Sobrien   Language".  Read it.
5090277Sobrien
5190277Sobrien   2. In this file, add an entry to "option_map" equating the long
5290277Sobrien   `--' argument version and any shorter, single letter version.  Read
5390277Sobrien   the comments in the declaration of "struct option_map" for an
5490277Sobrien   explanation.  Do not omit the first `-'.
5590277Sobrien
5690277Sobrien   3. Look in the "specs" file to determine which program or option
5790277Sobrien   list should be given the argument, e.g., "cc1_options".  Add the
5890277Sobrien   appropriate syntax for the shorter option version to the
5990277Sobrien   corresponding "const char *" entry in this file.  Omit the first
6090277Sobrien   `-' from the option.  For example, use `-bar', rather than `--bar'.
6190277Sobrien
6290277Sobrien   4. If the argument takes an argument, e.g., `--baz argument1',
6390277Sobrien   modify either DEFAULT_SWITCH_TAKES_ARG or
64169704Skan   DEFAULT_WORD_SWITCH_TAKES_ARG in gcc.h.  Omit the first `-'
6590277Sobrien   from `--baz'.
6690277Sobrien
6790277Sobrien   5. Document the option in this file's display_help().  If the
6890277Sobrien   option is passed to a subprogram, modify its corresponding
6990277Sobrien   function, e.g., cppinit.c:print_help() or toplev.c:display_help(),
7090277Sobrien   instead.
7190277Sobrien
7290277Sobrien   6. Compile and test.  Make sure that your new specs file is being
7390277Sobrien   read.  For example, use a debugger to investigate the value of
7490277Sobrien   "specs_file" in main().  */
7590277Sobrien
7650599Sobrien#include "config.h"
7750599Sobrien#include "system.h"
78132733Skan#include "coretypes.h"
79132733Skan#include "multilib.h" /* before tm.h */
80132733Skan#include "tm.h"
8150599Sobrien#include <signal.h>
8290277Sobrien#if ! defined( SIGCHLD ) && defined( SIGCLD )
8390277Sobrien#  define SIGCHLD SIGCLD
8490277Sobrien#endif
85169704Skan#include "xregex.h"
8650599Sobrien#include "obstack.h"
8752520Sobrien#include "intl.h"
8852520Sobrien#include "prefix.h"
8990277Sobrien#include "gcc.h"
9090277Sobrien#include "flags.h"
91169704Skan#include "opts.h"
9218334Speter
9390277Sobrien/* By default there is no special suffix for target executables.  */
9490277Sobrien/* FIXME: when autoconf is fixed, remove the host check - dj */
9590277Sobrien#if defined(TARGET_EXECUTABLE_SUFFIX) && defined(HOST_EXECUTABLE_SUFFIX)
9690277Sobrien#define HAVE_TARGET_EXECUTABLE_SUFFIX
9718334Speter#endif
9818334Speter
9990277Sobrien/* By default there is no special suffix for host executables.  */
10090277Sobrien#ifdef HOST_EXECUTABLE_SUFFIX
10190277Sobrien#define HAVE_HOST_EXECUTABLE_SUFFIX
10218334Speter#else
10390277Sobrien#define HOST_EXECUTABLE_SUFFIX ""
10418334Speter#endif
10518334Speter
10690277Sobrien/* By default, the suffix for target object files is ".o".  */
10790277Sobrien#ifdef TARGET_OBJECT_SUFFIX
10890277Sobrien#define HAVE_TARGET_OBJECT_SUFFIX
10990277Sobrien#else
11090277Sobrien#define TARGET_OBJECT_SUFFIX ".o"
11118334Speter#endif
11218334Speter
11390277Sobrienstatic const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
11452520Sobrien
11590277Sobrien/* Most every one is fine with LIBRARY_PATH.  For some, it conflicts.  */
11690277Sobrien#ifndef LIBRARY_PATH_ENV
11790277Sobrien#define LIBRARY_PATH_ENV "LIBRARY_PATH"
11890277Sobrien#endif
11990277Sobrien
12050599Sobrien#ifndef HAVE_KILL
12150599Sobrien#define kill(p,s) raise(s)
12218334Speter#endif
12318334Speter
12418334Speter/* If a stage of compilation returns an exit status >= 1,
12518334Speter   compilation of that file ceases.  */
12618334Speter
12718334Speter#define MIN_FATAL_STATUS 1
12818334Speter
12990277Sobrien/* Flag set by cppspec.c to 1.  */
13090277Sobrienint is_cpp_driver;
13190277Sobrien
13290277Sobrien/* Flag saying to pass the greatest exit code returned by a sub-process
13390277Sobrien   to the calling program.  */
13490277Sobrienstatic int pass_exit_codes;
13590277Sobrien
13690277Sobrien/* Definition of string containing the arguments given to configure.  */
13790277Sobrien#include "configargs.h"
13890277Sobrien
13918334Speter/* Flag saying to print the directories gcc will search through looking for
14018334Speter   programs, libraries, etc.  */
14118334Speter
14218334Speterstatic int print_search_dirs;
14318334Speter
14418334Speter/* Flag saying to print the full filename of this file
14518334Speter   as found through our usual search mechanism.  */
14618334Speter
14752520Sobrienstatic const char *print_file_name = NULL;
14818334Speter
14950599Sobrien/* As print_file_name, but search for executable file.  */
15018334Speter
15152520Sobrienstatic const char *print_prog_name = NULL;
15218334Speter
15318334Speter/* Flag saying to print the relative path we'd use to
15418334Speter   find libgcc.a given the current compiler flags.  */
15518334Speter
15618334Speterstatic int print_multi_directory;
15718334Speter
158104763Skan/* Flag saying to print the relative path we'd use to
159104763Skan   find OS libraries given the current compiler flags.  */
160104763Skan
161104763Skanstatic int print_multi_os_directory;
162104763Skan
16318334Speter/* Flag saying to print the list of subdirectories and
16418334Speter   compiler flags used to select them in a standard form.  */
16518334Speter
16618334Speterstatic int print_multi_lib;
16718334Speter
16850599Sobrien/* Flag saying to print the command line options understood by gcc and its
16950599Sobrien   sub-processes.  */
17050599Sobrien
17150599Sobrienstatic int print_help_list;
17250599Sobrien
17318334Speter/* Flag indicating whether we should print the command and arguments */
17418334Speter
17518334Speterstatic int verbose_flag;
17618334Speter
17790277Sobrien/* Flag indicating whether we should ONLY print the command and
17890277Sobrien   arguments (like verbose_flag) without executing the command.
17990277Sobrien   Displayed arguments are quoted so that the generated command
18090277Sobrien   line is suitable for execution.  This is intended for use in
18190277Sobrien   shell scripts to capture the driver-generated command line.  */
18290277Sobrienstatic int verbose_only_flag;
18390277Sobrien
18490277Sobrien/* Flag indicating to print target specific command line options.  */
18590277Sobrien
18690277Sobrienstatic int target_help_flag;
18790277Sobrien
18890277Sobrien/* Flag indicating whether we should report subprocess execution times
18990277Sobrien   (if this is supported by the system - see pexecute.c).  */
19090277Sobrien
19190277Sobrienstatic int report_times;
19290277Sobrien
193132733Skan/* Nonzero means place this string before uses of /, so that include
194132733Skan   and library files can be found in an alternate location.  */
195132733Skan
196132733Skan#ifdef TARGET_SYSTEM_ROOT
197132733Skanstatic const char *target_system_root = TARGET_SYSTEM_ROOT;
198132733Skan#else
199132733Skanstatic const char *target_system_root = 0;
200132733Skan#endif
201132733Skan
202132733Skan/* Nonzero means pass the updated target_system_root to the compiler.  */
203132733Skan
204132733Skanstatic int target_system_root_changed;
205132733Skan
206132733Skan/* Nonzero means append this string to target_system_root.  */
207132733Skan
208132733Skanstatic const char *target_sysroot_suffix = 0;
209132733Skan
210132733Skan/* Nonzero means append this string to target_system_root for headers.  */
211132733Skan
212132733Skanstatic const char *target_sysroot_hdrs_suffix = 0;
213132733Skan
21418334Speter/* Nonzero means write "temp" files in source directory
21518334Speter   and use the source file's name in them, and don't delete them.  */
21618334Speter
21718334Speterstatic int save_temps_flag;
21818334Speter
219169704Skan/* Nonzero means pass multiple source files to the compiler at one time.  */
220169704Skan
221169704Skanstatic int combine_flag = 0;
222169704Skan
223132733Skan/* Nonzero means use pipes to communicate between subprocesses.
224132733Skan   Overridden by either of the above two flags.  */
225132733Skan
226132733Skanstatic int use_pipes;
227132733Skan
22818334Speter/* The compiler version.  */
22918334Speter
23090277Sobrienstatic const char *compiler_version;
23118334Speter
23218334Speter/* The target version specified with -V */
23318334Speter
234117413Skanstatic const char *const spec_version = DEFAULT_TARGET_VERSION;
23518334Speter
23618334Speter/* The target machine specified with -b.  */
23718334Speter
23852520Sobrienstatic const char *spec_machine = DEFAULT_TARGET_MACHINE;
23918334Speter
24018334Speter/* Nonzero if cross-compiling.
24118334Speter   When -b is used, the value comes from the `specs' file.  */
24218334Speter
243259563Spfg#ifdef CROSS_DIRECTORY_STRUCTURE
24490277Sobrienstatic const char *cross_compile = "1";
24518334Speter#else
24690277Sobrienstatic const char *cross_compile = "0";
24718334Speter#endif
24818334Speter
24990277Sobrien#ifdef MODIFY_TARGET_NAME
25090277Sobrien
25190277Sobrien/* Information on how to alter the target name based on a command-line
25290277Sobrien   switch.  The only case we support now is simply appending or deleting a
25390277Sobrien   string to or from the end of the first part of the configuration name.  */
25490277Sobrien
25590277Sobrienstatic const struct modify_target
25690277Sobrien{
25790277Sobrien  const char *const sw;
25890277Sobrien  const enum add_del {ADD, DELETE} add_del;
25990277Sobrien  const char *const str;
26090277Sobrien}
26190277Sobrienmodify_target[] = MODIFY_TARGET_NAME;
26290277Sobrien#endif
263117413Skan
26418334Speter/* The number of errors that have occurred; the link phase will not be
265117413Skan   run if this is nonzero.  */
26618334Speterstatic int error_count = 0;
26718334Speter
26890277Sobrien/* Greatest exit code of sub-processes that has been encountered up to
26990277Sobrien   now.  */
27090277Sobrienstatic int greatest_status = 1;
27190277Sobrien
27218334Speter/* This is the obstack which we use to allocate many strings.  */
27318334Speter
27418334Speterstatic struct obstack obstack;
27518334Speter
27618334Speter/* This is the obstack to build an environment variable to pass to
27718334Speter   collect2 that describes all of the relevant switches of what to
27818334Speter   pass the compiler in building the list of pointers to constructors
27918334Speter   and destructors.  */
28018334Speter
28118334Speterstatic struct obstack collect_obstack;
28218334Speter
28318334Speter/* Forward declaration for prototypes.  */
28418334Speterstruct path_prefix;
285169704Skanstruct prefix_list;
28618334Speter
287132733Skanstatic void init_spec (void);
288132733Skanstatic void store_arg (const char *, int, int);
289132733Skanstatic char *load_specs (const char *);
290132733Skanstatic void read_specs (const char *, int);
291132733Skanstatic void set_spec (const char *, const char *);
292132733Skanstatic struct compiler *lookup_compiler (const char *, size_t, const char *);
293169704Skanstatic char *build_search_list (const struct path_prefix *, const char *,
294169704Skan				bool, bool);
295169704Skanstatic void putenv_from_prefixes (const struct path_prefix *, const char *,
296169704Skan				  bool);
297132733Skanstatic int access_check (const char *, int);
298169704Skanstatic char *find_a_file (const struct path_prefix *, const char *, int, bool);
299132733Skanstatic void add_prefix (struct path_prefix *, const char *, const char *,
300169704Skan			int, int, int);
301132733Skanstatic void add_sysrooted_prefix (struct path_prefix *, const char *,
302169704Skan				  const char *, int, int, int);
303132733Skanstatic void translate_options (int *, const char *const **);
304132733Skanstatic char *skip_whitespace (char *);
305132733Skanstatic void delete_if_ordinary (const char *);
306132733Skanstatic void delete_temp_files (void);
307132733Skanstatic void delete_failure_queue (void);
308132733Skanstatic void clear_failure_queue (void);
309132733Skanstatic int check_live_switch (int, int);
310132733Skanstatic const char *handle_braces (const char *);
311132733Skanstatic inline bool input_suffix_matches (const char *, const char *);
312132733Skanstatic inline bool switch_matches (const char *, const char *, int);
313132733Skanstatic inline void mark_matching_switches (const char *, const char *, int);
314132733Skanstatic inline void process_marked_switches (void);
315132733Skanstatic const char *process_brace_body (const char *, const char *, const char *, int, int);
316132733Skanstatic const struct spec_function *lookup_spec_function (const char *);
317132733Skanstatic const char *eval_spec_function (const char *, const char *);
318132733Skanstatic const char *handle_spec_function (const char *);
319132733Skanstatic char *save_string (const char *, int);
320132733Skanstatic void set_collect_gcc_options (void);
321132733Skanstatic int do_spec_1 (const char *, int, const char *);
322132733Skanstatic int do_spec_2 (const char *);
323132733Skanstatic void do_option_spec (const char *, const char *);
324132733Skanstatic void do_self_spec (const char *);
325132733Skanstatic const char *find_file (const char *);
326169704Skanstatic int is_directory (const char *, bool);
327132733Skanstatic const char *validate_switches (const char *);
328132733Skanstatic void validate_all_switches (void);
329132733Skanstatic inline void validate_switches_from_spec (const char *);
330132733Skanstatic void give_switch (int, int);
331132733Skanstatic int used_arg (const char *, int);
332132733Skanstatic int default_arg (const char *, int);
333132733Skanstatic void set_multilib_dir (void);
334132733Skanstatic void print_multilib_info (void);
335132733Skanstatic void perror_with_name (const char *);
336169704Skanstatic void fatal_ice (const char *, ...) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
337132733Skanstatic void notice (const char *, ...) ATTRIBUTE_PRINTF_1;
338132733Skanstatic void display_help (void);
339132733Skanstatic void add_preprocessor_option (const char *, int);
340132733Skanstatic void add_assembler_option (const char *, int);
341132733Skanstatic void add_linker_option (const char *, int);
342132733Skanstatic void process_command (int, const char **);
343132733Skanstatic int execute (void);
344132733Skanstatic void alloc_args (void);
345132733Skanstatic void clear_args (void);
346132733Skanstatic void fatal_error (int);
347169704Skan#if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC)
348132733Skanstatic void init_gcc_specs (struct obstack *, const char *, const char *,
349132733Skan			    const char *);
35090277Sobrien#endif
35190277Sobrien#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
352132733Skanstatic const char *convert_filename (const char *, int, int);
35390277Sobrien#endif
354117413Skan
355132733Skanstatic const char *if_exists_spec_function (int, const char **);
356132733Skanstatic const char *if_exists_else_spec_function (int, const char **);
357169704Skanstatic const char *replace_outfile_spec_function (int, const char **);
358169704Skanstatic const char *version_compare_spec_function (int, const char **);
359169704Skanstatic const char *include_spec_function (int, const char **);
36090277Sobrien
36190277Sobrien/* The Specs Language
36218334Speter
36390277SobrienSpecs are strings containing lines, each of which (if not blank)
36418334Speteris made up of a program name, and arguments separated by spaces.
36518334SpeterThe program name must be exact and start from root, since no path
36618334Speteris searched and it is unreliable to depend on the current working directory.
36718334SpeterRedirection of input or output is not supported; the subprograms must
36818334Speteraccept filenames saying what files to read and write.
36918334Speter
37018334SpeterIn addition, the specs can contain %-sequences to substitute variable text
37118334Speteror for conditional text.  Here is a table of all defined %-sequences.
37218334SpeterNote that spaces are not generated automatically around the results of
37318334Speterexpanding these sequences; therefore, you can concatenate them together
37418334Speteror with constant text in a single argument.
37518334Speter
37618334Speter %%	substitute one % into the program name or argument.
37718334Speter %i     substitute the name of the input file being processed.
37818334Speter %b     substitute the basename of the input file being processed.
37918334Speter	This is the substring up to (and not including) the last period
38018334Speter	and not including the directory.
38190277Sobrien %B	same as %b, but include the file suffix (text after the last period).
38250599Sobrien %gSUFFIX
38350599Sobrien	substitute a file name that has suffix SUFFIX and is chosen
38450599Sobrien	once per compilation, and mark the argument a la %d.  To reduce
38550599Sobrien	exposure to denial-of-service attacks, the file name is now
38650599Sobrien	chosen in a way that is hard to predict even when previously
38750599Sobrien	chosen file names are known.  For example, `%g.s ... %g.o ... %g.s'
38850599Sobrien	might turn into `ccUVUUAU.s ccXYAXZ12.o ccUVUUAU.s'.  SUFFIX matches
389169704Skan	the regexp "[.0-9A-Za-z]*%O"; "%O" is treated exactly as if it
39090277Sobrien	had been pre-processed.  Previously, %g was simply substituted
39190277Sobrien	with a file name chosen once per compilation, without regard
39290277Sobrien	to any appended suffix (which was therefore treated just like
39390277Sobrien	ordinary text), making such attacks more likely to succeed.
394132733Skan %|SUFFIX
395132733Skan	like %g, but if -pipe is in effect, expands simply to "-".
396132733Skan %mSUFFIX
397132733Skan        like %g, but if -pipe is in effect, expands to nothing.  (We have both
398132733Skan	%| and %m to accommodate differences between system assemblers; see
399132733Skan	the AS_NEEDS_DASH_FOR_PIPED_INPUT target macro.)
40050599Sobrien %uSUFFIX
40150599Sobrien	like %g, but generates a new temporary file name even if %uSUFFIX
40250599Sobrien	was already seen.
40350599Sobrien %USUFFIX
40450599Sobrien	substitutes the last file name generated with %uSUFFIX, generating a
40550599Sobrien	new one if there is no such last file name.  In the absence of any
40650599Sobrien	%uSUFFIX, this is just like %gSUFFIX, except they don't share
40750599Sobrien	the same suffix "space", so `%g.s ... %U.s ... %g.s ... %U.s'
40850599Sobrien	would involve the generation of two distinct file names, one
40950599Sobrien	for each `%g.s' and another for each `%U.s'.  Previously, %U was
41050599Sobrien	simply substituted with a file name chosen for the previous %u,
41150599Sobrien	without regard to any appended suffix.
41290277Sobrien %jSUFFIX
41390277Sobrien        substitutes the name of the HOST_BIT_BUCKET, if any, and if it is
41490277Sobrien        writable, and if save-temps is off; otherwise, substitute the name
41590277Sobrien        of a temporary file, just like %u.  This temporary file is not
41690277Sobrien        meant for communication between processes, but rather as a junk
41790277Sobrien        disposal mechanism.
41890277Sobrien %.SUFFIX
41990277Sobrien        substitutes .SUFFIX for the suffixes of a matched switch's args when
42090277Sobrien        it is subsequently output with %*. SUFFIX is terminated by the next
42190277Sobrien        space or %.
42218334Speter %d	marks the argument containing or following the %d as a
42318334Speter	temporary file name, so that that file will be deleted if CC exits
42418334Speter	successfully.  Unlike %g, this contributes no text to the argument.
42518334Speter %w	marks the argument containing or following the %w as the
42618334Speter	"output file" of this compilation.  This puts the argument
42718334Speter	into the sequence of arguments that %o will substitute later.
428132733Skan %V	indicates that this compilation produces no "output file".
42918334Speter %W{...}
43018334Speter	like %{...} but mark last argument supplied within
43118334Speter	as a file to be deleted on failure.
43218334Speter %o	substitutes the names of all the output files, with spaces
43318334Speter	automatically placed around them.  You should write spaces
43418334Speter	around the %o as well or the results are undefined.
43518334Speter	%o is for use in the specs for running the linker.
43618334Speter	Input files whose names have no recognized suffix are not compiled
43718334Speter	at all, but they are included among the output files, so they will
43818334Speter	be linked.
43950599Sobrien %O	substitutes the suffix for object files.  Note that this is
44090277Sobrien        handled specially when it immediately follows %g, %u, or %U
44190277Sobrien	(with or without a suffix argument) because of the need for
44290277Sobrien	those to form complete file names.  The handling is such that
44390277Sobrien	%O is treated exactly as if it had already been substituted,
44490277Sobrien	except that %g, %u, and %U do not currently support additional
44590277Sobrien	SUFFIX characters following %O as they would following, for
44690277Sobrien	example, `.o'.
447132733Skan %I	Substitute any of -iprefix (made from GCC_EXEC_PREFIX), -isysroot
448169704Skan	(made from TARGET_SYSTEM_ROOT), -isystem (made from COMPILER_PATH
449169704Skan	and -B options) and -imultilib as necessary.
45018334Speter %s     current argument is the name of a library or startup file of some sort.
45118334Speter        Search for that file in a standard list of directories
45218334Speter	and substitute the full name found.
45318334Speter %eSTR  Print STR as an error message.  STR is terminated by a newline.
45418334Speter        Use this when inconsistent options are detected.
455117413Skan %nSTR  Print STR as a notice.  STR is terminated by a newline.
45618334Speter %x{OPTION}	Accumulate an option for %X.
45718334Speter %X	Output the accumulated linker options specified by compilations.
45818334Speter %Y	Output the accumulated assembler options specified by compilations.
45918334Speter %Z	Output the accumulated preprocessor options specified by compilations.
46018334Speter %a     process ASM_SPEC as a spec.
46118334Speter        This allows config.h to specify part of the spec for running as.
46218334Speter %A	process ASM_FINAL_SPEC as a spec.  A capital A is actually
46318334Speter	used here.  This can be used to run a post-processor after the
46450599Sobrien	assembler has done its job.
46518334Speter %D	Dump out a -L option for each directory in startfile_prefixes.
46618334Speter	If multilib_dir is set, extra entries are generated with it affixed.
46718334Speter %l     process LINK_SPEC as a spec.
46818334Speter %L     process LIB_SPEC as a spec.
46918334Speter %G     process LIBGCC_SPEC as a spec.
470169704Skan %R     Output the concatenation of target_system_root and
471169704Skan        target_sysroot_suffix.
47218334Speter %S     process STARTFILE_SPEC as a spec.  A capital S is actually used here.
47318334Speter %E     process ENDFILE_SPEC as a spec.  A capital E is actually used here.
47490277Sobrien %C     process CPP_SPEC as a spec.
47518334Speter %1	process CC1_SPEC as a spec.
47618334Speter %2	process CC1PLUS_SPEC as a spec.
47718334Speter %*	substitute the variable part of a matched option.  (See below.)
47818334Speter	Note that each comma in the substituted string is replaced by
47918334Speter	a single space.
480132733Skan %<S    remove all occurrences of -S from the command line.
481132733Skan        Note - this command is position dependent.  % commands in the
482132733Skan        spec string before this one will see -S, % commands in the
483132733Skan        spec string after this one will not.
484132733Skan %<S*	remove all occurrences of all switches beginning with -S from the
485132733Skan        command line.
486117413Skan %:function(args)
487117413Skan	Call the named function FUNCTION, passing it ARGS.  ARGS is
488117413Skan	first processed as a nested spec string, then split into an
489117413Skan	argument vector in the usual fashion.  The function returns
490117413Skan	a string which is processed as if it had appeared literally
491117413Skan	as part of the current spec.
49218334Speter %{S}   substitutes the -S switch, if that switch was given to CC.
49318334Speter	If that switch was not specified, this substitutes nothing.
49418334Speter	Here S is a metasyntactic variable.
49518334Speter %{S*}  substitutes all the switches specified to CC whose names start
49690277Sobrien	with -S.  This is used for -o, -I, etc; switches that take
49718334Speter	arguments.  CC considers `-o foo' as being one switch whose
49818334Speter	name starts with `o'.  %{o*} would substitute this text,
49918334Speter	including the space; thus, two arguments would be generated.
50090277Sobrien %{S*&T*} likewise, but preserve order of S and T options (the order
501132733Skan	of S and T in the spec is not significant).  Can be any number
502132733Skan	of ampersand-separated variables; for each the wild card is
503132733Skan	optional.  Useful for CPP as %{D*&U*&A*}.
504132733Skan
505132733Skan %{S:X}   substitutes X, if the -S switch was given to CC.
506132733Skan %{!S:X}  substitutes X, if the -S switch was NOT given to CC.
507132733Skan %{S*:X}  substitutes X if one or more switches whose names start
508132733Skan          with -S was given to CC.  Normally X is substituted only
509132733Skan          once, no matter how many such switches appeared.  However,
510132733Skan          if %* appears somewhere in X, then X will be substituted
511132733Skan          once for each matching switch, with the %* replaced by the
512132733Skan          part of that switch that matched the '*'.
513132733Skan %{.S:X}  substitutes X, if processing a file with suffix S.
514132733Skan %{!.S:X} substitutes X, if NOT processing a file with suffix S.
515132733Skan
516132733Skan %{S|T:X} substitutes X if either -S or -T was given to CC.  This may be
517132733Skan	  combined with !, ., and * as above binding stronger than the OR.
518132733Skan	  If %* appears in X, all of the alternatives must be starred, and
519132733Skan	  only the first matching alternative is substituted.
520132733Skan %{S:X;   if S was given to CC, substitutes X;
521132733Skan   T:Y;   else if T was given to CC, substitutes Y;
522132733Skan    :D}   else substitutes D.  There can be as many clauses as you need.
523132733Skan          This may be combined with ., !, |, and * as above.
524132733Skan
52518334Speter %(Spec) processes a specification defined in a specs file as *Spec:
52618334Speter %[Spec] as above, but put __ around -D arguments
52718334Speter
528132733SkanThe conditional text X in a %{S:X} or similar construct may contain
52918334Speterother nested % constructs or spaces, or even newlines.  They are
530132733Skanprocessed as usual, as described above.  Trailing white space in X is
531132733Skanignored.  White space may also appear anywhere on the left side of the
532132733Skancolon in these constructs, except between . or * and the corresponding
533132733Skanword.
53418334Speter
53518334SpeterThe -O, -f, -m, and -W switches are handled specifically in these
53618334Speterconstructs.  If another value of -O or the negated form of a -f, -m, or
53718334Speter-W switch is found later in the command line, the earlier switch
53818334Spetervalue is ignored, except with {S*} where S is just one letter; this
53918334Speterpasses all matching options.
54018334Speter
54150599SobrienThe character | at the beginning of the predicate text is used to indicate
54250599Sobrienthat a command should be piped to the following command, but only if -pipe
54350599Sobrienis specified.
54418334Speter
54518334SpeterNote that it is built into CC which switches take arguments and which
54618334Speterdo not.  You might think it would be useful to generalize this to
54718334Speterallow each compiler's spec to say which switches take arguments.  But
54818334Speterthis cannot be done in a consistent fashion.  CC cannot even decide
54918334Speterwhich input files have been specified without knowing which switches
55018334Spetertake arguments, and it must know which input files to compile in order
55118334Speterto tell which compilers to run.
55218334Speter
55318334SpeterCC also knows implicitly that arguments starting in `-l' are to be
55418334Spetertreated as compiler output files, and passed to the linker in their
55518334Speterproper position among the other output files.  */
55618334Speter
55796285Sobrien/* Define the macros used for specs %a, %l, %L, %S, %C, %1.  */
55818334Speter
55918334Speter/* config.h can define ASM_SPEC to provide extra args to the assembler
56018334Speter   or extra switch-translations.  */
56118334Speter#ifndef ASM_SPEC
56218334Speter#define ASM_SPEC ""
56318334Speter#endif
56418334Speter
56518334Speter/* config.h can define ASM_FINAL_SPEC to run a post processor after
56618334Speter   the assembler has run.  */
56718334Speter#ifndef ASM_FINAL_SPEC
56818334Speter#define ASM_FINAL_SPEC ""
56918334Speter#endif
57018334Speter
57118334Speter/* config.h can define CPP_SPEC to provide extra args to the C preprocessor
57218334Speter   or extra switch-translations.  */
57318334Speter#ifndef CPP_SPEC
57418334Speter#define CPP_SPEC ""
57518334Speter#endif
57618334Speter
57718334Speter/* config.h can define CC1_SPEC to provide extra args to cc1 and cc1plus
57818334Speter   or extra switch-translations.  */
57918334Speter#ifndef CC1_SPEC
58018334Speter#define CC1_SPEC ""
58118334Speter#endif
58218334Speter
58318334Speter/* config.h can define CC1PLUS_SPEC to provide extra args to cc1plus
58418334Speter   or extra switch-translations.  */
58518334Speter#ifndef CC1PLUS_SPEC
58618334Speter#define CC1PLUS_SPEC ""
58718334Speter#endif
58818334Speter
58918334Speter/* config.h can define LINK_SPEC to provide extra args to the linker
59018334Speter   or extra switch-translations.  */
59118334Speter#ifndef LINK_SPEC
59218334Speter#define LINK_SPEC ""
59318334Speter#endif
59418334Speter
59518334Speter/* config.h can define LIB_SPEC to override the default libraries.  */
59618334Speter#ifndef LIB_SPEC
59718334Speter#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
59818334Speter#endif
59918334Speter
600169704Skan/* mudflap specs */
601169704Skan#ifndef MFWRAP_SPEC
602169704Skan/* XXX: valid only for GNU ld */
603169704Skan/* XXX: should exactly match hooks provided by libmudflap.a */
604169704Skan#define MFWRAP_SPEC " %{static: %{fmudflap|fmudflapth: \
605169704Skan --wrap=malloc --wrap=free --wrap=calloc --wrap=realloc\
606169704Skan --wrap=mmap --wrap=munmap --wrap=alloca\
607169704Skan} %{fmudflapth: --wrap=pthread_create\
608169704Skan}} %{fmudflap|fmudflapth: --wrap=main}"
609169704Skan#endif
610169704Skan#ifndef MFLIB_SPEC
611169704Skan#define MFLIB_SPEC "%{fmudflap|fmudflapth: -export-dynamic}"
612169704Skan#endif
613169704Skan
61418334Speter/* config.h can define LIBGCC_SPEC to override how and when libgcc.a is
61518334Speter   included.  */
61618334Speter#ifndef LIBGCC_SPEC
617169704Skan#if defined(REAL_LIBGCC_SPEC)
618169704Skan#define LIBGCC_SPEC REAL_LIBGCC_SPEC
619169704Skan#elif defined(LINK_LIBGCC_SPECIAL_1)
62018334Speter/* Have gcc do the search for libgcc.a.  */
62150599Sobrien#define LIBGCC_SPEC "libgcc.a%s"
62218334Speter#else
62350599Sobrien#define LIBGCC_SPEC "-lgcc"
62418334Speter#endif
62518334Speter#endif
62618334Speter
62718334Speter/* config.h can define STARTFILE_SPEC to override the default crt0 files.  */
62818334Speter#ifndef STARTFILE_SPEC
62918334Speter#define STARTFILE_SPEC  \
63018334Speter  "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}"
63118334Speter#endif
63218334Speter
63350599Sobrien/* config.h can define SWITCHES_NEED_SPACES to control which options
63450599Sobrien   require spaces between the option and the argument.  */
63518334Speter#ifndef SWITCHES_NEED_SPACES
63618334Speter#define SWITCHES_NEED_SPACES ""
63718334Speter#endif
63818334Speter
63918334Speter/* config.h can define ENDFILE_SPEC to override the default crtn files.  */
64018334Speter#ifndef ENDFILE_SPEC
64118334Speter#define ENDFILE_SPEC ""
64218334Speter#endif
64318334Speter
64450599Sobrien#ifndef LINKER_NAME
64550599Sobrien#define LINKER_NAME "collect2"
64618334Speter#endif
64718334Speter
64890277Sobrien/* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g'
64990277Sobrien   to the assembler.  */
65090277Sobrien#ifndef ASM_DEBUG_SPEC
65190277Sobrien# if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \
65290277Sobrien     && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
65390277Sobrien#  define ASM_DEBUG_SPEC					\
65490277Sobrien      (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG			\
65590277Sobrien       ? "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}"	\
65690277Sobrien       : "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}")
65790277Sobrien# else
65890277Sobrien#  if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
65990277Sobrien#   define ASM_DEBUG_SPEC "%{g*:--gstabs}"
66090277Sobrien#  endif
66190277Sobrien#  if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG)
66290277Sobrien#   define ASM_DEBUG_SPEC "%{g*:--gdwarf2}"
66390277Sobrien#  endif
66490277Sobrien# endif
66590277Sobrien#endif
66690277Sobrien#ifndef ASM_DEBUG_SPEC
66790277Sobrien# define ASM_DEBUG_SPEC ""
66890277Sobrien#endif
66918334Speter
67090277Sobrien/* Here is the spec for running the linker, after compiling all files.  */
67190277Sobrien
67296285Sobrien/* This is overridable by the target in case they need to specify the
67396285Sobrien   -lgcc and -lc order specially, yet not require them to override all
67496285Sobrien   of LINK_COMMAND_SPEC.  */
67596285Sobrien#ifndef LINK_GCC_C_SEQUENCE_SPEC
67696285Sobrien#define LINK_GCC_C_SEQUENCE_SPEC "%G %L %G"
67796285Sobrien#endif
67896285Sobrien
679169704Skan#ifndef LINK_SSP_SPEC
680169704Skan#ifdef TARGET_LIBC_PROVIDES_SSP
681169704Skan#define LINK_SSP_SPEC "%{fstack-protector:}"
682169704Skan#else
683286713Spfg#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-strong|fstack-protector-all:-lssp_nonshared -lssp}"
684169704Skan#endif
685169704Skan#endif
686169704Skan
687132733Skan#ifndef LINK_PIE_SPEC
688132733Skan#ifdef HAVE_LD_PIE
689132733Skan#define LINK_PIE_SPEC "%{pie:-pie} "
690132733Skan#else
691132733Skan#define LINK_PIE_SPEC "%{pie:} "
692132733Skan#endif
693132733Skan#endif
694132733Skan
69590277Sobrien/* -u* was put back because both BSD and SysV seem to support it.  */
69690277Sobrien/* %{static:} simply prevents an error message if the target machine
69790277Sobrien   doesn't handle -static.  */
69890277Sobrien/* We want %{T*} after %{L*} and %D so that it can be used to specify linker
69990277Sobrien   scripts which exist in user specified directories, or in standard
70090277Sobrien   directories.  */
70190277Sobrien#ifndef LINK_COMMAND_SPEC
702169704Skan#ifndef FREEBSD_NATIVE
70390277Sobrien#define LINK_COMMAND_SPEC "\
70490277Sobrien%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
705132733Skan    %(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
706132733Skan    %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
707169704Skan    %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
708169704Skan    %{fopenmp:%:include(libgomp.spec)%(link_gomp)} %(mflib)\
709169704Skan    %{fprofile-arcs|fprofile-generate|coverage:-lgcov}\
710169704Skan    %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
71190277Sobrien    %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
712169704Skan#else
713169704Skan#define LINK_COMMAND_SPEC "\
714169704Skan%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
715169704Skan    %(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
716169704Skan    %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
717169704Skan    %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
718169704Skan    %{fopenmp: -lgomp} %(mflib)\
719169704Skan    %{fprofile-arcs|fprofile-generate|coverage:-lgcov}\
720169704Skan    %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
721169704Skan    %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
72290277Sobrien#endif
723169704Skan#endif
72490277Sobrien
72590277Sobrien#ifndef LINK_LIBGCC_SPEC
726169704Skan/* Generate -L options for startfile prefix list.  */
727169704Skan# define LINK_LIBGCC_SPEC "%D"
72890277Sobrien#endif
72990277Sobrien
730117413Skan#ifndef STARTFILE_PREFIX_SPEC
731117413Skan# define STARTFILE_PREFIX_SPEC ""
732117413Skan#endif
733117413Skan
734169704Skan#ifndef SYSROOT_SPEC
735169704Skan# define SYSROOT_SPEC "--sysroot=%R"
736169704Skan#endif
737169704Skan
738132733Skan#ifndef SYSROOT_SUFFIX_SPEC
739132733Skan# define SYSROOT_SUFFIX_SPEC ""
740132733Skan#endif
741132733Skan
742132733Skan#ifndef SYSROOT_HEADERS_SUFFIX_SPEC
743132733Skan# define SYSROOT_HEADERS_SUFFIX_SPEC ""
744132733Skan#endif
745132733Skan
746117413Skanstatic const char *asm_debug;
74790277Sobrienstatic const char *cpp_spec = CPP_SPEC;
74890277Sobrienstatic const char *cc1_spec = CC1_SPEC;
74990277Sobrienstatic const char *cc1plus_spec = CC1PLUS_SPEC;
75096285Sobrienstatic const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC;
751169704Skanstatic const char *link_ssp_spec = LINK_SSP_SPEC;
75290277Sobrienstatic const char *asm_spec = ASM_SPEC;
75390277Sobrienstatic const char *asm_final_spec = ASM_FINAL_SPEC;
75490277Sobrienstatic const char *link_spec = LINK_SPEC;
75590277Sobrienstatic const char *lib_spec = LIB_SPEC;
756169704Skanstatic const char *mfwrap_spec = MFWRAP_SPEC;
757169704Skanstatic const char *mflib_spec = MFLIB_SPEC;
758169704Skanstatic const char *link_gomp_spec = "";
75990277Sobrienstatic const char *libgcc_spec = LIBGCC_SPEC;
76090277Sobrienstatic const char *endfile_spec = ENDFILE_SPEC;
76190277Sobrienstatic const char *startfile_spec = STARTFILE_SPEC;
76290277Sobrienstatic const char *switches_need_spaces = SWITCHES_NEED_SPACES;
76390277Sobrienstatic const char *linker_name_spec = LINKER_NAME;
76490277Sobrienstatic const char *link_command_spec = LINK_COMMAND_SPEC;
76590277Sobrienstatic const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
766117413Skanstatic const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC;
767169704Skanstatic const char *sysroot_spec = SYSROOT_SPEC;
768132733Skanstatic const char *sysroot_suffix_spec = SYSROOT_SUFFIX_SPEC;
769132733Skanstatic const char *sysroot_hdrs_suffix_spec = SYSROOT_HEADERS_SUFFIX_SPEC;
77090277Sobrien
77190277Sobrien/* Standard options to cpp, cc1, and as, to reduce duplication in specs.
77290277Sobrien   There should be no need to override these in target dependent files,
77390277Sobrien   but we need to copy them to the specs file so that newer versions
77490277Sobrien   of the GCC driver can correctly drive older tool chains with the
77590277Sobrien   appropriate -B options.  */
77690277Sobrien
777117413Skan/* When cpplib handles traditional preprocessing, get rid of this, and
778117413Skan   call cc1 (or cc1obj in objc/lang-specs.h) from the main specs so
779117413Skan   that we default the front end language better.  */
78090277Sobrienstatic const char *trad_capable_cpp =
781117413Skan"cc1 -E %{traditional|ftraditional|traditional-cpp:-traditional-cpp}";
78290277Sobrien
783107594Sobrien/* We don't wrap .d files in %W{} since a missing .d file, and
784107594Sobrien   therefore no dependency entry, confuses make into thinking a .o
785107594Sobrien   file that happens to exist is up-to-date.  */
78690277Sobrienstatic const char *cpp_unique_options =
787132733Skan"%{C|CC:%{!E:%eGCC does not support -C or -CC without -E}}\
788169704Skan %{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*&F*} %{P} %I\
789107594Sobrien %{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\
790107594Sobrien %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\
791107594Sobrien %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\
79296285Sobrien %{!E:%{!M:%{!MM:%{MD|MMD:%{o*:-MQ %*}}}}}\
793146908Skan %{remap} %{g3:-dD} %{H} %C %{D*&U*&A*} %{i*} %Z %i\
794169704Skan %{fmudflap:-D_MUDFLAP -include mf-runtime.h}\
795169704Skan %{fmudflapth:-D_MUDFLAP -D_MUDFLAPTH -include mf-runtime.h}\
79696285Sobrien %{E|M|MM:%W{o*}}";
79790277Sobrien
79890277Sobrien/* This contains cpp options which are common with cc1_options and are passed
799117413Skan   only when preprocessing only to avoid duplication.  We pass the cc1 spec
800117413Skan   options to the preprocessor so that it the cc1 spec may manipulate
801117413Skan   options used to set target flags.  Those special target flags settings may
802117413Skan   in turn cause preprocessor symbols to be defined specially.  */
80390277Sobrienstatic const char *cpp_options =
804146908Skan"%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w}\
805146908Skan %{f*} %{g*:%{!g0:%{!fno-working-directory:-fworking-directory}}} %{O*}\
806169704Skan %{undef} %{save-temps:-fpch-preprocess}";
80790277Sobrien
808117413Skan/* This contains cpp options which are not passed when the preprocessor
809117413Skan   output will be used by another program.  */
810117413Skanstatic const char *cpp_debug_options = "%{d*}";
811117413Skan
81290277Sobrien/* NB: This is shared amongst all front-ends.  */
81390277Sobrienstatic const char *cc1_options =
81490277Sobrien"%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
81590277Sobrien %1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\
816132733Skan %{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}%{!c:%{!S:-auxbase %b}}\
817146908Skan %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs}\
818117413Skan %{v:-version} %{pg:-p} %{p} %{f*} %{undef}\
81990277Sobrien %{Qn:-fno-ident} %{--help:--help}\
82090277Sobrien %{--target-help:--target-help}\
82190277Sobrien %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\
822169704Skan %{fsyntax-only:-o %j} %{-param*}\
823169704Skan %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants}\
824169704Skan %{coverage:-fprofile-arcs -ftest-coverage}";
82590277Sobrien
82690277Sobrienstatic const char *asm_options =
82790277Sobrien"%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
82890277Sobrien
82990277Sobrienstatic const char *invoke_as =
830132733Skan#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
831132733Skan"%{!S:-o %|.s |\n as %(asm_options) %|.s %A }";
832132733Skan#else
833132733Skan"%{!S:-o %|.s |\n as %(asm_options) %m.s %A }";
834132733Skan#endif
83590277Sobrien
83650599Sobrien/* Some compilers have limits on line lengths, and the multilib_select
83750599Sobrien   and/or multilib_matches strings can be very long, so we build them at
83850599Sobrien   run time.  */
83950599Sobrienstatic struct obstack multilib_obstack;
84090277Sobrienstatic const char *multilib_select;
84190277Sobrienstatic const char *multilib_matches;
84290277Sobrienstatic const char *multilib_defaults;
84390277Sobrienstatic const char *multilib_exclusions;
84450599Sobrien
84550599Sobrien/* Check whether a particular argument is a default argument.  */
84650599Sobrien
84750599Sobrien#ifndef MULTILIB_DEFAULTS
84850599Sobrien#define MULTILIB_DEFAULTS { "" }
84950599Sobrien#endif
85050599Sobrien
85190277Sobrienstatic const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
85250599Sobrien
853117413Skan#ifndef DRIVER_SELF_SPECS
854117413Skan#define DRIVER_SELF_SPECS ""
855117413Skan#endif
856117413Skan
857169704Skan/* Adding -fopenmp should imply pthreads.  This is particularly important
858169704Skan   for targets that use different start files and suchlike.  */
859169704Skan#ifndef GOMP_SELF_SPECS
860169704Skan#define GOMP_SELF_SPECS "%{fopenmp: -pthread}"
861169704Skan#endif
862117413Skan
863169704Skanstatic const char *const driver_self_specs[] = {
864169704Skan  DRIVER_SELF_SPECS, GOMP_SELF_SPECS
865169704Skan};
866169704Skan
867132733Skan#ifndef OPTION_DEFAULT_SPECS
868132733Skan#define OPTION_DEFAULT_SPECS { "", "" }
869132733Skan#endif
870132733Skan
871132733Skanstruct default_spec
872132733Skan{
873132733Skan  const char *name;
874132733Skan  const char *spec;
875132733Skan};
876132733Skan
877132733Skanstatic const struct default_spec
878132733Skan  option_default_specs[] = { OPTION_DEFAULT_SPECS };
879132733Skan
88090277Sobrienstruct user_specs
88190277Sobrien{
88250599Sobrien  struct user_specs *next;
88352520Sobrien  const char *filename;
88450599Sobrien};
88550599Sobrien
88650599Sobrienstatic struct user_specs *user_specs_head, *user_specs_tail;
88750599Sobrien
88850599Sobrien#ifndef SWITCH_TAKES_ARG
88950599Sobrien#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
89018334Speter#endif
89118334Speter
89218334Speter#ifndef WORD_SWITCH_TAKES_ARG
89318334Speter#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
89418334Speter#endif
89518334Speter
89690277Sobrien#ifdef HAVE_TARGET_EXECUTABLE_SUFFIX
89750599Sobrien/* This defines which switches stop a full compilation.  */
89850599Sobrien#define DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) \
89950599Sobrien  ((CHAR) == 'c' || (CHAR) == 'S')
90050599Sobrien
90150599Sobrien#ifndef SWITCH_CURTAILS_COMPILATION
90250599Sobrien#define SWITCH_CURTAILS_COMPILATION(CHAR) \
90350599Sobrien  DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR)
90450599Sobrien#endif
90550599Sobrien#endif
90650599Sobrien
90718334Speter/* Record the mapping from file suffixes for compilation specs.  */
90818334Speter
90918334Speterstruct compiler
91018334Speter{
91152520Sobrien  const char *suffix;		/* Use this compiler for input files
91218334Speter				   whose names end in this suffix.  */
91318334Speter
91490277Sobrien  const char *spec;		/* To use this compiler, run this spec.  */
91590277Sobrien
91690277Sobrien  const char *cpp_spec;         /* If non-NULL, substitute this spec
91790277Sobrien				   for `%C', rather than the usual
91890277Sobrien				   cpp_spec.  */
919169704Skan  const int combinable;          /* If nonzero, compiler can deal with
920169704Skan				    multiple source files at once (IMA).  */
921169704Skan  const int needs_preprocessing; /* If nonzero, source files need to
922169704Skan				    be run through a preprocessor.  */
92318334Speter};
92418334Speter
92518334Speter/* Pointer to a vector of `struct compiler' that gives the spec for
92618334Speter   compiling a file, based on its suffix.
92718334Speter   A file that does not end in any of these suffixes will be passed
92818334Speter   unchanged to the loader and nothing else will be done to it.
92918334Speter
93018334Speter   An entry containing two 0s is used to terminate the vector.
93118334Speter
93218334Speter   If multiple entries match a file, the last matching one is used.  */
93318334Speter
93418334Speterstatic struct compiler *compilers;
93518334Speter
93618334Speter/* Number of entries in `compilers', not counting the null terminator.  */
93718334Speter
93818334Speterstatic int n_compilers;
93918334Speter
94018334Speter/* The default list of file name suffixes and their compilation specs.  */
94118334Speter
94290277Sobrienstatic const struct compiler default_compilers[] =
94318334Speter{
94450599Sobrien  /* Add lists of suffixes of known languages here.  If those languages
94550599Sobrien     were not present when we built the driver, we will hit these copies
94650599Sobrien     and be given a more meaningful error than "file not used since
94750599Sobrien     linking is not done".  */
948169704Skan  {".m",  "#Objective-C", 0, 0, 0}, {".mi",  "#Objective-C", 0, 0, 0},
949169704Skan  {".mm", "#Objective-C++", 0, 0, 0}, {".M", "#Objective-C++", 0, 0, 0},
950169704Skan  {".mii", "#Objective-C++", 0, 0, 0},
951169704Skan  {".cc", "#C++", 0, 0, 0}, {".cxx", "#C++", 0, 0, 0},
952169704Skan  {".cpp", "#C++", 0, 0, 0}, {".cp", "#C++", 0, 0, 0},
953169704Skan  {".c++", "#C++", 0, 0, 0}, {".C", "#C++", 0, 0, 0},
954169704Skan  {".CPP", "#C++", 0, 0, 0}, {".ii", "#C++", 0, 0, 0},
955169704Skan  {".ads", "#Ada", 0, 0, 0}, {".adb", "#Ada", 0, 0, 0},
956169704Skan  {".f", "#Fortran", 0, 0, 0}, {".for", "#Fortran", 0, 0, 0},
957169704Skan  {".fpp", "#Fortran", 0, 0, 0}, {".F", "#Fortran", 0, 0, 0},
958169704Skan  {".FOR", "#Fortran", 0, 0, 0}, {".FPP", "#Fortran", 0, 0, 0},
959169704Skan  {".f90", "#Fortran", 0, 0, 0}, {".f95", "#Fortran", 0, 0, 0},
960169704Skan  {".F90", "#Fortran", 0, 0, 0}, {".F95", "#Fortran", 0, 0, 0},
961169704Skan  {".r", "#Ratfor", 0, 0, 0},
962169704Skan  {".p", "#Pascal", 0, 0, 0}, {".pas", "#Pascal", 0, 0, 0},
963169704Skan  {".java", "#Java", 0, 0, 0}, {".class", "#Java", 0, 0, 0},
964169704Skan  {".zip", "#Java", 0, 0, 0}, {".jar", "#Java", 0, 0, 0},
96550599Sobrien  /* Next come the entries for C.  */
966169704Skan  {".c", "@c", 0, 1, 1},
96718334Speter  {"@c",
96890277Sobrien   /* cc1 has an integrated ISO C preprocessor.  We should invoke the
969117413Skan      external preprocessor if -save-temps is given.  */
970117413Skan     "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
97190277Sobrien      %{!E:%{!M:%{!MM:\
972117413Skan          %{traditional|ftraditional:\
973117413Skan%eGNU C no longer supports -traditional without -E}\
974169704Skan       %{!combine:\
975117413Skan	  %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
976132733Skan		%(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\
977132733Skan		    cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \
978132733Skan			%(cc1_options)}\
979117413Skan	  %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
980117413Skan		cc1 %(cpp_unique_options) %(cc1_options)}}}\
981169704Skan          %{!fsyntax-only:%(invoke_as)}} \
982169704Skan      %{combine:\
983169704Skan	  %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
984169704Skan		%(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i}}\
985169704Skan	  %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
986169704Skan		cc1 %(cpp_unique_options) %(cc1_options)}}\
987169704Skan                %{!fsyntax-only:%(invoke_as)}}}}}}", 0, 1, 1},
98818334Speter  {"-",
989146908Skan   "%{!E:%e-E or -x required when input is from standard input}\
990169704Skan    %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 0, 0, 0},
991169704Skan  {".h", "@c-header", 0, 0, 0},
99218334Speter  {"@c-header",
993132733Skan   /* cc1 has an integrated ISO C preprocessor.  We should invoke the
994132733Skan      external preprocessor if -save-temps is given.  */
995132733Skan     "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
996132733Skan      %{!E:%{!M:%{!MM:\
997132733Skan	  %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
998132733Skan		%(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\
999132733Skan		    cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \
1000132733Skan			%(cc1_options)\
1001132733Skan                        -o %g.s %{!o*:--output-pch=%i.gch}\
1002132733Skan                        %W{o*:--output-pch=%*}%V}\
1003132733Skan	  %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
1004132733Skan		cc1 %(cpp_unique_options) %(cc1_options)\
1005132733Skan                    -o %g.s %{!o*:--output-pch=%i.gch}\
1006169704Skan                    %W{o*:--output-pch=%*}%V}}}}}}", 0, 0, 0},
1007169704Skan  {".i", "@cpp-output", 0, 1, 0},
100818334Speter  {"@cpp-output",
1009169704Skan   "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 1, 0},
1010169704Skan  {".s", "@assembler", 0, 1, 0},
101118334Speter  {"@assembler",
1012169704Skan   "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0, 1, 0},
1013169704Skan  {".S", "@assembler-with-cpp", 0, 1, 0},
101418334Speter  {"@assembler-with-cpp",
1015132733Skan#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
101690277Sobrien   "%(trad_capable_cpp) -lang-asm %(cpp_options)\
1017117413Skan      %{E|M|MM:%(cpp_debug_options)}\
1018132733Skan      %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
1019132733Skan       as %(asm_debug) %(asm_options) %|.s %A }}}}"
1020132733Skan#else
1021132733Skan   "%(trad_capable_cpp) -lang-asm %(cpp_options)\
1022132733Skan      %{E|M|MM:%(cpp_debug_options)}\
1023132733Skan      %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
1024132733Skan       as %(asm_debug) %(asm_options) %m.s %A }}}}"
1025132733Skan#endif
1026169704Skan   , 0, 1, 0},
1027132733Skan
102818334Speter#include "specs.h"
1029132733Skan  /* Mark end of table.  */
1030169704Skan  {0, 0, 0, 0, 0}
103118334Speter};
103218334Speter
103318334Speter/* Number of elements in default_compilers, not counting the terminator.  */
103418334Speter
1035117413Skanstatic const int n_default_compilers = ARRAY_SIZE (default_compilers) - 1;
103618334Speter
103718334Speter/* A vector of options to give to the linker.
103818334Speter   These options are accumulated by %x,
103918334Speter   and substituted into the linker command with %X.  */
104018334Speterstatic int n_linker_options;
104118334Speterstatic char **linker_options;
104218334Speter
104318334Speter/* A vector of options to give to the assembler.
104418334Speter   These options are accumulated by -Wa,
104518334Speter   and substituted into the assembler command with %Y.  */
104618334Speterstatic int n_assembler_options;
104718334Speterstatic char **assembler_options;
104818334Speter
104918334Speter/* A vector of options to give to the preprocessor.
105018334Speter   These options are accumulated by -Wp,
105118334Speter   and substituted into the preprocessor command with %Z.  */
105218334Speterstatic int n_preprocessor_options;
105318334Speterstatic char **preprocessor_options;
105418334Speter
105518334Speter/* Define how to map long options into short ones.  */
105618334Speter
105718334Speter/* This structure describes one mapping.  */
105818334Speterstruct option_map
105918334Speter{
106018334Speter  /* The long option's name.  */
106190277Sobrien  const char *const name;
106218334Speter  /* The equivalent short option.  */
106390277Sobrien  const char *const equivalent;
106418334Speter  /* Argument info.  A string of flag chars; NULL equals no options.
106518334Speter     a => argument required.
106618334Speter     o => argument optional.
106718334Speter     j => join argument to equivalent, making one word.
106818334Speter     * => require other text after NAME as an argument.  */
106990277Sobrien  const char *const arg_info;
107018334Speter};
107118334Speter
107218334Speter/* This is the table of mappings.  Mappings are tried sequentially
107318334Speter   for each option encountered; the first one that matches, wins.  */
107418334Speter
107590277Sobrienstatic const struct option_map option_map[] =
107618334Speter {
107718334Speter   {"--all-warnings", "-Wall", 0},
107818334Speter   {"--ansi", "-ansi", 0},
107918334Speter   {"--assemble", "-S", 0},
108018334Speter   {"--assert", "-A", "a"},
108152520Sobrien   {"--classpath", "-fclasspath=", "aj"},
108296285Sobrien   {"--bootclasspath", "-fbootclasspath=", "aj"},
108396285Sobrien   {"--CLASSPATH", "-fclasspath=", "aj"},
1084169704Skan   {"--combine", "-combine", 0},
108518334Speter   {"--comments", "-C", 0},
1086117413Skan   {"--comments-in-macros", "-CC", 0},
108718334Speter   {"--compile", "-c", 0},
108818334Speter   {"--debug", "-g", "oj"},
108950599Sobrien   {"--define-macro", "-D", "aj"},
109018334Speter   {"--dependencies", "-M", 0},
109118334Speter   {"--dump", "-d", "a"},
109218334Speter   {"--dumpbase", "-dumpbase", "a"},
1093169704Skan   {"--encoding", "-fencoding=", "aj"},
109418334Speter   {"--entry", "-e", 0},
109518334Speter   {"--extra-warnings", "-W", 0},
1096169704Skan   {"--extdirs", "-fextdirs=", "aj"},
109718334Speter   {"--for-assembler", "-Wa", "a"},
109818334Speter   {"--for-linker", "-Xlinker", "a"},
109918334Speter   {"--force-link", "-u", "a"},
1100169704Skan   {"--coverage", "-coverage", 0},
110118334Speter   {"--imacros", "-imacros", "a"},
110218334Speter   {"--include", "-include", "a"},
110318334Speter   {"--include-barrier", "-I-", 0},
110450599Sobrien   {"--include-directory", "-I", "aj"},
110518334Speter   {"--include-directory-after", "-idirafter", "a"},
110618334Speter   {"--include-prefix", "-iprefix", "a"},
110718334Speter   {"--include-with-prefix", "-iwithprefix", "a"},
110818334Speter   {"--include-with-prefix-before", "-iwithprefixbefore", "a"},
110918334Speter   {"--include-with-prefix-after", "-iwithprefix", "a"},
111018334Speter   {"--language", "-x", "a"},
111118334Speter   {"--library-directory", "-L", "a"},
111218334Speter   {"--machine", "-m", "aj"},
111318334Speter   {"--machine-", "-m", "*j"},
111496285Sobrien   {"--no-integrated-cpp", "-no-integrated-cpp", 0},
111518334Speter   {"--no-line-commands", "-P", 0},
111618334Speter   {"--no-precompiled-includes", "-noprecomp", 0},
111718334Speter   {"--no-standard-includes", "-nostdinc", 0},
111818334Speter   {"--no-standard-libraries", "-nostdlib", 0},
111918334Speter   {"--no-warnings", "-w", 0},
112018334Speter   {"--optimize", "-O", "oj"},
112118334Speter   {"--output", "-o", "a"},
112252520Sobrien   {"--output-class-directory", "-foutput-class-dir=", "ja"},
112390277Sobrien   {"--param", "--param", "a"},
1124169704Skan   {"--pass-exit-codes", "-pass-exit-codes", 0},
112518334Speter   {"--pedantic", "-pedantic", 0},
112618334Speter   {"--pedantic-errors", "-pedantic-errors", 0},
1127132733Skan   {"--pie", "-pie", 0},
112818334Speter   {"--pipe", "-pipe", 0},
112918334Speter   {"--prefix", "-B", "a"},
113018334Speter   {"--preprocess", "-E", 0},
113118334Speter   {"--print-search-dirs", "-print-search-dirs", 0},
113218334Speter   {"--print-file-name", "-print-file-name=", "aj"},
113318334Speter   {"--print-libgcc-file-name", "-print-libgcc-file-name", 0},
113418334Speter   {"--print-missing-file-dependencies", "-MG", 0},
113518334Speter   {"--print-multi-lib", "-print-multi-lib", 0},
113618334Speter   {"--print-multi-directory", "-print-multi-directory", 0},
1137104763Skan   {"--print-multi-os-directory", "-print-multi-os-directory", 0},
113818334Speter   {"--print-prog-name", "-print-prog-name=", "aj"},
113918334Speter   {"--profile", "-p", 0},
114018334Speter   {"--profile-blocks", "-a", 0},
114118334Speter   {"--quiet", "-q", 0},
114296285Sobrien   {"--resource", "-fcompile-resource=", "aj"},
114318334Speter   {"--save-temps", "-save-temps", 0},
114418334Speter   {"--shared", "-shared", 0},
114518334Speter   {"--silent", "-q", 0},
114650599Sobrien   {"--specs", "-specs=", "aj"},
114718334Speter   {"--static", "-static", 0},
114852520Sobrien   {"--std", "-std=", "aj"},
114918334Speter   {"--symbolic", "-symbolic", 0},
1150169704Skan   {"--sysroot", "--sysroot=", "aj"},
115190277Sobrien   {"--time", "-time", 0},
115218334Speter   {"--trace-includes", "-H", 0},
115318334Speter   {"--traditional", "-traditional", 0},
115418334Speter   {"--traditional-cpp", "-traditional-cpp", 0},
115518334Speter   {"--trigraphs", "-trigraphs", 0},
115650599Sobrien   {"--undefine-macro", "-U", "aj"},
115718334Speter   {"--user-dependencies", "-MM", 0},
115818334Speter   {"--verbose", "-v", 0},
115918334Speter   {"--warn-", "-W", "*j"},
116018334Speter   {"--write-dependencies", "-MD", 0},
116118334Speter   {"--write-user-dependencies", "-MMD", 0},
116218334Speter   {"--", "-f", "*j"}
116318334Speter };
116418334Speter
116590277Sobrien
116690277Sobrien#ifdef TARGET_OPTION_TRANSLATE_TABLE
116790277Sobrienstatic const struct {
116890277Sobrien  const char *const option_found;
116990277Sobrien  const char *const replacements;
117090277Sobrien} target_option_translations[] =
117190277Sobrien{
117290277Sobrien  TARGET_OPTION_TRANSLATE_TABLE,
117390277Sobrien  { 0, 0 }
117490277Sobrien};
117590277Sobrien#endif
117690277Sobrien
117718334Speter/* Translate the options described by *ARGCP and *ARGVP.
117818334Speter   Make a new vector and store it back in *ARGVP,
117918334Speter   and store its length in *ARGVC.  */
118018334Speter
118118334Speterstatic void
1182132733Skantranslate_options (int *argcp, const char *const **argvp)
118318334Speter{
118452520Sobrien  int i;
118518334Speter  int argc = *argcp;
118690277Sobrien  const char *const *argv = *argvp;
118790277Sobrien  int newvsize = (argc + 2) * 2 * sizeof (const char *);
1188132733Skan  const char **newv = xmalloc (newvsize);
118918334Speter  int newindex = 0;
119018334Speter
119118334Speter  i = 0;
119218334Speter  newv[newindex++] = argv[i++];
119318334Speter
119418334Speter  while (i < argc)
119518334Speter    {
119690277Sobrien#ifdef TARGET_OPTION_TRANSLATE_TABLE
119790277Sobrien      int tott_idx;
119890277Sobrien
119990277Sobrien      for (tott_idx = 0;
120090277Sobrien	   target_option_translations[tott_idx].option_found;
120190277Sobrien	   tott_idx++)
120290277Sobrien	{
120390277Sobrien	  if (strcmp (target_option_translations[tott_idx].option_found,
120490277Sobrien		      argv[i]) == 0)
120590277Sobrien	    {
120690277Sobrien	      int spaces = 1;
120790277Sobrien	      const char *sp;
120890277Sobrien	      char *np;
120990277Sobrien
121090277Sobrien	      for (sp = target_option_translations[tott_idx].replacements;
121190277Sobrien		   *sp; sp++)
121290277Sobrien		{
121390277Sobrien		  if (*sp == ' ')
121490277Sobrien		    spaces ++;
121590277Sobrien		}
121690277Sobrien
121790277Sobrien	      newvsize += spaces * sizeof (const char *);
1218132733Skan	      newv =  xrealloc (newv, newvsize);
121990277Sobrien
122090277Sobrien	      sp = target_option_translations[tott_idx].replacements;
122190277Sobrien	      np = xstrdup (sp);
122290277Sobrien
122390277Sobrien	      while (1)
122490277Sobrien		{
122590277Sobrien		  while (*np == ' ')
122690277Sobrien		    np++;
122790277Sobrien		  if (*np == 0)
122890277Sobrien		    break;
122990277Sobrien		  newv[newindex++] = np;
123090277Sobrien		  while (*np != ' ' && *np)
123190277Sobrien		    np++;
123290277Sobrien		  if (*np == 0)
123390277Sobrien		    break;
123490277Sobrien		  *np++ = 0;
123590277Sobrien		}
123690277Sobrien
123790277Sobrien	      i ++;
123890277Sobrien	      break;
123990277Sobrien	    }
124090277Sobrien	}
124190277Sobrien      if (target_option_translations[tott_idx].option_found)
124290277Sobrien	continue;
124390277Sobrien#endif
124490277Sobrien
124518334Speter      /* Translate -- options.  */
124618334Speter      if (argv[i][0] == '-' && argv[i][1] == '-')
124718334Speter	{
124852520Sobrien	  size_t j;
124918334Speter	  /* Find a mapping that applies to this option.  */
125090277Sobrien	  for (j = 0; j < ARRAY_SIZE (option_map); j++)
125118334Speter	    {
125250599Sobrien	      size_t optlen = strlen (option_map[j].name);
125350599Sobrien	      size_t arglen = strlen (argv[i]);
125450599Sobrien	      size_t complen = arglen > optlen ? optlen : arglen;
125552520Sobrien	      const char *arginfo = option_map[j].arg_info;
125618334Speter
125718334Speter	      if (arginfo == 0)
125818334Speter		arginfo = "";
125918334Speter
126018334Speter	      if (!strncmp (argv[i], option_map[j].name, complen))
126118334Speter		{
126252520Sobrien		  const char *arg = 0;
126318334Speter
126418334Speter		  if (arglen < optlen)
126518334Speter		    {
126652520Sobrien		      size_t k;
126790277Sobrien		      for (k = j + 1; k < ARRAY_SIZE (option_map); k++)
126818334Speter			if (strlen (option_map[k].name) >= arglen
126918334Speter			    && !strncmp (argv[i], option_map[k].name, arglen))
127018334Speter			  {
127190277Sobrien			    error ("ambiguous abbreviation %s", argv[i]);
127218334Speter			    break;
127318334Speter			  }
127418334Speter
127590277Sobrien		      if (k != ARRAY_SIZE (option_map))
127618334Speter			break;
127718334Speter		    }
127818334Speter
127918334Speter		  if (arglen > optlen)
128018334Speter		    {
128118334Speter		      /* If the option has an argument, accept that.  */
128218334Speter		      if (argv[i][optlen] == '=')
128318334Speter			arg = argv[i] + optlen + 1;
128418334Speter
128518334Speter		      /* If this mapping requires extra text at end of name,
128618334Speter			 accept that as "argument".  */
128790277Sobrien		      else if (strchr (arginfo, '*') != 0)
128818334Speter			arg = argv[i] + optlen;
128918334Speter
129018334Speter		      /* Otherwise, extra text at end means mismatch.
129118334Speter			 Try other mappings.  */
129218334Speter		      else
129318334Speter			continue;
129418334Speter		    }
129518334Speter
129690277Sobrien		  else if (strchr (arginfo, '*') != 0)
129718334Speter		    {
1298169704Skan		      error ("incomplete '%s' option", option_map[j].name);
129918334Speter		      break;
130018334Speter		    }
130118334Speter
130218334Speter		  /* Handle arguments.  */
130390277Sobrien		  if (strchr (arginfo, 'a') != 0)
130418334Speter		    {
130518334Speter		      if (arg == 0)
130618334Speter			{
130718334Speter			  if (i + 1 == argc)
130818334Speter			    {
1309169704Skan			      error ("missing argument to '%s' option",
131018334Speter				     option_map[j].name);
131118334Speter			      break;
131218334Speter			    }
131318334Speter
131418334Speter			  arg = argv[++i];
131518334Speter			}
131618334Speter		    }
131790277Sobrien		  else if (strchr (arginfo, '*') != 0)
131818334Speter		    ;
131990277Sobrien		  else if (strchr (arginfo, 'o') == 0)
132018334Speter		    {
132118334Speter		      if (arg != 0)
1322169704Skan			error ("extraneous argument to '%s' option",
132318334Speter			       option_map[j].name);
132418334Speter		      arg = 0;
132518334Speter		    }
132618334Speter
132718334Speter		  /* Store the translation as one argv elt or as two.  */
132890277Sobrien		  if (arg != 0 && strchr (arginfo, 'j') != 0)
132950599Sobrien		    newv[newindex++] = concat (option_map[j].equivalent, arg,
133090277Sobrien					       NULL);
133118334Speter		  else if (arg != 0)
133218334Speter		    {
133318334Speter		      newv[newindex++] = option_map[j].equivalent;
133418334Speter		      newv[newindex++] = arg;
133518334Speter		    }
133618334Speter		  else
133718334Speter		    newv[newindex++] = option_map[j].equivalent;
133818334Speter
133918334Speter		  break;
134018334Speter		}
134118334Speter	    }
134218334Speter	  i++;
134318334Speter	}
134418334Speter
134518334Speter      /* Handle old-fashioned options--just copy them through,
134618334Speter	 with their arguments.  */
134718334Speter      else if (argv[i][0] == '-')
134818334Speter	{
134952520Sobrien	  const char *p = argv[i] + 1;
135018334Speter	  int c = *p;
135118334Speter	  int nskip = 1;
135218334Speter
135318334Speter	  if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
135418334Speter	    nskip += SWITCH_TAKES_ARG (c) - (p[1] != 0);
135518334Speter	  else if (WORD_SWITCH_TAKES_ARG (p))
135618334Speter	    nskip += WORD_SWITCH_TAKES_ARG (p);
1357117413Skan	  else if ((c == 'B' || c == 'b' || c == 'x')
135818334Speter		   && p[1] == 0)
135918334Speter	    nskip += 1;
136018334Speter	  else if (! strcmp (p, "Xlinker"))
136118334Speter	    nskip += 1;
1362132733Skan	  else if (! strcmp (p, "Xpreprocessor"))
1363132733Skan	    nskip += 1;
1364132733Skan	  else if (! strcmp (p, "Xassembler"))
1365132733Skan	    nskip += 1;
136618334Speter
136718334Speter	  /* Watch out for an option at the end of the command line that
136818334Speter	     is missing arguments, and avoid skipping past the end of the
136918334Speter	     command line.  */
137018334Speter	  if (nskip + i > argc)
137118334Speter	    nskip = argc - i;
137218334Speter
137318334Speter	  while (nskip > 0)
137418334Speter	    {
137518334Speter	      newv[newindex++] = argv[i++];
137618334Speter	      nskip--;
137718334Speter	    }
137818334Speter	}
137918334Speter      else
138018334Speter	/* Ordinary operands, or +e options.  */
138118334Speter	newv[newindex++] = argv[i++];
138218334Speter    }
138318334Speter
138418334Speter  newv[newindex] = 0;
138518334Speter
138618334Speter  *argvp = newv;
138718334Speter  *argcp = newindex;
138818334Speter}
138918334Speter
139018334Speterstatic char *
1391132733Skanskip_whitespace (char *p)
139218334Speter{
139318334Speter  while (1)
139418334Speter    {
139518334Speter      /* A fully-blank line is a delimiter in the SPEC file and shouldn't
139618334Speter	 be considered whitespace.  */
139718334Speter      if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n')
139818334Speter	return p + 1;
139918334Speter      else if (*p == '\n' || *p == ' ' || *p == '\t')
140018334Speter	p++;
140118334Speter      else if (*p == '#')
140218334Speter	{
140390277Sobrien	  while (*p != '\n')
140490277Sobrien	    p++;
140518334Speter	  p++;
140618334Speter	}
140718334Speter      else
140818334Speter	break;
140918334Speter    }
141018334Speter
141118334Speter  return p;
141218334Speter}
141390277Sobrien/* Structures to keep track of prefixes to try when looking for files.  */
141490277Sobrien
141590277Sobrienstruct prefix_list
141690277Sobrien{
141790277Sobrien  const char *prefix;	      /* String to prepend to the path.  */
141890277Sobrien  struct prefix_list *next;   /* Next in linked list.  */
141990277Sobrien  int require_machine_suffix; /* Don't use without machine_suffix.  */
142090277Sobrien  /* 2 means try both machine_suffix and just_machine_suffix.  */
1421104763Skan  int priority;		      /* Sort key - priority within list.  */
1422104763Skan  int os_multilib;	      /* 1 if OS multilib scheme should be used,
1423104763Skan				 0 for GCC multilib scheme.  */
142490277Sobrien};
142590277Sobrien
142690277Sobrienstruct path_prefix
142790277Sobrien{
142890277Sobrien  struct prefix_list *plist;  /* List of prefixes to try */
142990277Sobrien  int max_len;                /* Max length of a prefix in PLIST */
143090277Sobrien  const char *name;           /* Name of this list (used in config stuff) */
143190277Sobrien};
143290277Sobrien
143390277Sobrien/* List of prefixes to try when looking for executables.  */
143490277Sobrien
143590277Sobrienstatic struct path_prefix exec_prefixes = { 0, 0, "exec" };
143690277Sobrien
143790277Sobrien/* List of prefixes to try when looking for startup (crt0) files.  */
143890277Sobrien
143990277Sobrienstatic struct path_prefix startfile_prefixes = { 0, 0, "startfile" };
144090277Sobrien
144190277Sobrien/* List of prefixes to try when looking for include files.  */
144290277Sobrien
144390277Sobrienstatic struct path_prefix include_prefixes = { 0, 0, "include" };
144490277Sobrien
144590277Sobrien/* Suffix to attach to directories searched for commands.
144690277Sobrien   This looks like `MACHINE/VERSION/'.  */
144790277Sobrien
144890277Sobrienstatic const char *machine_suffix = 0;
144990277Sobrien
145090277Sobrien/* Suffix to attach to directories searched for commands.
145190277Sobrien   This is just `MACHINE/'.  */
145290277Sobrien
145390277Sobrienstatic const char *just_machine_suffix = 0;
145490277Sobrien
145590277Sobrien/* Adjusted value of GCC_EXEC_PREFIX envvar.  */
145690277Sobrien
145790277Sobrienstatic const char *gcc_exec_prefix;
145890277Sobrien
1459132733Skan/* Adjusted value of standard_libexec_prefix.  */
1460132733Skan
1461132733Skanstatic const char *gcc_libexec_prefix;
1462132733Skan
146390277Sobrien/* Default prefixes to attach to command names.  */
146490277Sobrien
1465169704Skan#ifndef STANDARD_STARTFILE_PREFIX_1
1466169704Skan#define STANDARD_STARTFILE_PREFIX_1 "/lib/"
1467169704Skan#endif
1468169704Skan#ifndef STANDARD_STARTFILE_PREFIX_2
1469169704Skan#define STANDARD_STARTFILE_PREFIX_2 "/usr/lib/"
1470169704Skan#endif
1471169704Skan
1472259563Spfg#ifdef CROSS_DIRECTORY_STRUCTURE  /* Don't use these prefixes for a cross compiler.  */
147390277Sobrien#undef MD_EXEC_PREFIX
147490277Sobrien#undef MD_STARTFILE_PREFIX
147590277Sobrien#undef MD_STARTFILE_PREFIX_1
147690277Sobrien#endif
147790277Sobrien
147890277Sobrien/* If no prefixes defined, use the null string, which will disable them.  */
147990277Sobrien#ifndef MD_EXEC_PREFIX
148090277Sobrien#define MD_EXEC_PREFIX ""
148190277Sobrien#endif
148290277Sobrien#ifndef MD_STARTFILE_PREFIX
148390277Sobrien#define MD_STARTFILE_PREFIX ""
148490277Sobrien#endif
148590277Sobrien#ifndef MD_STARTFILE_PREFIX_1
148690277Sobrien#define MD_STARTFILE_PREFIX_1 ""
148790277Sobrien#endif
148890277Sobrien
148990277Sobrienstatic const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX;
1490132733Skanstatic const char *const standard_exec_prefix_1 = "/usr/libexec/gcc/";
1491132733Skanstatic const char *const standard_exec_prefix_2 = "/usr/lib/gcc/";
149290277Sobrienstatic const char *md_exec_prefix = MD_EXEC_PREFIX;
149390277Sobrien
149490277Sobrienstatic const char *md_startfile_prefix = MD_STARTFILE_PREFIX;
149590277Sobrienstatic const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
149690277Sobrienstatic const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
1497169704Skanstatic const char *const standard_startfile_prefix_1
1498169704Skan  = STANDARD_STARTFILE_PREFIX_1;
1499169704Skanstatic const char *const standard_startfile_prefix_2
1500169704Skan  = STANDARD_STARTFILE_PREFIX_2;
150190277Sobrien
150290277Sobrienstatic const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
150390277Sobrienstatic const char *tooldir_prefix;
150490277Sobrien
150596736Sru#ifndef FREEBSD_NATIVE
150690277Sobrienstatic const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
150796736Sru#endif	/* not FREEBSD_NATIVE */
150890277Sobrien
1509132733Skanstatic const char *standard_libexec_prefix = STANDARD_LIBEXEC_PREFIX;
1510132733Skan
151190277Sobrien/* Subdirectory to use for locating libraries.  Set by
151290277Sobrien   set_multilib_dir based on the compilation options.  */
151390277Sobrien
151490277Sobrienstatic const char *multilib_dir;
1515104763Skan
1516104763Skan/* Subdirectory to use for locating libraries in OS conventions.  Set by
1517104763Skan   set_multilib_dir based on the compilation options.  */
1518104763Skan
1519104763Skanstatic const char *multilib_os_dir;
152018334Speter
152150599Sobrien/* Structure to keep track of the specs that have been defined so far.
152250599Sobrien   These are accessed using %(specname) or %[specname] in a compiler
152350599Sobrien   or link spec.  */
152418334Speter
152518334Speterstruct spec_list
152618334Speter{
152750599Sobrien				/* The following 2 fields must be first */
152850599Sobrien				/* to allow EXTRA_SPECS to be initialized */
152990277Sobrien  const char *name;		/* name of the spec.  */
153090277Sobrien  const char *ptr;		/* available ptr if no static pointer */
153150599Sobrien
153250599Sobrien				/* The following fields are not initialized */
153350599Sobrien				/* by EXTRA_SPECS */
153490277Sobrien  const char **ptr_spec;	/* pointer to the spec itself.  */
153550599Sobrien  struct spec_list *next;	/* Next spec in linked list.  */
153650599Sobrien  int name_len;			/* length of the name */
153750599Sobrien  int alloc_p;			/* whether string was allocated */
153818334Speter};
153918334Speter
154050599Sobrien#define INIT_STATIC_SPEC(NAME,PTR) \
154190277Sobrien{ NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, 0 }
154218334Speter
154390277Sobrien/* List of statically defined specs.  */
154490277Sobrienstatic struct spec_list static_specs[] =
154590277Sobrien{
154650599Sobrien  INIT_STATIC_SPEC ("asm",			&asm_spec),
154790277Sobrien  INIT_STATIC_SPEC ("asm_debug",		&asm_debug),
154850599Sobrien  INIT_STATIC_SPEC ("asm_final",		&asm_final_spec),
154990277Sobrien  INIT_STATIC_SPEC ("asm_options",		&asm_options),
155090277Sobrien  INIT_STATIC_SPEC ("invoke_as",		&invoke_as),
155150599Sobrien  INIT_STATIC_SPEC ("cpp",			&cpp_spec),
155290277Sobrien  INIT_STATIC_SPEC ("cpp_options",		&cpp_options),
1553117413Skan  INIT_STATIC_SPEC ("cpp_debug_options",	&cpp_debug_options),
155490277Sobrien  INIT_STATIC_SPEC ("cpp_unique_options",	&cpp_unique_options),
155590277Sobrien  INIT_STATIC_SPEC ("trad_capable_cpp",		&trad_capable_cpp),
155650599Sobrien  INIT_STATIC_SPEC ("cc1",			&cc1_spec),
155790277Sobrien  INIT_STATIC_SPEC ("cc1_options",		&cc1_options),
155850599Sobrien  INIT_STATIC_SPEC ("cc1plus",			&cc1plus_spec),
155996285Sobrien  INIT_STATIC_SPEC ("link_gcc_c_sequence",	&link_gcc_c_sequence_spec),
1560169704Skan  INIT_STATIC_SPEC ("link_ssp",			&link_ssp_spec),
156150599Sobrien  INIT_STATIC_SPEC ("endfile",			&endfile_spec),
156250599Sobrien  INIT_STATIC_SPEC ("link",			&link_spec),
156350599Sobrien  INIT_STATIC_SPEC ("lib",			&lib_spec),
1564169704Skan  INIT_STATIC_SPEC ("mfwrap",			&mfwrap_spec),
1565169704Skan  INIT_STATIC_SPEC ("mflib",			&mflib_spec),
1566169704Skan  INIT_STATIC_SPEC ("link_gomp",		&link_gomp_spec),
156750599Sobrien  INIT_STATIC_SPEC ("libgcc",			&libgcc_spec),
156850599Sobrien  INIT_STATIC_SPEC ("startfile",		&startfile_spec),
156950599Sobrien  INIT_STATIC_SPEC ("switches_need_spaces",	&switches_need_spaces),
157050599Sobrien  INIT_STATIC_SPEC ("cross_compile",		&cross_compile),
157150599Sobrien  INIT_STATIC_SPEC ("version",			&compiler_version),
157250599Sobrien  INIT_STATIC_SPEC ("multilib",			&multilib_select),
157350599Sobrien  INIT_STATIC_SPEC ("multilib_defaults",	&multilib_defaults),
157450599Sobrien  INIT_STATIC_SPEC ("multilib_extra",		&multilib_extra),
157550599Sobrien  INIT_STATIC_SPEC ("multilib_matches",		&multilib_matches),
157690277Sobrien  INIT_STATIC_SPEC ("multilib_exclusions",	&multilib_exclusions),
1577104763Skan  INIT_STATIC_SPEC ("multilib_options",		&multilib_options),
157850599Sobrien  INIT_STATIC_SPEC ("linker",			&linker_name_spec),
157990277Sobrien  INIT_STATIC_SPEC ("link_libgcc",		&link_libgcc_spec),
158090277Sobrien  INIT_STATIC_SPEC ("md_exec_prefix",		&md_exec_prefix),
158190277Sobrien  INIT_STATIC_SPEC ("md_startfile_prefix",	&md_startfile_prefix),
158290277Sobrien  INIT_STATIC_SPEC ("md_startfile_prefix_1",	&md_startfile_prefix_1),
1583117413Skan  INIT_STATIC_SPEC ("startfile_prefix_spec",	&startfile_prefix_spec),
1584169704Skan  INIT_STATIC_SPEC ("sysroot_spec",             &sysroot_spec),
1585132733Skan  INIT_STATIC_SPEC ("sysroot_suffix_spec",	&sysroot_suffix_spec),
1586132733Skan  INIT_STATIC_SPEC ("sysroot_hdrs_suffix_spec",	&sysroot_hdrs_suffix_spec),
158750599Sobrien};
158850599Sobrien
158950599Sobrien#ifdef EXTRA_SPECS		/* additional specs needed */
159052520Sobrien/* Structure to keep track of just the first two args of a spec_list.
159190277Sobrien   That is all that the EXTRA_SPECS macro gives us.  */
159252520Sobrienstruct spec_list_1
159352520Sobrien{
159490277Sobrien  const char *const name;
159590277Sobrien  const char *const ptr;
159652520Sobrien};
159752520Sobrien
159890277Sobrienstatic const struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
159990277Sobrienstatic struct spec_list *extra_specs = (struct spec_list *) 0;
160050599Sobrien#endif
160150599Sobrien
160250599Sobrien/* List of dynamically allocates specs that have been defined so far.  */
160350599Sobrien
160490277Sobrienstatic struct spec_list *specs = (struct spec_list *) 0;
160590277Sobrien
1606117413Skan/* List of static spec functions.  */
1607117413Skan
1608117413Skanstatic const struct spec_function static_spec_functions[] =
1609117413Skan{
1610117413Skan  { "if-exists",		if_exists_spec_function },
1611117413Skan  { "if-exists-else",		if_exists_else_spec_function },
1612169704Skan  { "replace-outfile",		replace_outfile_spec_function },
1613169704Skan  { "version-compare",		version_compare_spec_function },
1614169704Skan  { "include",			include_spec_function },
1615169704Skan#ifdef EXTRA_SPEC_FUNCTIONS
1616169704Skan  EXTRA_SPEC_FUNCTIONS
1617169704Skan#endif
1618117413Skan  { 0, 0 }
1619117413Skan};
1620117413Skan
1621117413Skanstatic int processing_spec_function;
1622117413Skan
162390277Sobrien/* Add appropriate libgcc specs to OBSTACK, taking into account
162490277Sobrien   various permutations of -shared-libgcc, -shared, and such.  */
162550599Sobrien
1626169704Skan#if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC)
1627169704Skan
1628169704Skan#ifndef USE_LD_AS_NEEDED
1629169704Skan#define USE_LD_AS_NEEDED 0
1630169704Skan#endif
1631169704Skan
163290277Sobrienstatic void
1633132733Skaninit_gcc_specs (struct obstack *obstack, const char *shared_name,
1634132733Skan		const char *static_name, const char *eh_name)
163590277Sobrien{
163696285Sobrien  char *buf;
163790277Sobrien
1638170077Skan  buf = concat ("%{pg:",  static_name, " ", eh_name, "} %{!pg:",
1639170077Skan		"%{static|static-libgcc|pg:", static_name, " ", eh_name, "}"
1640169704Skan		"%{!static:%{!static-libgcc:"
1641169704Skan#if USE_LD_AS_NEEDED
1642169704Skan		"%{!shared-libgcc:",
1643169704Skan		static_name, " --as-needed ", shared_name, " --no-as-needed"
1644169704Skan		"}"
1645169704Skan		"%{shared-libgcc:",
1646169704Skan		shared_name, "%{!shared: ", static_name, "}"
1647169704Skan		"}"
1648132733Skan#else
1649169704Skan		"%{!shared:"
1650169704Skan		"%{!shared-libgcc:", static_name, " ", eh_name, "}"
1651169704Skan		"%{shared-libgcc:", shared_name, " ", static_name, "}"
1652169704Skan		"}"
165390277Sobrien#ifdef LINK_EH_SPEC
1654169704Skan		"%{shared:"
1655169704Skan		"%{shared-libgcc:", shared_name, "}"
1656169704Skan		"%{!shared-libgcc:", static_name, "}"
1657169704Skan		"}"
165890277Sobrien#else
1659169704Skan		"%{shared:", shared_name, "}"
166090277Sobrien#endif
1661132733Skan#endif
1662170077Skan		"}}}", NULL);
166396285Sobrien
166496285Sobrien  obstack_grow (obstack, buf, strlen (buf));
166596285Sobrien  free (buf);
166690277Sobrien}
166790277Sobrien#endif /* ENABLE_SHARED_LIBGCC */
166890277Sobrien
166950599Sobrien/* Initialize the specs lookup routines.  */
167050599Sobrien
167150599Sobrienstatic void
1672132733Skaninit_spec (void)
167350599Sobrien{
167490277Sobrien  struct spec_list *next = (struct spec_list *) 0;
167590277Sobrien  struct spec_list *sl   = (struct spec_list *) 0;
167650599Sobrien  int i;
167750599Sobrien
167850599Sobrien  if (specs)
167990277Sobrien    return;			/* Already initialized.  */
168050599Sobrien
168150599Sobrien  if (verbose_flag)
168290277Sobrien    notice ("Using built-in specs.\n");
168350599Sobrien
168450599Sobrien#ifdef EXTRA_SPECS
1685132733Skan  extra_specs = xcalloc (sizeof (struct spec_list),
1686132733Skan			 ARRAY_SIZE (extra_specs_1));
168790277Sobrien
168890277Sobrien  for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--)
168950599Sobrien    {
169050599Sobrien      sl = &extra_specs[i];
169152520Sobrien      sl->name = extra_specs_1[i].name;
169252520Sobrien      sl->ptr = extra_specs_1[i].ptr;
169350599Sobrien      sl->next = next;
169450599Sobrien      sl->name_len = strlen (sl->name);
169550599Sobrien      sl->ptr_spec = &sl->ptr;
169650599Sobrien      next = sl;
169750599Sobrien    }
169850599Sobrien#endif
169950599Sobrien
1700117413Skan  /* Initialize here, not in definition.  The IRIX 6 O32 cc sometimes chokes
1701117413Skan     on ?: in file-scope variable initializations.  */
1702117413Skan  asm_debug = ASM_DEBUG_SPEC;
1703117413Skan
170490277Sobrien  for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
170550599Sobrien    {
170650599Sobrien      sl = &static_specs[i];
170750599Sobrien      sl->next = next;
170850599Sobrien      next = sl;
170950599Sobrien    }
171050599Sobrien
1711169704Skan#if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC)
171290277Sobrien  /* ??? If neither -shared-libgcc nor --static-libgcc was
171390277Sobrien     seen, then we should be making an educated guess.  Some proposed
171490277Sobrien     heuristics for ELF include:
171590277Sobrien
171690277Sobrien	(1) If "-Wl,--export-dynamic", then it's a fair bet that the
171790277Sobrien	    program will be doing dynamic loading, which will likely
171890277Sobrien	    need the shared libgcc.
171990277Sobrien
172090277Sobrien	(2) If "-ldl", then it's also a fair bet that we're doing
172190277Sobrien	    dynamic loading.
172290277Sobrien
172390277Sobrien	(3) For each ET_DYN we're linking against (either through -lfoo
172490277Sobrien	    or /some/path/foo.so), check to see whether it or one of
172590277Sobrien	    its dependencies depends on a shared libgcc.
172690277Sobrien
172790277Sobrien	(4) If "-shared"
172890277Sobrien
172990277Sobrien	    If the runtime is fixed to look for program headers instead
173090277Sobrien	    of calling __register_frame_info at all, for each object,
173190277Sobrien	    use the shared libgcc if any EH symbol referenced.
173290277Sobrien
173390277Sobrien	    If crtstuff is fixed to not invoke __register_frame_info
173490277Sobrien	    automatically, for each object, use the shared libgcc if
173590277Sobrien	    any non-empty unwind section found.
173690277Sobrien
173790277Sobrien     Doing any of this probably requires invoking an external program to
173890277Sobrien     do the actual object file scanning.  */
173990277Sobrien  {
174090277Sobrien    const char *p = libgcc_spec;
174190277Sobrien    int in_sep = 1;
1742117413Skan
174390277Sobrien    /* Transform the extant libgcc_spec into one that uses the shared libgcc
174490277Sobrien       when given the proper command line arguments.  */
174590277Sobrien    while (*p)
174690277Sobrien      {
1747117413Skan	if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0)
174890277Sobrien	  {
174990277Sobrien	    init_gcc_specs (&obstack,
175090277Sobrien			    "-lgcc_s"
1751146908Skan#ifdef USE_LIBUNWIND_EXCEPTIONS
1752146908Skan			    " -lunwind"
1753146908Skan#endif
1754132733Skan			    ,
1755169704Skan#ifdef FREEBSD_NATIVE
1756169704Skan			    LIBGCC_STATIC_LIB_SPEC,
1757169704Skan			    LIBGCC_EH_STATIC_LIB_SPEC
1758169704Skan#else
1759132733Skan			    "-lgcc",
1760132733Skan			    "-lgcc_eh"
1761169704Skan#endif
1762122197Skan#ifdef USE_LIBUNWIND_EXCEPTIONS
1763146908Skan# ifdef HAVE_LD_STATIC_DYNAMIC
1764146908Skan			    " %{!static:-Bstatic} -lunwind %{!static:-Bdynamic}"
1765146908Skan# else
1766122197Skan			    " -lunwind"
1767146908Skan# endif
1768122197Skan#endif
1769132733Skan			    );
1770132733Skan
177190277Sobrien	    p += 5;
177290277Sobrien	    in_sep = 0;
177390277Sobrien	  }
177490277Sobrien	else if (in_sep && *p == 'l' && strncmp (p, "libgcc.a%s", 10) == 0)
177590277Sobrien	  {
177690277Sobrien	    /* Ug.  We don't know shared library extensions.  Hope that
177790277Sobrien	       systems that use this form don't do shared libraries.  */
177890277Sobrien	    init_gcc_specs (&obstack,
1779169704Skan			    "-lgcc_s",
178090277Sobrien			    "libgcc.a%s",
1781132733Skan			    "libgcc_eh.a%s"
1782132733Skan#ifdef USE_LIBUNWIND_EXCEPTIONS
1783132733Skan			    " -lunwind"
1784132733Skan#endif
1785132733Skan			    );
178690277Sobrien	    p += 10;
178790277Sobrien	    in_sep = 0;
178890277Sobrien	  }
178990277Sobrien	else
179090277Sobrien	  {
179190277Sobrien	    obstack_1grow (&obstack, *p);
179290277Sobrien	    in_sep = (*p == ' ');
179390277Sobrien	    p += 1;
179490277Sobrien	  }
179590277Sobrien      }
179690277Sobrien
179790277Sobrien    obstack_1grow (&obstack, '\0');
1798169704Skan    libgcc_spec = XOBFINISH (&obstack, const char *);
179990277Sobrien  }
180090277Sobrien#endif
180190277Sobrien#ifdef USE_AS_TRADITIONAL_FORMAT
180290277Sobrien  /* Prepend "--traditional-format" to whatever asm_spec we had before.  */
180390277Sobrien  {
180490277Sobrien    static const char tf[] = "--traditional-format ";
180590277Sobrien    obstack_grow (&obstack, tf, sizeof(tf) - 1);
180690277Sobrien    obstack_grow0 (&obstack, asm_spec, strlen (asm_spec));
1807169704Skan    asm_spec = XOBFINISH (&obstack, const char *);
180890277Sobrien  }
180990277Sobrien#endif
181090277Sobrien#ifdef LINK_EH_SPEC
181190277Sobrien  /* Prepend LINK_EH_SPEC to whatever link_spec we had before.  */
181290277Sobrien  obstack_grow (&obstack, LINK_EH_SPEC, sizeof(LINK_EH_SPEC) - 1);
181390277Sobrien  obstack_grow0 (&obstack, link_spec, strlen (link_spec));
1814169704Skan  link_spec = XOBFINISH (&obstack, const char *);
181590277Sobrien#endif
181690277Sobrien
181750599Sobrien  specs = sl;
181850599Sobrien}
181950599Sobrien
182018334Speter/* Change the value of spec NAME to SPEC.  If SPEC is empty, then the spec is
182118334Speter   removed; If the spec starts with a + then SPEC is added to the end of the
182250599Sobrien   current spec.  */
182318334Speter
182418334Speterstatic void
1825132733Skanset_spec (const char *name, const char *spec)
182618334Speter{
182718334Speter  struct spec_list *sl;
182890277Sobrien  const char *old_spec;
182950599Sobrien  int name_len = strlen (name);
183050599Sobrien  int i;
183118334Speter
183290277Sobrien  /* If this is the first call, initialize the statically allocated specs.  */
183350599Sobrien  if (!specs)
183450599Sobrien    {
183590277Sobrien      struct spec_list *next = (struct spec_list *) 0;
183690277Sobrien      for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
183750599Sobrien	{
183850599Sobrien	  sl = &static_specs[i];
183950599Sobrien	  sl->next = next;
184050599Sobrien	  next = sl;
184150599Sobrien	}
184250599Sobrien      specs = sl;
184350599Sobrien    }
184450599Sobrien
184590277Sobrien  /* See if the spec already exists.  */
184618334Speter  for (sl = specs; sl; sl = sl->next)
184750599Sobrien    if (name_len == sl->name_len && !strcmp (sl->name, name))
184818334Speter      break;
184918334Speter
185018334Speter  if (!sl)
185118334Speter    {
185290277Sobrien      /* Not found - make it.  */
1853169704Skan      sl = XNEW (struct spec_list);
185490277Sobrien      sl->name = xstrdup (name);
185550599Sobrien      sl->name_len = name_len;
185650599Sobrien      sl->ptr_spec = &sl->ptr;
185750599Sobrien      sl->alloc_p = 0;
185850599Sobrien      *(sl->ptr_spec) = "";
185918334Speter      sl->next = specs;
186018334Speter      specs = sl;
186118334Speter    }
186218334Speter
186350599Sobrien  old_spec = *(sl->ptr_spec);
186452520Sobrien  *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1]))
186590277Sobrien		     ? concat (old_spec, spec + 1, NULL)
186690277Sobrien		     : xstrdup (spec));
186718334Speter
186850599Sobrien#ifdef DEBUG_SPECS
186950599Sobrien  if (verbose_flag)
187052520Sobrien    notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
187150599Sobrien#endif
187250599Sobrien
187390277Sobrien  /* Free the old spec.  */
187450599Sobrien  if (old_spec && sl->alloc_p)
1875132733Skan    free ((void *) old_spec);
187650599Sobrien
187750599Sobrien  sl->alloc_p = 1;
187818334Speter}
187918334Speter
188018334Speter/* Accumulate a command (program name and args), and run it.  */
188118334Speter
188218334Speter/* Vector of pointers to arguments in the current line of specifications.  */
188318334Speter
188490277Sobrienstatic const char **argbuf;
188518334Speter
188618334Speter/* Number of elements allocated in argbuf.  */
188718334Speter
188818334Speterstatic int argbuf_length;
188918334Speter
189018334Speter/* Number of elements in argbuf currently in use (containing args).  */
189118334Speter
189218334Speterstatic int argbuf_index;
189318334Speter
1894169704Skan/* Position in the argbuf array containing the name of the output file
1895169704Skan   (the value associated with the "-o" flag).  */
1896169704Skan
1897169704Skanstatic int have_o_argbuf_index = 0;
1898169704Skan
1899169704Skan/* Were the options -c or -S passed.  */
1900169704Skanstatic int have_c = 0;
1901169704Skan
1902169704Skan/* Was the option -o passed.  */
1903169704Skanstatic int have_o = 0;
1904169704Skan
190590277Sobrien/* This is the list of suffixes and codes (%g/%u/%U/%j) and the associated
190690277Sobrien   temp file.  If the HOST_BIT_BUCKET is used for %j, no entry is made for
190790277Sobrien   it here.  */
190850599Sobrien
190918334Speterstatic struct temp_name {
191052520Sobrien  const char *suffix;	/* suffix associated with the code.  */
191118334Speter  int length;		/* strlen (suffix).  */
191218334Speter  int unique;		/* Indicates whether %g or %u/%U was used.  */
191352520Sobrien  const char *filename;	/* associated filename.  */
191418334Speter  int filename_length;	/* strlen (filename).  */
191518334Speter  struct temp_name *next;
191618334Speter} *temp_names;
191718334Speter
191818334Speter/* Number of commands executed so far.  */
191918334Speter
192018334Speterstatic int execution_count;
192118334Speter
192218334Speter/* Number of commands that exited with a signal.  */
192318334Speter
192418334Speterstatic int signal_count;
192518334Speter
192618334Speter/* Name with which this program was invoked.  */
192718334Speter
192852520Sobrienstatic const char *programname;
192918334Speter
1930117413Skan/* Allocate the argument vector.  */
1931117413Skan
1932117413Skanstatic void
1933132733Skanalloc_args (void)
1934117413Skan{
1935117413Skan  argbuf_length = 10;
1936169704Skan  argbuf = XNEWVEC (const char *, argbuf_length);
1937117413Skan}
1938117413Skan
193918334Speter/* Clear out the vector of arguments (after a command is executed).  */
194018334Speter
194118334Speterstatic void
1942132733Skanclear_args (void)
194318334Speter{
194418334Speter  argbuf_index = 0;
194518334Speter}
194618334Speter
194718334Speter/* Add one argument to the vector at the end.
194818334Speter   This is done when a space is seen or at the end of the line.
194918334Speter   If DELETE_ALWAYS is nonzero, the arg is a filename
195018334Speter    and the file should be deleted eventually.
195118334Speter   If DELETE_FAILURE is nonzero, the arg is a filename
195218334Speter    and the file should be deleted if this compilation fails.  */
195318334Speter
195418334Speterstatic void
1955132733Skanstore_arg (const char *arg, int delete_always, int delete_failure)
195618334Speter{
195718334Speter  if (argbuf_index + 1 == argbuf_length)
1958132733Skan    argbuf = xrealloc (argbuf, (argbuf_length *= 2) * sizeof (const char *));
195918334Speter
196018334Speter  argbuf[argbuf_index++] = arg;
196118334Speter  argbuf[argbuf_index] = 0;
196218334Speter
1963169704Skan  if (strcmp (arg, "-o") == 0)
1964169704Skan    have_o_argbuf_index = argbuf_index;
196518334Speter  if (delete_always || delete_failure)
196618334Speter    record_temp_file (arg, delete_always, delete_failure);
196718334Speter}
196818334Speter
196990277Sobrien/* Load specs from a file name named FILENAME, replacing occurrences of
197090277Sobrien   various different types of line-endings, \r\n, \n\r and just \r, with
197190277Sobrien   a single \n.  */
197250599Sobrien
197390277Sobrienstatic char *
1974132733Skanload_specs (const char *filename)
197550599Sobrien{
197650599Sobrien  int desc;
197750599Sobrien  int readlen;
197850599Sobrien  struct stat statbuf;
197950599Sobrien  char *buffer;
198090277Sobrien  char *buffer_p;
198190277Sobrien  char *specs;
198290277Sobrien  char *specs_p;
198350599Sobrien
198450599Sobrien  if (verbose_flag)
198552520Sobrien    notice ("Reading specs from %s\n", filename);
198650599Sobrien
198750599Sobrien  /* Open and stat the file.  */
198850599Sobrien  desc = open (filename, O_RDONLY, 0);
198950599Sobrien  if (desc < 0)
199050599Sobrien    pfatal_with_name (filename);
199150599Sobrien  if (stat (filename, &statbuf) < 0)
199250599Sobrien    pfatal_with_name (filename);
199350599Sobrien
199450599Sobrien  /* Read contents of file into BUFFER.  */
1995169704Skan  buffer = XNEWVEC (char, statbuf.st_size + 1);
199650599Sobrien  readlen = read (desc, buffer, (unsigned) statbuf.st_size);
199750599Sobrien  if (readlen < 0)
199850599Sobrien    pfatal_with_name (filename);
199950599Sobrien  buffer[readlen] = 0;
200050599Sobrien  close (desc);
200150599Sobrien
2002169704Skan  specs = XNEWVEC (char, readlen + 1);
200390277Sobrien  specs_p = specs;
200490277Sobrien  for (buffer_p = buffer; buffer_p && *buffer_p; buffer_p++)
200590277Sobrien    {
200690277Sobrien      int skip = 0;
200790277Sobrien      char c = *buffer_p;
200890277Sobrien      if (c == '\r')
200990277Sobrien	{
201090277Sobrien	  if (buffer_p > buffer && *(buffer_p - 1) == '\n')	/* \n\r */
201190277Sobrien	    skip = 1;
201290277Sobrien	  else if (*(buffer_p + 1) == '\n')			/* \r\n */
201390277Sobrien	    skip = 1;
201490277Sobrien	  else							/* \r */
201590277Sobrien	    c = '\n';
201690277Sobrien	}
201790277Sobrien      if (! skip)
201890277Sobrien	*specs_p++ = c;
201990277Sobrien    }
202090277Sobrien  *specs_p = '\0';
202190277Sobrien
202290277Sobrien  free (buffer);
202390277Sobrien  return (specs);
202490277Sobrien}
202590277Sobrien
202690277Sobrien/* Read compilation specs from a file named FILENAME,
202790277Sobrien   replacing the default ones.
202890277Sobrien
202990277Sobrien   A suffix which starts with `*' is a definition for
203090277Sobrien   one of the machine-specific sub-specs.  The "suffix" should be
203196285Sobrien   *asm, *cc1, *cpp, *link, *startfile, etc.
203290277Sobrien   The corresponding spec is stored in asm_spec, etc.,
203390277Sobrien   rather than in the `compilers' vector.
203490277Sobrien
203590277Sobrien   Anything invalid in the file is a fatal error.  */
203690277Sobrien
203790277Sobrienstatic void
2038132733Skanread_specs (const char *filename, int main_p)
203990277Sobrien{
204090277Sobrien  char *buffer;
204190277Sobrien  char *p;
204290277Sobrien
204390277Sobrien  buffer = load_specs (filename);
204490277Sobrien
204550599Sobrien  /* Scan BUFFER for specs, putting them in the vector.  */
204650599Sobrien  p = buffer;
204750599Sobrien  while (1)
204850599Sobrien    {
204950599Sobrien      char *suffix;
205050599Sobrien      char *spec;
205150599Sobrien      char *in, *out, *p1, *p2, *p3;
205250599Sobrien
205350599Sobrien      /* Advance P in BUFFER to the next nonblank nocomment line.  */
205450599Sobrien      p = skip_whitespace (p);
205550599Sobrien      if (*p == 0)
205650599Sobrien	break;
205750599Sobrien
205850599Sobrien      /* Is this a special command that starts with '%'? */
205950599Sobrien      /* Don't allow this for the main specs file, since it would
206050599Sobrien	 encourage people to overwrite it.  */
206150599Sobrien      if (*p == '%' && !main_p)
206250599Sobrien	{
206350599Sobrien	  p1 = p;
206450599Sobrien	  while (*p && *p != '\n')
206550599Sobrien	    p++;
206650599Sobrien
206790277Sobrien	  /* Skip '\n'.  */
206890277Sobrien	  p++;
206950599Sobrien
207090277Sobrien	  if (!strncmp (p1, "%include", sizeof ("%include") - 1)
207150599Sobrien	      && (p1[sizeof "%include" - 1] == ' '
207250599Sobrien		  || p1[sizeof "%include" - 1] == '\t'))
207350599Sobrien	    {
207450599Sobrien	      char *new_filename;
207550599Sobrien
207650599Sobrien	      p1 += sizeof ("%include");
207750599Sobrien	      while (*p1 == ' ' || *p1 == '\t')
207850599Sobrien		p1++;
207950599Sobrien
208050599Sobrien	      if (*p1++ != '<' || p[-2] != '>')
208152520Sobrien		fatal ("specs %%include syntax malformed after %ld characters",
208252520Sobrien		       (long) (p1 - buffer + 1));
208350599Sobrien
208450599Sobrien	      p[-2] = '\0';
2085169704Skan	      new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
208650599Sobrien	      read_specs (new_filename ? new_filename : p1, FALSE);
208750599Sobrien	      continue;
208850599Sobrien	    }
208950599Sobrien	  else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1)
209050599Sobrien		   && (p1[sizeof "%include_noerr" - 1] == ' '
209150599Sobrien		       || p1[sizeof "%include_noerr" - 1] == '\t'))
209250599Sobrien	    {
209350599Sobrien	      char *new_filename;
209450599Sobrien
209550599Sobrien	      p1 += sizeof "%include_noerr";
209690277Sobrien	      while (*p1 == ' ' || *p1 == '\t')
209790277Sobrien		p1++;
209850599Sobrien
209950599Sobrien	      if (*p1++ != '<' || p[-2] != '>')
210052520Sobrien		fatal ("specs %%include syntax malformed after %ld characters",
210152520Sobrien		       (long) (p1 - buffer + 1));
210250599Sobrien
210350599Sobrien	      p[-2] = '\0';
2104169704Skan	      new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
210550599Sobrien	      if (new_filename)
210650599Sobrien		read_specs (new_filename, FALSE);
210750599Sobrien	      else if (verbose_flag)
210890277Sobrien		notice ("could not find specs file %s\n", p1);
210950599Sobrien	      continue;
211050599Sobrien	    }
211150599Sobrien	  else if (!strncmp (p1, "%rename", sizeof "%rename" - 1)
211250599Sobrien		   && (p1[sizeof "%rename" - 1] == ' '
211350599Sobrien		       || p1[sizeof "%rename" - 1] == '\t'))
211450599Sobrien	    {
211550599Sobrien	      int name_len;
211650599Sobrien	      struct spec_list *sl;
2117117413Skan	      struct spec_list *newsl;
211850599Sobrien
2119117413Skan	      /* Get original name.  */
212050599Sobrien	      p1 += sizeof "%rename";
212150599Sobrien	      while (*p1 == ' ' || *p1 == '\t')
212250599Sobrien		p1++;
212350599Sobrien
212490277Sobrien	      if (! ISALPHA ((unsigned char) *p1))
212552520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
212652520Sobrien		       (long) (p1 - buffer));
212750599Sobrien
212850599Sobrien	      p2 = p1;
212990277Sobrien	      while (*p2 && !ISSPACE ((unsigned char) *p2))
213050599Sobrien		p2++;
213150599Sobrien
213250599Sobrien	      if (*p2 != ' ' && *p2 != '\t')
213352520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
213452520Sobrien		       (long) (p2 - buffer));
213550599Sobrien
213650599Sobrien	      name_len = p2 - p1;
213750599Sobrien	      *p2++ = '\0';
213850599Sobrien	      while (*p2 == ' ' || *p2 == '\t')
213950599Sobrien		p2++;
214050599Sobrien
214190277Sobrien	      if (! ISALPHA ((unsigned char) *p2))
214252520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
214352520Sobrien		       (long) (p2 - buffer));
214450599Sobrien
214590277Sobrien	      /* Get new spec name.  */
214650599Sobrien	      p3 = p2;
214790277Sobrien	      while (*p3 && !ISSPACE ((unsigned char) *p3))
214850599Sobrien		p3++;
214950599Sobrien
215090277Sobrien	      if (p3 != p - 1)
215152520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
215252520Sobrien		       (long) (p3 - buffer));
215350599Sobrien	      *p3 = '\0';
215450599Sobrien
215550599Sobrien	      for (sl = specs; sl; sl = sl->next)
215650599Sobrien		if (name_len == sl->name_len && !strcmp (sl->name, p1))
215750599Sobrien		  break;
215850599Sobrien
215950599Sobrien	      if (!sl)
216050599Sobrien		fatal ("specs %s spec was not found to be renamed", p1);
216150599Sobrien
216250599Sobrien	      if (strcmp (p1, p2) == 0)
216350599Sobrien		continue;
216450599Sobrien
2165117413Skan	      for (newsl = specs; newsl; newsl = newsl->next)
2166117413Skan		if (strcmp (newsl->name, p2) == 0)
2167117413Skan		  fatal ("%s: attempt to rename spec '%s' to already defined spec '%s'",
2168117413Skan		    filename, p1, p2);
2169117413Skan
217050599Sobrien	      if (verbose_flag)
217150599Sobrien		{
217252520Sobrien		  notice ("rename spec %s to %s\n", p1, p2);
217350599Sobrien#ifdef DEBUG_SPECS
217452520Sobrien		  notice ("spec is '%s'\n\n", *(sl->ptr_spec));
217550599Sobrien#endif
217650599Sobrien		}
217750599Sobrien
217850599Sobrien	      set_spec (p2, *(sl->ptr_spec));
217950599Sobrien	      if (sl->alloc_p)
2180132733Skan		free ((void *) *(sl->ptr_spec));
218150599Sobrien
218250599Sobrien	      *(sl->ptr_spec) = "";
218350599Sobrien	      sl->alloc_p = 0;
218450599Sobrien	      continue;
218550599Sobrien	    }
218650599Sobrien	  else
218752520Sobrien	    fatal ("specs unknown %% command after %ld characters",
218852520Sobrien		   (long) (p1 - buffer));
218950599Sobrien	}
219050599Sobrien
219150599Sobrien      /* Find the colon that should end the suffix.  */
219250599Sobrien      p1 = p;
219350599Sobrien      while (*p1 && *p1 != ':' && *p1 != '\n')
219450599Sobrien	p1++;
219550599Sobrien
219650599Sobrien      /* The colon shouldn't be missing.  */
219750599Sobrien      if (*p1 != ':')
219852520Sobrien	fatal ("specs file malformed after %ld characters",
219952520Sobrien	       (long) (p1 - buffer));
220050599Sobrien
220150599Sobrien      /* Skip back over trailing whitespace.  */
220250599Sobrien      p2 = p1;
220350599Sobrien      while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t'))
220450599Sobrien	p2--;
220550599Sobrien
220650599Sobrien      /* Copy the suffix to a string.  */
220750599Sobrien      suffix = save_string (p, p2 - p);
220850599Sobrien      /* Find the next line.  */
220950599Sobrien      p = skip_whitespace (p1 + 1);
221050599Sobrien      if (p[1] == 0)
221152520Sobrien	fatal ("specs file malformed after %ld characters",
221252520Sobrien	       (long) (p - buffer));
221350599Sobrien
221450599Sobrien      p1 = p;
221550599Sobrien      /* Find next blank line or end of string.  */
221650599Sobrien      while (*p1 && !(*p1 == '\n' && (p1[1] == '\n' || p1[1] == '\0')))
221750599Sobrien	p1++;
221850599Sobrien
221950599Sobrien      /* Specs end at the blank line and do not include the newline.  */
222050599Sobrien      spec = save_string (p, p1 - p);
222150599Sobrien      p = p1;
222250599Sobrien
222350599Sobrien      /* Delete backslash-newline sequences from the spec.  */
222450599Sobrien      in = spec;
222550599Sobrien      out = spec;
222650599Sobrien      while (*in != 0)
222750599Sobrien	{
222850599Sobrien	  if (in[0] == '\\' && in[1] == '\n')
222950599Sobrien	    in += 2;
223050599Sobrien	  else if (in[0] == '#')
223150599Sobrien	    while (*in && *in != '\n')
223250599Sobrien	      in++;
223350599Sobrien
223450599Sobrien	  else
223550599Sobrien	    *out++ = *in++;
223650599Sobrien	}
223750599Sobrien      *out = 0;
223850599Sobrien
223950599Sobrien      if (suffix[0] == '*')
224050599Sobrien	{
224150599Sobrien	  if (! strcmp (suffix, "*link_command"))
224250599Sobrien	    link_command_spec = spec;
224350599Sobrien	  else
224450599Sobrien	    set_spec (suffix + 1, spec);
224550599Sobrien	}
224650599Sobrien      else
224750599Sobrien	{
224850599Sobrien	  /* Add this pair to the vector.  */
224950599Sobrien	  compilers
2250132733Skan	    = xrealloc (compilers,
2251132733Skan			(n_compilers + 2) * sizeof (struct compiler));
225250599Sobrien
225350599Sobrien	  compilers[n_compilers].suffix = suffix;
225490277Sobrien	  compilers[n_compilers].spec = spec;
225550599Sobrien	  n_compilers++;
225690277Sobrien	  memset (&compilers[n_compilers], 0, sizeof compilers[n_compilers]);
225750599Sobrien	}
225850599Sobrien
225950599Sobrien      if (*suffix == 0)
226050599Sobrien	link_command_spec = spec;
226150599Sobrien    }
226250599Sobrien
226350599Sobrien  if (link_command_spec == 0)
226450599Sobrien    fatal ("spec file has no spec for linking");
226550599Sobrien}
226650599Sobrien
226718334Speter/* Record the names of temporary files we tell compilers to write,
226818334Speter   and delete them at the end of the run.  */
226918334Speter
227018334Speter/* This is the common prefix we use to make temp file names.
227118334Speter   It is chosen once for each run of this program.
227290277Sobrien   It is substituted into a spec by %g or %j.
227318334Speter   Thus, all temp file names contain this prefix.
227418334Speter   In practice, all temp file names start with this prefix.
227518334Speter
227618334Speter   This prefix comes from the envvar TMPDIR if it is defined;
227718334Speter   otherwise, from the P_tmpdir macro if that is defined;
227850599Sobrien   otherwise, in /usr/tmp or /tmp;
227950599Sobrien   or finally the current directory if all else fails.  */
228018334Speter
228152520Sobrienstatic const char *temp_filename;
228218334Speter
228318334Speter/* Length of the prefix.  */
228418334Speter
228518334Speterstatic int temp_filename_length;
228618334Speter
228718334Speter/* Define the list of temporary files to delete.  */
228818334Speter
228918334Speterstruct temp_file
229018334Speter{
229152520Sobrien  const char *name;
229218334Speter  struct temp_file *next;
229318334Speter};
229418334Speter
229518334Speter/* Queue of files to delete on success or failure of compilation.  */
229618334Speterstatic struct temp_file *always_delete_queue;
229718334Speter/* Queue of files to delete on failure of compilation.  */
229818334Speterstatic struct temp_file *failure_delete_queue;
229918334Speter
230018334Speter/* Record FILENAME as a file to be deleted automatically.
230118334Speter   ALWAYS_DELETE nonzero means delete it if all compilation succeeds;
230218334Speter   otherwise delete it in any case.
230318334Speter   FAIL_DELETE nonzero means delete it if a compilation step fails;
230418334Speter   otherwise delete it in any case.  */
230518334Speter
230690277Sobrienvoid
2307132733Skanrecord_temp_file (const char *filename, int always_delete, int fail_delete)
230818334Speter{
230990277Sobrien  char *const name = xstrdup (filename);
231018334Speter
231118334Speter  if (always_delete)
231218334Speter    {
231390277Sobrien      struct temp_file *temp;
231418334Speter      for (temp = always_delete_queue; temp; temp = temp->next)
231518334Speter	if (! strcmp (name, temp->name))
231618334Speter	  goto already1;
231750599Sobrien
2318169704Skan      temp = XNEW (struct temp_file);
231918334Speter      temp->next = always_delete_queue;
232018334Speter      temp->name = name;
232118334Speter      always_delete_queue = temp;
232250599Sobrien
232318334Speter    already1:;
232418334Speter    }
232518334Speter
232618334Speter  if (fail_delete)
232718334Speter    {
232890277Sobrien      struct temp_file *temp;
232918334Speter      for (temp = failure_delete_queue; temp; temp = temp->next)
233018334Speter	if (! strcmp (name, temp->name))
233118334Speter	  goto already2;
233250599Sobrien
2333169704Skan      temp = XNEW (struct temp_file);
233418334Speter      temp->next = failure_delete_queue;
233518334Speter      temp->name = name;
233618334Speter      failure_delete_queue = temp;
233750599Sobrien
233818334Speter    already2:;
233918334Speter    }
234018334Speter}
234118334Speter
234218334Speter/* Delete all the temporary files whose names we previously recorded.  */
234318334Speter
2344169704Skan#ifndef DELETE_IF_ORDINARY
2345169704Skan#define DELETE_IF_ORDINARY(NAME,ST,VERBOSE_FLAG)        \
2346169704Skando                                                      \
2347169704Skan  {                                                     \
2348169704Skan    if (stat (NAME, &ST) >= 0 && S_ISREG (ST.st_mode))  \
2349169704Skan      if (unlink (NAME) < 0)                            \
2350169704Skan	if (VERBOSE_FLAG)                               \
2351169704Skan	  perror_with_name (NAME);                      \
2352169704Skan  } while (0)
2353169704Skan#endif
2354169704Skan
235518334Speterstatic void
2356132733Skandelete_if_ordinary (const char *name)
235718334Speter{
235818334Speter  struct stat st;
235918334Speter#ifdef DEBUG
236018334Speter  int i, c;
236118334Speter
236218334Speter  printf ("Delete %s? (y or n) ", name);
236318334Speter  fflush (stdout);
236418334Speter  i = getchar ();
236518334Speter  if (i != '\n')
236650599Sobrien    while ((c = getchar ()) != '\n' && c != EOF)
236750599Sobrien      ;
236850599Sobrien
236918334Speter  if (i == 'y' || i == 'Y')
237018334Speter#endif /* DEBUG */
2371169704Skan  DELETE_IF_ORDINARY (name, st, verbose_flag);
237218334Speter}
237318334Speter
237418334Speterstatic void
2375132733Skandelete_temp_files (void)
237618334Speter{
237790277Sobrien  struct temp_file *temp;
237818334Speter
237918334Speter  for (temp = always_delete_queue; temp; temp = temp->next)
238018334Speter    delete_if_ordinary (temp->name);
238118334Speter  always_delete_queue = 0;
238218334Speter}
238318334Speter
238418334Speter/* Delete all the files to be deleted on error.  */
238518334Speter
238618334Speterstatic void
2387132733Skandelete_failure_queue (void)
238818334Speter{
238990277Sobrien  struct temp_file *temp;
239018334Speter
239118334Speter  for (temp = failure_delete_queue; temp; temp = temp->next)
239218334Speter    delete_if_ordinary (temp->name);
239318334Speter}
239418334Speter
239518334Speterstatic void
2396132733Skanclear_failure_queue (void)
239718334Speter{
239818334Speter  failure_delete_queue = 0;
239918334Speter}
240018334Speter
2401169704Skan/* Call CALLBACK for each path in PATHS, breaking out early if CALLBACK
2402169704Skan   returns non-NULL.
2403169704Skan   If DO_MULTI is true iterate over the paths twice, first with multilib
2404169704Skan   suffix then without, otherwise iterate over the paths once without
2405169704Skan   adding a multilib suffix.  When DO_MULTI is true, some attempt is made
2406169704Skan   to avoid visiting the same path twice, but we could do better.  For
2407169704Skan   instance, /usr/lib/../lib is considered different from /usr/lib.
2408169704Skan   At least EXTRA_SPACE chars past the end of the path passed to
2409169704Skan   CALLBACK are available for use by the callback.
2410169704Skan   CALLBACK_INFO allows extra parameters to be passed to CALLBACK.
241118334Speter
2412169704Skan   Returns the value returned by CALLBACK.  */
2413169704Skan
2414169704Skanstatic void *
2415169704Skanfor_each_path (const struct path_prefix *paths,
2416169704Skan	       bool do_multi,
2417169704Skan	       size_t extra_space,
2418169704Skan	       void *(*callback) (char *, void *),
2419169704Skan	       void *callback_info)
242018334Speter{
2421169704Skan  struct prefix_list *pl;
2422169704Skan  const char *multi_dir = NULL;
2423169704Skan  const char *multi_os_dir = NULL;
2424169704Skan  const char *multi_suffix;
2425169704Skan  const char *just_multi_suffix;
2426169704Skan  char *path = NULL;
2427169704Skan  void *ret = NULL;
2428169704Skan  bool skip_multi_dir = false;
2429169704Skan  bool skip_multi_os_dir = false;
243018334Speter
2431169704Skan  multi_suffix = machine_suffix;
2432169704Skan  just_multi_suffix = just_machine_suffix;
2433169704Skan  if (do_multi && multilib_dir && strcmp (multilib_dir, ".") != 0)
2434169704Skan    {
2435169704Skan      multi_dir = concat (multilib_dir, dir_separator_str, NULL);
2436169704Skan      multi_suffix = concat (multi_suffix, multi_dir, NULL);
2437169704Skan      just_multi_suffix = concat (just_multi_suffix, multi_dir, NULL);
2438169704Skan    }
2439169704Skan  if (do_multi && multilib_os_dir && strcmp (multilib_os_dir, ".") != 0)
2440169704Skan    multi_os_dir = concat (multilib_os_dir, dir_separator_str, NULL);
244118334Speter
2442169704Skan  while (1)
244318334Speter    {
2444169704Skan      size_t multi_dir_len = 0;
2445169704Skan      size_t multi_os_dir_len = 0;
2446169704Skan      size_t suffix_len;
2447169704Skan      size_t just_suffix_len;
2448169704Skan      size_t len;
244918334Speter
2450169704Skan      if (multi_dir)
2451169704Skan	multi_dir_len = strlen (multi_dir);
2452169704Skan      if (multi_os_dir)
2453169704Skan	multi_os_dir_len = strlen (multi_os_dir);
2454169704Skan      suffix_len = strlen (multi_suffix);
2455169704Skan      just_suffix_len = strlen (just_multi_suffix);
2456169704Skan
2457169704Skan      if (path == NULL)
245818334Speter	{
2459169704Skan	  len = paths->max_len + extra_space + 1;
2460169704Skan	  if (suffix_len > multi_os_dir_len)
2461169704Skan	    len += suffix_len;
2462169704Skan	  else
2463169704Skan	    len += multi_os_dir_len;
2464169704Skan	  path = XNEWVEC (char, len);
246518334Speter	}
246618334Speter
2467169704Skan      for (pl = paths->plist; pl != 0; pl = pl->next)
246818334Speter	{
2469169704Skan	  len = strlen (pl->prefix);
2470169704Skan	  memcpy (path, pl->prefix, len);
247190277Sobrien
2472169704Skan	  /* Look first in MACHINE/VERSION subdirectory.  */
2473169704Skan	  if (!skip_multi_dir)
2474169704Skan	    {
2475169704Skan	      memcpy (path + len, multi_suffix, suffix_len + 1);
2476169704Skan	      ret = callback (path, callback_info);
2477169704Skan	      if (ret)
2478169704Skan		break;
2479169704Skan	    }
2480169704Skan
2481169704Skan	  /* Some paths are tried with just the machine (ie. target)
2482169704Skan	     subdir.  This is used for finding as, ld, etc.  */
2483169704Skan	  if (!skip_multi_dir
2484169704Skan	      && pl->require_machine_suffix == 2)
2485169704Skan	    {
2486169704Skan	      memcpy (path + len, just_multi_suffix, just_suffix_len + 1);
2487169704Skan	      ret = callback (path, callback_info);
2488169704Skan	      if (ret)
2489169704Skan		break;
2490169704Skan	    }
2491169704Skan
2492169704Skan	  /* Now try the base path.  */
2493169704Skan	  if (!pl->require_machine_suffix
2494169704Skan	      && !(pl->os_multilib ? skip_multi_os_dir : skip_multi_dir))
2495169704Skan	    {
2496169704Skan	      const char *this_multi;
2497169704Skan	      size_t this_multi_len;
2498169704Skan
2499169704Skan	      if (pl->os_multilib)
2500169704Skan		{
2501169704Skan		  this_multi = multi_os_dir;
2502169704Skan		  this_multi_len = multi_os_dir_len;
2503169704Skan		}
2504169704Skan	      else
2505169704Skan		{
2506169704Skan		  this_multi = multi_dir;
2507169704Skan		  this_multi_len = multi_dir_len;
2508169704Skan		}
2509169704Skan
2510169704Skan	      if (this_multi_len)
2511169704Skan		memcpy (path + len, this_multi, this_multi_len + 1);
2512169704Skan	      else
2513169704Skan		path[len] = '\0';
2514169704Skan
2515169704Skan	      ret = callback (path, callback_info);
2516169704Skan	      if (ret)
2517169704Skan		break;
2518169704Skan	    }
251918334Speter	}
2520169704Skan      if (pl)
2521169704Skan	break;
252218334Speter
2523169704Skan      if (multi_dir == NULL && multi_os_dir == NULL)
2524169704Skan	break;
2525169704Skan
2526169704Skan      /* Run through the paths again, this time without multilibs.
2527169704Skan	 Don't repeat any we have already seen.  */
2528169704Skan      if (multi_dir)
252918334Speter	{
2530169704Skan	  free ((char *) multi_dir);
2531169704Skan	  multi_dir = NULL;
2532169704Skan	  free ((char *) multi_suffix);
2533169704Skan	  multi_suffix = machine_suffix;
2534169704Skan	  free ((char *) just_multi_suffix);
2535169704Skan	  just_multi_suffix = just_machine_suffix;
253618334Speter	}
2537169704Skan      else
2538169704Skan	skip_multi_dir = true;
2539169704Skan      if (multi_os_dir)
2540169704Skan	{
2541169704Skan	  free ((char *) multi_os_dir);
2542169704Skan	  multi_os_dir = NULL;
2543169704Skan	}
2544169704Skan      else
2545169704Skan	skip_multi_os_dir = true;
254618334Speter    }
254750599Sobrien
2548169704Skan  if (multi_dir)
2549169704Skan    {
2550169704Skan      free ((char *) multi_dir);
2551169704Skan      free ((char *) multi_suffix);
2552169704Skan      free ((char *) just_multi_suffix);
2553169704Skan    }
2554169704Skan  if (multi_os_dir)
2555169704Skan    free ((char *) multi_os_dir);
2556169704Skan  if (ret != path)
2557169704Skan    free (path);
2558169704Skan  return ret;
2559169704Skan}
2560169704Skan
2561169704Skan/* Callback for build_search_list.  Adds path to obstack being built.  */
2562169704Skan
2563169704Skanstruct add_to_obstack_info {
2564169704Skan  struct obstack *ob;
2565169704Skan  bool check_dir;
2566169704Skan  bool first_time;
2567169704Skan};
2568169704Skan
2569169704Skanstatic void *
2570169704Skanadd_to_obstack (char *path, void *data)
2571169704Skan{
2572169704Skan  struct add_to_obstack_info *info = data;
2573169704Skan
2574169704Skan  if (info->check_dir && !is_directory (path, false))
2575169704Skan    return NULL;
2576169704Skan
2577169704Skan  if (!info->first_time)
2578169704Skan    obstack_1grow (info->ob, PATH_SEPARATOR);
2579169704Skan
2580169704Skan  obstack_grow (info->ob, path, strlen (path));
2581169704Skan
2582169704Skan  info->first_time = false;
2583169704Skan  return NULL;
2584169704Skan}
2585169704Skan
2586169704Skan/* Build a list of search directories from PATHS.
2587169704Skan   PREFIX is a string to prepend to the list.
2588169704Skan   If CHECK_DIR_P is true we ensure the directory exists.
2589169704Skan   If DO_MULTI is true, multilib paths are output first, then
2590169704Skan   non-multilib paths.
2591169704Skan   This is used mostly by putenv_from_prefixes so we use `collect_obstack'.
2592169704Skan   It is also used by the --print-search-dirs flag.  */
2593169704Skan
2594169704Skanstatic char *
2595169704Skanbuild_search_list (const struct path_prefix *paths, const char *prefix,
2596169704Skan		   bool check_dir, bool do_multi)
2597169704Skan{
2598169704Skan  struct add_to_obstack_info info;
2599169704Skan
2600169704Skan  info.ob = &collect_obstack;
2601169704Skan  info.check_dir = check_dir;
2602169704Skan  info.first_time = true;
2603169704Skan
2604169704Skan  obstack_grow (&collect_obstack, prefix, strlen (prefix));
2605169704Skan  obstack_1grow (&collect_obstack, '=');
2606169704Skan
2607169704Skan  for_each_path (paths, do_multi, 0, add_to_obstack, &info);
2608169704Skan
260918334Speter  obstack_1grow (&collect_obstack, '\0');
2610169704Skan  return XOBFINISH (&collect_obstack, char *);
261118334Speter}
261218334Speter
261350599Sobrien/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
261450599Sobrien   for collect.  */
261518334Speter
261618334Speterstatic void
2617169704Skanputenv_from_prefixes (const struct path_prefix *paths, const char *env_var,
2618169704Skan		      bool do_multi)
261918334Speter{
2620169704Skan  putenv (build_search_list (paths, env_var, true, do_multi));
262118334Speter}
262218334Speter
262390277Sobrien/* Check whether NAME can be accessed in MODE.  This is like access,
262490277Sobrien   except that it never considers directories to be executable.  */
262590277Sobrien
262690277Sobrienstatic int
2627132733Skanaccess_check (const char *name, int mode)
262890277Sobrien{
262990277Sobrien  if (mode == X_OK)
263090277Sobrien    {
263190277Sobrien      struct stat st;
263290277Sobrien
263390277Sobrien      if (stat (name, &st) < 0
263490277Sobrien	  || S_ISDIR (st.st_mode))
263590277Sobrien	return -1;
263690277Sobrien    }
263790277Sobrien
263890277Sobrien  return access (name, mode);
263990277Sobrien}
264090277Sobrien
2641169704Skan/* Callback for find_a_file.  Appends the file name to the directory
2642169704Skan   path.  If the resulting file exists in the right mode, return the
2643169704Skan   full pathname to the file.  */
2644169704Skan
2645169704Skanstruct file_at_path_info {
2646169704Skan  const char *name;
2647169704Skan  const char *suffix;
2648169704Skan  int name_len;
2649169704Skan  int suffix_len;
2650169704Skan  int mode;
2651169704Skan};
2652169704Skan
2653169704Skanstatic void *
2654169704Skanfile_at_path (char *path, void *data)
2655169704Skan{
2656169704Skan  struct file_at_path_info *info = data;
2657169704Skan  size_t len = strlen (path);
2658169704Skan
2659169704Skan  memcpy (path + len, info->name, info->name_len);
2660169704Skan  len += info->name_len;
2661169704Skan
2662169704Skan  /* Some systems have a suffix for executable files.
2663169704Skan     So try appending that first.  */
2664169704Skan  if (info->suffix_len)
2665169704Skan    {
2666169704Skan      memcpy (path + len, info->suffix, info->suffix_len + 1);
2667169704Skan      if (access_check (path, info->mode) == 0)
2668169704Skan	return path;
2669169704Skan    }
2670169704Skan
2671169704Skan  path[len] = '\0';
2672169704Skan  if (access_check (path, info->mode) == 0)
2673169704Skan    return path;
2674169704Skan
2675169704Skan  return NULL;
2676169704Skan}
2677169704Skan
267818334Speter/* Search for NAME using the prefix list PREFIXES.  MODE is passed to
2679169704Skan   access to check permissions.  If DO_MULTI is true, search multilib
2680169704Skan   paths then non-multilib paths, otherwise do not search multilib paths.
268150599Sobrien   Return 0 if not found, otherwise return its name, allocated with malloc.  */
268218334Speter
268318334Speterstatic char *
2684169704Skanfind_a_file (const struct path_prefix *pprefix, const char *name, int mode,
2685169704Skan	     bool do_multi)
268618334Speter{
2687169704Skan  struct file_at_path_info info;
268818334Speter
268952520Sobrien#ifdef DEFAULT_ASSEMBLER
269090277Sobrien  if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0)
269190277Sobrien    return xstrdup (DEFAULT_ASSEMBLER);
269252520Sobrien#endif
269352520Sobrien
269452520Sobrien#ifdef DEFAULT_LINKER
269590277Sobrien  if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0)
269690277Sobrien    return xstrdup (DEFAULT_LINKER);
269752520Sobrien#endif
269852520Sobrien
2699231336Skientzle#ifdef FREEBSD_NATIVE
2700231336Skientzle  if (! strcmp(name, "include"))
2701231336Skientzle    {
2702231336Skientzle#ifdef CROSS_INCLUDE_DIR
2703231336Skientzle      return xstrdup(CROSS_INCLUDE_DIR);
2704231336Skientzle#else
2705231336Skientzle      return xstrdup(STANDARD_INCLUDE_DIR);
2706231336Skientzle#endif
2707231336Skientzle    }
2708231336Skientzle#endif
2709231336Skientzle
271018334Speter  /* Determine the filename to execute (special case for absolute paths).  */
271118334Speter
2712132733Skan  if (IS_ABSOLUTE_PATH (name))
271318334Speter    {
271452520Sobrien      if (access (name, mode) == 0)
2715169704Skan	return xstrdup (name);
2716169704Skan
2717169704Skan      return NULL;
271818334Speter    }
2719104763Skan
2720169704Skan  info.name = name;
2721169704Skan  info.suffix = (mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : "";
2722169704Skan  info.name_len = strlen (info.name);
2723169704Skan  info.suffix_len = strlen (info.suffix);
2724169704Skan  info.mode = mode;
272518334Speter
2726169704Skan  return for_each_path (pprefix, do_multi, info.name_len + info.suffix_len,
2727169704Skan			file_at_path, &info);
272818334Speter}
272918334Speter
273090277Sobrien/* Ranking of prefixes in the sort list. -B prefixes are put before
273190277Sobrien   all others.  */
273218334Speter
273390277Sobrienenum path_prefix_priority
273490277Sobrien{
273590277Sobrien  PREFIX_PRIORITY_B_OPT,
273690277Sobrien  PREFIX_PRIORITY_LAST
273790277Sobrien};
273890277Sobrien
2739132733Skan/* Add an entry for PREFIX in PLIST.  The PLIST is kept in ascending
274090277Sobrien   order according to PRIORITY.  Within each PRIORITY, new entries are
274190277Sobrien   appended.
274290277Sobrien
274318334Speter   If WARN is nonzero, we will warn if no file is found
274418334Speter   through this prefix.  WARN should point to an int
274518334Speter   which will be set to 1 if this entry is used.
274618334Speter
274750599Sobrien   COMPONENT is the value to be passed to update_path.
274850599Sobrien
274918334Speter   REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without
275018334Speter   the complete value of machine_suffix.
275118334Speter   2 means try both machine_suffix and just_machine_suffix.  */
275218334Speter
275318334Speterstatic void
2754132733Skanadd_prefix (struct path_prefix *pprefix, const char *prefix,
2755132733Skan	    const char *component, /* enum prefix_priority */ int priority,
2756169704Skan	    int require_machine_suffix, int os_multilib)
275718334Speter{
275818334Speter  struct prefix_list *pl, **prev;
275918334Speter  int len;
276018334Speter
276190277Sobrien  for (prev = &pprefix->plist;
276290277Sobrien       (*prev) != NULL && (*prev)->priority <= priority;
276390277Sobrien       prev = &(*prev)->next)
276490277Sobrien    ;
276518334Speter
2766132733Skan  /* Keep track of the longest prefix.  */
276718334Speter
276850599Sobrien  prefix = update_path (prefix, component);
276918334Speter  len = strlen (prefix);
277018334Speter  if (len > pprefix->max_len)
277118334Speter    pprefix->max_len = len;
277218334Speter
2773169704Skan  pl = XNEW (struct prefix_list);
277490277Sobrien  pl->prefix = prefix;
277518334Speter  pl->require_machine_suffix = require_machine_suffix;
277690277Sobrien  pl->priority = priority;
2777104763Skan  pl->os_multilib = os_multilib;
277818334Speter
2779132733Skan  /* Insert after PREV.  */
278090277Sobrien  pl->next = (*prev);
278190277Sobrien  (*prev) = pl;
278218334Speter}
2783132733Skan
2784132733Skan/* Same as add_prefix, but prepending target_system_root to prefix.  */
2785132733Skanstatic void
2786132733Skanadd_sysrooted_prefix (struct path_prefix *pprefix, const char *prefix,
2787132733Skan		      const char *component,
2788132733Skan		      /* enum prefix_priority */ int priority,
2789169704Skan		      int require_machine_suffix, int os_multilib)
2790132733Skan{
2791132733Skan  if (!IS_ABSOLUTE_PATH (prefix))
2792169704Skan    fatal ("system path '%s' is not absolute", prefix);
2793132733Skan
2794132733Skan  if (target_system_root)
2795132733Skan    {
2796132733Skan      if (target_sysroot_suffix)
2797132733Skan	  prefix = concat (target_sysroot_suffix, prefix, NULL);
2798132733Skan      prefix = concat (target_system_root, prefix, NULL);
2799132733Skan
2800132733Skan      /* We have to override this because GCC's notion of sysroot
2801132733Skan	 moves along with GCC.  */
2802132733Skan      component = "GCC";
2803132733Skan    }
2804132733Skan
2805132733Skan  add_prefix (pprefix, prefix, component, priority,
2806169704Skan	      require_machine_suffix, os_multilib);
2807132733Skan}
280818334Speter
280918334Speter/* Execute the command specified by the arguments on the current line of spec.
281018334Speter   When using pipes, this includes several piped-together commands
281118334Speter   with `|' between them.
281218334Speter
281318334Speter   Return 0 if successful, -1 if failed.  */
281418334Speter
281518334Speterstatic int
2816132733Skanexecute (void)
281718334Speter{
281818334Speter  int i;
281918334Speter  int n_commands;		/* # of command.  */
282018334Speter  char *string;
2821169704Skan  struct pex_obj *pex;
282218334Speter  struct command
282390277Sobrien  {
282490277Sobrien    const char *prog;		/* program name.  */
282590277Sobrien    const char **argv;		/* vector of args.  */
282690277Sobrien  };
282718334Speter
282818334Speter  struct command *commands;	/* each command buffer with above info.  */
282918334Speter
2830169704Skan  gcc_assert (!processing_spec_function);
2831117413Skan
283218334Speter  /* Count # of piped commands.  */
283318334Speter  for (n_commands = 1, i = 0; i < argbuf_index; i++)
283418334Speter    if (strcmp (argbuf[i], "|") == 0)
283518334Speter      n_commands++;
283618334Speter
283718334Speter  /* Get storage for each command.  */
2838132733Skan  commands = alloca (n_commands * sizeof (struct command));
283918334Speter
284018334Speter  /* Split argbuf into its separate piped processes,
284118334Speter     and record info about each one.
284218334Speter     Also search for the programs that are to be run.  */
284318334Speter
284418334Speter  commands[0].prog = argbuf[0]; /* first command.  */
284518334Speter  commands[0].argv = &argbuf[0];
2846169704Skan  string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
284750599Sobrien
284818334Speter  if (string)
284918334Speter    commands[0].argv[0] = string;
285018334Speter
285118334Speter  for (n_commands = 1, i = 0; i < argbuf_index; i++)
285218334Speter    if (strcmp (argbuf[i], "|") == 0)
285318334Speter      {				/* each command.  */
285452520Sobrien#if defined (__MSDOS__) || defined (OS2) || defined (VMS)
285590277Sobrien	fatal ("-pipe not supported");
285618334Speter#endif
285718334Speter	argbuf[i] = 0;	/* termination of command args.  */
285818334Speter	commands[n_commands].prog = argbuf[i + 1];
285918334Speter	commands[n_commands].argv = &argbuf[i + 1];
2860104763Skan	string = find_a_file (&exec_prefixes, commands[n_commands].prog,
2861169704Skan			      X_OK, false);
286218334Speter	if (string)
286318334Speter	  commands[n_commands].argv[0] = string;
286418334Speter	n_commands++;
286518334Speter      }
286618334Speter
286718334Speter  argbuf[argbuf_index] = 0;
286818334Speter
286918334Speter  /* If -v, print what we are about to do, and maybe query.  */
287018334Speter
287118334Speter  if (verbose_flag)
287218334Speter    {
287350599Sobrien      /* For help listings, put a blank line between sub-processes.  */
287450599Sobrien      if (print_help_list)
287550599Sobrien	fputc ('\n', stderr);
287690277Sobrien
287718334Speter      /* Print each piped command as a separate line.  */
287890277Sobrien      for (i = 0; i < n_commands; i++)
287918334Speter	{
288090277Sobrien	  const char *const *j;
288118334Speter
2882117413Skan	  if (verbose_only_flag)
2883117413Skan	    {
288490277Sobrien	      for (j = commands[i].argv; *j; j++)
288590277Sobrien		{
288690277Sobrien		  const char *p;
288790277Sobrien		  fprintf (stderr, " \"");
288890277Sobrien		  for (p = *j; *p; ++p)
288990277Sobrien		    {
289090277Sobrien		      if (*p == '"' || *p == '\\' || *p == '$')
289190277Sobrien			fputc ('\\', stderr);
289290277Sobrien		      fputc (*p, stderr);
289390277Sobrien		    }
289490277Sobrien		  fputc ('"', stderr);
289590277Sobrien		}
2896117413Skan	    }
2897117413Skan	  else
289890277Sobrien	    for (j = commands[i].argv; *j; j++)
289990277Sobrien	      fprintf (stderr, " %s", *j);
290018334Speter
290118334Speter	  /* Print a pipe symbol after all but the last command.  */
290218334Speter	  if (i + 1 != n_commands)
290318334Speter	    fprintf (stderr, " |");
290418334Speter	  fprintf (stderr, "\n");
290518334Speter	}
290618334Speter      fflush (stderr);
290790277Sobrien      if (verbose_only_flag != 0)
2908132733Skan        {
2909132733Skan	  /* verbose_only_flag should act as if the spec was
2910132733Skan	     executed, so increment execution_count before
2911132733Skan	     returning.  This prevents spurious warnings about
2912132733Skan	     unused linker input files, etc.  */
2913132733Skan	  execution_count++;
2914132733Skan	  return 0;
2915132733Skan        }
291618334Speter#ifdef DEBUG
291752520Sobrien      notice ("\nGo ahead? (y or n) ");
291818334Speter      fflush (stderr);
291918334Speter      i = getchar ();
292018334Speter      if (i != '\n')
292150599Sobrien	while (getchar () != '\n')
292250599Sobrien	  ;
292350599Sobrien
292418334Speter      if (i != 'y' && i != 'Y')
292518334Speter	return 0;
292618334Speter#endif /* DEBUG */
292718334Speter    }
292818334Speter
2929117413Skan#ifdef ENABLE_VALGRIND_CHECKING
2930132733Skan  /* Run the each command through valgrind.  To simplify prepending the
2931117413Skan     path to valgrind and the option "-q" (for quiet operation unless
2932117413Skan     something triggers), we allocate a separate argv array.  */
2933117413Skan
2934117413Skan  for (i = 0; i < n_commands; i++)
2935117413Skan    {
2936117413Skan      const char **argv;
2937117413Skan      int argc;
2938117413Skan      int j;
2939117413Skan
2940117413Skan      for (argc = 0; commands[i].argv[argc] != NULL; argc++)
2941117413Skan	;
2942117413Skan
2943117413Skan      argv = alloca ((argc + 3) * sizeof (char *));
2944117413Skan
2945117413Skan      argv[0] = VALGRIND_PATH;
2946117413Skan      argv[1] = "-q";
2947117413Skan      for (j = 2; j < argc + 2; j++)
2948117413Skan	argv[j] = commands[i].argv[j - 2];
2949117413Skan      argv[j] = NULL;
2950117413Skan
2951117413Skan      commands[i].argv = argv;
2952117413Skan      commands[i].prog = argv[0];
2953117413Skan    }
2954117413Skan#endif
2955117413Skan
295618334Speter  /* Run each piped subprocess.  */
295718334Speter
2958169704Skan  pex = pex_init (PEX_USE_PIPES | (report_times ? PEX_RECORD_TIMES : 0),
2959169704Skan		  programname, temp_filename);
2960169704Skan  if (pex == NULL)
2961169704Skan    pfatal_with_name (_("pex_init failed"));
2962169704Skan
296318334Speter  for (i = 0; i < n_commands; i++)
296418334Speter    {
2965169704Skan      const char *errmsg;
2966169704Skan      int err;
296790277Sobrien      const char *string = commands[i].argv[0];
296818334Speter
2969169704Skan      errmsg = pex_run (pex,
2970169704Skan			((i + 1 == n_commands ? PEX_LAST : 0)
2971169704Skan			 | (string == commands[i].prog ? PEX_SEARCH : 0)),
2972169704Skan			string, (char * const *) commands[i].argv,
2973169704Skan			NULL, NULL, &err);
2974169704Skan      if (errmsg != NULL)
2975169704Skan	{
2976169704Skan	  if (err == 0)
2977260011Spfg	    fatal ("%s", errmsg);
2978169704Skan	  else
2979169704Skan	    {
2980169704Skan	      errno = err;
2981169704Skan	      pfatal_with_name (errmsg);
2982169704Skan	    }
2983169704Skan	}
298418334Speter
298518334Speter      if (string != commands[i].prog)
2986132733Skan	free ((void *) string);
298718334Speter    }
298818334Speter
298918334Speter  execution_count++;
299018334Speter
2991169704Skan  /* Wait for all the subprocesses to finish.  */
299218334Speter
299318334Speter  {
2994169704Skan    int *statuses;
2995169704Skan    struct pex_time *times = NULL;
299618334Speter    int ret_code = 0;
299718334Speter
2998169704Skan    statuses = alloca (n_commands * sizeof (int));
2999169704Skan    if (!pex_get_status (pex, n_commands, statuses))
3000169704Skan      pfatal_with_name (_("failed to get exit status"));
3001169704Skan
3002169704Skan    if (report_times)
300318334Speter      {
3004169704Skan	times = alloca (n_commands * sizeof (struct pex_time));
3005169704Skan	if (!pex_get_times (pex, n_commands, times))
3006169704Skan	  pfatal_with_name (_("failed to get process times"));
3007169704Skan      }
300818334Speter
3009169704Skan    pex_free (pex);
301018334Speter
3011169704Skan    for (i = 0; i < n_commands; ++i)
3012169704Skan      {
3013169704Skan	int status = statuses[i];
3014169704Skan
3015169704Skan	if (WIFSIGNALED (status))
301690277Sobrien	  {
301790277Sobrien#ifdef SIGPIPE
3018169704Skan	    /* SIGPIPE is a special case.  It happens in -pipe mode
3019169704Skan	       when the compiler dies before the preprocessor is done,
3020169704Skan	       or the assembler dies before the compiler is done.
3021169704Skan	       There's generally been an error already, and this is
3022169704Skan	       just fallout.  So don't generate another error unless
3023169704Skan	       we would otherwise have succeeded.  */
3024169704Skan	    if (WTERMSIG (status) == SIGPIPE
3025169704Skan		&& (signal_count || greatest_status >= MIN_FATAL_STATUS))
3026169704Skan	      {
3027169704Skan		signal_count++;
3028169704Skan		ret_code = -1;
3029169704Skan	      }
3030169704Skan	    else
303190277Sobrien#endif
3032169704Skan	      fatal_ice ("\
303390277SobrienInternal error: %s (program %s)\n\
303490277SobrienPlease submit a full bug report.\n\
303590277SobrienSee %s for instructions.",
3036169704Skan		 	strsignal (WTERMSIG (status)), commands[i].prog,
3037169704Skan		 	bug_report_url);
3038169704Skan	  }
3039169704Skan	else if (WIFEXITED (status)
3040169704Skan		 && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
3041169704Skan	  {
3042169704Skan	    if (WEXITSTATUS (status) > greatest_status)
3043169704Skan	      greatest_status = WEXITSTATUS (status);
3044169704Skan	    ret_code = -1;
3045169704Skan	  }
3046169704Skan
3047169704Skan	if (report_times)
3048169704Skan	  {
3049169704Skan	    struct pex_time *pt = &times[i];
3050169704Skan	    double ut, st;
3051169704Skan
3052169704Skan	    ut = ((double) pt->user_seconds
3053169704Skan		  + (double) pt->user_microseconds / 1.0e6);
3054169704Skan	    st = ((double) pt->system_seconds
3055169704Skan		  + (double) pt->system_microseconds / 1.0e6);
3056169704Skan
3057169704Skan	    if (ut + st != 0)
3058169704Skan	      notice ("# %s %.2f %.2f\n", commands[i].prog, ut, st);
3059169704Skan	  }
306018334Speter      }
3061169704Skan
306218334Speter    return ret_code;
306318334Speter  }
306418334Speter}
306518334Speter
306618334Speter/* Find all the switches given to us
306718334Speter   and make a vector describing them.
306818334Speter   The elements of the vector are strings, one per switch given.
306918334Speter   If a switch uses following arguments, then the `part1' field
307018334Speter   is the switch itself and the `args' field
307118334Speter   is a null-terminated vector containing the following arguments.
307290277Sobrien   The `live_cond' field is:
307390277Sobrien   0 when initialized
307490277Sobrien   1 if the switch is true in a conditional spec,
307590277Sobrien   -1 if false (overridden by a later switch)
3076132733Skan   -2 if this switch should be ignored (used in %<S)
307752520Sobrien   The `validated' field is nonzero if any spec has looked at this switch;
307818334Speter   if it remains zero at the end of the run, it must be meaningless.  */
307918334Speter
308090277Sobrien#define SWITCH_OK       0
308190277Sobrien#define SWITCH_FALSE   -1
308290277Sobrien#define SWITCH_IGNORE  -2
308390277Sobrien#define SWITCH_LIVE     1
308490277Sobrien
308518334Speterstruct switchstr
308618334Speter{
308752520Sobrien  const char *part1;
308890277Sobrien  const char **args;
308918334Speter  int live_cond;
309090277Sobrien  unsigned char validated;
309190277Sobrien  unsigned char ordering;
309218334Speter};
309318334Speter
309418334Speterstatic struct switchstr *switches;
309518334Speter
309618334Speterstatic int n_switches;
309718334Speter
3098169704Skan/* Language is one of three things:
3099169704Skan
3100169704Skan   1) The name of a real programming language.
3101169704Skan   2) NULL, indicating that no one has figured out
3102169704Skan   what it is yet.
3103169704Skan   3) '*', indicating that the file should be passed
3104169704Skan   to the linker.  */
310518334Speterstruct infile
310618334Speter{
310752520Sobrien  const char *name;
310852520Sobrien  const char *language;
3109169704Skan  struct compiler *incompiler;
3110169704Skan  bool compiled;
3111169704Skan  bool preprocessed;
311218334Speter};
311318334Speter
311418334Speter/* Also a vector of input files specified.  */
311518334Speter
311618334Speterstatic struct infile *infiles;
311718334Speter
311890277Sobrienint n_infiles;
311918334Speter
3120132733Skan/* True if multiple input files are being compiled to a single
3121132733Skan   assembly file.  */
3122132733Skan
3123132733Skanstatic bool combine_inputs;
3124132733Skan
312552520Sobrien/* This counts the number of libraries added by lang_specific_driver, so that
312650599Sobrien   we can tell if there were any user supplied any files or libraries.  */
312750599Sobrien
312850599Sobrienstatic int added_libraries;
312950599Sobrien
313018334Speter/* And a vector of corresponding output files is made up later.  */
313118334Speter
313290277Sobrienconst char **outfiles;
313350599Sobrien
313490277Sobrien#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
313550599Sobrien
313650599Sobrien/* Convert NAME to a new name if it is the standard suffix.  DO_EXE
313790277Sobrien   is true if we should look for an executable suffix.  DO_OBJ
313890277Sobrien   is true if we should look for an object suffix.  */
313950599Sobrien
314090277Sobrienstatic const char *
3141132733Skanconvert_filename (const char *name, int do_exe ATTRIBUTE_UNUSED,
3142132733Skan		  int do_obj ATTRIBUTE_UNUSED)
314350599Sobrien{
314490277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
314550599Sobrien  int i;
314690277Sobrien#endif
314752520Sobrien  int len;
314850599Sobrien
314952520Sobrien  if (name == NULL)
315052520Sobrien    return NULL;
315190277Sobrien
315252520Sobrien  len = strlen (name);
315352520Sobrien
315490277Sobrien#ifdef HAVE_TARGET_OBJECT_SUFFIX
315590277Sobrien  /* Convert x.o to x.obj if TARGET_OBJECT_SUFFIX is ".obj".  */
315690277Sobrien  if (do_obj && len > 2
315750599Sobrien      && name[len - 2] == '.'
315850599Sobrien      && name[len - 1] == 'o')
315950599Sobrien    {
316050599Sobrien      obstack_grow (&obstack, name, len - 2);
316190277Sobrien      obstack_grow0 (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
3162169704Skan      name = XOBFINISH (&obstack, const char *);
316350599Sobrien    }
316450599Sobrien#endif
316550599Sobrien
316690277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
316750599Sobrien  /* If there is no filetype, make it the executable suffix (which includes
316850599Sobrien     the ".").  But don't get confused if we have just "-o".  */
316990277Sobrien  if (! do_exe || TARGET_EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-'))
317050599Sobrien    return name;
317150599Sobrien
317250599Sobrien  for (i = len - 1; i >= 0; i--)
317352520Sobrien    if (IS_DIR_SEPARATOR (name[i]))
317450599Sobrien      break;
317550599Sobrien
317650599Sobrien  for (i++; i < len; i++)
317750599Sobrien    if (name[i] == '.')
317850599Sobrien      return name;
317950599Sobrien
318050599Sobrien  obstack_grow (&obstack, name, len);
318190277Sobrien  obstack_grow0 (&obstack, TARGET_EXECUTABLE_SUFFIX,
318290277Sobrien		 strlen (TARGET_EXECUTABLE_SUFFIX));
3183169704Skan  name = XOBFINISH (&obstack, const char *);
318450599Sobrien#endif
318550599Sobrien
318650599Sobrien  return name;
318750599Sobrien}
318850599Sobrien#endif
318950599Sobrien
319050599Sobrien/* Display the command line switches accepted by gcc.  */
319150599Sobrienstatic void
3192132733Skandisplay_help (void)
319350599Sobrien{
319490277Sobrien  printf (_("Usage: %s [options] file...\n"), programname);
319590277Sobrien  fputs (_("Options:\n"), stdout);
319650599Sobrien
319790277Sobrien  fputs (_("  -pass-exit-codes         Exit with highest error code from a phase\n"), stdout);
319890277Sobrien  fputs (_("  --help                   Display this information\n"), stdout);
319990277Sobrien  fputs (_("  --target-help            Display target specific command line options\n"), stdout);
320050599Sobrien  if (! verbose_flag)
320190277Sobrien    fputs (_("  (Use '-v --help' to display command line options of sub-processes)\n"), stdout);
320290277Sobrien  fputs (_("  -dumpspecs               Display all of the built in spec strings\n"), stdout);
320390277Sobrien  fputs (_("  -dumpversion             Display the version of the compiler\n"), stdout);
320490277Sobrien  fputs (_("  -dumpmachine             Display the compiler's target processor\n"), stdout);
320590277Sobrien  fputs (_("  -print-search-dirs       Display the directories in the compiler's search path\n"), stdout);
320690277Sobrien  fputs (_("  -print-libgcc-file-name  Display the name of the compiler's companion library\n"), stdout);
320790277Sobrien  fputs (_("  -print-file-name=<lib>   Display the full path to library <lib>\n"), stdout);
320890277Sobrien  fputs (_("  -print-prog-name=<prog>  Display the full path to compiler component <prog>\n"), stdout);
320990277Sobrien  fputs (_("  -print-multi-directory   Display the root directory for versions of libgcc\n"), stdout);
321090277Sobrien  fputs (_("\
321190277Sobrien  -print-multi-lib         Display the mapping between command line options and\n\
321290277Sobrien                           multiple library search directories\n"), stdout);
3213104763Skan  fputs (_("  -print-multi-os-directory Display the relative path to OS libraries\n"), stdout);
321490277Sobrien  fputs (_("  -Wa,<options>            Pass comma-separated <options> on to the assembler\n"), stdout);
321590277Sobrien  fputs (_("  -Wp,<options>            Pass comma-separated <options> on to the preprocessor\n"), stdout);
321690277Sobrien  fputs (_("  -Wl,<options>            Pass comma-separated <options> on to the linker\n"), stdout);
3217132733Skan  fputs (_("  -Xassembler <arg>        Pass <arg> on to the assembler\n"), stdout);
3218132733Skan  fputs (_("  -Xpreprocessor <arg>     Pass <arg> on to the preprocessor\n"), stdout);
321990277Sobrien  fputs (_("  -Xlinker <arg>           Pass <arg> on to the linker\n"), stdout);
3220169704Skan  fputs (_("  -combine                 Pass multiple source files to compiler at once\n"), stdout);
322190277Sobrien  fputs (_("  -save-temps              Do not delete intermediate files\n"), stdout);
322290277Sobrien  fputs (_("  -pipe                    Use pipes rather than intermediate files\n"), stdout);
322390277Sobrien  fputs (_("  -time                    Time the execution of each subprocess\n"), stdout);
322490277Sobrien  fputs (_("  -specs=<file>            Override built-in specs with the contents of <file>\n"), stdout);
322590277Sobrien  fputs (_("  -std=<standard>          Assume that the input sources are for <standard>\n"), stdout);
3226169704Skan  fputs (_("\
3227169704Skan  --sysroot=<directory>    Use <directory> as the root directory for headers\n\
3228169704Skan                           and libraries\n"), stdout);
322990277Sobrien  fputs (_("  -B <directory>           Add <directory> to the compiler's search paths\n"), stdout);
323090277Sobrien  fputs (_("  -b <machine>             Run gcc for target <machine>, if installed\n"), stdout);
323190277Sobrien  fputs (_("  -V <version>             Run gcc version number <version>, if installed\n"), stdout);
323290277Sobrien  fputs (_("  -v                       Display the programs invoked by the compiler\n"), stdout);
323390277Sobrien  fputs (_("  -###                     Like -v but options quoted and commands not executed\n"), stdout);
323490277Sobrien  fputs (_("  -E                       Preprocess only; do not compile, assemble or link\n"), stdout);
323590277Sobrien  fputs (_("  -S                       Compile only; do not assemble or link\n"), stdout);
323690277Sobrien  fputs (_("  -c                       Compile and assemble, but do not link\n"), stdout);
323790277Sobrien  fputs (_("  -o <file>                Place the output into <file>\n"), stdout);
323890277Sobrien  fputs (_("\
323990277Sobrien  -x <language>            Specify the language of the following input files\n\
3240117413Skan                           Permissible languages include: c c++ assembler none\n\
324190277Sobrien                           'none' means revert to the default behavior of\n\
324290277Sobrien                           guessing the language based on the file's extension\n\
324390277Sobrien"), stdout);
324450599Sobrien
324590277Sobrien  printf (_("\
324690277Sobrien\nOptions starting with -g, -f, -m, -O, -W, or --param are automatically\n\
324790277Sobrien passed on to the various sub-processes invoked by %s.  In order to pass\n\
324890277Sobrien other options on to these processes the -W<letter> options must be used.\n\
324990277Sobrien"), programname);
325050599Sobrien
325150599Sobrien  /* The rest of the options are displayed by invocations of the various
325250599Sobrien     sub-processes.  */
325350599Sobrien}
325450599Sobrien
325590277Sobrienstatic void
3256132733Skanadd_preprocessor_option (const char *option, int len)
325790277Sobrien{
325852520Sobrien  n_preprocessor_options++;
325990277Sobrien
326052520Sobrien  if (! preprocessor_options)
3261169704Skan    preprocessor_options = XNEWVEC (char *, n_preprocessor_options);
326252520Sobrien  else
3263132733Skan    preprocessor_options = xrealloc (preprocessor_options,
3264132733Skan				     n_preprocessor_options * sizeof (char *));
326590277Sobrien
326652520Sobrien  preprocessor_options [n_preprocessor_options - 1] =
326752520Sobrien    save_string (option, len);
326850599Sobrien}
326990277Sobrien
327090277Sobrienstatic void
3271132733Skanadd_assembler_option (const char *option, int len)
327252520Sobrien{
327352520Sobrien  n_assembler_options++;
327452520Sobrien
327552520Sobrien  if (! assembler_options)
3276169704Skan    assembler_options = XNEWVEC (char *, n_assembler_options);
327752520Sobrien  else
3278132733Skan    assembler_options = xrealloc (assembler_options,
3279132733Skan				  n_assembler_options * sizeof (char *));
328052520Sobrien
328152520Sobrien  assembler_options [n_assembler_options - 1] = save_string (option, len);
328250599Sobrien}
328390277Sobrien
328490277Sobrienstatic void
3285132733Skanadd_linker_option (const char *option, int len)
328652520Sobrien{
328752520Sobrien  n_linker_options++;
328852520Sobrien
328952520Sobrien  if (! linker_options)
3290169704Skan    linker_options = XNEWVEC (char *, n_linker_options);
329152520Sobrien  else
3292132733Skan    linker_options = xrealloc (linker_options,
3293132733Skan			       n_linker_options * sizeof (char *));
329452520Sobrien
329552520Sobrien  linker_options [n_linker_options - 1] = save_string (option, len);
329650599Sobrien}
329750599Sobrien
329818334Speter/* Create the vector `switches' and its contents.
329918334Speter   Store its length in `n_switches'.  */
330018334Speter
330118334Speterstatic void
3302132733Skanprocess_command (int argc, const char **argv)
330318334Speter{
330490277Sobrien  int i;
330552520Sobrien  const char *temp;
330652520Sobrien  char *temp1;
330790277Sobrien  const char *spec_lang = 0;
330818334Speter  int last_language_n_infiles;
330950599Sobrien  int lang_n_infiles = 0;
331090277Sobrien#ifdef MODIFY_TARGET_NAME
331190277Sobrien  int is_modify_target_name;
3312169704Skan  unsigned int j;
331390277Sobrien#endif
331418334Speter
3315117413Skan  GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
331618334Speter
331718334Speter  n_switches = 0;
331818334Speter  n_infiles = 0;
331950599Sobrien  added_libraries = 0;
332018334Speter
332118334Speter  /* Figure compiler version from version string.  */
332218334Speter
332390277Sobrien  compiler_version = temp1 = xstrdup (version_string);
332490277Sobrien
332552520Sobrien  for (; *temp1; ++temp1)
332618334Speter    {
332752520Sobrien      if (*temp1 == ' ')
332818334Speter	{
332952520Sobrien	  *temp1 = '\0';
333018334Speter	  break;
333118334Speter	}
333218334Speter    }
333318334Speter
3334117413Skan  /* If there is a -V or -b option (or both), process it now, before
3335169704Skan     trying to interpret the rest of the command line.
3336169704Skan     Use heuristic that all configuration names must have at least
3337169704Skan     one dash '-'. This allows us to pass options starting with -b.  */
3338117413Skan  if (argc > 1 && argv[1][0] == '-'
3339169704Skan      && (argv[1][1] == 'V' ||
3340169704Skan	 ((argv[1][1] == 'b') && (NULL != strchr(argv[1] + 2,'-')))))
3341117413Skan    {
3342117413Skan      const char *new_version = DEFAULT_TARGET_VERSION;
3343117413Skan      const char *new_machine = DEFAULT_TARGET_MACHINE;
3344117413Skan      const char *progname = argv[0];
3345117413Skan      char **new_argv;
3346117413Skan      char *new_argv0;
3347117413Skan      int baselen;
3348132733Skan
3349117413Skan      while (argc > 1 && argv[1][0] == '-'
3350169704Skan	     && (argv[1][1] == 'V' ||
3351169704Skan		((argv[1][1] == 'b') && ( NULL != strchr(argv[1] + 2,'-')))))
3352117413Skan	{
3353117413Skan	  char opt = argv[1][1];
3354117413Skan	  const char *arg;
3355117413Skan	  if (argv[1][2] != '\0')
3356117413Skan	    {
3357117413Skan	      arg = argv[1] + 2;
3358117413Skan	      argc -= 1;
3359117413Skan	      argv += 1;
3360117413Skan	    }
3361117413Skan	  else if (argc > 2)
3362117413Skan	    {
3363117413Skan	      arg = argv[2];
3364117413Skan	      argc -= 2;
3365117413Skan	      argv += 2;
3366117413Skan	    }
3367117413Skan	  else
3368169704Skan	    fatal ("'-%c' option must have argument", opt);
3369117413Skan	  if (opt == 'V')
3370117413Skan	    new_version = arg;
3371117413Skan	  else
3372117413Skan	    new_machine = arg;
3373117413Skan	}
3374117413Skan
3375117413Skan      for (baselen = strlen (progname); baselen > 0; baselen--)
3376117413Skan	if (IS_DIR_SEPARATOR (progname[baselen-1]))
3377117413Skan	  break;
3378132733Skan      new_argv0 = xmemdup (progname, baselen,
3379117413Skan			   baselen + concat_length (new_version, new_machine,
3380117413Skan						    "-gcc-", NULL) + 1);
3381117413Skan      strcpy (new_argv0 + baselen, new_machine);
3382117413Skan      strcat (new_argv0, "-gcc-");
3383117413Skan      strcat (new_argv0, new_version);
3384117413Skan
3385117413Skan      new_argv = xmemdup (argv, (argc + 1) * sizeof (argv[0]),
3386117413Skan			  (argc + 1) * sizeof (argv[0]));
3387117413Skan      new_argv[0] = new_argv0;
3388117413Skan
3389117413Skan      execvp (new_argv0, new_argv);
3390169704Skan      fatal ("couldn't run '%s': %s", new_argv0, xstrerror (errno));
3391117413Skan    }
3392117413Skan
339390277Sobrien  /* Set up the default search paths.  If there is no GCC_EXEC_PREFIX,
339490277Sobrien     see if we can create it from the pathname specified in argv[0].  */
339518334Speter
3396132733Skan  gcc_libexec_prefix = standard_libexec_prefix;
339796736Sru#ifndef FREEBSD_NATIVE
339890277Sobrien#ifndef VMS
339990277Sobrien  /* FIXME: make_relative_prefix doesn't yet work for VMS.  */
340090277Sobrien  if (!gcc_exec_prefix)
340190277Sobrien    {
340290277Sobrien      gcc_exec_prefix = make_relative_prefix (argv[0], standard_bindir_prefix,
340390277Sobrien					      standard_exec_prefix);
3404169704Skan      gcc_libexec_prefix = make_relative_prefix (argv[0],
3405132733Skan						 standard_bindir_prefix,
3406132733Skan						 standard_libexec_prefix);
340790277Sobrien      if (gcc_exec_prefix)
340890277Sobrien	putenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL));
340990277Sobrien    }
3410132733Skan  else
3411169704Skan    {
3412169704Skan      /* make_relative_prefix requires a program name, but
3413169704Skan	 GCC_EXEC_PREFIX is typically a directory name with a trailing
3414169704Skan	 / (which is ignored by make_relative_prefix), so append a
3415169704Skan	 program name.  */
3416169704Skan      char *tmp_prefix = concat (gcc_exec_prefix, "gcc", NULL);
3417169704Skan      gcc_libexec_prefix = make_relative_prefix (tmp_prefix,
3418169704Skan						 standard_exec_prefix,
3419169704Skan						 standard_libexec_prefix);
3420169704Skan      free (tmp_prefix);
3421169704Skan    }
3422132733Skan#else
342390277Sobrien#endif
342496736Sru#endif	/* not FREEBSD_NATIVE */
342590277Sobrien
342618334Speter  if (gcc_exec_prefix)
342718334Speter    {
342850599Sobrien      int len = strlen (gcc_exec_prefix);
342990277Sobrien
3430132733Skan      if (len > (int) sizeof ("/lib/gcc/") - 1
343152520Sobrien	  && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1])))
343250599Sobrien	{
3433132733Skan	  temp = gcc_exec_prefix + len - sizeof ("/lib/gcc/") + 1;
343452520Sobrien	  if (IS_DIR_SEPARATOR (*temp)
343590277Sobrien	      && strncmp (temp + 1, "lib", 3) == 0
343652520Sobrien	      && IS_DIR_SEPARATOR (temp[4])
3437132733Skan	      && strncmp (temp + 5, "gcc", 3) == 0)
3438132733Skan	    len -= sizeof ("/lib/gcc/") - 1;
343950599Sobrien	}
344050599Sobrien
344150599Sobrien      set_std_prefix (gcc_exec_prefix, len);
3442132733Skan      add_prefix (&exec_prefixes, gcc_libexec_prefix, "GCC",
3443169704Skan		  PREFIX_PRIORITY_LAST, 0, 0);
344490277Sobrien      add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC",
3445169704Skan		  PREFIX_PRIORITY_LAST, 0, 0);
344618334Speter    }
344718334Speter
344818334Speter  /* COMPILER_PATH and LIBRARY_PATH have values
344918334Speter     that are lists of directory names with colons.  */
345018334Speter
3451117413Skan  GET_ENVIRONMENT (temp, "COMPILER_PATH");
345218334Speter  if (temp)
345318334Speter    {
345452520Sobrien      const char *startp, *endp;
3455132733Skan      char *nstore = alloca (strlen (temp) + 3);
345618334Speter
345718334Speter      startp = endp = temp;
345818334Speter      while (1)
345918334Speter	{
346018334Speter	  if (*endp == PATH_SEPARATOR || *endp == 0)
346118334Speter	    {
346290277Sobrien	      strncpy (nstore, startp, endp - startp);
346318334Speter	      if (endp == startp)
346490277Sobrien		strcpy (nstore, concat (".", dir_separator_str, NULL));
346552520Sobrien	      else if (!IS_DIR_SEPARATOR (endp[-1]))
346618334Speter		{
346790277Sobrien		  nstore[endp - startp] = DIR_SEPARATOR;
346890277Sobrien		  nstore[endp - startp + 1] = 0;
346918334Speter		}
347018334Speter	      else
347190277Sobrien		nstore[endp - startp] = 0;
347290277Sobrien	      add_prefix (&exec_prefixes, nstore, 0,
3473169704Skan			  PREFIX_PRIORITY_LAST, 0, 0);
3474169704Skan	      add_prefix (&include_prefixes, nstore, 0,
3475169704Skan			  PREFIX_PRIORITY_LAST, 0, 0);
347618334Speter	      if (*endp == 0)
347718334Speter		break;
347818334Speter	      endp = startp = endp + 1;
347918334Speter	    }
348018334Speter	  else
348118334Speter	    endp++;
348218334Speter	}
348318334Speter    }
348418334Speter
3485117413Skan  GET_ENVIRONMENT (temp, LIBRARY_PATH_ENV);
348691651Sobrien  if (temp && *cross_compile == '0')
348718334Speter    {
348852520Sobrien      const char *startp, *endp;
3489132733Skan      char *nstore = alloca (strlen (temp) + 3);
349018334Speter
349118334Speter      startp = endp = temp;
349218334Speter      while (1)
349318334Speter	{
349418334Speter	  if (*endp == PATH_SEPARATOR || *endp == 0)
349518334Speter	    {
349690277Sobrien	      strncpy (nstore, startp, endp - startp);
349718334Speter	      if (endp == startp)
349890277Sobrien		strcpy (nstore, concat (".", dir_separator_str, NULL));
349952520Sobrien	      else if (!IS_DIR_SEPARATOR (endp[-1]))
350018334Speter		{
350190277Sobrien		  nstore[endp - startp] = DIR_SEPARATOR;
350290277Sobrien		  nstore[endp - startp + 1] = 0;
350318334Speter		}
350418334Speter	      else
350590277Sobrien		nstore[endp - startp] = 0;
350690277Sobrien	      add_prefix (&startfile_prefixes, nstore, NULL,
3507169704Skan			  PREFIX_PRIORITY_LAST, 0, 1);
350818334Speter	      if (*endp == 0)
350918334Speter		break;
351018334Speter	      endp = startp = endp + 1;
351118334Speter	    }
351218334Speter	  else
351318334Speter	    endp++;
351418334Speter	}
351518334Speter    }
351618334Speter
351718334Speter  /* Use LPATH like LIBRARY_PATH (for the CMU build program).  */
3518117413Skan  GET_ENVIRONMENT (temp, "LPATH");
351950599Sobrien  if (temp && *cross_compile == '0')
352018334Speter    {
352152520Sobrien      const char *startp, *endp;
3522132733Skan      char *nstore = alloca (strlen (temp) + 3);
352318334Speter
352418334Speter      startp = endp = temp;
352518334Speter      while (1)
352618334Speter	{
352718334Speter	  if (*endp == PATH_SEPARATOR || *endp == 0)
352818334Speter	    {
352990277Sobrien	      strncpy (nstore, startp, endp - startp);
353018334Speter	      if (endp == startp)
353190277Sobrien		strcpy (nstore, concat (".", dir_separator_str, NULL));
353252520Sobrien	      else if (!IS_DIR_SEPARATOR (endp[-1]))
353318334Speter		{
353490277Sobrien		  nstore[endp - startp] = DIR_SEPARATOR;
353590277Sobrien		  nstore[endp - startp + 1] = 0;
353618334Speter		}
353718334Speter	      else
353890277Sobrien		nstore[endp - startp] = 0;
353990277Sobrien	      add_prefix (&startfile_prefixes, nstore, NULL,
3540169704Skan			  PREFIX_PRIORITY_LAST, 0, 1);
354118334Speter	      if (*endp == 0)
354218334Speter		break;
354318334Speter	      endp = startp = endp + 1;
354418334Speter	    }
354518334Speter	  else
354618334Speter	    endp++;
354718334Speter	}
354818334Speter    }
354918334Speter
355077389Sobrien  /* Options specified as if they appeared on the command line.  */
355177389Sobrien  temp = getenv ("GCC_OPTIONS");
355277389Sobrien  if ((temp) && (strlen (temp) > 0))
355377389Sobrien    {
355477389Sobrien      int len;
355577389Sobrien      int optc = 1;
355677389Sobrien      int new_argc;
3557110024Sobrien      const char **new_argv;
355877389Sobrien      char *envopts;
355977389Sobrien
356077389Sobrien      while (isspace (*temp))
356177389Sobrien	temp++;
356277389Sobrien      len = strlen (temp);
356377389Sobrien      envopts = (char *) xmalloc (len + 1);
356477389Sobrien      strcpy (envopts, temp);
356577389Sobrien
356677389Sobrien      for (i = 0; i < (len - 1); i++)
356777389Sobrien	if ((isspace (envopts[i])) && ! (isspace (envopts[i+1])))
356877389Sobrien	  optc++;
356977389Sobrien
3570110024Sobrien      new_argv = (const char **) alloca ((optc + argc) * sizeof(char *));
357177389Sobrien
357277389Sobrien      for (i = 0, new_argc = 1; new_argc <= optc; new_argc++)
357377389Sobrien	{
357477389Sobrien	  while (isspace (envopts[i]))
357577389Sobrien	    i++;
357677389Sobrien	  new_argv[new_argc] = envopts + i;
357777389Sobrien	  while (!isspace (envopts[i]) && (envopts[i] != '\0'))
357877389Sobrien	    i++;
357977389Sobrien	  envopts[i++] = '\0';
358077389Sobrien	}
358177389Sobrien      for (i = 1; i < argc; i++)
358277389Sobrien	new_argv[new_argc++] = argv[i];
358377389Sobrien
358477389Sobrien      argv = new_argv;
358577389Sobrien      argc = new_argc;
358677389Sobrien    }
358777389Sobrien
358818334Speter  /* Convert new-style -- options to old-style.  */
3589132733Skan  translate_options (&argc, (const char *const **) &argv);
359018334Speter
359150599Sobrien  /* Do language-specific adjustment/addition of flags.  */
3592132733Skan  lang_specific_driver (&argc, (const char *const **) &argv, &added_libraries);
359350599Sobrien
359418334Speter  /* Scan argv twice.  Here, the first time, just count how many switches
359518334Speter     there will be in their vector, and how many input files in theirs.
359618334Speter     Here we also parse the switches that cc itself uses (e.g. -v).  */
359718334Speter
359818334Speter  for (i = 1; i < argc; i++)
359918334Speter    {
360018334Speter      if (! strcmp (argv[i], "-dumpspecs"))
360118334Speter	{
360250599Sobrien	  struct spec_list *sl;
360350599Sobrien	  init_spec ();
360450599Sobrien	  for (sl = specs; sl; sl = sl->next)
360550599Sobrien	    printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec));
360690277Sobrien	  if (link_command_spec)
360790277Sobrien	    printf ("*link_command:\n%s\n\n", link_command_spec);
360818334Speter	  exit (0);
360918334Speter	}
361018334Speter      else if (! strcmp (argv[i], "-dumpversion"))
361118334Speter	{
361250599Sobrien	  printf ("%s\n", spec_version);
361318334Speter	  exit (0);
361418334Speter	}
361518334Speter      else if (! strcmp (argv[i], "-dumpmachine"))
361618334Speter	{
361718334Speter	  printf ("%s\n", spec_machine);
361890277Sobrien	  exit (0);
361918334Speter	}
362090277Sobrien      else if (strcmp (argv[i], "-fversion") == 0)
362190277Sobrien	{
362290277Sobrien	  /* translate_options () has turned --version into -fversion.  */
362390277Sobrien	  printf (_("%s (GCC) %s\n"), programname, version_string);
3624169704Skan	  printf ("Copyright %s 2007 Free Software Foundation, Inc.\n",
3625132733Skan		  _("(C)"));
362690277Sobrien	  fputs (_("This is free software; see the source for copying conditions.  There is NO\n\
362790277Sobrienwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
362890277Sobrien		 stdout);
362990277Sobrien	  exit (0);
363090277Sobrien	}
363150599Sobrien      else if (strcmp (argv[i], "-fhelp") == 0)
363250599Sobrien	{
363350599Sobrien	  /* translate_options () has turned --help into -fhelp.  */
363450599Sobrien	  print_help_list = 1;
363550599Sobrien
363650599Sobrien	  /* We will be passing a dummy file on to the sub-processes.  */
363750599Sobrien	  n_infiles++;
363850599Sobrien	  n_switches++;
363990277Sobrien
364090277Sobrien	  /* CPP driver cannot obtain switch from cc1_options.  */
364190277Sobrien	  if (is_cpp_driver)
364290277Sobrien	    add_preprocessor_option ("--help", 6);
364350599Sobrien	  add_assembler_option ("--help", 6);
364450599Sobrien	  add_linker_option ("--help", 6);
364550599Sobrien	}
364690277Sobrien      else if (strcmp (argv[i], "-ftarget-help") == 0)
3647117413Skan	{
3648117413Skan	  /* translate_options() has turned --target-help into -ftarget-help.  */
3649117413Skan	  target_help_flag = 1;
365090277Sobrien
3651117413Skan	  /* We will be passing a dummy file on to the sub-processes.  */
3652117413Skan	  n_infiles++;
3653117413Skan	  n_switches++;
365490277Sobrien
365590277Sobrien	  /* CPP driver cannot obtain switch from cc1_options.  */
365690277Sobrien	  if (is_cpp_driver)
365790277Sobrien	    add_preprocessor_option ("--target-help", 13);
3658117413Skan	  add_assembler_option ("--target-help", 13);
3659117413Skan	  add_linker_option ("--target-help", 13);
3660117413Skan	}
366190277Sobrien      else if (! strcmp (argv[i], "-pass-exit-codes"))
366290277Sobrien	{
366390277Sobrien	  pass_exit_codes = 1;
366490277Sobrien	  n_switches++;
366590277Sobrien	}
366618334Speter      else if (! strcmp (argv[i], "-print-search-dirs"))
366718334Speter	print_search_dirs = 1;
366818334Speter      else if (! strcmp (argv[i], "-print-libgcc-file-name"))
366918334Speter	print_file_name = "libgcc.a";
367018334Speter      else if (! strncmp (argv[i], "-print-file-name=", 17))
367118334Speter	print_file_name = argv[i] + 17;
367218334Speter      else if (! strncmp (argv[i], "-print-prog-name=", 17))
367318334Speter	print_prog_name = argv[i] + 17;
367418334Speter      else if (! strcmp (argv[i], "-print-multi-lib"))
367518334Speter	print_multi_lib = 1;
367618334Speter      else if (! strcmp (argv[i], "-print-multi-directory"))
367718334Speter	print_multi_directory = 1;
3678104763Skan      else if (! strcmp (argv[i], "-print-multi-os-directory"))
3679104763Skan	print_multi_os_directory = 1;
368018334Speter      else if (! strncmp (argv[i], "-Wa,", 4))
368118334Speter	{
368218334Speter	  int prev, j;
368318334Speter	  /* Pass the rest of this option to the assembler.  */
368418334Speter
368518334Speter	  /* Split the argument at commas.  */
368618334Speter	  prev = 4;
368718334Speter	  for (j = 4; argv[i][j]; j++)
368818334Speter	    if (argv[i][j] == ',')
368918334Speter	      {
369050599Sobrien		add_assembler_option (argv[i] + prev, j - prev);
369118334Speter		prev = j + 1;
369218334Speter	      }
369390277Sobrien
369418334Speter	  /* Record the part after the last comma.  */
369550599Sobrien	  add_assembler_option (argv[i] + prev, j - prev);
369618334Speter	}
369718334Speter      else if (! strncmp (argv[i], "-Wp,", 4))
369818334Speter	{
369918334Speter	  int prev, j;
370018334Speter	  /* Pass the rest of this option to the preprocessor.  */
370118334Speter
370218334Speter	  /* Split the argument at commas.  */
370318334Speter	  prev = 4;
370418334Speter	  for (j = 4; argv[i][j]; j++)
370518334Speter	    if (argv[i][j] == ',')
370618334Speter	      {
370750599Sobrien		add_preprocessor_option (argv[i] + prev, j - prev);
370818334Speter		prev = j + 1;
370918334Speter	      }
371090277Sobrien
371118334Speter	  /* Record the part after the last comma.  */
371250599Sobrien	  add_preprocessor_option (argv[i] + prev, j - prev);
371318334Speter	}
371418334Speter      else if (argv[i][0] == '+' && argv[i][1] == 'e')
371518334Speter	/* The +e options to the C++ front-end.  */
371618334Speter	n_switches++;
371718334Speter      else if (strncmp (argv[i], "-Wl,", 4) == 0)
371818334Speter	{
371918334Speter	  int j;
372018334Speter	  /* Split the argument at commas.  */
372118334Speter	  for (j = 3; argv[i][j]; j++)
372218334Speter	    n_infiles += (argv[i][j] == ',');
372318334Speter	}
372418334Speter      else if (strcmp (argv[i], "-Xlinker") == 0)
372518334Speter	{
372618334Speter	  if (i + 1 == argc)
3727169704Skan	    fatal ("argument to '-Xlinker' is missing");
372818334Speter
372918334Speter	  n_infiles++;
373018334Speter	  i++;
373118334Speter	}
3732132733Skan      else if (strcmp (argv[i], "-Xpreprocessor") == 0)
3733132733Skan	{
3734132733Skan	  if (i + 1 == argc)
3735169704Skan	    fatal ("argument to '-Xpreprocessor' is missing");
3736132733Skan
3737132733Skan	  add_preprocessor_option (argv[i+1], strlen (argv[i+1]));
3738132733Skan	}
3739132733Skan      else if (strcmp (argv[i], "-Xassembler") == 0)
3740132733Skan	{
3741132733Skan	  if (i + 1 == argc)
3742169704Skan	    fatal ("argument to '-Xassembler' is missing");
3743132733Skan
3744132733Skan	  add_assembler_option (argv[i+1], strlen (argv[i+1]));
3745132733Skan	}
374677389Sobrien      else if (strcmp (argv[i], "-l") == 0)
374777389Sobrien	{
374877389Sobrien	  if (i + 1 == argc)
3749169704Skan	    fatal ("argument to '-l' is missing");
375077389Sobrien
375177389Sobrien	  n_infiles++;
375277389Sobrien	  i++;
375377389Sobrien	}
375418334Speter      else if (strncmp (argv[i], "-l", 2) == 0)
375518334Speter	n_infiles++;
375650599Sobrien      else if (strcmp (argv[i], "-save-temps") == 0)
375750599Sobrien	{
375850599Sobrien	  save_temps_flag = 1;
375950599Sobrien	  n_switches++;
376050599Sobrien	}
3761169704Skan      else if (strcmp (argv[i], "-combine") == 0)
3762169704Skan	{
3763169704Skan	  combine_flag = 1;
3764169704Skan	  n_switches++;
3765169704Skan	}
376650599Sobrien      else if (strcmp (argv[i], "-specs") == 0)
376750599Sobrien	{
3768169704Skan	  struct user_specs *user = XNEW (struct user_specs);
376950599Sobrien	  if (++i >= argc)
3770169704Skan	    fatal ("argument to '-specs' is missing");
377150599Sobrien
377290277Sobrien	  user->next = (struct user_specs *) 0;
377350599Sobrien	  user->filename = argv[i];
377450599Sobrien	  if (user_specs_tail)
377550599Sobrien	    user_specs_tail->next = user;
377650599Sobrien	  else
377750599Sobrien	    user_specs_head = user;
377850599Sobrien	  user_specs_tail = user;
377950599Sobrien	}
378050599Sobrien      else if (strncmp (argv[i], "-specs=", 7) == 0)
378150599Sobrien	{
3782169704Skan	  struct user_specs *user = XNEW (struct user_specs);
378350599Sobrien	  if (strlen (argv[i]) == 7)
3784169704Skan	    fatal ("argument to '-specs=' is missing");
378550599Sobrien
378690277Sobrien	  user->next = (struct user_specs *) 0;
378790277Sobrien	  user->filename = argv[i] + 7;
378850599Sobrien	  if (user_specs_tail)
378950599Sobrien	    user_specs_tail->next = user;
379050599Sobrien	  else
379150599Sobrien	    user_specs_head = user;
379250599Sobrien	  user_specs_tail = user;
379350599Sobrien	}
379490277Sobrien      else if (strcmp (argv[i], "-time") == 0)
379590277Sobrien	report_times = 1;
3796132733Skan      else if (strcmp (argv[i], "-pipe") == 0)
3797132733Skan	{
3798132733Skan	  /* -pipe has to go into the switches array as well as
3799132733Skan	     setting a flag.  */
3800132733Skan	  use_pipes = 1;
3801132733Skan	  n_switches++;
3802132733Skan	}
380390277Sobrien      else if (strcmp (argv[i], "-###") == 0)
380490277Sobrien	{
380590277Sobrien	  /* This is similar to -v except that there is no execution
380690277Sobrien	     of the commands and the echoed arguments are quoted.  It
380790277Sobrien	     is intended for use in shell scripts to capture the
380890277Sobrien	     driver-generated command line.  */
380990277Sobrien	  verbose_only_flag++;
381090277Sobrien	  verbose_flag++;
381190277Sobrien	}
381218334Speter      else if (argv[i][0] == '-' && argv[i][1] != 0)
381318334Speter	{
381490277Sobrien	  const char *p = &argv[i][1];
381590277Sobrien	  int c = *p;
381618334Speter
381718334Speter	  switch (c)
381818334Speter	    {
381918334Speter	    case 'b':
3820169704Skan	      if (NULL == strchr(argv[i] + 2, '-'))
3821169704Skan		goto normal_switch;
3822169704Skan
3823169704Skan	      /* Fall through.  */
3824117413Skan	    case 'V':
3825169704Skan	      fatal ("'-%c' must come at the start of the command line", c);
382618334Speter	      break;
382718334Speter
382818334Speter	    case 'B':
382918334Speter	      {
383090277Sobrien		const char *value;
383190277Sobrien		int len;
383290277Sobrien
383318334Speter		if (p[1] == 0 && i + 1 == argc)
3834169704Skan		  fatal ("argument to '-B' is missing");
383518334Speter		if (p[1] == 0)
383618334Speter		  value = argv[++i];
383718334Speter		else
383818334Speter		  value = p + 1;
383918334Speter
384090277Sobrien		len = strlen (value);
384190277Sobrien
384290277Sobrien		/* Catch the case where the user has forgotten to append a
384390277Sobrien		   directory separator to the path.  Note, they may be using
384490277Sobrien		   -B to add an executable name prefix, eg "i386-elf-", in
384590277Sobrien		   order to distinguish between multiple installations of
384690277Sobrien		   GCC in the same directory.  Hence we must check to see
384790277Sobrien		   if appending a directory separator actually makes a
384890277Sobrien		   valid directory name.  */
384990277Sobrien		if (! IS_DIR_SEPARATOR (value [len - 1])
3850169704Skan		    && is_directory (value, false))
385190277Sobrien		  {
3852169704Skan		    char *tmp = XNEWVEC (char, len + 2);
385390277Sobrien		    strcpy (tmp, value);
385490277Sobrien		    tmp[len] = DIR_SEPARATOR;
385590277Sobrien		    tmp[++ len] = 0;
385690277Sobrien		    value = tmp;
385790277Sobrien		  }
3858117413Skan
385990277Sobrien		/* As a kludge, if the arg is "[foo/]stageN/", just
386090277Sobrien		   add "[foo/]include" to the include prefix.  */
386190277Sobrien		if ((len == 7
386290277Sobrien		     || (len > 7
386390277Sobrien			 && (IS_DIR_SEPARATOR (value[len - 8]))))
386490277Sobrien		    && strncmp (value + len - 7, "stage", 5) == 0
386590277Sobrien		    && ISDIGIT (value[len - 2])
386690277Sobrien		    && (IS_DIR_SEPARATOR (value[len - 1])))
386790277Sobrien		  {
386890277Sobrien		    if (len == 7)
3869169704Skan		      add_prefix (&include_prefixes, "./", NULL,
3870169704Skan				  PREFIX_PRIORITY_B_OPT, 0, 0);
387190277Sobrien		    else
387290277Sobrien		      {
3873169704Skan		        char *string = xmalloc (len - 6);
3874169704Skan			memcpy (string, value, len - 7);
3875169704Skan			string[len - 7] = 0;
3876169704Skan		        add_prefix (&include_prefixes, string, NULL,
3877169704Skan				    PREFIX_PRIORITY_B_OPT, 0, 0);
387890277Sobrien		      }
387990277Sobrien		  }
388090277Sobrien
388190277Sobrien		add_prefix (&exec_prefixes, value, NULL,
3882169704Skan			    PREFIX_PRIORITY_B_OPT, 0, 0);
388390277Sobrien		add_prefix (&startfile_prefixes, value, NULL,
3884169704Skan			    PREFIX_PRIORITY_B_OPT, 0, 0);
3885169704Skan		add_prefix (&include_prefixes, value, NULL,
3886169704Skan			    PREFIX_PRIORITY_B_OPT, 0, 0);
388790277Sobrien		n_switches++;
388818334Speter	      }
388918334Speter	      break;
389018334Speter
389118334Speter	    case 'v':	/* Print our subcommands and print versions.  */
389218334Speter	      n_switches++;
389318334Speter	      /* If they do anything other than exactly `-v', don't set
389418334Speter		 verbose_flag; rather, continue on to give the error.  */
389518334Speter	      if (p[1] != 0)
389618334Speter		break;
389718334Speter	      verbose_flag++;
389818334Speter	      break;
389918334Speter
390050599Sobrien	    case 'S':
390150599Sobrien	    case 'c':
390250599Sobrien	      if (p[1] == 0)
390318334Speter		{
390450599Sobrien		  have_c = 1;
390518334Speter		  n_switches++;
390618334Speter		  break;
390718334Speter		}
390850599Sobrien	      goto normal_switch;
390950599Sobrien
391050599Sobrien	    case 'o':
391150599Sobrien	      have_o = 1;
391290277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
391350599Sobrien	      if (! have_c)
391450599Sobrien		{
391550599Sobrien		  int skip;
391690277Sobrien
391750599Sobrien		  /* Forward scan, just in case -S or -c is specified
391850599Sobrien		     after -o.  */
391950599Sobrien		  int j = i + 1;
392050599Sobrien		  if (p[1] == 0)
392150599Sobrien		    ++j;
392250599Sobrien		  while (j < argc)
392350599Sobrien		    {
392450599Sobrien		      if (argv[j][0] == '-')
392550599Sobrien			{
392650599Sobrien			  if (SWITCH_CURTAILS_COMPILATION (argv[j][1])
392750599Sobrien			      && argv[j][2] == 0)
392850599Sobrien			    {
392950599Sobrien			      have_c = 1;
393050599Sobrien			      break;
393150599Sobrien			    }
393290277Sobrien			  else if ((skip = SWITCH_TAKES_ARG (argv[j][1])))
393350599Sobrien			    j += skip - (argv[j][2] != 0);
393490277Sobrien			  else if ((skip = WORD_SWITCH_TAKES_ARG (argv[j] + 1)))
393550599Sobrien			    j += skip;
393650599Sobrien			}
393750599Sobrien		      j++;
393850599Sobrien		    }
393950599Sobrien		}
394050599Sobrien#endif
394190277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX)
394250599Sobrien	      if (p[1] == 0)
394390277Sobrien		argv[i + 1] = convert_filename (argv[i + 1], ! have_c, 0);
394450599Sobrien	      else
394590277Sobrien		argv[i] = convert_filename (argv[i], ! have_c, 0);
394650599Sobrien#endif
394750599Sobrien	      goto normal_switch;
394850599Sobrien
394918334Speter	    default:
395050599Sobrien	    normal_switch:
395190277Sobrien
395290277Sobrien#ifdef MODIFY_TARGET_NAME
395390277Sobrien	      is_modify_target_name = 0;
395490277Sobrien
3955117413Skan	      for (j = 0; j < ARRAY_SIZE (modify_target); j++)
395690277Sobrien		if (! strcmp (argv[i], modify_target[j].sw))
395790277Sobrien		  {
3958132733Skan		    char *new_name = xmalloc (strlen (modify_target[j].str)
3959132733Skan					      + strlen (spec_machine));
396090277Sobrien		    const char *p, *r;
396190277Sobrien		    char *q;
396290277Sobrien		    int made_addition = 0;
396390277Sobrien
396490277Sobrien		    is_modify_target_name = 1;
396590277Sobrien		    for (p = spec_machine, q = new_name; *p != 0; )
396690277Sobrien		      {
396790277Sobrien			if (modify_target[j].add_del == DELETE
396890277Sobrien			    && (! strncmp (q, modify_target[j].str,
396990277Sobrien					   strlen (modify_target[j].str))))
397090277Sobrien			  p += strlen (modify_target[j].str);
397190277Sobrien			else if (modify_target[j].add_del == ADD
397290277Sobrien				 && ! made_addition && *p == '-')
397390277Sobrien			  {
397490277Sobrien			    for (r = modify_target[j].str; *r != 0; )
397590277Sobrien			      *q++ = *r++;
397690277Sobrien			    made_addition = 1;
397790277Sobrien			  }
397890277Sobrien
397990277Sobrien			*q++ = *p++;
398090277Sobrien		      }
398190277Sobrien
398290277Sobrien		    spec_machine = new_name;
398390277Sobrien		  }
398490277Sobrien
398590277Sobrien	      if (is_modify_target_name)
398690277Sobrien		break;
3987117413Skan#endif
398890277Sobrien
398918334Speter	      n_switches++;
399018334Speter
399118334Speter	      if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
399218334Speter		i += SWITCH_TAKES_ARG (c) - (p[1] != 0);
399318334Speter	      else if (WORD_SWITCH_TAKES_ARG (p))
399418334Speter		i += WORD_SWITCH_TAKES_ARG (p);
399518334Speter	    }
399618334Speter	}
399718334Speter      else
399850599Sobrien	{
399950599Sobrien	  n_infiles++;
400050599Sobrien	  lang_n_infiles++;
400150599Sobrien	}
400218334Speter    }
400318334Speter
4004169704Skan  if (save_temps_flag && use_pipes)
4005132733Skan    {
4006132733Skan      /* -save-temps overrides -pipe, so that temp files are produced */
4007132733Skan      if (save_temps_flag)
4008132733Skan	error ("warning: -pipe ignored because -save-temps specified");
4009132733Skan      use_pipes = 0;
4010132733Skan    }
4011132733Skan
401218334Speter  /* Set up the search paths before we go looking for config files.  */
4013169704Skan#ifdef	FREEBSD_NATIVE
4014169704Skan  add_prefix (&exec_prefixes, PREFIX"/bin/", "BINUTILS",
4015169704Skan	      PREFIX_PRIORITY_LAST, 0, 0);
4016169704Skan#endif	/* FREEBSD_NATIVE */
401718334Speter
401818334Speter  /* These come before the md prefixes so that we will find gcc's subcommands
401918334Speter     (such as cpp) rather than those of the host system.  */
402018334Speter  /* Use 2 as fourth arg meaning try just the machine as a suffix,
402118334Speter     as well as trying the machine and the version.  */
402218334Speter#ifndef OS2
4023132733Skan  add_prefix (&exec_prefixes, standard_libexec_prefix, "GCC",
4024169704Skan	      PREFIX_PRIORITY_LAST, 1, 0);
4025132733Skan  add_prefix (&exec_prefixes, standard_libexec_prefix, "BINUTILS",
4026169704Skan	      PREFIX_PRIORITY_LAST, 2, 0);
4027169704Skan#ifndef	FREEBSD_NATIVE
402850599Sobrien  add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS",
4029169704Skan	      PREFIX_PRIORITY_LAST, 2, 0);
403050599Sobrien  add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS",
4031169704Skan	      PREFIX_PRIORITY_LAST, 2, 0);
4032132733Skan  add_prefix (&exec_prefixes, standard_exec_prefix_2, "BINUTILS",
4033169704Skan	      PREFIX_PRIORITY_LAST, 2, 0);
403418334Speter#endif
4035169704Skan#endif
403618334Speter
4037169704Skan#ifndef	FREEBSD_NATIVE
403850599Sobrien  add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS",
4039169704Skan	      PREFIX_PRIORITY_LAST, 1, 0);
4040132733Skan  add_prefix (&startfile_prefixes, standard_exec_prefix_2, "BINUTILS",
4041169704Skan	      PREFIX_PRIORITY_LAST, 1, 0);
404218334Speter
404390277Sobrien  tooldir_prefix = concat (tooldir_base_prefix, spec_machine,
404490277Sobrien			   dir_separator_str, NULL);
404518334Speter
404618334Speter  /* If tooldir is relative, base it on exec_prefixes.  A relative
404718334Speter     tooldir lets us move the installed tree as a unit.
404818334Speter
404918334Speter     If GCC_EXEC_PREFIX is defined, then we want to add two relative
405018334Speter     directories, so that we can search both the user specified directory
405118334Speter     and the standard place.  */
405218334Speter
4053132733Skan  if (!IS_ABSOLUTE_PATH (tooldir_prefix))
405418334Speter    {
405518334Speter      if (gcc_exec_prefix)
405618334Speter	{
405718334Speter	  char *gcc_exec_tooldir_prefix
405850599Sobrien	    = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
405990277Sobrien		      spec_version, dir_separator_str, tooldir_prefix, NULL);
406018334Speter
406118334Speter	  add_prefix (&exec_prefixes,
406290277Sobrien		      concat (gcc_exec_tooldir_prefix, "bin",
406390277Sobrien			      dir_separator_str, NULL),
4064169704Skan		      NULL, PREFIX_PRIORITY_LAST, 0, 0);
406518334Speter	  add_prefix (&startfile_prefixes,
406690277Sobrien		      concat (gcc_exec_tooldir_prefix, "lib",
406790277Sobrien			      dir_separator_str, NULL),
4068169704Skan		      NULL, PREFIX_PRIORITY_LAST, 0, 1);
406918334Speter	}
407018334Speter
407150599Sobrien      tooldir_prefix = concat (standard_exec_prefix, spec_machine,
407290277Sobrien			       dir_separator_str, spec_version,
407390277Sobrien			       dir_separator_str, tooldir_prefix, NULL);
407418334Speter    }
407518334Speter
407690277Sobrien  add_prefix (&exec_prefixes,
407790277Sobrien	      concat (tooldir_prefix, "bin", dir_separator_str, NULL),
4078169704Skan	      "BINUTILS", PREFIX_PRIORITY_LAST, 0, 0);
407918334Speter  add_prefix (&startfile_prefixes,
408090277Sobrien	      concat (tooldir_prefix, "lib", dir_separator_str, NULL),
4081169704Skan	      "BINUTILS", PREFIX_PRIORITY_LAST, 0, 1);
4082132733Skan
4083132733Skan#if defined(TARGET_SYSTEM_ROOT_RELOCATABLE) && !defined(VMS)
4084132733Skan  /* If the normal TARGET_SYSTEM_ROOT is inside of $exec_prefix,
4085132733Skan     then consider it to relocate with the rest of the GCC installation
4086132733Skan     if GCC_EXEC_PREFIX is set.
4087132733Skan     ``make_relative_prefix'' is not compiled for VMS, so don't call it.  */
4088132733Skan  if (target_system_root && gcc_exec_prefix)
4089132733Skan    {
4090132733Skan      char *tmp_prefix = make_relative_prefix (argv[0],
4091132733Skan					       standard_bindir_prefix,
4092132733Skan					       target_system_root);
4093132733Skan      if (tmp_prefix && access_check (tmp_prefix, F_OK) == 0)
4094132733Skan	{
4095132733Skan	  target_system_root = tmp_prefix;
4096132733Skan	  target_system_root_changed = 1;
4097132733Skan	}
4098132733Skan    }
4099132733Skan#endif
410018346Speter#endif /* FREEBSD_NATIVE */
410118334Speter
410218334Speter  /* More prefixes are enabled in main, after we read the specs file
410318334Speter     and determine whether this is cross-compilation or not.  */
410418334Speter
410518334Speter  /* Then create the space for the vectors and scan again.  */
410618334Speter
4107169704Skan  switches = XNEWVEC (struct switchstr, n_switches + 1);
4108169704Skan  infiles = XNEWVEC (struct infile, n_infiles + 1);
410918334Speter  n_switches = 0;
411018334Speter  n_infiles = 0;
411118334Speter  last_language_n_infiles = -1;
411218334Speter
411318334Speter  /* This, time, copy the text of each switch and store a pointer
411418334Speter     to the copy in the vector of switches.
411518334Speter     Store all the infiles in their vector.  */
411618334Speter
411718334Speter  for (i = 1; i < argc; i++)
411818334Speter    {
411918334Speter      /* Just skip the switches that were handled by the preceding loop.  */
412090277Sobrien#ifdef MODIFY_TARGET_NAME
412190277Sobrien      is_modify_target_name = 0;
412290277Sobrien
4123117413Skan      for (j = 0; j < ARRAY_SIZE (modify_target); j++)
412490277Sobrien	if (! strcmp (argv[i], modify_target[j].sw))
412590277Sobrien	  is_modify_target_name = 1;
412690277Sobrien
412790277Sobrien      if (is_modify_target_name)
412890277Sobrien	;
412990277Sobrien      else
413090277Sobrien#endif
413118334Speter      if (! strncmp (argv[i], "-Wa,", 4))
413218334Speter	;
413318334Speter      else if (! strncmp (argv[i], "-Wp,", 4))
413418334Speter	;
413590277Sobrien      else if (! strcmp (argv[i], "-pass-exit-codes"))
413690277Sobrien	;
413718334Speter      else if (! strcmp (argv[i], "-print-search-dirs"))
413818334Speter	;
413918334Speter      else if (! strcmp (argv[i], "-print-libgcc-file-name"))
414018334Speter	;
414118334Speter      else if (! strncmp (argv[i], "-print-file-name=", 17))
414218334Speter	;
414318334Speter      else if (! strncmp (argv[i], "-print-prog-name=", 17))
414418334Speter	;
414518334Speter      else if (! strcmp (argv[i], "-print-multi-lib"))
414618334Speter	;
414718334Speter      else if (! strcmp (argv[i], "-print-multi-directory"))
414818334Speter	;
4149104763Skan      else if (! strcmp (argv[i], "-print-multi-os-directory"))
4150104763Skan	;
415190277Sobrien      else if (! strcmp (argv[i], "-ftarget-help"))
415290277Sobrien	;
415390277Sobrien      else if (! strcmp (argv[i], "-fhelp"))
415490277Sobrien	;
4155169704Skan      else if (! strncmp (argv[i], "--sysroot=", strlen ("--sysroot=")))
4156169704Skan	{
4157169704Skan	  target_system_root = argv[i] + strlen ("--sysroot=");
4158169704Skan	  target_system_root_changed = 1;
4159169704Skan	}
416018334Speter      else if (argv[i][0] == '+' && argv[i][1] == 'e')
416118334Speter	{
416218334Speter	  /* Compensate for the +e options to the C++ front-end;
416318334Speter	     they're there simply for cfront call-compatibility.  We do
416418334Speter	     some magic in default_compilers to pass them down properly.
416518334Speter	     Note we deliberately start at the `+' here, to avoid passing
416618334Speter	     -e0 or -e1 down into the linker.  */
416718334Speter	  switches[n_switches].part1 = &argv[i][0];
416818334Speter	  switches[n_switches].args = 0;
416990277Sobrien	  switches[n_switches].live_cond = SWITCH_OK;
417052520Sobrien	  switches[n_switches].validated = 0;
417118334Speter	  n_switches++;
417218334Speter	}
417318334Speter      else if (strncmp (argv[i], "-Wl,", 4) == 0)
417418334Speter	{
417518334Speter	  int prev, j;
417618334Speter	  /* Split the argument at commas.  */
417718334Speter	  prev = 4;
417818334Speter	  for (j = 4; argv[i][j]; j++)
417918334Speter	    if (argv[i][j] == ',')
418018334Speter	      {
418150599Sobrien		infiles[n_infiles].language = "*";
418218334Speter		infiles[n_infiles++].name
418318334Speter		  = save_string (argv[i] + prev, j - prev);
418418334Speter		prev = j + 1;
418518334Speter	      }
418618334Speter	  /* Record the part after the last comma.  */
418750599Sobrien	  infiles[n_infiles].language = "*";
418818334Speter	  infiles[n_infiles++].name = argv[i] + prev;
418918334Speter	}
419018334Speter      else if (strcmp (argv[i], "-Xlinker") == 0)
419118334Speter	{
419250599Sobrien	  infiles[n_infiles].language = "*";
419318334Speter	  infiles[n_infiles++].name = argv[++i];
419418334Speter	}
4195169704Skan      /* Xassembler and Xpreprocessor were already handled in the first argv
4196169704Skan	 scan, so all we need to do here is ignore them and their argument.  */
4197132733Skan      else if (strcmp (argv[i], "-Xassembler") == 0)
4198169704Skan	i++;
4199132733Skan      else if (strcmp (argv[i], "-Xpreprocessor") == 0)
4200169704Skan	i++;
420177389Sobrien      else if (strcmp (argv[i], "-l") == 0)
420277389Sobrien	{ /* POSIX allows separation of -l and the lib arg;
420377389Sobrien	     canonicalize by concatenating -l with its arg */
420477389Sobrien	  infiles[n_infiles].language = "*";
420577389Sobrien	  infiles[n_infiles++].name = concat ("-l", argv[++i], NULL);
420677389Sobrien	}
420718334Speter      else if (strncmp (argv[i], "-l", 2) == 0)
420818334Speter	{
420950599Sobrien	  infiles[n_infiles].language = "*";
421018334Speter	  infiles[n_infiles++].name = argv[i];
421118334Speter	}
421250599Sobrien      else if (strcmp (argv[i], "-specs") == 0)
421350599Sobrien	i++;
421450599Sobrien      else if (strncmp (argv[i], "-specs=", 7) == 0)
421550599Sobrien	;
421690277Sobrien      else if (strcmp (argv[i], "-time") == 0)
421790277Sobrien	;
421890277Sobrien      else if (strcmp (argv[i], "-###") == 0)
421990277Sobrien	;
422018334Speter      else if (argv[i][0] == '-' && argv[i][1] != 0)
422118334Speter	{
422290277Sobrien	  const char *p = &argv[i][1];
422390277Sobrien	  int c = *p;
422418334Speter
422518334Speter	  if (c == 'x')
422618334Speter	    {
422718334Speter	      if (p[1] == 0 && i + 1 == argc)
4228169704Skan		fatal ("argument to '-x' is missing");
422918334Speter	      if (p[1] == 0)
423018334Speter		spec_lang = argv[++i];
423118334Speter	      else
423218334Speter		spec_lang = p + 1;
423318334Speter	      if (! strcmp (spec_lang, "none"))
423418334Speter		/* Suppress the warning if -xnone comes after the last input
423518334Speter		   file, because alternate command interfaces like g++ might
423618334Speter		   find it useful to place -xnone after each input file.  */
423718334Speter		spec_lang = 0;
423818334Speter	      else
423918334Speter		last_language_n_infiles = n_infiles;
424018334Speter	      continue;
424118334Speter	    }
424218334Speter	  switches[n_switches].part1 = p;
424318334Speter	  /* Deal with option arguments in separate argv elements.  */
424418334Speter	  if ((SWITCH_TAKES_ARG (c) > (p[1] != 0))
424518334Speter	      || WORD_SWITCH_TAKES_ARG (p))
424618334Speter	    {
424718334Speter	      int j = 0;
424818334Speter	      int n_args = WORD_SWITCH_TAKES_ARG (p);
424918334Speter
425018334Speter	      if (n_args == 0)
425118334Speter		{
425218334Speter		  /* Count only the option arguments in separate argv elements.  */
425318334Speter		  n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0);
425418334Speter		}
425518334Speter	      if (i + n_args >= argc)
4256169704Skan		fatal ("argument to '-%s' is missing", p);
425718334Speter	      switches[n_switches].args
4258169704Skan		= XNEWVEC (const char *, n_args + 1);
425918334Speter	      while (j < n_args)
426018334Speter		switches[n_switches].args[j++] = argv[++i];
426118334Speter	      /* Null-terminate the vector.  */
426218334Speter	      switches[n_switches].args[j] = 0;
426318334Speter	    }
426490277Sobrien	  else if (strchr (switches_need_spaces, c))
426518334Speter	    {
426650599Sobrien	      /* On some systems, ld cannot handle some options without
426750599Sobrien		 a space.  So split the option from its argument.  */
4268169704Skan	      char *part1 = XNEWVEC (char, 2);
426950599Sobrien	      part1[0] = c;
427050599Sobrien	      part1[1] = '\0';
427190277Sobrien
427250599Sobrien	      switches[n_switches].part1 = part1;
4273169704Skan	      switches[n_switches].args = XNEWVEC (const char *, 2);
427490277Sobrien	      switches[n_switches].args[0] = xstrdup (p+1);
427518334Speter	      switches[n_switches].args[1] = 0;
427618334Speter	    }
427718334Speter	  else
427818334Speter	    switches[n_switches].args = 0;
427918334Speter
428090277Sobrien	  switches[n_switches].live_cond = SWITCH_OK;
428152520Sobrien	  switches[n_switches].validated = 0;
428290277Sobrien	  switches[n_switches].ordering = 0;
4283132733Skan	  /* These are always valid, since gcc.c itself understands them.  */
428490277Sobrien	  if (!strcmp (p, "save-temps")
428590277Sobrien	      || !strcmp (p, "static-libgcc")
4286132733Skan	      || !strcmp (p, "shared-libgcc")
4287132733Skan	      || !strcmp (p, "pipe"))
428852520Sobrien	    switches[n_switches].validated = 1;
428990277Sobrien	  else
429090277Sobrien	    {
429190277Sobrien	      char ch = switches[n_switches].part1[0];
4292117413Skan	      if (ch == 'B')
429390277Sobrien		switches[n_switches].validated = 1;
429490277Sobrien	    }
429518334Speter	  n_switches++;
429618334Speter	}
429718334Speter      else
429818334Speter	{
429990277Sobrien#ifdef HAVE_TARGET_OBJECT_SUFFIX
430090277Sobrien	  argv[i] = convert_filename (argv[i], 0, access (argv[i], F_OK));
430118334Speter#endif
430218334Speter
430390277Sobrien	  if (strcmp (argv[i], "-") != 0 && access (argv[i], F_OK) < 0)
430418334Speter	    {
430518334Speter	      perror_with_name (argv[i]);
430618334Speter	      error_count++;
430718334Speter	    }
430818334Speter	  else
430918334Speter	    {
431018334Speter	      infiles[n_infiles].language = spec_lang;
431118334Speter	      infiles[n_infiles++].name = argv[i];
431218334Speter	    }
431318334Speter	}
431418334Speter    }
431518334Speter
431618334Speter  if (n_infiles == last_language_n_infiles && spec_lang != 0)
4317169704Skan    error ("warning: '-x %s' after last input file has no effect", spec_lang);
431818334Speter
431990277Sobrien  /* Ensure we only invoke each subprocess once.  */
432090277Sobrien  if (target_help_flag || print_help_list)
432190277Sobrien    {
432290277Sobrien      n_infiles = 1;
432390277Sobrien
432490277Sobrien      /* Create a dummy input file, so that we can pass --target-help on to
432590277Sobrien	 the various sub-processes.  */
432690277Sobrien      infiles[0].language = "c";
432790277Sobrien      infiles[0].name   = "help-dummy";
432890277Sobrien
432990277Sobrien      if (target_help_flag)
433090277Sobrien	{
433190277Sobrien	  switches[n_switches].part1     = "--target-help";
433290277Sobrien	  switches[n_switches].args      = 0;
433390277Sobrien	  switches[n_switches].live_cond = SWITCH_OK;
433490277Sobrien	  switches[n_switches].validated = 0;
433590277Sobrien
433690277Sobrien	  n_switches++;
433790277Sobrien	}
433890277Sobrien
433990277Sobrien      if (print_help_list)
434090277Sobrien	{
434190277Sobrien	  switches[n_switches].part1     = "--help";
434290277Sobrien	  switches[n_switches].args      = 0;
434390277Sobrien	  switches[n_switches].live_cond = SWITCH_OK;
434490277Sobrien	  switches[n_switches].validated = 0;
434590277Sobrien
434690277Sobrien	  n_switches++;
434790277Sobrien	}
434890277Sobrien    }
434990277Sobrien
435018334Speter  switches[n_switches].part1 = 0;
435118334Speter  infiles[n_infiles].name = 0;
435218334Speter}
435390277Sobrien
4354132733Skan/* Store switches not filtered out by %<S in spec in COLLECT_GCC_OPTIONS
435590277Sobrien   and place that in the environment.  */
435690277Sobrien
435790277Sobrienstatic void
4358132733Skanset_collect_gcc_options (void)
435990277Sobrien{
436090277Sobrien  int i;
436190277Sobrien  int first_time;
436290277Sobrien
436390277Sobrien  /* Build COLLECT_GCC_OPTIONS to have all of the options specified to
436490277Sobrien     the compiler.  */
436590277Sobrien  obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
436690277Sobrien		sizeof ("COLLECT_GCC_OPTIONS=") - 1);
436790277Sobrien
436890277Sobrien  first_time = TRUE;
436990277Sobrien  for (i = 0; (int) i < n_switches; i++)
437090277Sobrien    {
437190277Sobrien      const char *const *args;
437290277Sobrien      const char *p, *q;
437390277Sobrien      if (!first_time)
437490277Sobrien	obstack_grow (&collect_obstack, " ", 1);
437590277Sobrien
437690277Sobrien      first_time = FALSE;
437790277Sobrien
437890277Sobrien      /* Ignore elided switches.  */
437990277Sobrien      if (switches[i].live_cond == SWITCH_IGNORE)
438090277Sobrien	continue;
438190277Sobrien
438290277Sobrien      obstack_grow (&collect_obstack, "'-", 2);
438390277Sobrien      q = switches[i].part1;
438490277Sobrien      while ((p = strchr (q, '\'')))
438590277Sobrien	{
438690277Sobrien	  obstack_grow (&collect_obstack, q, p - q);
438790277Sobrien	  obstack_grow (&collect_obstack, "'\\''", 4);
438890277Sobrien	  q = ++p;
438990277Sobrien	}
439090277Sobrien      obstack_grow (&collect_obstack, q, strlen (q));
439190277Sobrien      obstack_grow (&collect_obstack, "'", 1);
439290277Sobrien
439390277Sobrien      for (args = switches[i].args; args && *args; args++)
439490277Sobrien	{
439590277Sobrien	  obstack_grow (&collect_obstack, " '", 2);
439690277Sobrien	  q = *args;
439790277Sobrien	  while ((p = strchr (q, '\'')))
439890277Sobrien	    {
439990277Sobrien	      obstack_grow (&collect_obstack, q, p - q);
440090277Sobrien	      obstack_grow (&collect_obstack, "'\\''", 4);
440190277Sobrien	      q = ++p;
440290277Sobrien	    }
440390277Sobrien	  obstack_grow (&collect_obstack, q, strlen (q));
440490277Sobrien	  obstack_grow (&collect_obstack, "'", 1);
440590277Sobrien	}
440690277Sobrien    }
440790277Sobrien  obstack_grow (&collect_obstack, "\0", 1);
4408169704Skan  putenv (XOBFINISH (&collect_obstack, char *));
440990277Sobrien}
441018334Speter
441118334Speter/* Process a spec string, accumulating and running commands.  */
441218334Speter
441318334Speter/* These variables describe the input file name.
441418334Speter   input_file_number is the index on outfiles of this file,
441518334Speter   so that the output file name can be stored for later use by %o.
441618334Speter   input_basename is the start of the part of the input file
441718334Speter   sans all directory names, and basename_length is the number
441818334Speter   of characters starting there excluding the suffix .c or whatever.  */
441918334Speter
4420132733Skanstatic const char *input_filename;
442118334Speterstatic int input_file_number;
442250599Sobriensize_t input_filename_length;
442318334Speterstatic int basename_length;
442490277Sobrienstatic int suffixed_basename_length;
442552520Sobrienstatic const char *input_basename;
442652520Sobrienstatic const char *input_suffix;
4427169704Skan#ifndef HOST_LACKS_INODE_NUMBERS
442890277Sobrienstatic struct stat input_stat;
4429169704Skan#endif
443090277Sobrienstatic int input_stat_set;
443118334Speter
443290277Sobrien/* The compiler used to process the current input file.  */
443390277Sobrienstatic struct compiler *input_file_compiler;
443490277Sobrien
443518334Speter/* These are variables used within do_spec and do_spec_1.  */
443618334Speter
443718334Speter/* Nonzero if an arg has been started and not yet terminated
443818334Speter   (with space, tab or newline).  */
443918334Speterstatic int arg_going;
444018334Speter
444118334Speter/* Nonzero means %d or %g has been seen; the next arg to be terminated
444218334Speter   is a temporary file name.  */
444318334Speterstatic int delete_this_arg;
444418334Speter
444518334Speter/* Nonzero means %w has been seen; the next arg to be terminated
444618334Speter   is the output file name of this compilation.  */
444718334Speterstatic int this_is_output_file;
444818334Speter
444918334Speter/* Nonzero means %s has been seen; the next arg to be terminated
445018334Speter   is the name of a library file and we should try the standard
445118334Speter   search dirs for it.  */
445218334Speterstatic int this_is_library_file;
445318334Speter
445418334Speter/* Nonzero means that the input of this command is coming from a pipe.  */
445518334Speterstatic int input_from_pipe;
445618334Speter
445790277Sobrien/* Nonnull means substitute this for any suffix when outputting a switches
445890277Sobrien   arguments.  */
445990277Sobrienstatic const char *suffix_subst;
446090277Sobrien
446118334Speter/* Process the spec SPEC and run the commands specified therein.
446218334Speter   Returns 0 if the spec is successfully processed; -1 if failed.  */
446318334Speter
446450599Sobrienint
4465132733Skando_spec (const char *spec)
446618334Speter{
446718334Speter  int value;
446818334Speter
4469117413Skan  value = do_spec_2 (spec);
447018334Speter
447118334Speter  /* Force out any unfinished command.
447218334Speter     If -pipe, this forces out the last command if it ended in `|'.  */
447318334Speter  if (value == 0)
447418334Speter    {
447518334Speter      if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
447618334Speter	argbuf_index--;
447718334Speter
447890277Sobrien      set_collect_gcc_options ();
447990277Sobrien
448018334Speter      if (argbuf_index > 0)
448118334Speter	value = execute ();
448218334Speter    }
448318334Speter
448418334Speter  return value;
448518334Speter}
448618334Speter
4487117413Skanstatic int
4488132733Skando_spec_2 (const char *spec)
4489117413Skan{
4490132733Skan  const char *string;
4491132733Skan  int result;
4492132733Skan
4493117413Skan  clear_args ();
4494117413Skan  arg_going = 0;
4495117413Skan  delete_this_arg = 0;
4496117413Skan  this_is_output_file = 0;
4497117413Skan  this_is_library_file = 0;
4498117413Skan  input_from_pipe = 0;
4499117413Skan  suffix_subst = NULL;
4500117413Skan
4501132733Skan  result = do_spec_1 (spec, 0, NULL);
4502132733Skan
4503132733Skan  /* End any pending argument.  */
4504132733Skan  if (arg_going)
4505132733Skan    {
4506132733Skan      obstack_1grow (&obstack, 0);
4507169704Skan      string = XOBFINISH (&obstack, const char *);
4508132733Skan      if (this_is_library_file)
4509132733Skan	string = find_file (string);
4510132733Skan      store_arg (string, delete_this_arg, this_is_output_file);
4511132733Skan      if (this_is_output_file)
4512132733Skan	outfiles[input_file_number] = string;
4513132733Skan      arg_going = 0;
4514132733Skan    }
4515132733Skan
4516132733Skan  return result;
4517117413Skan}
4518117413Skan
4519117413Skan
4520117413Skan/* Process the given spec string and add any new options to the end
4521117413Skan   of the switches/n_switches array.  */
4522117413Skan
4523117413Skanstatic void
4524132733Skando_option_spec (const char *name, const char *spec)
4525117413Skan{
4526132733Skan  unsigned int i, value_count, value_len;
4527132733Skan  const char *p, *q, *value;
4528132733Skan  char *tmp_spec, *tmp_spec_p;
4529132733Skan
4530132733Skan  if (configure_default_options[0].name == NULL)
4531132733Skan    return;
4532132733Skan
4533132733Skan  for (i = 0; i < ARRAY_SIZE (configure_default_options); i++)
4534132733Skan    if (strcmp (configure_default_options[i].name, name) == 0)
4535132733Skan      break;
4536132733Skan  if (i == ARRAY_SIZE (configure_default_options))
4537132733Skan    return;
4538132733Skan
4539132733Skan  value = configure_default_options[i].value;
4540132733Skan  value_len = strlen (value);
4541132733Skan
4542132733Skan  /* Compute the size of the final spec.  */
4543132733Skan  value_count = 0;
4544132733Skan  p = spec;
4545132733Skan  while ((p = strstr (p, "%(VALUE)")) != NULL)
4546132733Skan    {
4547132733Skan      p ++;
4548132733Skan      value_count ++;
4549132733Skan    }
4550132733Skan
4551132733Skan  /* Replace each %(VALUE) by the specified value.  */
4552132733Skan  tmp_spec = alloca (strlen (spec) + 1
4553132733Skan		     + value_count * (value_len - strlen ("%(VALUE)")));
4554132733Skan  tmp_spec_p = tmp_spec;
4555132733Skan  q = spec;
4556132733Skan  while ((p = strstr (q, "%(VALUE)")) != NULL)
4557132733Skan    {
4558132733Skan      memcpy (tmp_spec_p, q, p - q);
4559132733Skan      tmp_spec_p = tmp_spec_p + (p - q);
4560132733Skan      memcpy (tmp_spec_p, value, value_len);
4561132733Skan      tmp_spec_p += value_len;
4562132733Skan      q = p + strlen ("%(VALUE)");
4563132733Skan    }
4564132733Skan  strcpy (tmp_spec_p, q);
4565132733Skan
4566132733Skan  do_self_spec (tmp_spec);
4567132733Skan}
4568132733Skan
4569132733Skan/* Process the given spec string and add any new options to the end
4570132733Skan   of the switches/n_switches array.  */
4571132733Skan
4572132733Skanstatic void
4573132733Skando_self_spec (const char *spec)
4574132733Skan{
4575117413Skan  do_spec_2 (spec);
4576117413Skan  do_spec_1 (" ", 0, NULL);
4577117413Skan
4578117413Skan  if (argbuf_index > 0)
4579117413Skan    {
4580117413Skan      int i, first;
4581117413Skan
4582117413Skan      first = n_switches;
4583117413Skan      n_switches += argbuf_index;
4584117413Skan      switches = xrealloc (switches,
4585117413Skan			   sizeof (struct switchstr) * (n_switches + 1));
4586117413Skan
4587117413Skan      switches[n_switches] = switches[first];
4588117413Skan      for (i = 0; i < argbuf_index; i++)
4589117413Skan	{
4590117413Skan	  struct switchstr *sw;
4591117413Skan
4592117413Skan	  /* Each switch should start with '-'.  */
4593117413Skan	  if (argbuf[i][0] != '-')
4594169704Skan	    fatal ("switch '%s' does not start with '-'", argbuf[i]);
4595117413Skan
4596117413Skan	  sw = &switches[i + first];
4597117413Skan	  sw->part1 = &argbuf[i][1];
4598117413Skan	  sw->args = 0;
4599117413Skan	  sw->live_cond = SWITCH_OK;
4600117413Skan	  sw->validated = 0;
4601117413Skan	  sw->ordering = 0;
4602117413Skan	}
4603117413Skan    }
4604117413Skan}
4605117413Skan
4606169704Skan/* Callback for processing %D and %I specs.  */
4607169704Skan
4608169704Skanstruct spec_path_info {
4609169704Skan  const char *option;
4610169704Skan  const char *append;
4611169704Skan  size_t append_len;
4612169704Skan  bool omit_relative;
4613169704Skan  bool separate_options;
4614169704Skan};
4615169704Skan
4616169704Skanstatic void *
4617169704Skanspec_path (char *path, void *data)
4618169704Skan{
4619169704Skan  struct spec_path_info *info = data;
4620169704Skan  size_t len = 0;
4621169704Skan  char save = 0;
4622169704Skan
4623169704Skan  if (info->omit_relative && !IS_ABSOLUTE_PATH (path))
4624169704Skan    return NULL;
4625169704Skan
4626169704Skan  if (info->append_len != 0)
4627169704Skan    {
4628169704Skan      len = strlen (path);
4629169704Skan      memcpy (path + len, info->append, info->append_len + 1);
4630169704Skan    }
4631169704Skan
4632169704Skan  if (!is_directory (path, true))
4633169704Skan    return NULL;
4634169704Skan
4635169704Skan  do_spec_1 (info->option, 1, NULL);
4636169704Skan  if (info->separate_options)
4637169704Skan    do_spec_1 (" ", 0, NULL);
4638169704Skan
4639169704Skan  if (info->append_len == 0)
4640169704Skan    {
4641169704Skan      len = strlen (path);
4642169704Skan      save = path[len - 1];
4643169704Skan      if (IS_DIR_SEPARATOR (path[len - 1]))
4644169704Skan	path[len - 1] = '\0';
4645169704Skan    }
4646169704Skan
4647169704Skan  do_spec_1 (path, 1, NULL);
4648169704Skan  do_spec_1 (" ", 0, NULL);
4649169704Skan
4650169704Skan  /* Must not damage the original path.  */
4651169704Skan  if (info->append_len == 0)
4652169704Skan    path[len - 1] = save;
4653169704Skan
4654169704Skan  return NULL;
4655169704Skan}
4656169704Skan
465718334Speter/* Process the sub-spec SPEC as a portion of a larger spec.
465818334Speter   This is like processing a whole spec except that we do
465918334Speter   not initialize at the beginning and we do not supply a
466018334Speter   newline by default at the end.
466118334Speter   INSWITCH nonzero means don't process %-sequences in SPEC;
466218334Speter   in this case, % is treated as an ordinary character.
466318334Speter   This is used while substituting switches.
466418334Speter   INSWITCH nonzero also causes SPC not to terminate an argument.
466518334Speter
466618334Speter   Value is zero unless a line was finished
466718334Speter   and the command on that line reported an error.  */
466818334Speter
466918334Speterstatic int
4670132733Skando_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
467118334Speter{
467290277Sobrien  const char *p = spec;
467390277Sobrien  int c;
467418334Speter  int i;
467552520Sobrien  const char *string;
467618334Speter  int value;
467718334Speter
467850599Sobrien  while ((c = *p++))
467918334Speter    /* If substituting a switch, treat all chars like letters.
468018334Speter       Otherwise, NL, SPC, TAB and % are special.  */
468118334Speter    switch (inswitch ? 'a' : c)
468218334Speter      {
468318334Speter      case '\n':
468418334Speter	/* End of line: finish any pending argument,
468518334Speter	   then run the pending command if one has been started.  */
468618334Speter	if (arg_going)
468718334Speter	  {
468818334Speter	    obstack_1grow (&obstack, 0);
4689169704Skan	    string = XOBFINISH (&obstack, const char *);
469018334Speter	    if (this_is_library_file)
469118334Speter	      string = find_file (string);
469218334Speter	    store_arg (string, delete_this_arg, this_is_output_file);
469318334Speter	    if (this_is_output_file)
469418334Speter	      outfiles[input_file_number] = string;
469518334Speter	  }
469618334Speter	arg_going = 0;
469718334Speter
469818334Speter	if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
469918334Speter	  {
470018334Speter	    /* A `|' before the newline means use a pipe here,
470118334Speter	       but only if -pipe was specified.
470218334Speter	       Otherwise, execute now and don't pass the `|' as an arg.  */
4703132733Skan	    if (use_pipes)
470418334Speter	      {
470518334Speter		input_from_pipe = 1;
470618334Speter		break;
470718334Speter	      }
470818334Speter	    else
470918334Speter	      argbuf_index--;
471018334Speter	  }
471118334Speter
471290277Sobrien	set_collect_gcc_options ();
471390277Sobrien
471418334Speter	if (argbuf_index > 0)
471518334Speter	  {
471618334Speter	    value = execute ();
471718334Speter	    if (value)
471818334Speter	      return value;
471918334Speter	  }
472018334Speter	/* Reinitialize for a new command, and for a new argument.  */
472118334Speter	clear_args ();
472218334Speter	arg_going = 0;
472318334Speter	delete_this_arg = 0;
472418334Speter	this_is_output_file = 0;
472518334Speter	this_is_library_file = 0;
472618334Speter	input_from_pipe = 0;
472718334Speter	break;
472818334Speter
472918334Speter      case '|':
473018334Speter	/* End any pending argument.  */
473118334Speter	if (arg_going)
473218334Speter	  {
473318334Speter	    obstack_1grow (&obstack, 0);
4734169704Skan	    string = XOBFINISH (&obstack, const char *);
473518334Speter	    if (this_is_library_file)
473618334Speter	      string = find_file (string);
473718334Speter	    store_arg (string, delete_this_arg, this_is_output_file);
473818334Speter	    if (this_is_output_file)
473918334Speter	      outfiles[input_file_number] = string;
474018334Speter	  }
474118334Speter
474218334Speter	/* Use pipe */
474318334Speter	obstack_1grow (&obstack, c);
474418334Speter	arg_going = 1;
474518334Speter	break;
474618334Speter
474718334Speter      case '\t':
474818334Speter      case ' ':
474918334Speter	/* Space or tab ends an argument if one is pending.  */
475018334Speter	if (arg_going)
475118334Speter	  {
475218334Speter	    obstack_1grow (&obstack, 0);
4753169704Skan	    string = XOBFINISH (&obstack, const char *);
475418334Speter	    if (this_is_library_file)
475518334Speter	      string = find_file (string);
475618334Speter	    store_arg (string, delete_this_arg, this_is_output_file);
475718334Speter	    if (this_is_output_file)
475818334Speter	      outfiles[input_file_number] = string;
475918334Speter	  }
476018334Speter	/* Reinitialize for a new argument.  */
476118334Speter	arg_going = 0;
476218334Speter	delete_this_arg = 0;
476318334Speter	this_is_output_file = 0;
476418334Speter	this_is_library_file = 0;
476518334Speter	break;
476618334Speter
476718334Speter      case '%':
476818334Speter	switch (c = *p++)
476918334Speter	  {
477018334Speter	  case 0:
4771169704Skan	    fatal ("spec '%s' invalid", spec);
477218334Speter
477318334Speter	  case 'b':
477418334Speter	    obstack_grow (&obstack, input_basename, basename_length);
477518334Speter	    arg_going = 1;
477618334Speter	    break;
477718334Speter
477890277Sobrien	  case 'B':
477990277Sobrien	    obstack_grow (&obstack, input_basename, suffixed_basename_length);
478090277Sobrien	    arg_going = 1;
478190277Sobrien	    break;
478290277Sobrien
478318334Speter	  case 'd':
478418334Speter	    delete_this_arg = 2;
478518334Speter	    break;
478618334Speter
478718334Speter	  /* Dump out the directories specified with LIBRARY_PATH,
478818334Speter	     followed by the absolute directories
478918334Speter	     that we search for startfiles.  */
479018334Speter	  case 'D':
479118334Speter	    {
4792169704Skan	      struct spec_path_info info;
479318334Speter
4794169704Skan	      info.option = "-L";
4795169704Skan	      info.append_len = 0;
479618334Speter#ifdef RELATIVE_PREFIX_NOT_LINKDIR
4797169704Skan	      /* Used on systems which record the specified -L dirs
4798169704Skan		 and use them to search for dynamic linking.
4799169704Skan		 Relative directories always come from -B,
4800169704Skan		 and it is better not to use them for searching
4801169704Skan		 at run time.  In particular, stage1 loses.  */
4802169704Skan	      info.omit_relative = true;
4803169704Skan#else
4804169704Skan	      info.omit_relative = false;
480518334Speter#endif
4806169704Skan	      info.separate_options = false;
4807104763Skan
4808169704Skan	      for_each_path (&startfile_prefixes, true, 0, spec_path, &info);
480918334Speter	    }
481018334Speter	    break;
481118334Speter
481218334Speter	  case 'e':
481352520Sobrien	    /* %efoo means report an error with `foo' as error message
481418334Speter	       and don't execute any more commands for this file.  */
481518334Speter	    {
481652520Sobrien	      const char *q = p;
481718334Speter	      char *buf;
481890277Sobrien	      while (*p != 0 && *p != '\n')
481990277Sobrien		p++;
4820132733Skan	      buf = alloca (p - q + 1);
482118334Speter	      strncpy (buf, q, p - q);
482218334Speter	      buf[p - q] = 0;
482390277Sobrien	      error ("%s", buf);
482418334Speter	      return -1;
482518334Speter	    }
482618334Speter	    break;
482790277Sobrien	  case 'n':
4828117413Skan	    /* %nfoo means report a notice with `foo' on stderr.  */
482990277Sobrien	    {
483090277Sobrien	      const char *q = p;
483190277Sobrien	      char *buf;
483290277Sobrien	      while (*p != 0 && *p != '\n')
483390277Sobrien		p++;
4834132733Skan	      buf = alloca (p - q + 1);
483590277Sobrien	      strncpy (buf, q, p - q);
483690277Sobrien	      buf[p - q] = 0;
483790277Sobrien	      notice ("%s\n", buf);
483890277Sobrien	      if (*p)
483990277Sobrien		p++;
484090277Sobrien	    }
484190277Sobrien	    break;
484218334Speter
484390277Sobrien	  case 'j':
484490277Sobrien	    {
484590277Sobrien	      struct stat st;
484690277Sobrien
4847132733Skan	      /* If save_temps_flag is off, and the HOST_BIT_BUCKET is
4848132733Skan		 defined, and it is not a directory, and it is
4849132733Skan		 writable, use it.  Otherwise, treat this like any
4850132733Skan		 other temporary file.  */
485190277Sobrien
485290277Sobrien	      if ((!save_temps_flag)
485390277Sobrien		  && (stat (HOST_BIT_BUCKET, &st) == 0) && (!S_ISDIR (st.st_mode))
485490277Sobrien		  && (access (HOST_BIT_BUCKET, W_OK) == 0))
485590277Sobrien		{
485690277Sobrien		  obstack_grow (&obstack, HOST_BIT_BUCKET,
485790277Sobrien				strlen (HOST_BIT_BUCKET));
485890277Sobrien		  delete_this_arg = 0;
485990277Sobrien		  arg_going = 1;
486090277Sobrien		  break;
486190277Sobrien		}
486290277Sobrien	    }
4863132733Skan	    goto create_temp_file;
4864132733Skan	  case '|':
4865132733Skan	    if (use_pipes)
4866132733Skan	      {
4867132733Skan		obstack_1grow (&obstack, '-');
4868132733Skan		delete_this_arg = 0;
4869132733Skan		arg_going = 1;
4870132733Skan
4871132733Skan		/* consume suffix */
4872169704Skan		while (*p == '.' || ISALNUM ((unsigned char) *p))
4873132733Skan		  p++;
4874132733Skan		if (p[0] == '%' && p[1] == 'O')
4875132733Skan		  p += 2;
4876132733Skan
4877132733Skan		break;
4878132733Skan	      }
4879132733Skan	    goto create_temp_file;
4880132733Skan	  case 'm':
4881132733Skan	    if (use_pipes)
4882132733Skan	      {
4883132733Skan		/* consume suffix */
4884169704Skan		while (*p == '.' || ISALNUM ((unsigned char) *p))
4885132733Skan		  p++;
4886132733Skan		if (p[0] == '%' && p[1] == 'O')
4887132733Skan		  p += 2;
4888132733Skan
4889132733Skan		break;
4890132733Skan	      }
4891132733Skan	    goto create_temp_file;
489218334Speter	  case 'g':
489318334Speter	  case 'u':
489418334Speter	  case 'U':
4895132733Skan	  create_temp_file:
489618334Speter	      {
489718334Speter		struct temp_name *t;
489850599Sobrien		int suffix_length;
489952520Sobrien		const char *suffix = p;
490090277Sobrien		char *saved_suffix = NULL;
490118334Speter
4902169704Skan		while (*p == '.' || ISALNUM ((unsigned char) *p))
490390277Sobrien		  p++;
490490277Sobrien		suffix_length = p - suffix;
490550599Sobrien		if (p[0] == '%' && p[1] == 'O')
490650599Sobrien		  {
490750599Sobrien		    p += 2;
490850599Sobrien		    /* We don't support extra suffix characters after %O.  */
4909169704Skan		    if (*p == '.' || ISALNUM ((unsigned char) *p))
4910169704Skan		      fatal ("spec '%s' has invalid '%%0%c'", spec, *p);
491190277Sobrien		    if (suffix_length == 0)
491290277Sobrien		      suffix = TARGET_OBJECT_SUFFIX;
491390277Sobrien		    else
491490277Sobrien		      {
491590277Sobrien			saved_suffix
4916169704Skan			  = XNEWVEC (char, suffix_length
4917132733Skan				     + strlen (TARGET_OBJECT_SUFFIX));
491890277Sobrien			strncpy (saved_suffix, suffix, suffix_length);
491990277Sobrien			strcpy (saved_suffix + suffix_length,
492090277Sobrien				TARGET_OBJECT_SUFFIX);
492190277Sobrien		      }
492290277Sobrien		    suffix_length += strlen (TARGET_OBJECT_SUFFIX);
492350599Sobrien		  }
4924117413Skan
492590277Sobrien		/* If the input_filename has the same suffix specified
492690277Sobrien		   for the %g, %u, or %U, and -save-temps is specified,
492790277Sobrien		   we could end up using that file as an intermediate
492890277Sobrien		   thus clobbering the user's source file (.e.g.,
492990277Sobrien		   gcc -save-temps foo.s would clobber foo.s with the
493090277Sobrien		   output of cpp0).  So check for this condition and
493190277Sobrien		   generate a temp file as the intermediate.  */
4932117413Skan
493390277Sobrien		if (save_temps_flag)
493450599Sobrien		  {
493590277Sobrien		    temp_filename_length = basename_length + suffix_length;
493690277Sobrien		    temp_filename = alloca (temp_filename_length + 1);
493790277Sobrien		    strncpy ((char *) temp_filename, input_basename, basename_length);
493890277Sobrien		    strncpy ((char *) temp_filename + basename_length, suffix,
4939132733Skan			     suffix_length);
494090277Sobrien		    *((char *) temp_filename + temp_filename_length) = '\0';
494190277Sobrien		    if (strcmp (temp_filename, input_filename) != 0)
494290277Sobrien		      {
4943169704Skan#ifndef HOST_LACKS_INODE_NUMBERS
4944132733Skan			struct stat st_temp;
4945117413Skan
4946132733Skan			/* Note, set_input() resets input_stat_set to 0.  */
4947132733Skan			if (input_stat_set == 0)
4948132733Skan			  {
4949132733Skan			    input_stat_set = stat (input_filename, &input_stat);
4950132733Skan			    if (input_stat_set >= 0)
4951132733Skan			      input_stat_set = 1;
4952132733Skan			  }
4953117413Skan
4954132733Skan			/* If we have the stat for the input_filename
4955132733Skan			   and we can do the stat for the temp_filename
4956132733Skan			   then the they could still refer to the same
4957132733Skan			   file if st_dev/st_ino's are the same.  */
495890277Sobrien			if (input_stat_set != 1
495990277Sobrien			    || stat (temp_filename, &st_temp) < 0
496090277Sobrien			    || input_stat.st_dev != st_temp.st_dev
496190277Sobrien			    || input_stat.st_ino != st_temp.st_ino)
4962169704Skan#else
4963169704Skan			/* Just compare canonical pathnames.  */
4964169704Skan			char* input_realname = lrealpath (input_filename);
4965169704Skan			char* temp_realname = lrealpath (temp_filename);
4966169704Skan			bool files_differ = strcmp (input_realname, temp_realname);
4967169704Skan			free (input_realname);
4968169704Skan			free (temp_realname);
4969169704Skan			if (files_differ)
4970169704Skan#endif
4971117413Skan			  {
497290277Sobrien			    temp_filename = save_string (temp_filename,
497390277Sobrien							 temp_filename_length + 1);
497490277Sobrien			    obstack_grow (&obstack, temp_filename,
4975132733Skan						    temp_filename_length);
497690277Sobrien			    arg_going = 1;
4977117413Skan			    delete_this_arg = 0;
497890277Sobrien			    break;
497990277Sobrien			  }
498090277Sobrien		      }
498150599Sobrien		  }
498250599Sobrien
498318334Speter		/* See if we already have an association of %g/%u/%U and
498418334Speter		   suffix.  */
498518334Speter		for (t = temp_names; t; t = t->next)
498650599Sobrien		  if (t->length == suffix_length
498750599Sobrien		      && strncmp (t->suffix, suffix, suffix_length) == 0
4988132733Skan		      && t->unique == (c == 'u' || c == 'U' || c == 'j'))
498918334Speter		    break;
499018334Speter
499190277Sobrien		/* Make a new association if needed.  %u and %j
499290277Sobrien		   require one.  */
499390277Sobrien		if (t == 0 || c == 'u' || c == 'j')
499418334Speter		  {
499518334Speter		    if (t == 0)
499618334Speter		      {
4997132733Skan			t = xmalloc (sizeof (struct temp_name));
499818334Speter			t->next = temp_names;
499918334Speter			temp_names = t;
500018334Speter		      }
500150599Sobrien		    t->length = suffix_length;
500290277Sobrien		    if (saved_suffix)
500390277Sobrien		      {
500490277Sobrien			t->suffix = saved_suffix;
500590277Sobrien			saved_suffix = NULL;
500690277Sobrien		      }
500790277Sobrien		    else
500890277Sobrien		      t->suffix = save_string (suffix, suffix_length);
5009132733Skan		    t->unique = (c == 'u' || c == 'U' || c == 'j');
501050599Sobrien		    temp_filename = make_temp_file (t->suffix);
501150599Sobrien		    temp_filename_length = strlen (temp_filename);
501218334Speter		    t->filename = temp_filename;
501318334Speter		    t->filename_length = temp_filename_length;
501418334Speter		  }
501518334Speter
501690277Sobrien		if (saved_suffix)
501790277Sobrien		  free (saved_suffix);
501890277Sobrien
501918334Speter		obstack_grow (&obstack, t->filename, t->filename_length);
502018334Speter		delete_this_arg = 1;
502118334Speter	      }
502218334Speter	    arg_going = 1;
502318334Speter	    break;
502418334Speter
502518334Speter	  case 'i':
5026132733Skan	    if (combine_inputs)
5027132733Skan	      {
5028132733Skan		for (i = 0; (int) i < n_infiles; i++)
5029169704Skan		  if ((!infiles[i].language) || (infiles[i].language[0] != '*'))
5030169704Skan		    if (infiles[i].incompiler == input_file_compiler)
5031169704Skan		      {
5032169704Skan			store_arg (infiles[i].name, 0, 0);
5033169704Skan			infiles[i].compiled = true;
5034169704Skan		      }
5035132733Skan	      }
5036132733Skan	    else
5037132733Skan	      {
5038132733Skan		obstack_grow (&obstack, input_filename, input_filename_length);
5039132733Skan		arg_going = 1;
5040132733Skan	      }
504118334Speter	    break;
504218334Speter
504318334Speter	  case 'I':
504418334Speter	    {
5045169704Skan	      struct spec_path_info info;
504618334Speter
5047169704Skan	      if (multilib_dir)
5048169704Skan		{
5049169704Skan		  do_spec_1 ("-imultilib", 1, NULL);
5050169704Skan		  /* Make this a separate argument.  */
5051169704Skan		  do_spec_1 (" ", 0, NULL);
5052169704Skan		  do_spec_1 (multilib_dir, 1, NULL);
5053169704Skan		  do_spec_1 (" ", 0, NULL);
5054169704Skan		}
5055169704Skan
505618334Speter	      if (gcc_exec_prefix)
505718334Speter		{
505890277Sobrien		  do_spec_1 ("-iprefix", 1, NULL);
505918334Speter		  /* Make this a separate argument.  */
506090277Sobrien		  do_spec_1 (" ", 0, NULL);
506190277Sobrien		  do_spec_1 (gcc_exec_prefix, 1, NULL);
506290277Sobrien		  do_spec_1 (" ", 0, NULL);
506318334Speter		}
506418334Speter
5065132733Skan	      if (target_system_root_changed ||
5066132733Skan		  (target_system_root && target_sysroot_hdrs_suffix))
5067132733Skan		{
5068132733Skan		  do_spec_1 ("-isysroot", 1, NULL);
5069132733Skan		  /* Make this a separate argument.  */
5070132733Skan		  do_spec_1 (" ", 0, NULL);
5071132733Skan		  do_spec_1 (target_system_root, 1, NULL);
5072132733Skan		  if (target_sysroot_hdrs_suffix)
5073132733Skan		    do_spec_1 (target_sysroot_hdrs_suffix, 1, NULL);
5074132733Skan		  do_spec_1 (" ", 0, NULL);
5075132733Skan		}
5076132733Skan
5077169704Skan	      info.option = "-isystem";
5078169704Skan	      info.append = "include";
5079169704Skan	      info.append_len = strlen (info.append);
5080169704Skan	      info.omit_relative = false;
5081169704Skan	      info.separate_options = true;
5082169704Skan
5083169704Skan	      for_each_path (&include_prefixes, false, info.append_len,
5084169704Skan			     spec_path, &info);
508518334Speter	    }
508618334Speter	    break;
508718334Speter
508818334Speter	  case 'o':
508952520Sobrien	    {
509052520Sobrien	      int max = n_infiles;
509152520Sobrien	      max += lang_specific_extra_outfiles;
509218334Speter
509352520Sobrien	      for (i = 0; i < max; i++)
509452520Sobrien		if (outfiles[i])
509552520Sobrien		  store_arg (outfiles[i], 0, 0);
509652520Sobrien	      break;
509752520Sobrien	    }
509852520Sobrien
509918334Speter	  case 'O':
510090277Sobrien	    obstack_grow (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
510118334Speter	    arg_going = 1;
510218334Speter	    break;
510318334Speter
510418334Speter	  case 's':
510518334Speter	    this_is_library_file = 1;
510618334Speter	    break;
510718334Speter
5108132733Skan	  case 'V':
5109132733Skan	    outfiles[input_file_number] = NULL;
5110132733Skan	    break;
5111132733Skan
511218334Speter	  case 'w':
511318334Speter	    this_is_output_file = 1;
511418334Speter	    break;
511518334Speter
511618334Speter	  case 'W':
511718334Speter	    {
511850599Sobrien	      int cur_index = argbuf_index;
511918334Speter	      /* Handle the {...} following the %W.  */
512018334Speter	      if (*p != '{')
5121169704Skan		fatal ("spec '%s' has invalid '%%W%c", spec, *p);
512218334Speter	      p = handle_braces (p + 1);
512318334Speter	      if (p == 0)
512418334Speter		return -1;
5125132733Skan	      /* End any pending argument.  */
5126132733Skan	      if (arg_going)
5127132733Skan		{
5128132733Skan		  obstack_1grow (&obstack, 0);
5129169704Skan		  string = XOBFINISH (&obstack, const char *);
5130132733Skan		  if (this_is_library_file)
5131132733Skan		    string = find_file (string);
5132132733Skan		  store_arg (string, delete_this_arg, this_is_output_file);
5133132733Skan		  if (this_is_output_file)
5134132733Skan		    outfiles[input_file_number] = string;
5135132733Skan		  arg_going = 0;
5136132733Skan		}
513718334Speter	      /* If any args were output, mark the last one for deletion
513818334Speter		 on failure.  */
513950599Sobrien	      if (argbuf_index != cur_index)
514018334Speter		record_temp_file (argbuf[argbuf_index - 1], 0, 1);
514118334Speter	      break;
514218334Speter	    }
514318334Speter
514418334Speter	  /* %x{OPTION} records OPTION for %X to output.  */
514518334Speter	  case 'x':
514618334Speter	    {
514752520Sobrien	      const char *p1 = p;
514818334Speter	      char *string;
514918334Speter
515018334Speter	      /* Skip past the option value and make a copy.  */
515118334Speter	      if (*p != '{')
5152169704Skan		fatal ("spec '%s' has invalid '%%x%c'", spec, *p);
515318334Speter	      while (*p++ != '}')
515418334Speter		;
515518334Speter	      string = save_string (p1 + 1, p - p1 - 2);
515618334Speter
515718334Speter	      /* See if we already recorded this option.  */
515818334Speter	      for (i = 0; i < n_linker_options; i++)
515918334Speter		if (! strcmp (string, linker_options[i]))
516018334Speter		  {
516118334Speter		    free (string);
516218334Speter		    return 0;
516318334Speter		  }
516418334Speter
516518334Speter	      /* This option is new; add it.  */
516650599Sobrien	      add_linker_option (string, strlen (string));
516718334Speter	    }
516818334Speter	    break;
516918334Speter
517018334Speter	  /* Dump out the options accumulated previously using %x.  */
517118334Speter	  case 'X':
517218334Speter	    for (i = 0; i < n_linker_options; i++)
517318334Speter	      {
517490277Sobrien		do_spec_1 (linker_options[i], 1, NULL);
517518334Speter		/* Make each accumulated option a separate argument.  */
517690277Sobrien		do_spec_1 (" ", 0, NULL);
517718334Speter	      }
517818334Speter	    break;
517918334Speter
518018334Speter	  /* Dump out the options accumulated previously using -Wa,.  */
518118334Speter	  case 'Y':
518218334Speter	    for (i = 0; i < n_assembler_options; i++)
518318334Speter	      {
518490277Sobrien		do_spec_1 (assembler_options[i], 1, NULL);
518518334Speter		/* Make each accumulated option a separate argument.  */
518690277Sobrien		do_spec_1 (" ", 0, NULL);
518718334Speter	      }
518818334Speter	    break;
518918334Speter
519018334Speter	  /* Dump out the options accumulated previously using -Wp,.  */
519118334Speter	  case 'Z':
519218334Speter	    for (i = 0; i < n_preprocessor_options; i++)
519318334Speter	      {
519490277Sobrien		do_spec_1 (preprocessor_options[i], 1, NULL);
519518334Speter		/* Make each accumulated option a separate argument.  */
519690277Sobrien		do_spec_1 (" ", 0, NULL);
519718334Speter	      }
519818334Speter	    break;
519918334Speter
520018334Speter	    /* Here are digits and numbers that just process
520118334Speter	       a certain constant string as a spec.  */
520218334Speter
520318334Speter	  case '1':
520490277Sobrien	    value = do_spec_1 (cc1_spec, 0, NULL);
520518334Speter	    if (value != 0)
520618334Speter	      return value;
520718334Speter	    break;
520818334Speter
520918334Speter	  case '2':
521090277Sobrien	    value = do_spec_1 (cc1plus_spec, 0, NULL);
521118334Speter	    if (value != 0)
521218334Speter	      return value;
521318334Speter	    break;
521418334Speter
521518334Speter	  case 'a':
521690277Sobrien	    value = do_spec_1 (asm_spec, 0, NULL);
521718334Speter	    if (value != 0)
521818334Speter	      return value;
521918334Speter	    break;
522018334Speter
522118334Speter	  case 'A':
522290277Sobrien	    value = do_spec_1 (asm_final_spec, 0, NULL);
522318334Speter	    if (value != 0)
522418334Speter	      return value;
522518334Speter	    break;
522618334Speter
522718334Speter	  case 'C':
522890277Sobrien	    {
522990277Sobrien	      const char *const spec
5230117413Skan		= (input_file_compiler->cpp_spec
5231117413Skan		   ? input_file_compiler->cpp_spec
523290277Sobrien		   : cpp_spec);
523390277Sobrien	      value = do_spec_1 (spec, 0, NULL);
523490277Sobrien	      if (value != 0)
523590277Sobrien		return value;
523690277Sobrien	    }
523718334Speter	    break;
523818334Speter
523918334Speter	  case 'E':
524090277Sobrien	    value = do_spec_1 (endfile_spec, 0, NULL);
524118334Speter	    if (value != 0)
524218334Speter	      return value;
524318334Speter	    break;
524418334Speter
524518334Speter	  case 'l':
524690277Sobrien	    value = do_spec_1 (link_spec, 0, NULL);
524718334Speter	    if (value != 0)
524818334Speter	      return value;
524918334Speter	    break;
525018334Speter
525118334Speter	  case 'L':
525290277Sobrien	    value = do_spec_1 (lib_spec, 0, NULL);
525318334Speter	    if (value != 0)
525418334Speter	      return value;
525518334Speter	    break;
525618334Speter
525718334Speter	  case 'G':
525890277Sobrien	    value = do_spec_1 (libgcc_spec, 0, NULL);
525918334Speter	    if (value != 0)
526018334Speter	      return value;
526118334Speter	    break;
526218334Speter
5263132733Skan	  case 'R':
5264132733Skan	    /* We assume there is a directory
5265132733Skan	       separator at the end of this string.  */
5266132733Skan	    if (target_system_root)
5267132733Skan	      {
5268132733Skan	        obstack_grow (&obstack, target_system_root,
5269132733Skan			      strlen (target_system_root));
5270132733Skan		if (target_sysroot_suffix)
5271132733Skan		  obstack_grow (&obstack, target_sysroot_suffix,
5272132733Skan				strlen (target_sysroot_suffix));
5273132733Skan	      }
527418334Speter	    break;
527518334Speter
527618334Speter	  case 'S':
527790277Sobrien	    value = do_spec_1 (startfile_spec, 0, NULL);
527818334Speter	    if (value != 0)
527918334Speter	      return value;
528018334Speter	    break;
528118334Speter
528218334Speter	    /* Here we define characters other than letters and digits.  */
528318334Speter
528418334Speter	  case '{':
528518334Speter	    p = handle_braces (p);
528618334Speter	    if (p == 0)
528718334Speter	      return -1;
528818334Speter	    break;
528918334Speter
5290117413Skan	  case ':':
5291117413Skan	    p = handle_spec_function (p);
5292117413Skan	    if (p == 0)
5293117413Skan	      return -1;
5294117413Skan	    break;
5295117413Skan
529618334Speter	  case '%':
529718334Speter	    obstack_1grow (&obstack, '%');
529818334Speter	    break;
529918334Speter
5300117413Skan	  case '.':
5301117413Skan	    {
5302117413Skan	      unsigned len = 0;
530390277Sobrien
5304117413Skan	      while (p[len] && p[len] != ' ' && p[len] != '%')
5305117413Skan		len++;
5306117413Skan	      suffix_subst = save_string (p - 1, len + 1);
5307117413Skan	      p += len;
5308117413Skan	    }
530990277Sobrien	   break;
5310117413Skan
5311132733Skan	   /* Henceforth ignore the option(s) matching the pattern
5312132733Skan	      after the %<.  */
5313132733Skan	  case '<':
5314132733Skan	    {
5315132733Skan	      unsigned len = 0;
5316132733Skan	      int have_wildcard = 0;
5317132733Skan	      int i;
5318132733Skan
5319132733Skan	      while (p[len] && p[len] != ' ' && p[len] != '\t')
5320132733Skan		len++;
5321132733Skan
5322132733Skan	      if (p[len-1] == '*')
5323132733Skan		have_wildcard = 1;
5324132733Skan
5325132733Skan	      for (i = 0; i < n_switches; i++)
5326132733Skan		if (!strncmp (switches[i].part1, p, len - have_wildcard)
5327132733Skan		    && (have_wildcard || switches[i].part1[len] == '\0'))
5328132733Skan		  {
5329132733Skan		    switches[i].live_cond = SWITCH_IGNORE;
5330132733Skan		    switches[i].validated = 1;
5331132733Skan		  }
5332132733Skan
5333132733Skan	      p += len;
5334132733Skan	    }
5335132733Skan	    break;
5336132733Skan
533718334Speter	  case '*':
533890277Sobrien	    if (soft_matched_part)
533990277Sobrien	      {
534090277Sobrien		do_spec_1 (soft_matched_part, 1, NULL);
534190277Sobrien		do_spec_1 (" ", 0, NULL);
534290277Sobrien	      }
534390277Sobrien	    else
534490277Sobrien	      /* Catch the case where a spec string contains something like
5345169704Skan		 '%{foo:%*}'.  i.e. there is no * in the pattern on the left
534690277Sobrien		 hand side of the :.  */
534790277Sobrien	      error ("spec failure: '%%*' has not been initialized by pattern match");
534818334Speter	    break;
534918334Speter
535018334Speter	    /* Process a string found as the value of a spec given by name.
535118334Speter	       This feature allows individual machine descriptions
535218334Speter	       to add and use their own specs.
535318334Speter	       %[...] modifies -D options the way %P does;
535418334Speter	       %(...) uses the spec unmodified.  */
535550599Sobrien	  case '[':
535690277Sobrien	    error ("warning: use of obsolete %%[ operator in specs");
535718334Speter	  case '(':
535818334Speter	    {
535952520Sobrien	      const char *name = p;
536018334Speter	      struct spec_list *sl;
536118334Speter	      int len;
536218334Speter
536318334Speter	      /* The string after the S/P is the name of a spec that is to be
536450599Sobrien		 processed.  */
536518334Speter	      while (*p && *p != ')' && *p != ']')
536618334Speter		p++;
536718334Speter
536890277Sobrien	      /* See if it's in the list.  */
536918334Speter	      for (len = p - name, sl = specs; sl; sl = sl->next)
537050599Sobrien		if (sl->name_len == len && !strncmp (sl->name, name, len))
537118334Speter		  {
537250599Sobrien		    name = *(sl->ptr_spec);
537350599Sobrien#ifdef DEBUG_SPECS
537452520Sobrien		    notice ("Processing spec %c%s%c, which is '%s'\n",
537552520Sobrien			    c, sl->name, (c == '(') ? ')' : ']', name);
537650599Sobrien#endif
537718334Speter		    break;
537818334Speter		  }
537918334Speter
538018334Speter	      if (sl)
538118334Speter		{
538218334Speter		  if (c == '(')
538318334Speter		    {
538490277Sobrien		      value = do_spec_1 (name, 0, NULL);
538518334Speter		      if (value != 0)
538618334Speter			return value;
538718334Speter		    }
538818334Speter		  else
538918334Speter		    {
5390132733Skan		      char *x = alloca (strlen (name) * 2 + 1);
539118334Speter		      char *buf = x;
539252520Sobrien		      const char *y = name;
539350599Sobrien		      int flag = 0;
539418334Speter
539518334Speter		      /* Copy all of NAME into BUF, but put __ after
539690277Sobrien			 every -D and at the end of each arg.  */
539718334Speter		      while (1)
539818334Speter			{
539918334Speter			  if (! strncmp (y, "-D", 2))
540018334Speter			    {
540118334Speter			      *x++ = '-';
540218334Speter			      *x++ = 'D';
540318334Speter			      *x++ = '_';
540418334Speter			      *x++ = '_';
540518334Speter			      y += 2;
540650599Sobrien			      flag = 1;
540750599Sobrien			      continue;
540818334Speter			    }
540990277Sobrien			  else if (flag
541090277Sobrien				   && (*y == ' ' || *y == '\t' || *y == '='
541190277Sobrien				       || *y == '}' || *y == 0))
541218334Speter			    {
541318334Speter			      *x++ = '_';
541418334Speter			      *x++ = '_';
541550599Sobrien			      flag = 0;
541618334Speter			    }
541790277Sobrien			  if (*y == 0)
541850599Sobrien			    break;
541918334Speter			  else
542018334Speter			    *x++ = *y++;
542118334Speter			}
542218334Speter		      *x = 0;
542318334Speter
542490277Sobrien		      value = do_spec_1 (buf, 0, NULL);
542518334Speter		      if (value != 0)
542618334Speter			return value;
542718334Speter		    }
542818334Speter		}
542918334Speter
543018334Speter	      /* Discard the closing paren or bracket.  */
543118334Speter	      if (*p)
543218334Speter		p++;
543318334Speter	    }
543418334Speter	    break;
543518334Speter
543618334Speter	  default:
543790277Sobrien	    error ("spec failure: unrecognized spec option '%c'", c);
543890277Sobrien	    break;
543918334Speter	  }
544018334Speter	break;
544118334Speter
544218334Speter      case '\\':
544318334Speter	/* Backslash: treat next character as ordinary.  */
544418334Speter	c = *p++;
544518334Speter
5446132733Skan	/* Fall through.  */
544718334Speter      default:
544818334Speter	/* Ordinary character: put it into the current argument.  */
544918334Speter	obstack_1grow (&obstack, c);
545018334Speter	arg_going = 1;
545118334Speter      }
545218334Speter
5453117413Skan  /* End of string.  If we are processing a spec function, we need to
5454117413Skan     end any pending argument.  */
5455117413Skan  if (processing_spec_function && arg_going)
5456117413Skan    {
5457117413Skan      obstack_1grow (&obstack, 0);
5458169704Skan      string = XOBFINISH (&obstack, const char *);
5459117413Skan      if (this_is_library_file)
5460117413Skan        string = find_file (string);
5461117413Skan      store_arg (string, delete_this_arg, this_is_output_file);
5462117413Skan      if (this_is_output_file)
5463117413Skan        outfiles[input_file_number] = string;
5464117413Skan      arg_going = 0;
5465117413Skan    }
5466117413Skan
546790277Sobrien  return 0;
546818334Speter}
546918334Speter
5470117413Skan/* Look up a spec function.  */
5471117413Skan
5472117413Skanstatic const struct spec_function *
5473132733Skanlookup_spec_function (const char *name)
5474117413Skan{
5475117413Skan  const struct spec_function *sf;
5476117413Skan
5477169704Skan  for (sf = static_spec_functions; sf->name != NULL; sf++)
5478169704Skan    if (strcmp (sf->name, name) == 0)
5479169704Skan      return sf;
5480117413Skan
5481117413Skan  return NULL;
5482117413Skan}
5483117413Skan
5484117413Skan/* Evaluate a spec function.  */
5485117413Skan
5486117413Skanstatic const char *
5487132733Skaneval_spec_function (const char *func, const char *args)
5488117413Skan{
5489117413Skan  const struct spec_function *sf;
5490117413Skan  const char *funcval;
5491117413Skan
5492117413Skan  /* Saved spec processing context.  */
5493117413Skan  int save_argbuf_index;
5494117413Skan  int save_argbuf_length;
5495117413Skan  const char **save_argbuf;
5496117413Skan
5497117413Skan  int save_arg_going;
5498117413Skan  int save_delete_this_arg;
5499117413Skan  int save_this_is_output_file;
5500117413Skan  int save_this_is_library_file;
5501117413Skan  int save_input_from_pipe;
5502117413Skan  const char *save_suffix_subst;
5503117413Skan
5504117413Skan
5505117413Skan  sf = lookup_spec_function (func);
5506117413Skan  if (sf == NULL)
5507169704Skan    fatal ("unknown spec function '%s'", func);
5508117413Skan
5509117413Skan  /* Push the spec processing context.  */
5510117413Skan  save_argbuf_index = argbuf_index;
5511117413Skan  save_argbuf_length = argbuf_length;
5512117413Skan  save_argbuf = argbuf;
5513117413Skan
5514117413Skan  save_arg_going = arg_going;
5515117413Skan  save_delete_this_arg = delete_this_arg;
5516117413Skan  save_this_is_output_file = this_is_output_file;
5517117413Skan  save_this_is_library_file = this_is_library_file;
5518117413Skan  save_input_from_pipe = input_from_pipe;
5519117413Skan  save_suffix_subst = suffix_subst;
5520117413Skan
5521117413Skan  /* Create a new spec processing context, and build the function
5522117413Skan     arguments.  */
5523117413Skan
5524117413Skan  alloc_args ();
5525117413Skan  if (do_spec_2 (args) < 0)
5526169704Skan    fatal ("error in args to spec function '%s'", func);
5527117413Skan
5528117413Skan  /* argbuf_index is an index for the next argument to be inserted, and
5529117413Skan     so contains the count of the args already inserted.  */
5530117413Skan
5531117413Skan  funcval = (*sf->func) (argbuf_index, argbuf);
5532117413Skan
5533117413Skan  /* Pop the spec processing context.  */
5534117413Skan  argbuf_index = save_argbuf_index;
5535117413Skan  argbuf_length = save_argbuf_length;
5536117413Skan  free (argbuf);
5537117413Skan  argbuf = save_argbuf;
5538117413Skan
5539117413Skan  arg_going = save_arg_going;
5540117413Skan  delete_this_arg = save_delete_this_arg;
5541117413Skan  this_is_output_file = save_this_is_output_file;
5542117413Skan  this_is_library_file = save_this_is_library_file;
5543117413Skan  input_from_pipe = save_input_from_pipe;
5544117413Skan  suffix_subst = save_suffix_subst;
5545117413Skan
5546117413Skan  return funcval;
5547117413Skan}
5548117413Skan
5549117413Skan/* Handle a spec function call of the form:
5550117413Skan
5551117413Skan   %:function(args)
5552117413Skan
5553117413Skan   ARGS is processed as a spec in a separate context and split into an
5554117413Skan   argument vector in the normal fashion.  The function returns a string
5555117413Skan   containing a spec which we then process in the caller's context, or
5556117413Skan   NULL if no processing is required.  */
5557117413Skan
5558117413Skanstatic const char *
5559132733Skanhandle_spec_function (const char *p)
5560117413Skan{
5561117413Skan  char *func, *args;
5562117413Skan  const char *endp, *funcval;
5563117413Skan  int count;
5564117413Skan
5565117413Skan  processing_spec_function++;
5566117413Skan
5567117413Skan  /* Get the function name.  */
5568117413Skan  for (endp = p; *endp != '\0'; endp++)
5569117413Skan    {
5570117413Skan      if (*endp == '(')		/* ) */
5571117413Skan        break;
5572117413Skan      /* Only allow [A-Za-z0-9], -, and _ in function names.  */
5573117413Skan      if (!ISALNUM (*endp) && !(*endp == '-' || *endp == '_'))
5574117413Skan	fatal ("malformed spec function name");
5575117413Skan    }
5576117413Skan  if (*endp != '(')		/* ) */
5577117413Skan    fatal ("no arguments for spec function");
5578117413Skan  func = save_string (p, endp - p);
5579117413Skan  p = ++endp;
5580117413Skan
5581117413Skan  /* Get the arguments.  */
5582117413Skan  for (count = 0; *endp != '\0'; endp++)
5583117413Skan    {
5584117413Skan      /* ( */
5585117413Skan      if (*endp == ')')
5586117413Skan	{
5587117413Skan	  if (count == 0)
5588117413Skan	    break;
5589117413Skan	  count--;
5590117413Skan	}
5591117413Skan      else if (*endp == '(')	/* ) */
5592117413Skan	count++;
5593117413Skan    }
5594117413Skan  /* ( */
5595117413Skan  if (*endp != ')')
5596117413Skan    fatal ("malformed spec function arguments");
5597117413Skan  args = save_string (p, endp - p);
5598117413Skan  p = ++endp;
5599117413Skan
5600117413Skan  /* p now points to just past the end of the spec function expression.  */
5601117413Skan
5602117413Skan  funcval = eval_spec_function (func, args);
5603117413Skan  if (funcval != NULL && do_spec_1 (funcval, 0, NULL) < 0)
5604117413Skan    p = NULL;
5605117413Skan
5606117413Skan  free (func);
5607117413Skan  free (args);
5608117413Skan
5609117413Skan  processing_spec_function--;
5610117413Skan
5611117413Skan  return p;
5612117413Skan}
5613117413Skan
5614132733Skan/* Inline subroutine of handle_braces.  Returns true if the current
5615132733Skan   input suffix matches the atom bracketed by ATOM and END_ATOM.  */
5616132733Skanstatic inline bool
5617132733Skaninput_suffix_matches (const char *atom, const char *end_atom)
5618132733Skan{
5619169704Skan  /* We special case the semantics of {.s:...} and {.S:...} and their
5620169704Skan     negative variants.  Instead of testing the input filename suffix,
5621169704Skan     we test whether the input source file is an assembler file or an
5622169704Skan     assembler-with-cpp file respectively.  This allows us to correctly
5623169704Skan     handle the -x command line option.  */
5624169704Skan
5625169704Skan  if (atom + 1 == end_atom
5626169704Skan      && input_file_compiler
5627169704Skan      && input_file_compiler->suffix)
5628169704Skan    {
5629169704Skan      if (*atom == 's')
5630169704Skan	return !strcmp (input_file_compiler->suffix, "@assembler");
5631169704Skan      if (*atom == 'S')
5632169704Skan	return !strcmp (input_file_compiler->suffix, "@assembler-with-cpp");
5633169704Skan    }
5634169704Skan
5635132733Skan  return (input_suffix
5636132733Skan	  && !strncmp (input_suffix, atom, end_atom - atom)
5637132733Skan	  && input_suffix[end_atom - atom] == '\0');
5638132733Skan}
563918334Speter
5640169704Skan/* Subroutine of handle_braces.  Returns true if a switch
5641132733Skan   matching the atom bracketed by ATOM and END_ATOM appeared on the
5642132733Skan   command line.  */
5643169704Skanstatic bool
5644132733Skanswitch_matches (const char *atom, const char *end_atom, int starred)
564518334Speter{
5646132733Skan  int i;
5647132733Skan  int len = end_atom - atom;
5648132733Skan  int plen = starred ? len : -1;
564918334Speter
5650132733Skan  for (i = 0; i < n_switches; i++)
5651132733Skan    if (!strncmp (switches[i].part1, atom, len)
5652132733Skan	&& (starred || switches[i].part1[len] == '\0')
5653132733Skan	&& check_live_switch (i, plen))
5654132733Skan      return true;
565550599Sobrien
5656132733Skan  return false;
5657132733Skan}
565818334Speter
5659132733Skan/* Inline subroutine of handle_braces.  Mark all of the switches which
5660132733Skan   match ATOM (extends to END_ATOM; STARRED indicates whether there
5661132733Skan   was a star after the atom) for later processing.  */
5662132733Skanstatic inline void
5663132733Skanmark_matching_switches (const char *atom, const char *end_atom, int starred)
5664132733Skan{
5665132733Skan  int i;
5666132733Skan  int len = end_atom - atom;
5667132733Skan  int plen = starred ? len : -1;
566890277Sobrien
5669132733Skan  for (i = 0; i < n_switches; i++)
5670132733Skan    if (!strncmp (switches[i].part1, atom, len)
5671132733Skan	&& (starred || switches[i].part1[len] == '\0')
5672132733Skan	&& check_live_switch (i, plen))
5673132733Skan      switches[i].ordering = 1;
5674132733Skan}
567550599Sobrien
5676132733Skan/* Inline subroutine of handle_braces.  Process all the currently
5677132733Skan   marked switches through give_switch, and clear the marks.  */
5678132733Skanstatic inline void
5679132733Skanprocess_marked_switches (void)
5680132733Skan{
5681132733Skan  int i;
568218334Speter
5683132733Skan  for (i = 0; i < n_switches; i++)
5684132733Skan    if (switches[i].ordering == 1)
5685132733Skan      {
5686132733Skan	switches[i].ordering = 0;
5687132733Skan	give_switch (i, 0);
5688132733Skan      }
5689132733Skan}
569018334Speter
5691132733Skan/* Handle a %{ ... } construct.  P points just inside the leading {.
5692132733Skan   Returns a pointer one past the end of the brace block, or 0
5693132733Skan   if we call do_spec_1 and that returns -1.  */
569418334Speter
5695132733Skanstatic const char *
5696132733Skanhandle_braces (const char *p)
5697132733Skan{
5698132733Skan  const char *atom, *end_atom;
5699132733Skan  const char *d_atom = NULL, *d_end_atom = NULL;
5700169704Skan  const char *orig = p;
570190277Sobrien
5702132733Skan  bool a_is_suffix;
5703132733Skan  bool a_is_starred;
5704132733Skan  bool a_is_negated;
5705132733Skan  bool a_matched;
570650599Sobrien
5707132733Skan  bool a_must_be_last = false;
5708132733Skan  bool ordered_set    = false;
5709132733Skan  bool disjunct_set   = false;
5710132733Skan  bool disj_matched   = false;
5711132733Skan  bool disj_starred   = true;
5712132733Skan  bool n_way_choice   = false;
5713132733Skan  bool n_way_matched  = false;
571450599Sobrien
5715132733Skan#define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0)
5716132733Skan
5717132733Skan  do
571818334Speter    {
5719132733Skan      if (a_must_be_last)
5720169704Skan	goto invalid;
572150599Sobrien
5722132733Skan      /* Scan one "atom" (S in the description above of %{}, possibly
5723132733Skan	 with !, ., or * modifiers).  */
5724132733Skan      a_matched = a_is_suffix = a_is_starred = a_is_negated = false;
572590277Sobrien
5726132733Skan      SKIP_WHITE();
5727132733Skan      if (*p == '!')
5728132733Skan	p++, a_is_negated = true;
572918334Speter
5730132733Skan      SKIP_WHITE();
5731132733Skan      if (*p == '.')
5732132733Skan	p++, a_is_suffix = true;
573318334Speter
5734132733Skan      atom = p;
5735132733Skan      while (ISIDNUM(*p) || *p == '-' || *p == '+' || *p == '='
5736132733Skan	     || *p == ',' || *p == '.' || *p == '@')
5737132733Skan	p++;
5738132733Skan      end_atom = p;
573918334Speter
5740132733Skan      if (*p == '*')
5741132733Skan	p++, a_is_starred = 1;
574290277Sobrien
5743132733Skan      SKIP_WHITE();
5744169704Skan      switch (*p)
5745132733Skan	{
5746169704Skan	case '&': case '}':
5747132733Skan	  /* Substitute the switch(es) indicated by the current atom.  */
5748132733Skan	  ordered_set = true;
5749132733Skan	  if (disjunct_set || n_way_choice || a_is_negated || a_is_suffix
5750132733Skan	      || atom == end_atom)
5751169704Skan	    goto invalid;
575218334Speter
5753132733Skan	  mark_matching_switches (atom, end_atom, a_is_starred);
5754132733Skan
5755132733Skan	  if (*p == '}')
5756132733Skan	    process_marked_switches ();
5757169704Skan	  break;
5758169704Skan
5759169704Skan	case '|': case ':':
5760132733Skan	  /* Substitute some text if the current atom appears as a switch
5761132733Skan	     or suffix.  */
5762132733Skan	  disjunct_set = true;
5763132733Skan	  if (ordered_set)
5764169704Skan	    goto invalid;
576518334Speter
5766132733Skan	  if (atom == end_atom)
576718334Speter	    {
5768132733Skan	      if (!n_way_choice || disj_matched || *p == '|'
5769132733Skan		  || a_is_negated || a_is_suffix || a_is_starred)
5770169704Skan		goto invalid;
5771132733Skan
5772132733Skan	      /* An empty term may appear as the last choice of an
5773132733Skan		 N-way choice set; it means "otherwise".  */
5774132733Skan	      a_must_be_last = true;
5775132733Skan	      disj_matched = !n_way_matched;
5776132733Skan	      disj_starred = false;
577718334Speter	    }
5778132733Skan	  else
577918334Speter	    {
5780132733Skan	       if (a_is_suffix && a_is_starred)
5781169704Skan		 goto invalid;
578218334Speter
5783132733Skan	       if (!a_is_starred)
5784132733Skan		 disj_starred = false;
578518334Speter
5786132733Skan	       /* Don't bother testing this atom if we already have a
5787132733Skan                  match.  */
5788132733Skan	       if (!disj_matched && !n_way_matched)
5789132733Skan		 {
5790132733Skan		   if (a_is_suffix)
5791132733Skan		     a_matched = input_suffix_matches (atom, end_atom);
5792132733Skan		   else
5793132733Skan		     a_matched = switch_matches (atom, end_atom, a_is_starred);
579418334Speter
5795132733Skan		   if (a_matched != a_is_negated)
5796132733Skan		     {
5797132733Skan		       disj_matched = true;
5798132733Skan		       d_atom = atom;
5799132733Skan		       d_end_atom = end_atom;
5800132733Skan		     }
5801132733Skan		 }
580218334Speter	    }
580318334Speter
5804132733Skan	  if (*p == ':')
580518334Speter	    {
5806132733Skan	      /* Found the body, that is, the text to substitute if the
5807132733Skan		 current disjunction matches.  */
5808132733Skan	      p = process_brace_body (p + 1, d_atom, d_end_atom, disj_starred,
5809132733Skan				      disj_matched && !n_way_matched);
5810132733Skan	      if (p == 0)
5811132733Skan		return 0;
581218334Speter
5813132733Skan	      /* If we have an N-way choice, reset state for the next
5814132733Skan		 disjunction.  */
5815132733Skan	      if (*p == ';')
581618334Speter		{
5817132733Skan		  n_way_choice = true;
5818132733Skan		  n_way_matched |= disj_matched;
5819132733Skan		  disj_matched = false;
5820132733Skan		  disj_starred = true;
5821132733Skan		  d_atom = d_end_atom = NULL;
582218334Speter		}
582318334Speter	    }
5824169704Skan	  break;
5825169704Skan
5826169704Skan	default:
5827169704Skan	  goto invalid;
582818334Speter	}
5829132733Skan    }
5830132733Skan  while (*p++ != '}');
583118334Speter
5832132733Skan  return p;
5833132733Skan
5834169704Skan invalid:
5835169704Skan  fatal ("braced spec '%s' is invalid at '%c'", orig, *p);
5836169704Skan
5837132733Skan#undef SKIP_WHITE
5838132733Skan}
5839132733Skan
5840132733Skan/* Subroutine of handle_braces.  Scan and process a brace substitution body
5841132733Skan   (X in the description of %{} syntax).  P points one past the colon;
5842132733Skan   ATOM and END_ATOM bracket the first atom which was found to be true
5843132733Skan   (present) in the current disjunction; STARRED indicates whether all
5844132733Skan   the atoms in the current disjunction were starred (for syntax validation);
5845132733Skan   MATCHED indicates whether the disjunction matched or not, and therefore
5846132733Skan   whether or not the body is to be processed through do_spec_1 or just
5847132733Skan   skipped.  Returns a pointer to the closing } or ;, or 0 if do_spec_1
5848132733Skan   returns -1.  */
5849132733Skan
5850132733Skanstatic const char *
5851132733Skanprocess_brace_body (const char *p, const char *atom, const char *end_atom,
5852132733Skan		    int starred, int matched)
5853132733Skan{
5854132733Skan  const char *body, *end_body;
5855132733Skan  unsigned int nesting_level;
5856132733Skan  bool have_subst     = false;
5857132733Skan
5858132733Skan  /* Locate the closing } or ;, honoring nested braces.
5859132733Skan     Trim trailing whitespace.  */
5860132733Skan  body = p;
5861132733Skan  nesting_level = 1;
5862132733Skan  for (;;)
5863132733Skan    {
5864132733Skan      if (*p == '{')
5865132733Skan	nesting_level++;
5866132733Skan      else if (*p == '}')
586718334Speter	{
5868132733Skan	  if (!--nesting_level)
5869132733Skan	    break;
587018334Speter	}
5871132733Skan      else if (*p == ';' && nesting_level == 1)
5872132733Skan	break;
5873132733Skan      else if (*p == '%' && p[1] == '*' && nesting_level == 1)
5874132733Skan	have_subst = true;
5875132733Skan      else if (*p == '\0')
5876169704Skan	goto invalid;
5877132733Skan      p++;
587818334Speter    }
587918334Speter
5880132733Skan  end_body = p;
5881132733Skan  while (end_body[-1] == ' ' || end_body[-1] == '\t')
5882132733Skan    end_body--;
588350599Sobrien
5884132733Skan  if (have_subst && !starred)
5885169704Skan    goto invalid;
5886132733Skan
5887132733Skan  if (matched)
588890277Sobrien    {
5889132733Skan      /* Copy the substitution body to permanent storage and execute it.
5890132733Skan	 If have_subst is false, this is a simple matter of running the
5891132733Skan	 body through do_spec_1...  */
5892132733Skan      char *string = save_string (body, end_body - body);
5893132733Skan      if (!have_subst)
5894132733Skan	{
5895132733Skan	  if (do_spec_1 (string, 0, NULL) < 0)
5896132733Skan	    return 0;
5897132733Skan	}
5898132733Skan      else
5899132733Skan	{
5900132733Skan	  /* ... but if have_subst is true, we have to process the
5901132733Skan	     body once for each matching switch, with %* set to the
5902132733Skan	     variant part of the switch.  */
5903132733Skan	  unsigned int hard_match_len = end_atom - atom;
5904132733Skan	  int i;
590590277Sobrien
5906132733Skan	  for (i = 0; i < n_switches; i++)
5907132733Skan	    if (!strncmp (switches[i].part1, atom, hard_match_len)
5908132733Skan		&& check_live_switch (i, hard_match_len))
5909132733Skan	      {
5910132733Skan		if (do_spec_1 (string, 0,
5911132733Skan			       &switches[i].part1[hard_match_len]) < 0)
5912132733Skan		  return 0;
5913132733Skan		/* Pass any arguments this switch has.  */
5914132733Skan		give_switch (i, 1);
5915132733Skan		suffix_subst = NULL;
5916132733Skan	      }
5917132733Skan	}
591890277Sobrien    }
591990277Sobrien
5920132733Skan  return p;
5921169704Skan
5922169704Skan invalid:
5923169704Skan  fatal ("braced spec body '%s' is invalid", body);
592418334Speter}
592518334Speter
592618334Speter/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch
592718334Speter   on the command line.  PREFIX_LENGTH is the length of XXX in an {XXX*}
592818334Speter   spec, or -1 if either exact match or %* is used.
592918334Speter
593018334Speter   A -O switch is obsoleted by a later -O switch.  A -f, -m, or -W switch
593118334Speter   whose value does not begin with "no-" is obsoleted by the same value
593218334Speter   with the "no-", similarly for a switch with the "no-" prefix.  */
593318334Speter
593418334Speterstatic int
5935132733Skancheck_live_switch (int switchnum, int prefix_length)
593618334Speter{
593752520Sobrien  const char *name = switches[switchnum].part1;
593818334Speter  int i;
593918334Speter
594018334Speter  /* In the common case of {<at-most-one-letter>*}, a negating
594118334Speter     switch would always match, so ignore that case.  We will just
594218334Speter     send the conflicting switches to the compiler phase.  */
594318334Speter  if (prefix_length >= 0 && prefix_length <= 1)
594418334Speter    return 1;
594518334Speter
594618334Speter  /* If we already processed this switch and determined if it was
594718334Speter     live or not, return our past determination.  */
594818334Speter  if (switches[switchnum].live_cond != 0)
594918334Speter    return switches[switchnum].live_cond > 0;
595018334Speter
595118334Speter  /* Now search for duplicate in a manner that depends on the name.  */
595218334Speter  switch (*name)
595318334Speter    {
595418334Speter    case 'O':
595590277Sobrien      for (i = switchnum + 1; i < n_switches; i++)
595690277Sobrien	if (switches[i].part1[0] == 'O')
595790277Sobrien	  {
595890277Sobrien	    switches[switchnum].validated = 1;
595990277Sobrien	    switches[switchnum].live_cond = SWITCH_FALSE;
596090277Sobrien	    return 0;
596190277Sobrien	  }
596218334Speter      break;
596318334Speter
596418334Speter    case 'W':  case 'f':  case 'm':
596518334Speter      if (! strncmp (name + 1, "no-", 3))
596618334Speter	{
596750599Sobrien	  /* We have Xno-YYY, search for XYYY.  */
596818334Speter	  for (i = switchnum + 1; i < n_switches; i++)
596918334Speter	    if (switches[i].part1[0] == name[0]
597018334Speter		&& ! strcmp (&switches[i].part1[1], &name[4]))
597190277Sobrien	      {
597290277Sobrien		switches[switchnum].validated = 1;
597390277Sobrien		switches[switchnum].live_cond = SWITCH_FALSE;
597490277Sobrien		return 0;
597590277Sobrien	      }
597618334Speter	}
597718334Speter      else
597818334Speter	{
597918334Speter	  /* We have XYYY, search for Xno-YYY.  */
598018334Speter	  for (i = switchnum + 1; i < n_switches; i++)
598118334Speter	    if (switches[i].part1[0] == name[0]
598218334Speter		&& switches[i].part1[1] == 'n'
598318334Speter		&& switches[i].part1[2] == 'o'
598418334Speter		&& switches[i].part1[3] == '-'
598518334Speter		&& !strcmp (&switches[i].part1[4], &name[1]))
598690277Sobrien	      {
598790277Sobrien		switches[switchnum].validated = 1;
598890277Sobrien		switches[switchnum].live_cond = SWITCH_FALSE;
598990277Sobrien		return 0;
599090277Sobrien	      }
599118334Speter	}
599218334Speter      break;
599318334Speter    }
599418334Speter
599518334Speter  /* Otherwise the switch is live.  */
599690277Sobrien  switches[switchnum].live_cond = SWITCH_LIVE;
599718334Speter  return 1;
599818334Speter}
599918334Speter
600018334Speter/* Pass a switch to the current accumulating command
600118334Speter   in the same form that we received it.
600218334Speter   SWITCHNUM identifies the switch; it is an index into
600318334Speter   the vector of switches gcc received, which is `switches'.
600418334Speter   This cannot fail since it never finishes a command line.
600518334Speter
6006132733Skan   If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument.  */
600718334Speter
600818334Speterstatic void
6009132733Skangive_switch (int switchnum, int omit_first_word)
601018334Speter{
601190277Sobrien  if (switches[switchnum].live_cond == SWITCH_IGNORE)
601290277Sobrien    return;
601390277Sobrien
601418334Speter  if (!omit_first_word)
601518334Speter    {
601690277Sobrien      do_spec_1 ("-", 0, NULL);
601790277Sobrien      do_spec_1 (switches[switchnum].part1, 1, NULL);
601818334Speter    }
601950599Sobrien
602018334Speter  if (switches[switchnum].args != 0)
602118334Speter    {
602290277Sobrien      const char **p;
602318334Speter      for (p = switches[switchnum].args; *p; p++)
602418334Speter	{
602590277Sobrien	  const char *arg = *p;
602690277Sobrien
6027132733Skan	  do_spec_1 (" ", 0, NULL);
602890277Sobrien	  if (suffix_subst)
602990277Sobrien	    {
603090277Sobrien	      unsigned length = strlen (arg);
603190277Sobrien	      int dot = 0;
603290277Sobrien
603390277Sobrien	      while (length-- && !IS_DIR_SEPARATOR (arg[length]))
603490277Sobrien		if (arg[length] == '.')
603590277Sobrien		  {
603690277Sobrien		    ((char *)arg)[length] = 0;
603790277Sobrien		    dot = 1;
603890277Sobrien		    break;
603990277Sobrien		  }
604090277Sobrien	      do_spec_1 (arg, 1, NULL);
604190277Sobrien	      if (dot)
604290277Sobrien		((char *)arg)[length] = '.';
604390277Sobrien	      do_spec_1 (suffix_subst, 1, NULL);
604490277Sobrien	    }
604590277Sobrien	  else
604690277Sobrien	    do_spec_1 (arg, 1, NULL);
604718334Speter	}
604818334Speter    }
604950599Sobrien
605090277Sobrien  do_spec_1 (" ", 0, NULL);
605152520Sobrien  switches[switchnum].validated = 1;
605218334Speter}
605318334Speter
605418334Speter/* Search for a file named NAME trying various prefixes including the
605518334Speter   user's -B prefix and some standard ones.
605618334Speter   Return the absolute file name found.  If nothing is found, return NAME.  */
605718334Speter
605852520Sobrienstatic const char *
6059132733Skanfind_file (const char *name)
606018334Speter{
6061169704Skan  char *newname = find_a_file (&startfile_prefixes, name, R_OK, true);
606218334Speter  return newname ? newname : name;
606318334Speter}
606418334Speter
606518334Speter/* Determine whether a directory exists.  If LINKER, return 0 for
6066169704Skan   certain fixed names not needed by the linker.  */
606718334Speter
606818334Speterstatic int
6069169704Skanis_directory (const char *path1, bool linker)
607018334Speter{
6071169704Skan  int len1;
6072169704Skan  char *path;
607318334Speter  char *cp;
607418334Speter  struct stat st;
607518334Speter
6076169704Skan  /* Ensure the string ends with "/.".  The resulting path will be a
6077169704Skan     directory even if the given path is a symbolic link.  */
6078169704Skan  len1 = strlen (path1);
6079169704Skan  path = alloca (3 + len1);
608052520Sobrien  memcpy (path, path1, len1);
6081169704Skan  cp = path + len1;
608252520Sobrien  if (!IS_DIR_SEPARATOR (cp[-1]))
608318334Speter    *cp++ = DIR_SEPARATOR;
608418334Speter  *cp++ = '.';
608518334Speter  *cp = '\0';
608618334Speter
608751232Sbde#ifndef FREEBSD_NATIVE
608818334Speter  /* Exclude directories that the linker is known to search.  */
608918334Speter  if (linker
6090169704Skan      && IS_DIR_SEPARATOR (path[0])
609118334Speter      && ((cp - path == 6
6092169704Skan	   && strncmp (path + 1, "lib", 3) == 0)
609318334Speter	  || (cp - path == 10
6094169704Skan	      && strncmp (path + 1, "usr", 3) == 0
6095169704Skan	      && IS_DIR_SEPARATOR (path[4])
6096169704Skan	      && strncmp (path + 5, "lib", 3) == 0)))
609718334Speter    return 0;
609851232Sbde#endif /* FREEBSD_NATIVE */
609918334Speter
610018334Speter  return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
610118334Speter}
610290277Sobrien
610390277Sobrien/* Set up the various global variables to indicate that we're processing
610490277Sobrien   the input file named FILENAME.  */
610590277Sobrien
610690277Sobrienvoid
6107132733Skanset_input (const char *filename)
610890277Sobrien{
610990277Sobrien  const char *p;
611090277Sobrien
611190277Sobrien  input_filename = filename;
611290277Sobrien  input_filename_length = strlen (input_filename);
611390277Sobrien
611490277Sobrien  input_basename = input_filename;
611590277Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM
611690277Sobrien  /* Skip drive name so 'x:foo' is handled properly.  */
611790277Sobrien  if (input_basename[1] == ':')
611890277Sobrien    input_basename += 2;
611990277Sobrien#endif
612090277Sobrien  for (p = input_basename; *p; p++)
612190277Sobrien    if (IS_DIR_SEPARATOR (*p))
612290277Sobrien      input_basename = p + 1;
612390277Sobrien
612490277Sobrien  /* Find a suffix starting with the last period,
612590277Sobrien     and set basename_length to exclude that suffix.  */
612690277Sobrien  basename_length = strlen (input_basename);
612790277Sobrien  suffixed_basename_length = basename_length;
612890277Sobrien  p = input_basename + basename_length;
612990277Sobrien  while (p != input_basename && *p != '.')
613090277Sobrien    --p;
613190277Sobrien  if (*p == '.' && p != input_basename)
613290277Sobrien    {
613390277Sobrien      basename_length = p - input_basename;
613490277Sobrien      input_suffix = p + 1;
613590277Sobrien    }
613690277Sobrien  else
613790277Sobrien    input_suffix = "";
6138117413Skan
613990277Sobrien  /* If a spec for 'g', 'u', or 'U' is seen with -save-temps then
614090277Sobrien     we will need to do a stat on the input_filename.  The
614190277Sobrien     INPUT_STAT_SET signals that the stat is needed.  */
614290277Sobrien  input_stat_set = 0;
614390277Sobrien}
614418334Speter
614518334Speter/* On fatal signals, delete all the temporary files.  */
614618334Speter
614718334Speterstatic void
6148132733Skanfatal_error (int signum)
614918334Speter{
615018334Speter  signal (signum, SIG_DFL);
615118334Speter  delete_failure_queue ();
615218334Speter  delete_temp_files ();
615318334Speter  /* Get the same signal again, this time not handled,
615418334Speter     so its normal effect occurs.  */
615518334Speter  kill (getpid (), signum);
615618334Speter}
615718334Speter
6158169704Skanextern int main (int, char **);
615990277Sobrien
616018334Speterint
6161169704Skanmain (int argc, char **argv)
616218334Speter{
616390277Sobrien  size_t i;
616418334Speter  int value;
616518334Speter  int linker_was_run = 0;
6166169704Skan  int lang_n_infiles = 0;
6167132733Skan  int num_linker_inputs = 0;
616818334Speter  char *explicit_link_files;
616918334Speter  char *specs_file;
617052520Sobrien  const char *p;
617150599Sobrien  struct user_specs *uptr;
617218334Speter
617318334Speter  p = argv[0] + strlen (argv[0]);
617452520Sobrien  while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
617552520Sobrien    --p;
617618334Speter  programname = p;
617718334Speter
617890277Sobrien  xmalloc_set_program_name (programname);
617990277Sobrien
6180169704Skan  expandargv (&argc, &argv);
6181169704Skan
6182169704Skan  prune_options (&argc, &argv);
6183169704Skan
618490277Sobrien#ifdef GCC_DRIVER_HOST_INITIALIZATION
618590277Sobrien  /* Perform host dependent initialization when needed.  */
618690277Sobrien  GCC_DRIVER_HOST_INITIALIZATION;
618752520Sobrien#endif
618852520Sobrien
6189169704Skan  /* Unlock the stdio streams.  */
6190169704Skan  unlock_std_streams ();
6191169704Skan
619290277Sobrien  gcc_init_libintl ();
619390277Sobrien
619418334Speter  if (signal (SIGINT, SIG_IGN) != SIG_IGN)
619518334Speter    signal (SIGINT, fatal_error);
619618334Speter#ifdef SIGHUP
619718334Speter  if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
619818334Speter    signal (SIGHUP, fatal_error);
619918334Speter#endif
620018334Speter  if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
620118334Speter    signal (SIGTERM, fatal_error);
620218334Speter#ifdef SIGPIPE
620318334Speter  if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
620418334Speter    signal (SIGPIPE, fatal_error);
620518334Speter#endif
620690277Sobrien#ifdef SIGCHLD
620790277Sobrien  /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
620890277Sobrien     receive the signal.  A different setting is inheritable */
620990277Sobrien  signal (SIGCHLD, SIG_DFL);
621090277Sobrien#endif
621118334Speter
6212117413Skan  /* Allocate the argument vector.  */
6213117413Skan  alloc_args ();
621418334Speter
621518334Speter  obstack_init (&obstack);
621618334Speter
621750599Sobrien  /* Build multilib_select, et. al from the separate lines that make up each
621850599Sobrien     multilib selection.  */
621950599Sobrien  {
622090277Sobrien    const char *const *q = multilib_raw;
622150599Sobrien    int need_space;
622250599Sobrien
622350599Sobrien    obstack_init (&multilib_obstack);
622450599Sobrien    while ((p = *q++) != (char *) 0)
622550599Sobrien      obstack_grow (&multilib_obstack, p, strlen (p));
622650599Sobrien
622750599Sobrien    obstack_1grow (&multilib_obstack, 0);
6228169704Skan    multilib_select = XOBFINISH (&multilib_obstack, const char *);
622950599Sobrien
623050599Sobrien    q = multilib_matches_raw;
623150599Sobrien    while ((p = *q++) != (char *) 0)
623250599Sobrien      obstack_grow (&multilib_obstack, p, strlen (p));
623350599Sobrien
623450599Sobrien    obstack_1grow (&multilib_obstack, 0);
6235169704Skan    multilib_matches = XOBFINISH (&multilib_obstack, const char *);
623650599Sobrien
623790277Sobrien    q = multilib_exclusions_raw;
623890277Sobrien    while ((p = *q++) != (char *) 0)
623990277Sobrien      obstack_grow (&multilib_obstack, p, strlen (p));
624090277Sobrien
624190277Sobrien    obstack_1grow (&multilib_obstack, 0);
6242169704Skan    multilib_exclusions = XOBFINISH (&multilib_obstack, const char *);
624390277Sobrien
624450599Sobrien    need_space = FALSE;
624590277Sobrien    for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++)
624650599Sobrien      {
624750599Sobrien	if (need_space)
624850599Sobrien	  obstack_1grow (&multilib_obstack, ' ');
624950599Sobrien	obstack_grow (&multilib_obstack,
625050599Sobrien		      multilib_defaults_raw[i],
625150599Sobrien		      strlen (multilib_defaults_raw[i]));
625250599Sobrien	need_space = TRUE;
625350599Sobrien      }
625450599Sobrien
625550599Sobrien    obstack_1grow (&multilib_obstack, 0);
6256169704Skan    multilib_defaults = XOBFINISH (&multilib_obstack, const char *);
625750599Sobrien  }
625850599Sobrien
625918334Speter  /* Set up to remember the pathname of gcc and any options
626018334Speter     needed for collect.  We use argv[0] instead of programname because
626118334Speter     we need the complete pathname.  */
626218334Speter  obstack_init (&collect_obstack);
626390277Sobrien  obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1);
626490277Sobrien  obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1);
6265169704Skan  putenv (XOBFINISH (&collect_obstack, char *));
626618334Speter
626718334Speter#ifdef INIT_ENVIRONMENT
626818334Speter  /* Set up any other necessary machine specific environment variables.  */
626918334Speter  putenv (INIT_ENVIRONMENT);
627018334Speter#endif
627118334Speter
627218334Speter  /* Make a table of what switches there are (switches, n_switches).
627318334Speter     Make a table of specified input files (infiles, n_infiles).
627418334Speter     Decode switches that are handled locally.  */
627518334Speter
6276169704Skan  process_command (argc, (const char **) argv);
627718334Speter
627818334Speter  /* Initialize the vector of specs to just the default.
627918334Speter     This means one element containing 0s, as a terminator.  */
628018334Speter
6281132733Skan  compilers = xmalloc (sizeof default_compilers);
6282132733Skan  memcpy (compilers, default_compilers, sizeof default_compilers);
628318334Speter  n_compilers = n_default_compilers;
628418334Speter
628518334Speter  /* Read specs from a file if there is one.  */
628618334Speter
628791561Sobrien#ifdef FREEBSD_NATIVE
6288169704Skan  machine_suffix = "";
628991561Sobrien  just_machine_suffix = "";
629091561Sobrien#else	/* FREEBSD_NATIVE */
629150599Sobrien  machine_suffix = concat (spec_machine, dir_separator_str,
629290277Sobrien			   spec_version, dir_separator_str, NULL);
629390277Sobrien  just_machine_suffix = concat (spec_machine, dir_separator_str, NULL);
629450599Sobrien#endif /* FREEBSD_NATIVE */
629518334Speter
6296169704Skan  specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, true);
629718334Speter  /* Read the specs file unless it is a default one.  */
629818334Speter  if (specs_file != 0 && strcmp (specs_file, "specs"))
629950599Sobrien    read_specs (specs_file, TRUE);
630050599Sobrien  else
630150599Sobrien    init_spec ();
630218334Speter
630350599Sobrien  /* We need to check standard_exec_prefix/just_machine_suffix/specs
630490277Sobrien     for any override of as, ld and libraries.  */
630597902Sobrien  specs_file = (char *) alloca (strlen (FBSD_DATA_PREFIX)
630650599Sobrien				+ strlen (just_machine_suffix)
630750599Sobrien				+ sizeof ("specs"));
630850599Sobrien
630997902Sobrien  strcpy (specs_file, FBSD_DATA_PREFIX);
631050599Sobrien  strcat (specs_file, just_machine_suffix);
631150599Sobrien  strcat (specs_file, "specs");
631250599Sobrien  if (access (specs_file, R_OK) == 0)
631350599Sobrien    read_specs (specs_file, TRUE);
631490277Sobrien
6315132733Skan  /* Process any configure-time defaults specified for the command line
6316132733Skan     options, via OPTION_DEFAULT_SPECS.  */
6317132733Skan  for (i = 0; i < ARRAY_SIZE (option_default_specs); i++)
6318132733Skan    do_option_spec (option_default_specs[i].name,
6319132733Skan		    option_default_specs[i].spec);
6320132733Skan
6321132733Skan  /* Process DRIVER_SELF_SPECS, adding any new options to the end
6322132733Skan     of the command line.  */
6323132733Skan
6324132733Skan  for (i = 0; i < ARRAY_SIZE (driver_self_specs); i++)
6325132733Skan    do_self_spec (driver_self_specs[i]);
6326132733Skan
6327132733Skan  /* If not cross-compiling, look for executables in the standard
6328132733Skan     places.  */
6329132733Skan  if (*cross_compile == '0')
633018334Speter    {
633190277Sobrien      if (*md_exec_prefix)
633290277Sobrien	{
633390277Sobrien	  add_prefix (&exec_prefixes, md_exec_prefix, "GCC",
6334169704Skan		      PREFIX_PRIORITY_LAST, 0, 0);
633590277Sobrien	}
6336132733Skan    }
633718334Speter
6338132733Skan  /* Process sysroot_suffix_spec.  */
6339132733Skan  if (*sysroot_suffix_spec != 0
6340132733Skan      && do_spec_2 (sysroot_suffix_spec) == 0)
6341132733Skan    {
6342132733Skan      if (argbuf_index > 1)
6343169704Skan        error ("spec failure: more than one arg to SYSROOT_SUFFIX_SPEC");
6344132733Skan      else if (argbuf_index == 1)
6345132733Skan        target_sysroot_suffix = xstrdup (argbuf[argbuf_index -1]);
6346132733Skan    }
6347132733Skan
6348169704Skan#ifdef HAVE_LD_SYSROOT
6349169704Skan  /* Pass the --sysroot option to the linker, if it supports that.  If
6350169704Skan     there is a sysroot_suffix_spec, it has already been processed by
6351169704Skan     this point, so target_system_root really is the system root we
6352169704Skan     should be using.  */
6353169704Skan  if (target_system_root)
6354169704Skan    {
6355169704Skan      obstack_grow (&obstack, "%(sysroot_spec) ", strlen ("%(sysroot_spec) "));
6356169704Skan      obstack_grow0 (&obstack, link_spec, strlen (link_spec));
6357169704Skan      set_spec ("link", XOBFINISH (&obstack, const char *));
6358169704Skan    }
6359169704Skan#endif
6360169704Skan
6361132733Skan  /* Process sysroot_hdrs_suffix_spec.  */
6362132733Skan  if (*sysroot_hdrs_suffix_spec != 0
6363132733Skan      && do_spec_2 (sysroot_hdrs_suffix_spec) == 0)
6364132733Skan    {
6365132733Skan      if (argbuf_index > 1)
6366169704Skan        error ("spec failure: more than one arg to SYSROOT_HEADERS_SUFFIX_SPEC");
6367132733Skan      else if (argbuf_index == 1)
6368132733Skan        target_sysroot_hdrs_suffix = xstrdup (argbuf[argbuf_index -1]);
6369132733Skan    }
6370132733Skan
6371132733Skan  /* Look for startfiles in the standard places.  */
6372132733Skan  if (*startfile_prefix_spec != 0
6373132733Skan      && do_spec_2 (startfile_prefix_spec) == 0
6374132733Skan      && do_spec_1 (" ", 0, NULL) == 0)
6375132733Skan    {
6376132733Skan      int ndx;
6377132733Skan      for (ndx = 0; ndx < argbuf_index; ndx++)
6378132733Skan	add_sysrooted_prefix (&startfile_prefixes, argbuf[ndx], "BINUTILS",
6379169704Skan			      PREFIX_PRIORITY_LAST, 0, 1);
6380132733Skan    }
6381132733Skan  /* We should eventually get rid of all these and stick to
6382132733Skan     startfile_prefix_spec exclusively.  */
6383132733Skan  else if (*cross_compile == '0' || target_system_root)
6384132733Skan    {
638590277Sobrien      if (*md_startfile_prefix)
6386132733Skan	add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix,
6387169704Skan			      "GCC", PREFIX_PRIORITY_LAST, 0, 1);
638818334Speter
638990277Sobrien      if (*md_startfile_prefix_1)
6390132733Skan	add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix_1,
6391169704Skan			      "GCC", PREFIX_PRIORITY_LAST, 0, 1);
639218334Speter
639318334Speter      /* If standard_startfile_prefix is relative, base it on
639418334Speter	 standard_exec_prefix.  This lets us move the installed tree
639518334Speter	 as a unit.  If GCC_EXEC_PREFIX is defined, base
6396132733Skan	 standard_startfile_prefix on that as well.
6397132733Skan
6398132733Skan         If the prefix is relative, only search it for native compilers;
6399132733Skan         otherwise we will search a directory containing host libraries.  */
6400132733Skan      if (IS_ABSOLUTE_PATH (standard_startfile_prefix))
6401132733Skan	add_sysrooted_prefix (&startfile_prefixes,
6402132733Skan			      standard_startfile_prefix, "BINUTILS",
6403169704Skan			      PREFIX_PRIORITY_LAST, 0, 1);
6404132733Skan      else if (*cross_compile == '0')
640518334Speter	{
640618334Speter	  if (gcc_exec_prefix)
640718334Speter	    add_prefix (&startfile_prefixes,
640850599Sobrien			concat (gcc_exec_prefix, machine_suffix,
640990277Sobrien				standard_startfile_prefix, NULL),
6410169704Skan			NULL, PREFIX_PRIORITY_LAST, 0, 1);
641118334Speter	  add_prefix (&startfile_prefixes,
641250599Sobrien		      concat (standard_exec_prefix,
641350599Sobrien			      machine_suffix,
641490277Sobrien			      standard_startfile_prefix, NULL),
6415169704Skan		      NULL, PREFIX_PRIORITY_LAST, 0, 1);
641690277Sobrien	}
641718334Speter
641818346Speter#ifndef FREEBSD_NATIVE
6419169704Skan      if (*standard_startfile_prefix_1)
6420169704Skan 	add_sysrooted_prefix (&startfile_prefixes,
6421169704Skan			      standard_startfile_prefix_1, "BINUTILS",
6422169704Skan			      PREFIX_PRIORITY_LAST, 0, 1);
6423169704Skan      if (*standard_startfile_prefix_2)
6424169704Skan	add_sysrooted_prefix (&startfile_prefixes,
6425169704Skan			      standard_startfile_prefix_2, "BINUTILS",
6426169704Skan			      PREFIX_PRIORITY_LAST, 0, 1);
642718334Speter#endif
642818334Speter    }
642918334Speter
643052520Sobrien  /* Process any user specified specs in the order given on the command
643152520Sobrien     line.  */
643252520Sobrien  for (uptr = user_specs_head; uptr; uptr = uptr->next)
643352520Sobrien    {
6434104763Skan      char *filename = find_a_file (&startfile_prefixes, uptr->filename,
6435169704Skan				    R_OK, true);
643652520Sobrien      read_specs (filename ? filename : uptr->filename, FALSE);
643752520Sobrien    }
643852520Sobrien
643918334Speter  /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake.  */
644018334Speter  if (gcc_exec_prefix)
644190277Sobrien    gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
644290277Sobrien			      spec_version, dir_separator_str, NULL);
644318334Speter
644418334Speter  /* Now we have the specs.
644518334Speter     Set the `valid' bits for switches that match anything in any spec.  */
644618334Speter
644718334Speter  validate_all_switches ();
644818334Speter
644918334Speter  /* Now that we have the switches and the specs, set
645018334Speter     the subdirectory based on the options.  */
645118334Speter  set_multilib_dir ();
645218334Speter
645318334Speter  /* Warn about any switches that no pass was interested in.  */
645418334Speter
645590277Sobrien  for (i = 0; (int) i < n_switches; i++)
645652520Sobrien    if (! switches[i].validated)
6457169704Skan      error ("unrecognized option '-%s'", switches[i].part1);
645818334Speter
645918334Speter  /* Obey some of the options.  */
646018334Speter
646118334Speter  if (print_search_dirs)
646218334Speter    {
6463169704Skan#ifndef	FREEBSD_NATIVE
646490277Sobrien      printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix);
6465169704Skan#else
6466169704Skan      printf (_("install: %s\n"), standard_exec_prefix);
6467169704Skan#endif
6468169704Skan      printf (_("programs: %s\n"),
6469169704Skan	      build_search_list (&exec_prefixes, "", false, false));
6470169704Skan      printf (_("libraries: %s\n"),
6471169704Skan	      build_search_list (&startfile_prefixes, "", false, true));
647290277Sobrien      return (0);
647318334Speter    }
647418334Speter
647518334Speter  if (print_file_name)
647618334Speter    {
647718334Speter      printf ("%s\n", find_file (print_file_name));
647890277Sobrien      return (0);
647918334Speter    }
648018334Speter
648118334Speter  if (print_prog_name)
648218334Speter    {
6483104763Skan      char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK, 0);
648418334Speter      printf ("%s\n", (newname ? newname : print_prog_name));
648590277Sobrien      return (0);
648618334Speter    }
648718334Speter
648818334Speter  if (print_multi_lib)
648918334Speter    {
649018334Speter      print_multilib_info ();
649190277Sobrien      return (0);
649218334Speter    }
649318334Speter
649418334Speter  if (print_multi_directory)
649518334Speter    {
649618334Speter      if (multilib_dir == NULL)
649718334Speter	printf (".\n");
649818334Speter      else
649918334Speter	printf ("%s\n", multilib_dir);
650090277Sobrien      return (0);
650118334Speter    }
650218334Speter
6503104763Skan  if (print_multi_os_directory)
6504104763Skan    {
6505104763Skan      if (multilib_os_dir == NULL)
6506104763Skan	printf (".\n");
6507104763Skan      else
6508104763Skan	printf ("%s\n", multilib_os_dir);
6509104763Skan      return (0);
6510104763Skan    }
6511104763Skan
651290277Sobrien  if (target_help_flag)
651390277Sobrien   {
651490277Sobrien      /* Print if any target specific options.  */
651590277Sobrien
651690277Sobrien      /* We do not exit here. Instead we have created a fake input file
651790277Sobrien         called 'target-dummy' which needs to be compiled, and we pass this
651890277Sobrien         on to the various sub-processes, along with the --target-help
651990277Sobrien         switch.  */
652090277Sobrien    }
652190277Sobrien
652250599Sobrien  if (print_help_list)
652350599Sobrien    {
652450599Sobrien      display_help ();
652550599Sobrien
652650599Sobrien      if (! verbose_flag)
652750599Sobrien	{
6528260011Spfg	  printf ("%s", _("\nFor bug reporting instructions, please see:\n"));
6529117413Skan	  printf ("%s.\n", bug_report_url);
653090277Sobrien
653190277Sobrien	  return (0);
653250599Sobrien	}
653350599Sobrien
653450599Sobrien      /* We do not exit here.  Instead we have created a fake input file
653550599Sobrien	 called 'help-dummy' which needs to be compiled, and we pass this
653690277Sobrien	 on the various sub-processes, along with the --help switch.  */
653750599Sobrien    }
653890277Sobrien
653918334Speter  if (verbose_flag)
654018334Speter    {
654150599Sobrien      int n;
654290277Sobrien      const char *thrmod;
654350599Sobrien
6544169704Skan      notice ("Target: %s\n", spec_machine);
654590277Sobrien      notice ("Configured with: %s\n", configuration_arguments);
654690277Sobrien
654790277Sobrien#ifdef THREAD_MODEL_SPEC
654890277Sobrien      /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
654990277Sobrien	 but there's no point in doing all this processing just to get
655090277Sobrien	 thread_model back.  */
655190277Sobrien      obstack_init (&obstack);
655290277Sobrien      do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
655390277Sobrien      obstack_1grow (&obstack, '\0');
6554169704Skan      thrmod = XOBFINISH (&obstack, const char *);
655590277Sobrien#else
655690277Sobrien      thrmod = thread_model;
655790277Sobrien#endif
655890277Sobrien
655990277Sobrien      notice ("Thread model: %s\n", thrmod);
656090277Sobrien
656150599Sobrien      /* compiler_version is truncated at the first space when initialized
656250599Sobrien	 from version string, so truncate version_string at the first space
656350599Sobrien	 before comparing.  */
656450599Sobrien      for (n = 0; version_string[n]; n++)
656550599Sobrien	if (version_string[n] == ' ')
656650599Sobrien	  break;
656750599Sobrien
656850599Sobrien      if (! strncmp (version_string, compiler_version, n)
656950599Sobrien	  && compiler_version[n] == 0)
657052520Sobrien	notice ("gcc version %s\n", version_string);
657118334Speter      else
657252520Sobrien	notice ("gcc driver version %s executing gcc version %s\n",
657352520Sobrien		version_string, compiler_version);
657418334Speter
657518334Speter      if (n_infiles == 0)
657690277Sobrien	return (0);
657718334Speter    }
657818334Speter
657950599Sobrien  if (n_infiles == added_libraries)
658018346Speter    fatal ("No input files specified");
658118334Speter
658218334Speter  /* Make a place to record the compiler output file names
658318334Speter     that correspond to the input files.  */
658418334Speter
658550599Sobrien  i = n_infiles;
658650599Sobrien  i += lang_specific_extra_outfiles;
6587169704Skan  outfiles = XCNEWVEC (const char *, i);
658818334Speter
658918334Speter  /* Record which files were specified explicitly as link input.  */
659018334Speter
6591169704Skan  explicit_link_files = XCNEWVEC (char, n_infiles);
659218334Speter
6593169704Skan  if (combine_flag)
6594169704Skan    combine_inputs = true;
6595169704Skan  else
6596169704Skan    combine_inputs = false;
6597169704Skan
6598169704Skan  for (i = 0; (int) i < n_infiles; i++)
659918334Speter    {
6600169704Skan      const char *name = infiles[i].name;
6601169704Skan      struct compiler *compiler = lookup_compiler (name,
6602169704Skan						   strlen (name),
6603169704Skan						   infiles[i].language);
6604169704Skan
6605169704Skan      if (compiler && !(compiler->combinable))
6606169704Skan	combine_inputs = false;
6607169704Skan
6608169704Skan      if (lang_n_infiles > 0 && compiler != input_file_compiler
6609169704Skan	  && infiles[i].language && infiles[i].language[0] != '*')
6610169704Skan	infiles[i].incompiler = compiler;
6611169704Skan      else if (compiler)
6612169704Skan	{
6613169704Skan	  lang_n_infiles++;
6614169704Skan	  input_file_compiler = compiler;
6615169704Skan	  infiles[i].incompiler = compiler;
6616169704Skan	}
6617169704Skan      else
6618169704Skan	{
6619169704Skan	  /* Since there is no compiler for this input file, assume it is a
6620169704Skan	     linker file.  */
6621169704Skan	  explicit_link_files[i] = 1;
6622169704Skan	  infiles[i].incompiler = NULL;
6623169704Skan	}
6624169704Skan      infiles[i].compiled = false;
6625169704Skan      infiles[i].preprocessed = false;
6626132733Skan    }
6627169704Skan
6628169704Skan  if (!combine_inputs && have_c && have_o && lang_n_infiles > 1)
6629169704Skan   fatal ("cannot specify -o with -c or -S with multiple files");
6630169704Skan
6631169704Skan  if (combine_flag && save_temps_flag)
6632132733Skan    {
6633169704Skan      bool save_combine_inputs = combine_inputs;
6634169704Skan      /* Must do a separate pre-processing pass for C & Objective-C files, to
6635169704Skan	 obtain individual .i files.  */
6636169704Skan
6637169704Skan      combine_inputs = false;
6638169704Skan      for (i = 0; (int) i < n_infiles; i++)
6639169704Skan	{
6640169704Skan	  int this_file_error = 0;
6641169704Skan
6642169704Skan	  input_file_number = i;
6643169704Skan	  set_input (infiles[i].name);
6644169704Skan	  if (infiles[i].incompiler
6645169704Skan	      && (infiles[i].incompiler)->needs_preprocessing)
6646169704Skan	    input_file_compiler = infiles[i].incompiler;
6647169704Skan	  else
6648169704Skan	    continue;
6649169704Skan
6650169704Skan	  if (input_file_compiler)
6651169704Skan	    {
6652169704Skan	      if (input_file_compiler->spec[0] == '#')
6653169704Skan		{
6654169704Skan		  error ("%s: %s compiler not installed on this system",
6655169704Skan			 input_filename, &input_file_compiler->spec[1]);
6656169704Skan		  this_file_error = 1;
6657169704Skan		}
6658169704Skan	      else
6659169704Skan		{
6660169704Skan		  value = do_spec (input_file_compiler->spec);
6661169704Skan		  infiles[i].preprocessed = true;
6662169704Skan		  if (!have_o_argbuf_index)
6663169704Skan		    fatal ("spec '%s' is invalid", input_file_compiler->spec);
6664169704Skan		  infiles[i].name = argbuf[have_o_argbuf_index];
6665169704Skan		  infiles[i].incompiler
6666169704Skan		    = lookup_compiler (infiles[i].name,
6667169704Skan				       strlen (infiles[i].name),
6668169704Skan				       infiles[i].language);
6669169704Skan
6670169704Skan		  if (value < 0)
6671169704Skan		    this_file_error = 1;
6672169704Skan		}
6673169704Skan	    }
6674169704Skan
6675169704Skan	  if (this_file_error)
6676169704Skan	    {
6677169704Skan	      delete_failure_queue ();
6678169704Skan	      error_count++;
6679169704Skan	      break;
6680169704Skan	    }
6681169704Skan	  clear_failure_queue ();
6682169704Skan	}
6683169704Skan      combine_inputs = save_combine_inputs;
6684169704Skan    }
6685169704Skan
6686169704Skan  for (i = 0; (int) i < n_infiles; i++)
6687169704Skan    {
668818334Speter      int this_file_error = 0;
668918334Speter
669018334Speter      /* Tell do_spec what to substitute for %i.  */
669118334Speter
669218334Speter      input_file_number = i;
669390277Sobrien      set_input (infiles[i].name);
669418334Speter
6695169704Skan      if (infiles[i].compiled)
6696169704Skan	continue;
6697169704Skan
669818334Speter      /* Use the same thing in %o, unless cp->spec says otherwise.  */
669918334Speter
670018334Speter      outfiles[i] = input_filename;
670118334Speter
670218334Speter      /* Figure out which compiler from the file's suffix.  */
670318334Speter
6704132733Skan      if (! combine_inputs)
6705132733Skan	input_file_compiler
6706132733Skan	  = lookup_compiler (infiles[i].name, input_filename_length,
6707132733Skan			     infiles[i].language);
6708169704Skan      else
6709169704Skan	input_file_compiler = infiles[i].incompiler;
6710117413Skan
671190277Sobrien      if (input_file_compiler)
671218334Speter	{
671318334Speter	  /* Ok, we found an applicable compiler.  Run its spec.  */
671418334Speter
671590277Sobrien	  if (input_file_compiler->spec[0] == '#')
671618334Speter	    {
671790277Sobrien	      error ("%s: %s compiler not installed on this system",
671890277Sobrien		     input_filename, &input_file_compiler->spec[1]);
671990277Sobrien	      this_file_error = 1;
672018334Speter	    }
672118334Speter	  else
672290277Sobrien	    {
672390277Sobrien	      value = do_spec (input_file_compiler->spec);
6724169704Skan	      infiles[i].compiled = true;
672590277Sobrien	      if (value < 0)
672690277Sobrien		this_file_error = 1;
672790277Sobrien	    }
672818334Speter	}
672918334Speter
673018334Speter      /* If this file's name does not contain a recognized suffix,
673118334Speter	 record it as explicit linker input.  */
673218334Speter
673318334Speter      else
673418334Speter	explicit_link_files[i] = 1;
673518334Speter
673618334Speter      /* Clear the delete-on-failure queue, deleting the files in it
673718334Speter	 if this compilation failed.  */
673818334Speter
673918334Speter      if (this_file_error)
674018334Speter	{
674118334Speter	  delete_failure_queue ();
674218334Speter	  error_count++;
674318334Speter	}
674418334Speter      /* If this compilation succeeded, don't delete those files later.  */
674518334Speter      clear_failure_queue ();
674618334Speter    }
674718334Speter
6748169704Skan  /* Reset the input file name to the first compile/object file name, for use
6749169704Skan     with %b in LINK_SPEC. We use the first input file that we can find
6750169704Skan     a compiler to compile it instead of using infiles.language since for
6751169704Skan     languages other than C we use aliases that we then lookup later.  */
675290277Sobrien  if (n_infiles > 0)
6753169704Skan    {
6754169704Skan      int i;
675590277Sobrien
6756169704Skan      for (i = 0; i < n_infiles ; i++)
6757169704Skan	if (infiles[i].language && infiles[i].language[0] != '*')
6758169704Skan	  {
6759169704Skan	    set_input (infiles[i].name);
6760169704Skan	    break;
6761169704Skan	  }
6762169704Skan    }
6763169704Skan
676452520Sobrien  if (error_count == 0)
676552520Sobrien    {
676652520Sobrien      /* Make sure INPUT_FILE_NUMBER points to first available open
676752520Sobrien	 slot.  */
676852520Sobrien      input_file_number = n_infiles;
676952520Sobrien      if (lang_specific_pre_link ())
677052520Sobrien	error_count++;
677152520Sobrien    }
677250599Sobrien
6773132733Skan  /* Determine if there are any linker input files.  */
6774132733Skan  num_linker_inputs = 0;
6775132733Skan  for (i = 0; (int) i < n_infiles; i++)
6776132733Skan    if (explicit_link_files[i] || outfiles[i] != NULL)
6777132733Skan      num_linker_inputs++;
6778132733Skan
677918334Speter  /* Run ld to link all the compiler output files.  */
678018334Speter
6781132733Skan  if (num_linker_inputs > 0 && error_count == 0)
678218334Speter    {
678318334Speter      int tmp = execution_count;
678418334Speter
678590277Sobrien      /* We'll use ld if we can't find collect2.  */
678650599Sobrien      if (! strcmp (linker_name_spec, "collect2"))
678750599Sobrien	{
6788169704Skan	  char *s = find_a_file (&exec_prefixes, "collect2", X_OK, false);
678950599Sobrien	  if (s == NULL)
679050599Sobrien	    linker_name_spec = "ld";
679150599Sobrien	}
679218334Speter      /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
679318334Speter	 for collect.  */
6794169704Skan      putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH", false);
6795169704Skan      putenv_from_prefixes (&startfile_prefixes, LIBRARY_PATH_ENV, true);
679618334Speter
679718334Speter      value = do_spec (link_command_spec);
679818334Speter      if (value < 0)
679918334Speter	error_count = 1;
680018334Speter      linker_was_run = (tmp != execution_count);
680118334Speter    }
680218334Speter
680318334Speter  /* If options said don't run linker,
680418334Speter     complain about input files to be given to the linker.  */
680518334Speter
680618334Speter  if (! linker_was_run && error_count == 0)
680790277Sobrien    for (i = 0; (int) i < n_infiles; i++)
680818334Speter      if (explicit_link_files[i])
680990277Sobrien	error ("%s: linker input file unused because linking not done",
681018334Speter	       outfiles[i]);
681118334Speter
681218334Speter  /* Delete some or all of the temporary files we made.  */
681318334Speter
681418334Speter  if (error_count)
681518334Speter    delete_failure_queue ();
681618334Speter  delete_temp_files ();
681718334Speter
681850599Sobrien  if (print_help_list)
681950599Sobrien    {
682090277Sobrien      printf (("\nFor bug reporting instructions, please see:\n"));
6821117413Skan      printf ("%s\n", bug_report_url);
682250599Sobrien    }
682390277Sobrien
682490277Sobrien  return (signal_count != 0 ? 2
682590277Sobrien	  : error_count > 0 ? (pass_exit_codes ? greatest_status : 1)
682690277Sobrien	  : 0);
682718334Speter}
682818334Speter
682918334Speter/* Find the proper compilation spec for the file name NAME,
683018334Speter   whose length is LENGTH.  LANGUAGE is the specified language,
683150599Sobrien   or 0 if this file is to be passed to the linker.  */
683218334Speter
683318334Speterstatic struct compiler *
6834132733Skanlookup_compiler (const char *name, size_t length, const char *language)
683518334Speter{
683618334Speter  struct compiler *cp;
683718334Speter
683890277Sobrien  /* If this was specified by the user to be a linker input, indicate that.  */
683950599Sobrien  if (language != 0 && language[0] == '*')
684050599Sobrien    return 0;
684150599Sobrien
684250599Sobrien  /* Otherwise, look for the language, if one is spec'd.  */
684318334Speter  if (language != 0)
684418334Speter    {
684518334Speter      for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
684650599Sobrien	if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language))
684750599Sobrien	  return cp;
684850599Sobrien
684918334Speter      error ("language %s not recognized", language);
685050599Sobrien      return 0;
685118334Speter    }
685218334Speter
685318334Speter  /* Look for a suffix.  */
685418334Speter  for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
685518334Speter    {
685618334Speter      if (/* The suffix `-' matches only the file name `-'.  */
685718334Speter	  (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
685850599Sobrien	  || (strlen (cp->suffix) < length
685950599Sobrien	      /* See if the suffix matches the end of NAME.  */
686050599Sobrien	      && !strcmp (cp->suffix,
686150599Sobrien			  name + length - strlen (cp->suffix))
686250599Sobrien	 ))
6863117413Skan	break;
686490277Sobrien    }
686550599Sobrien
686690277Sobrien#if defined (OS2) ||defined (HAVE_DOS_BASED_FILE_SYSTEM)
6867169704Skan  /* Look again, but case-insensitively this time.  */
686890277Sobrien  if (cp < compilers)
686990277Sobrien    for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
687090277Sobrien      {
687190277Sobrien	if (/* The suffix `-' matches only the file name `-'.  */
687290277Sobrien	    (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
687390277Sobrien	    || (strlen (cp->suffix) < length
687490277Sobrien		/* See if the suffix matches the end of NAME.  */
687590277Sobrien		&& ((!strcmp (cp->suffix,
687690277Sobrien			     name + length - strlen (cp->suffix))
687790277Sobrien		     || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
687890277Sobrien		    && !strcasecmp (cp->suffix,
687990277Sobrien				    name + length - strlen (cp->suffix)))
688090277Sobrien	   ))
688190277Sobrien	  break;
688290277Sobrien      }
688390277Sobrien#endif
688450599Sobrien
688590277Sobrien  if (cp >= compilers)
688690277Sobrien    {
688790277Sobrien      if (cp->spec[0] != '@')
688890277Sobrien	/* A non-alias entry: return it.  */
688990277Sobrien	return cp;
689090277Sobrien
689190277Sobrien      /* An alias entry maps a suffix to a language.
689290277Sobrien	 Search for the language; pass 0 for NAME and LENGTH
689390277Sobrien	 to avoid infinite recursion if language not found.  */
689490277Sobrien      return lookup_compiler (NULL, 0, cp->spec + 1);
689518334Speter    }
689618334Speter  return 0;
689718334Speter}
689818334Speter
689918334Speterstatic char *
6900132733Skansave_string (const char *s, int len)
690118334Speter{
6902169704Skan  char *result = XNEWVEC (char, len + 1);
690318334Speter
690490277Sobrien  memcpy (result, s, len);
690518334Speter  result[len] = 0;
690618334Speter  return result;
690718334Speter}
690818334Speter
690990277Sobrienvoid
6910132733Skanpfatal_with_name (const char *name)
691118334Speter{
691252520Sobrien  perror_with_name (name);
691352520Sobrien  delete_temp_files ();
691452520Sobrien  exit (1);
691518334Speter}
691618334Speter
691718334Speterstatic void
6918132733Skanperror_with_name (const char *name)
691918334Speter{
692052520Sobrien  error ("%s: %s", name, xstrerror (errno));
692118334Speter}
692218334Speter
6923132733Skan/* Output an error message and exit.  */
692418334Speter
692518334Spetervoid
6926169704Skanfancy_abort (const char *file, int line, const char *func)
692718334Speter{
6928169704Skan  fatal_ice ("internal gcc abort in %s, at %s:%d", func, file, line);
692918334Speter}
693018334Speter
6931132733Skan/* Output an error message and exit.  */
693218334Speter
693352520Sobrienvoid
6934169704Skanfatal_ice (const char *cmsgid, ...)
693518334Speter{
6936132733Skan  va_list ap;
693718334Speter
6938169704Skan  va_start (ap, cmsgid);
6939132733Skan
694018334Speter  fprintf (stderr, "%s: ", programname);
6941169704Skan  vfprintf (stderr, _(cmsgid), ap);
6942132733Skan  va_end (ap);
694318334Speter  fprintf (stderr, "\n");
694418334Speter  delete_temp_files ();
6945169704Skan  exit (pass_exit_codes ? ICE_EXIT_CODE : 1);
6946169704Skan}
6947169704Skan
6948169704Skanvoid
6949169704Skanfatal (const char *cmsgid, ...)
6950169704Skan{
6951169704Skan  va_list ap;
6952169704Skan
6953169704Skan  va_start (ap, cmsgid);
6954169704Skan
6955169704Skan  fprintf (stderr, "%s: ", programname);
6956169704Skan  vfprintf (stderr, _(cmsgid), ap);
6957169704Skan  va_end (ap);
6958169704Skan  fprintf (stderr, "\n");
6959169704Skan  delete_temp_files ();
696018334Speter  exit (1);
696118334Speter}
696218334Speter
6963169704Skan/* The argument is actually c-format, not gcc-internal-format,
6964169704Skan   but because functions with identical names are used through
6965169704Skan   the rest of the compiler with gcc-internal-format, we just
6966169704Skan   need to hope all users of these functions use the common
6967169704Skan   subset between c-format and gcc-internal-format.  */
6968169704Skan
696990277Sobrienvoid
6970169704Skanerror (const char *gmsgid, ...)
697118334Speter{
6972132733Skan  va_list ap;
697318334Speter
6974169704Skan  va_start (ap, gmsgid);
697518334Speter  fprintf (stderr, "%s: ", programname);
6976169704Skan  vfprintf (stderr, _(gmsgid), ap);
6977132733Skan  va_end (ap);
697818334Speter
697918334Speter  fprintf (stderr, "\n");
698018334Speter}
698152520Sobrien
698252520Sobrienstatic void
6983169704Skannotice (const char *cmsgid, ...)
698452520Sobrien{
6985132733Skan  va_list ap;
698652520Sobrien
6987169704Skan  va_start (ap, cmsgid);
6988169704Skan  vfprintf (stderr, _(cmsgid), ap);
6989132733Skan  va_end (ap);
699052520Sobrien}
699118334Speter
6992132733Skanstatic inline void
6993132733Skanvalidate_switches_from_spec (const char *spec)
6994132733Skan{
6995132733Skan  const char *p = spec;
6996132733Skan  char c;
6997132733Skan  while ((c = *p++))
6998132733Skan    if (c == '%' && (*p == '{' || *p == '<' || (*p == 'W' && *++p == '{')))
6999132733Skan      /* We have a switch spec.  */
7000132733Skan      p = validate_switches (p + 1);
7001132733Skan}
7002132733Skan
700318334Speterstatic void
7004132733Skanvalidate_all_switches (void)
700518334Speter{
700618334Speter  struct compiler *comp;
700718334Speter  struct spec_list *spec;
700818334Speter
700990277Sobrien  for (comp = compilers; comp->spec; comp++)
7010132733Skan    validate_switches_from_spec (comp->spec);
701118334Speter
701290277Sobrien  /* Look through the linked list of specs read from the specs file.  */
701390277Sobrien  for (spec = specs; spec; spec = spec->next)
7014132733Skan    validate_switches_from_spec (*spec->ptr_spec);
701518334Speter
7016132733Skan  validate_switches_from_spec (link_command_spec);
701718334Speter}
701818334Speter
701918334Speter/* Look at the switch-name that comes after START
702018334Speter   and mark as valid all supplied switches that match it.  */
702118334Speter
7022132733Skanstatic const char *
7023132733Skanvalidate_switches (const char *start)
702418334Speter{
702590277Sobrien  const char *p = start;
7026132733Skan  const char *atom;
7027132733Skan  size_t len;
702890277Sobrien  int i;
7029132733Skan  bool suffix = false;
7030132733Skan  bool starred = false;
703118334Speter
7032132733Skan#define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0)
703318334Speter
703490277Sobriennext_member:
7035132733Skan  SKIP_WHITE ();
7036132733Skan
703718334Speter  if (*p == '!')
7038132733Skan    p++;
703918334Speter
7040132733Skan  SKIP_WHITE ();
704118334Speter  if (*p == '.')
7042132733Skan    suffix = true, p++;
704318334Speter
7044132733Skan  atom = p;
7045132733Skan  while (ISIDNUM (*p) || *p == '-' || *p == '+' || *p == '='
7046132733Skan	 || *p == ',' || *p == '.' || *p == '@')
704790277Sobrien    p++;
7048132733Skan  len = p - atom;
704918334Speter
7050132733Skan  if (*p == '*')
7051132733Skan    starred = true, p++;
7052132733Skan
7053132733Skan  SKIP_WHITE ();
7054132733Skan
7055132733Skan  if (!suffix)
705618334Speter    {
705718334Speter      /* Mark all matching switches as valid.  */
705818334Speter      for (i = 0; i < n_switches; i++)
7059132733Skan	if (!strncmp (switches[i].part1, atom, len)
7060132733Skan	    && (starred || switches[i].part1[len] == 0))
706152520Sobrien	  switches[i].validated = 1;
706218334Speter    }
7063132733Skan
7064132733Skan  if (*p) p++;
7065132733Skan  if (*p && (p[-1] == '|' || p[-1] == '&'))
7066132733Skan    goto next_member;
7067132733Skan
7068132733Skan  if (*p && p[-1] == ':')
706918334Speter    {
7070132733Skan      while (*p && *p != ';' && *p != '}')
707118334Speter	{
7072132733Skan	  if (*p == '%')
7073132733Skan	    {
7074132733Skan	      p++;
7075132733Skan	      if (*p == '{' || *p == '<')
7076132733Skan		p = validate_switches (p+1);
7077132733Skan	      else if (p[0] == 'W' && p[1] == '{')
7078132733Skan		p = validate_switches (p+2);
7079132733Skan	    }
7080132733Skan	  else
7081132733Skan	    p++;
708218334Speter	}
7083132733Skan
7084132733Skan      if (*p) p++;
7085132733Skan      if (*p && p[-1] == ';')
7086132733Skan	goto next_member;
708718334Speter    }
708890277Sobrien
7089132733Skan  return p;
7090132733Skan#undef SKIP_WHITE
709118334Speter}
709218334Speter
7093104763Skanstruct mdswitchstr
7094104763Skan{
7095104763Skan  const char *str;
7096104763Skan  int len;
7097104763Skan};
7098104763Skan
7099104763Skanstatic struct mdswitchstr *mdswitches;
7100104763Skanstatic int n_mdswitches;
7101104763Skan
710250599Sobrien/* Check whether a particular argument was used.  The first time we
710350599Sobrien   canonicalize the switches to keep only the ones we care about.  */
710418334Speter
710518334Speterstatic int
7106132733Skanused_arg (const char *p, int len)
710718334Speter{
710890277Sobrien  struct mswitchstr
710990277Sobrien  {
711090277Sobrien    const char *str;
711190277Sobrien    const char *replace;
711250599Sobrien    int len;
711350599Sobrien    int rep_len;
711450599Sobrien  };
711518334Speter
711650599Sobrien  static struct mswitchstr *mswitches;
711750599Sobrien  static int n_mswitches;
711850599Sobrien  int i, j;
711950599Sobrien
712050599Sobrien  if (!mswitches)
712150599Sobrien    {
712250599Sobrien      struct mswitchstr *matches;
712390277Sobrien      const char *q;
712450599Sobrien      int cnt = 0;
712550599Sobrien
712690277Sobrien      /* Break multilib_matches into the component strings of string
712790277Sobrien         and replacement string.  */
712850599Sobrien      for (q = multilib_matches; *q != '\0'; q++)
712950599Sobrien	if (*q == ';')
713050599Sobrien	  cnt++;
713150599Sobrien
7132132733Skan      matches = alloca ((sizeof (struct mswitchstr)) * cnt);
713350599Sobrien      i = 0;
713450599Sobrien      q = multilib_matches;
713550599Sobrien      while (*q != '\0')
713650599Sobrien	{
713750599Sobrien	  matches[i].str = q;
713850599Sobrien	  while (*q != ' ')
713950599Sobrien	    {
714050599Sobrien	      if (*q == '\0')
7141169704Skan		{
7142169704Skan		invalid_matches:
7143169704Skan		  fatal ("multilib spec '%s' is invalid", multilib_matches);
7144169704Skan		}
714550599Sobrien	      q++;
714650599Sobrien	    }
714750599Sobrien	  matches[i].len = q - matches[i].str;
714850599Sobrien
714950599Sobrien	  matches[i].replace = ++q;
715050599Sobrien	  while (*q != ';' && *q != '\0')
715150599Sobrien	    {
715250599Sobrien	      if (*q == ' ')
7153169704Skan		goto invalid_matches;
715450599Sobrien	      q++;
715550599Sobrien	    }
715650599Sobrien	  matches[i].rep_len = q - matches[i].replace;
715750599Sobrien	  i++;
715850599Sobrien	  if (*q == ';')
715990277Sobrien	    q++;
716050599Sobrien	}
716150599Sobrien
716250599Sobrien      /* Now build a list of the replacement string for switches that we care
716350599Sobrien	 about.  Make sure we allocate at least one entry.  This prevents
716450599Sobrien	 xmalloc from calling fatal, and prevents us from re-executing this
716550599Sobrien	 block of code.  */
716650599Sobrien      mswitches
7167169704Skan	= XNEWVEC (struct mswitchstr, n_mdswitches + (n_switches ? n_switches : 1));
716850599Sobrien      for (i = 0; i < n_switches; i++)
7169169704Skan	if (switches[i].live_cond != SWITCH_IGNORE)
7170169704Skan	  {
7171169704Skan	    int xlen = strlen (switches[i].part1);
7172169704Skan	    for (j = 0; j < cnt; j++)
7173169704Skan	      if (xlen == matches[j].len
7174169704Skan		  && ! strncmp (switches[i].part1, matches[j].str, xlen))
7175169704Skan		{
7176169704Skan		  mswitches[n_mswitches].str = matches[j].replace;
7177169704Skan		  mswitches[n_mswitches].len = matches[j].rep_len;
7178169704Skan		  mswitches[n_mswitches].replace = (char *) 0;
7179169704Skan		  mswitches[n_mswitches].rep_len = 0;
7180169704Skan		  n_mswitches++;
7181169704Skan		  break;
7182169704Skan		}
7183169704Skan	  }
7184104763Skan
7185104763Skan      /* Add MULTILIB_DEFAULTS switches too, as long as they were not present
7186104763Skan	 on the command line nor any options mutually incompatible with
7187104763Skan	 them.  */
7188104763Skan      for (i = 0; i < n_mdswitches; i++)
7189104763Skan	{
7190104763Skan	  const char *r;
7191104763Skan
7192104763Skan	  for (q = multilib_options; *q != '\0'; q++)
7193104763Skan	    {
7194104763Skan	      while (*q == ' ')
7195104763Skan		q++;
7196104763Skan
7197104763Skan	      r = q;
7198104763Skan	      while (strncmp (q, mdswitches[i].str, mdswitches[i].len) != 0
7199104763Skan		     || strchr (" /", q[mdswitches[i].len]) == NULL)
7200104763Skan		{
7201104763Skan		  while (*q != ' ' && *q != '/' && *q != '\0')
7202104763Skan		    q++;
7203104763Skan		  if (*q != '/')
7204104763Skan		    break;
7205104763Skan		  q++;
7206104763Skan		}
7207104763Skan
7208104763Skan	      if (*q != ' ' && *q != '\0')
7209104763Skan		{
7210104763Skan		  while (*r != ' ' && *r != '\0')
7211104763Skan		    {
7212104763Skan		      q = r;
7213104763Skan		      while (*q != ' ' && *q != '/' && *q != '\0')
7214104763Skan			q++;
7215104763Skan
7216104763Skan		      if (used_arg (r, q - r))
7217104763Skan			break;
7218104763Skan
7219104763Skan		      if (*q != '/')
7220104763Skan			{
7221104763Skan			  mswitches[n_mswitches].str = mdswitches[i].str;
7222104763Skan			  mswitches[n_mswitches].len = mdswitches[i].len;
7223104763Skan			  mswitches[n_mswitches].replace = (char *) 0;
7224104763Skan			  mswitches[n_mswitches].rep_len = 0;
7225104763Skan			  n_mswitches++;
7226104763Skan			  break;
7227104763Skan			}
7228104763Skan
7229104763Skan		      r = q + 1;
7230104763Skan		    }
7231104763Skan		  break;
7232104763Skan		}
7233104763Skan	    }
7234104763Skan	}
723550599Sobrien    }
723650599Sobrien
723750599Sobrien  for (i = 0; i < n_mswitches; i++)
723850599Sobrien    if (len == mswitches[i].len && ! strncmp (p, mswitches[i].str, len))
723918334Speter      return 1;
724050599Sobrien
724118334Speter  return 0;
724218334Speter}
724318334Speter
724418334Speterstatic int
7245132733Skandefault_arg (const char *p, int len)
724618334Speter{
7247104763Skan  int i;
724818334Speter
7249104763Skan  for (i = 0; i < n_mdswitches; i++)
7250104763Skan    if (len == mdswitches[i].len && ! strncmp (p, mdswitches[i].str, len))
7251104763Skan      return 1;
725218334Speter
725318334Speter  return 0;
725418334Speter}
725518334Speter
725690277Sobrien/* Work out the subdirectory to use based on the options. The format of
725790277Sobrien   multilib_select is a list of elements. Each element is a subdirectory
725890277Sobrien   name followed by a list of options followed by a semicolon. The format
725990277Sobrien   of multilib_exclusions is the same, but without the preceding
726090277Sobrien   directory. First gcc will check the exclusions, if none of the options
726190277Sobrien   beginning with an exclamation point are present, and all of the other
726290277Sobrien   options are present, then we will ignore this completely. Passing
726390277Sobrien   that, gcc will consider each multilib_select in turn using the same
726490277Sobrien   rules for matching the options. If a match is found, that subdirectory
726590277Sobrien   will be used.  */
726618334Speter
726718334Speterstatic void
7268132733Skanset_multilib_dir (void)
726918334Speter{
727090277Sobrien  const char *p;
727190277Sobrien  unsigned int this_path_len;
727290277Sobrien  const char *this_path, *this_arg;
7273104763Skan  const char *start, *end;
727418334Speter  int not_arg;
7275104763Skan  int ok, ndfltok, first;
727618334Speter
7277104763Skan  n_mdswitches = 0;
7278104763Skan  start = multilib_defaults;
7279104763Skan  while (*start == ' ' || *start == '\t')
7280104763Skan    start++;
7281104763Skan  while (*start != '\0')
7282104763Skan    {
7283104763Skan      n_mdswitches++;
7284104763Skan      while (*start != ' ' && *start != '\t' && *start != '\0')
7285104763Skan	start++;
7286104763Skan      while (*start == ' ' || *start == '\t')
7287104763Skan        start++;
7288104763Skan    }
7289104763Skan
7290104763Skan  if (n_mdswitches)
7291104763Skan    {
7292104763Skan      int i = 0;
7293104763Skan
7294169704Skan      mdswitches = XNEWVEC (struct mdswitchstr, n_mdswitches);
7295104763Skan      for (start = multilib_defaults; *start != '\0'; start = end + 1)
7296104763Skan	{
7297104763Skan	  while (*start == ' ' || *start == '\t')
7298104763Skan	    start++;
7299104763Skan
7300104763Skan	  if (*start == '\0')
7301104763Skan	    break;
7302132733Skan
7303104763Skan	  for (end = start + 1;
7304104763Skan	       *end != ' ' && *end != '\t' && *end != '\0'; end++)
7305104763Skan	    ;
7306104763Skan
7307104763Skan	  obstack_grow (&multilib_obstack, start, end - start);
7308104763Skan	  obstack_1grow (&multilib_obstack, 0);
7309169704Skan	  mdswitches[i].str = XOBFINISH (&multilib_obstack, const char *);
7310104763Skan	  mdswitches[i++].len = end - start;
7311104763Skan
7312104763Skan	  if (*end == '\0')
7313104763Skan	    break;
7314104763Skan	}
7315104763Skan    }
7316104763Skan
731790277Sobrien  p = multilib_exclusions;
731818334Speter  while (*p != '\0')
731918334Speter    {
732018334Speter      /* Ignore newlines.  */
732118334Speter      if (*p == '\n')
732218334Speter	{
732318334Speter	  ++p;
732418334Speter	  continue;
732518334Speter	}
732618334Speter
732790277Sobrien      /* Check the arguments.  */
732890277Sobrien      ok = 1;
732990277Sobrien      while (*p != ';')
733090277Sobrien	{
733190277Sobrien	  if (*p == '\0')
7332169704Skan	    {
7333169704Skan	    invalid_exclusions:
7334169704Skan	      fatal ("multilib exclusions '%s' is invalid",
7335169704Skan		     multilib_exclusions);
7336169704Skan	    }
733790277Sobrien
733890277Sobrien	  if (! ok)
733990277Sobrien	    {
734090277Sobrien	      ++p;
734190277Sobrien	      continue;
734290277Sobrien	    }
734390277Sobrien
734490277Sobrien	  this_arg = p;
734590277Sobrien	  while (*p != ' ' && *p != ';')
734690277Sobrien	    {
734790277Sobrien	      if (*p == '\0')
7348169704Skan		goto invalid_exclusions;
734990277Sobrien	      ++p;
735090277Sobrien	    }
735190277Sobrien
735290277Sobrien	  if (*this_arg != '!')
735390277Sobrien	    not_arg = 0;
735490277Sobrien	  else
735590277Sobrien	    {
735690277Sobrien	      not_arg = 1;
735790277Sobrien	      ++this_arg;
735890277Sobrien	    }
735990277Sobrien
736090277Sobrien	  ok = used_arg (this_arg, p - this_arg);
736190277Sobrien	  if (not_arg)
736290277Sobrien	    ok = ! ok;
736390277Sobrien
736490277Sobrien	  if (*p == ' ')
736590277Sobrien	    ++p;
736690277Sobrien	}
736790277Sobrien
736890277Sobrien      if (ok)
736990277Sobrien	return;
737090277Sobrien
737190277Sobrien      ++p;
737290277Sobrien    }
737390277Sobrien
7374104763Skan  first = 1;
737590277Sobrien  p = multilib_select;
737690277Sobrien  while (*p != '\0')
737790277Sobrien    {
737890277Sobrien      /* Ignore newlines.  */
737990277Sobrien      if (*p == '\n')
738090277Sobrien	{
738190277Sobrien	  ++p;
738290277Sobrien	  continue;
738390277Sobrien	}
738490277Sobrien
738518334Speter      /* Get the initial path.  */
738618334Speter      this_path = p;
738718334Speter      while (*p != ' ')
738818334Speter	{
738918334Speter	  if (*p == '\0')
7390169704Skan	    {
7391169704Skan	    invalid_select:
7392169704Skan	      fatal ("multilib select '%s' is invalid",
7393169704Skan		     multilib_select);
7394169704Skan	    }
739518334Speter	  ++p;
739618334Speter	}
739718334Speter      this_path_len = p - this_path;
739818334Speter
739918334Speter      /* Check the arguments.  */
740018334Speter      ok = 1;
7401104763Skan      ndfltok = 1;
740218334Speter      ++p;
740318334Speter      while (*p != ';')
740418334Speter	{
740518334Speter	  if (*p == '\0')
7406169704Skan	    goto invalid_select;
740718334Speter
740818334Speter	  if (! ok)
740918334Speter	    {
741018334Speter	      ++p;
741118334Speter	      continue;
741218334Speter	    }
741318334Speter
741418334Speter	  this_arg = p;
741518334Speter	  while (*p != ' ' && *p != ';')
741618334Speter	    {
741718334Speter	      if (*p == '\0')
7418169704Skan		goto invalid_select;
741918334Speter	      ++p;
742018334Speter	    }
742118334Speter
742218334Speter	  if (*this_arg != '!')
742318334Speter	    not_arg = 0;
742418334Speter	  else
742518334Speter	    {
742618334Speter	      not_arg = 1;
742718334Speter	      ++this_arg;
742818334Speter	    }
742918334Speter
743018334Speter	  /* If this is a default argument, we can just ignore it.
743118334Speter	     This is true even if this_arg begins with '!'.  Beginning
743218334Speter	     with '!' does not mean that this argument is necessarily
743318334Speter	     inappropriate for this library: it merely means that
743418334Speter	     there is a more specific library which uses this
743518334Speter	     argument.  If this argument is a default, we need not
743618334Speter	     consider that more specific library.  */
7437104763Skan	  ok = used_arg (this_arg, p - this_arg);
7438104763Skan	  if (not_arg)
7439104763Skan	    ok = ! ok;
744018334Speter
7441104763Skan	  if (! ok)
7442104763Skan	    ndfltok = 0;
7443104763Skan
7444104763Skan	  if (default_arg (this_arg, p - this_arg))
7445104763Skan	    ok = 1;
7446104763Skan
744718334Speter	  if (*p == ' ')
744818334Speter	    ++p;
744918334Speter	}
745018334Speter
7451104763Skan      if (ok && first)
745218334Speter	{
745318334Speter	  if (this_path_len != 1
745418334Speter	      || this_path[0] != '.')
745518334Speter	    {
7456169704Skan	      char *new_multilib_dir = XNEWVEC (char, this_path_len + 1);
7457104763Skan	      char *q;
7458104763Skan
745952520Sobrien	      strncpy (new_multilib_dir, this_path, this_path_len);
746052520Sobrien	      new_multilib_dir[this_path_len] = '\0';
7461104763Skan	      q = strchr (new_multilib_dir, ':');
7462104763Skan	      if (q != NULL)
7463104763Skan		*q = '\0';
746452520Sobrien	      multilib_dir = new_multilib_dir;
746518334Speter	    }
7466104763Skan	  first = 0;
746718334Speter	}
746818334Speter
7469104763Skan      if (ndfltok)
7470104763Skan	{
7471104763Skan	  const char *q = this_path, *end = this_path + this_path_len;
7472104763Skan
7473104763Skan	  while (q < end && *q != ':')
7474104763Skan	    q++;
7475104763Skan	  if (q < end)
7476104763Skan	    {
7477169704Skan	      char *new_multilib_os_dir = XNEWVEC (char, end - q);
7478104763Skan	      memcpy (new_multilib_os_dir, q + 1, end - q - 1);
7479104763Skan	      new_multilib_os_dir[end - q - 1] = '\0';
7480104763Skan	      multilib_os_dir = new_multilib_os_dir;
7481104763Skan	      break;
7482104763Skan	    }
7483104763Skan	}
7484104763Skan
748518334Speter      ++p;
748690277Sobrien    }
7487104763Skan
7488104763Skan  if (multilib_dir == NULL && multilib_os_dir != NULL
7489104763Skan      && strcmp (multilib_os_dir, ".") == 0)
7490104763Skan    {
7491104763Skan      free ((char *) multilib_os_dir);
7492104763Skan      multilib_os_dir = NULL;
7493104763Skan    }
7494104763Skan  else if (multilib_dir != NULL && multilib_os_dir == NULL)
7495104763Skan    multilib_os_dir = multilib_dir;
749618334Speter}
749718334Speter
749818334Speter/* Print out the multiple library subdirectory selection
749918334Speter   information.  This prints out a series of lines.  Each line looks
750018334Speter   like SUBDIRECTORY;@OPTION@OPTION, with as many options as is
750118334Speter   required.  Only the desired options are printed out, the negative
750218334Speter   matches.  The options are print without a leading dash.  There are
750318334Speter   no spaces to make it easy to use the information in the shell.
750418334Speter   Each subdirectory is printed only once.  This assumes the ordering
750590277Sobrien   generated by the genmultilib script. Also, we leave out ones that match
750690277Sobrien   the exclusions.  */
750718334Speter
750818334Speterstatic void
7509132733Skanprint_multilib_info (void)
751018334Speter{
751190277Sobrien  const char *p = multilib_select;
751290277Sobrien  const char *last_path = 0, *this_path;
751318334Speter  int skip;
751490277Sobrien  unsigned int last_path_len = 0;
751518334Speter
751618334Speter  while (*p != '\0')
751718334Speter    {
751890277Sobrien      skip = 0;
751918334Speter      /* Ignore newlines.  */
752018334Speter      if (*p == '\n')
752118334Speter	{
752218334Speter	  ++p;
752318334Speter	  continue;
752418334Speter	}
752518334Speter
752618334Speter      /* Get the initial path.  */
752718334Speter      this_path = p;
752818334Speter      while (*p != ' ')
752918334Speter	{
753018334Speter	  if (*p == '\0')
7531169704Skan	    {
7532169704Skan	    invalid_select:
7533169704Skan	      fatal ("multilib select '%s' is invalid", multilib_select);
7534169704Skan	    }
7535169704Skan
753618334Speter	  ++p;
753718334Speter	}
753818334Speter
7539104763Skan      /* When --disable-multilib was used but target defines
7540104763Skan	 MULTILIB_OSDIRNAMES, entries starting with .: are there just
7541104763Skan	 to find multilib_os_dir, so skip them from output.  */
7542104763Skan      if (this_path[0] == '.' && this_path[1] == ':')
7543104763Skan	skip = 1;
7544104763Skan
754590277Sobrien      /* Check for matches with the multilib_exclusions. We don't bother
754690277Sobrien         with the '!' in either list. If any of the exclusion rules match
754790277Sobrien         all of its options with the select rule, we skip it.  */
754890277Sobrien      {
754990277Sobrien	const char *e = multilib_exclusions;
755090277Sobrien	const char *this_arg;
755118334Speter
755290277Sobrien	while (*e != '\0')
755390277Sobrien	  {
755490277Sobrien	    int m = 1;
755590277Sobrien	    /* Ignore newlines.  */
755690277Sobrien	    if (*e == '\n')
755790277Sobrien	      {
755890277Sobrien		++e;
755990277Sobrien		continue;
756090277Sobrien	      }
756118334Speter
756290277Sobrien	    /* Check the arguments.  */
756390277Sobrien	    while (*e != ';')
756490277Sobrien	      {
756590277Sobrien		const char *q;
756690277Sobrien		int mp = 0;
756790277Sobrien
756890277Sobrien		if (*e == '\0')
7569169704Skan		  {
7570169704Skan		  invalid_exclusion:
7571169704Skan		    fatal ("multilib exclusion '%s' is invalid",
7572169704Skan			   multilib_exclusions);
7573169704Skan		  }
757490277Sobrien
757590277Sobrien		if (! m)
757690277Sobrien		  {
757790277Sobrien		    ++e;
757890277Sobrien		    continue;
757990277Sobrien		  }
758090277Sobrien
758190277Sobrien		this_arg = e;
758290277Sobrien
758390277Sobrien		while (*e != ' ' && *e != ';')
758490277Sobrien		  {
758590277Sobrien		    if (*e == '\0')
7586169704Skan		      goto invalid_exclusion;
758790277Sobrien		    ++e;
758890277Sobrien		  }
758990277Sobrien
759090277Sobrien		q = p + 1;
759190277Sobrien		while (*q != ';')
759290277Sobrien		  {
759390277Sobrien		    const char *arg;
759490277Sobrien		    int len = e - this_arg;
759590277Sobrien
759690277Sobrien		    if (*q == '\0')
7597169704Skan		      goto invalid_select;
759890277Sobrien
759990277Sobrien		    arg = q;
760090277Sobrien
760190277Sobrien		    while (*q != ' ' && *q != ';')
760290277Sobrien		      {
760390277Sobrien			if (*q == '\0')
7604169704Skan			  goto invalid_select;
760590277Sobrien			++q;
760690277Sobrien		      }
760790277Sobrien
7608169704Skan		    if (! strncmp (arg, this_arg,
7609169704Skan				   (len < q - arg) ? q - arg : len)
7610169704Skan			|| default_arg (this_arg, e - this_arg))
761190277Sobrien		      {
761290277Sobrien			mp = 1;
761390277Sobrien			break;
761490277Sobrien		      }
761590277Sobrien
761690277Sobrien		    if (*q == ' ')
761790277Sobrien		      ++q;
761890277Sobrien		  }
761990277Sobrien
762090277Sobrien		if (! mp)
762190277Sobrien		  m = 0;
762290277Sobrien
762390277Sobrien		if (*e == ' ')
762490277Sobrien		  ++e;
762590277Sobrien	      }
762690277Sobrien
762790277Sobrien	    if (m)
762890277Sobrien	      {
762990277Sobrien		skip = 1;
763090277Sobrien		break;
763190277Sobrien	      }
763290277Sobrien
763390277Sobrien	    if (*e != '\0')
763490277Sobrien	      ++e;
763590277Sobrien	  }
763690277Sobrien      }
763790277Sobrien
763890277Sobrien      if (! skip)
763990277Sobrien	{
764090277Sobrien	  /* If this is a duplicate, skip it.  */
7641169704Skan	  skip = (last_path != 0
7642169704Skan		  && (unsigned int) (p - this_path) == last_path_len
764390277Sobrien		  && ! strncmp (last_path, this_path, last_path_len));
764490277Sobrien
764590277Sobrien	  last_path = this_path;
764690277Sobrien	  last_path_len = p - this_path;
764790277Sobrien	}
764890277Sobrien
764918334Speter      /* If this directory requires any default arguments, we can skip
765018334Speter	 it.  We will already have printed a directory identical to
765118334Speter	 this one which does not require that default argument.  */
765218334Speter      if (! skip)
765318334Speter	{
765490277Sobrien	  const char *q;
765518334Speter
765618334Speter	  q = p + 1;
765718334Speter	  while (*q != ';')
765818334Speter	    {
765990277Sobrien	      const char *arg;
766018334Speter
766118334Speter	      if (*q == '\0')
7662169704Skan		goto invalid_select;
766318334Speter
766418334Speter	      if (*q == '!')
766518334Speter		arg = NULL;
766618334Speter	      else
766718334Speter		arg = q;
766818334Speter
766918334Speter	      while (*q != ' ' && *q != ';')
767018334Speter		{
767118334Speter		  if (*q == '\0')
7672169704Skan		    goto invalid_select;
767318334Speter		  ++q;
767418334Speter		}
767518334Speter
767618334Speter	      if (arg != NULL
767718334Speter		  && default_arg (arg, q - arg))
767818334Speter		{
767918334Speter		  skip = 1;
768018334Speter		  break;
768118334Speter		}
768218334Speter
768318334Speter	      if (*q == ' ')
768418334Speter		++q;
768518334Speter	    }
768618334Speter	}
768718334Speter
768818334Speter      if (! skip)
768918334Speter	{
769090277Sobrien	  const char *p1;
769118334Speter
7692104763Skan	  for (p1 = last_path; p1 < p && *p1 != ':'; p1++)
769318334Speter	    putchar (*p1);
769418334Speter	  putchar (';');
769518334Speter	}
769618334Speter
769718334Speter      ++p;
769818334Speter      while (*p != ';')
769918334Speter	{
770018334Speter	  int use_arg;
770118334Speter
770218334Speter	  if (*p == '\0')
7703169704Skan	    goto invalid_select;
770418334Speter
770518334Speter	  if (skip)
770618334Speter	    {
770718334Speter	      ++p;
770818334Speter	      continue;
770918334Speter	    }
771018334Speter
771118334Speter	  use_arg = *p != '!';
771218334Speter
771318334Speter	  if (use_arg)
771418334Speter	    putchar ('@');
771518334Speter
771618334Speter	  while (*p != ' ' && *p != ';')
771718334Speter	    {
771818334Speter	      if (*p == '\0')
7719169704Skan		goto invalid_select;
772018334Speter	      if (use_arg)
772118334Speter		putchar (*p);
772218334Speter	      ++p;
772318334Speter	    }
772418334Speter
772518334Speter	  if (*p == ' ')
772618334Speter	    ++p;
772718334Speter	}
772818334Speter
772918334Speter      if (! skip)
773050599Sobrien	{
773190277Sobrien	  /* If there are extra options, print them now.  */
773250599Sobrien	  if (multilib_extra && *multilib_extra)
773350599Sobrien	    {
773450599Sobrien	      int print_at = TRUE;
773590277Sobrien	      const char *q;
773618334Speter
773750599Sobrien	      for (q = multilib_extra; *q != '\0'; q++)
773850599Sobrien		{
773950599Sobrien		  if (*q == ' ')
774050599Sobrien		    print_at = TRUE;
774150599Sobrien		  else
774250599Sobrien		    {
774350599Sobrien		      if (print_at)
774450599Sobrien			putchar ('@');
774550599Sobrien		      putchar (*q);
774650599Sobrien		      print_at = FALSE;
774750599Sobrien		    }
774850599Sobrien		}
774950599Sobrien	    }
775090277Sobrien
775150599Sobrien	  putchar ('\n');
775250599Sobrien	}
775350599Sobrien
775418334Speter      ++p;
775518334Speter    }
775618334Speter}
7757117413Skan
7758117413Skan/* if-exists built-in spec function.
7759117413Skan
7760117413Skan   Checks to see if the file specified by the absolute pathname in
7761117413Skan   ARGS exists.  Returns that pathname if found.
7762117413Skan
7763117413Skan   The usual use for this function is to check for a library file
7764117413Skan   (whose name has been expanded with %s).  */
7765117413Skan
7766117413Skanstatic const char *
7767132733Skanif_exists_spec_function (int argc, const char **argv)
7768117413Skan{
7769117413Skan  /* Must have only one argument.  */
7770132733Skan  if (argc == 1 && IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
7771117413Skan    return argv[0];
7772117413Skan
7773117413Skan  return NULL;
7774117413Skan}
7775117413Skan
7776117413Skan/* if-exists-else built-in spec function.
7777117413Skan
7778117413Skan   This is like if-exists, but takes an additional argument which
7779117413Skan   is returned if the first argument does not exist.  */
7780117413Skan
7781117413Skanstatic const char *
7782132733Skanif_exists_else_spec_function (int argc, const char **argv)
7783117413Skan{
7784117413Skan  /* Must have exactly two arguments.  */
7785117413Skan  if (argc != 2)
7786117413Skan    return NULL;
7787117413Skan
7788132733Skan  if (IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
7789117413Skan    return argv[0];
7790117413Skan
7791117413Skan  return argv[1];
7792117413Skan}
7793169704Skan
7794169704Skan/* replace-outfile built-in spec function.
7795169704Skan
7796169704Skan   This looks for the first argument in the outfiles array's name and
7797169704Skan   replaces it with the second argument.  */
7798169704Skan
7799169704Skanstatic const char *
7800169704Skanreplace_outfile_spec_function (int argc, const char **argv)
7801169704Skan{
7802169704Skan  int i;
7803169704Skan  /* Must have exactly two arguments.  */
7804169704Skan  if (argc != 2)
7805169704Skan    abort ();
7806169704Skan
7807169704Skan  for (i = 0; i < n_infiles; i++)
7808169704Skan    {
7809169704Skan      if (outfiles[i] && !strcmp (outfiles[i], argv[0]))
7810169704Skan	outfiles[i] = xstrdup (argv[1]);
7811169704Skan    }
7812169704Skan  return NULL;
7813169704Skan}
7814169704Skan
7815169704Skan/* Given two version numbers, compares the two numbers.
7816169704Skan   A version number must match the regular expression
7817169704Skan   ([1-9][0-9]*|0)(\.([1-9][0-9]*|0))*
7818169704Skan*/
7819169704Skanstatic int
7820169704Skancompare_version_strings (const char *v1, const char *v2)
7821169704Skan{
7822169704Skan  int rresult;
7823169704Skan  regex_t r;
7824169704Skan
7825169704Skan  if (regcomp (&r, "^([1-9][0-9]*|0)(\\.([1-9][0-9]*|0))*$",
7826169704Skan	       REG_EXTENDED | REG_NOSUB) != 0)
7827169704Skan    abort ();
7828169704Skan  rresult = regexec (&r, v1, 0, NULL, 0);
7829169704Skan  if (rresult == REG_NOMATCH)
7830169704Skan    fatal ("invalid version number `%s'", v1);
7831169704Skan  else if (rresult != 0)
7832169704Skan    abort ();
7833169704Skan  rresult = regexec (&r, v2, 0, NULL, 0);
7834169704Skan  if (rresult == REG_NOMATCH)
7835169704Skan    fatal ("invalid version number `%s'", v2);
7836169704Skan  else if (rresult != 0)
7837169704Skan    abort ();
7838169704Skan
7839169704Skan  return strverscmp (v1, v2);
7840169704Skan}
7841169704Skan
7842169704Skan
7843169704Skan/* version_compare built-in spec function.
7844169704Skan
7845169704Skan   This takes an argument of the following form:
7846169704Skan
7847169704Skan   <comparison-op> <arg1> [<arg2>] <switch> <result>
7848169704Skan
7849169704Skan   and produces "result" if the comparison evaluates to true,
7850169704Skan   and nothing if it doesn't.
7851169704Skan
7852169704Skan   The supported <comparison-op> values are:
7853169704Skan
7854169704Skan   >=  true if switch is a later (or same) version than arg1
7855169704Skan   !>  opposite of >=
7856169704Skan   <   true if switch is an earlier version than arg1
7857169704Skan   !<  opposite of <
7858169704Skan   ><  true if switch is arg1 or later, and earlier than arg2
7859169704Skan   <>  true if switch is earlier than arg1 or is arg2 or later
7860169704Skan
7861169704Skan   If the switch is not present, the condition is false unless
7862169704Skan   the first character of the <comparison-op> is '!'.
7863169704Skan
7864169704Skan   For example,
7865169704Skan   %:version-compare(>= 10.3 mmacosx-version-min= -lmx)
7866169704Skan   adds -lmx if -mmacosx-version-min=10.3.9 was passed.  */
7867169704Skan
7868169704Skanstatic const char *
7869169704Skanversion_compare_spec_function (int argc, const char **argv)
7870169704Skan{
7871169704Skan  int comp1, comp2;
7872169704Skan  size_t switch_len;
7873169704Skan  const char *switch_value = NULL;
7874169704Skan  int nargs = 1, i;
7875169704Skan  bool result;
7876169704Skan
7877169704Skan  if (argc < 3)
7878169704Skan    fatal ("too few arguments to %%:version-compare");
7879169704Skan  if (argv[0][0] == '\0')
7880169704Skan    abort ();
7881169704Skan  if ((argv[0][1] == '<' || argv[0][1] == '>') && argv[0][0] != '!')
7882169704Skan    nargs = 2;
7883169704Skan  if (argc != nargs + 3)
7884169704Skan    fatal ("too many arguments to %%:version-compare");
7885169704Skan
7886169704Skan  switch_len = strlen (argv[nargs + 1]);
7887169704Skan  for (i = 0; i < n_switches; i++)
7888169704Skan    if (!strncmp (switches[i].part1, argv[nargs + 1], switch_len)
7889169704Skan	&& check_live_switch (i, switch_len))
7890169704Skan      switch_value = switches[i].part1 + switch_len;
7891169704Skan
7892169704Skan  if (switch_value == NULL)
7893169704Skan    comp1 = comp2 = -1;
7894169704Skan  else
7895169704Skan    {
7896169704Skan      comp1 = compare_version_strings (switch_value, argv[1]);
7897169704Skan      if (nargs == 2)
7898169704Skan	comp2 = compare_version_strings (switch_value, argv[2]);
7899169704Skan      else
7900169704Skan	comp2 = -1;  /* This value unused.  */
7901169704Skan    }
7902169704Skan
7903169704Skan  switch (argv[0][0] << 8 | argv[0][1])
7904169704Skan    {
7905169704Skan    case '>' << 8 | '=':
7906169704Skan      result = comp1 >= 0;
7907169704Skan      break;
7908169704Skan    case '!' << 8 | '<':
7909169704Skan      result = comp1 >= 0 || switch_value == NULL;
7910169704Skan      break;
7911169704Skan    case '<' << 8:
7912169704Skan      result = comp1 < 0;
7913169704Skan      break;
7914169704Skan    case '!' << 8 | '>':
7915169704Skan      result = comp1 < 0 || switch_value == NULL;
7916169704Skan      break;
7917169704Skan    case '>' << 8 | '<':
7918169704Skan      result = comp1 >= 0 && comp2 < 0;
7919169704Skan      break;
7920169704Skan    case '<' << 8 | '>':
7921169704Skan      result = comp1 < 0 || comp2 >= 0;
7922169704Skan      break;
7923169704Skan
7924169704Skan    default:
7925169704Skan      fatal ("unknown operator '%s' in %%:version-compare", argv[0]);
7926169704Skan    }
7927169704Skan  if (! result)
7928169704Skan    return NULL;
7929169704Skan
7930169704Skan  return argv[nargs + 2];
7931169704Skan}
7932169704Skan
7933169704Skan/* %:include builtin spec function.  This differs from %include in that it
7934169704Skan   can be nested inside a spec, and thus be conditionalized.  It takes
7935169704Skan   one argument, the filename, and looks for it in the startfile path.
7936169704Skan   The result is always NULL, i.e. an empty expansion.  */
7937169704Skan
7938169704Skanstatic const char *
7939169704Skaninclude_spec_function (int argc, const char **argv)
7940169704Skan{
7941169704Skan  char *file;
7942169704Skan
7943169704Skan  if (argc != 1)
7944169704Skan    abort ();
7945169704Skan
7946169704Skan  file = find_a_file (&startfile_prefixes, argv[0], R_OK, 0);
7947169704Skan  read_specs (file ? file : argv[0], FALSE);
7948169704Skan
7949169704Skan  return NULL;
7950169704Skan}
7951