gcc.c revision 57849
118334Speter/* Compiler driver program that can handle many languages.
252520Sobrien   Copyright (C) 1987, 89, 92-98, 1999 Free Software Foundation, Inc.
318334Speter
418334SpeterThis file is part of GNU CC.
518334Speter
618334SpeterGNU CC is free software; you can redistribute it and/or modify
718334Speterit under the terms of the GNU General Public License as published by
818334Speterthe Free Software Foundation; either version 2, or (at your option)
918334Speterany later version.
1018334Speter
1118334SpeterGNU CC is distributed in the hope that it will be useful,
1218334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of
1318334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1418334SpeterGNU General Public License for more details.
1518334Speter
1618334SpeterYou should have received a copy of the GNU General Public License
1718334Speteralong with GNU CC; see the file COPYING.  If not, write to
1818334Speterthe Free Software Foundation, 59 Temple Place - Suite 330,
1918334SpeterBoston, MA 02111-1307, USA.
2018334Speter
2118334SpeterThis paragraph is here to try to keep Sun CC from dying.
2218334SpeterThe number of chars here seems crucial!!!!  */
2318334Speter
2451232Sbde/* $FreeBSD: head/contrib/gcc/gcc.c 57849 2000-03-09 10:11:08Z obrien $ */
2551232Sbde
2618334Speter/* This program is the user interface to the C compiler and possibly to
2718334Speterother compilers.  It is used because compilation is a complicated procedure
2818334Speterwhich involves running several programs and passing temporary files between
2918334Speterthem, forwarding the users switches to those programs selectively,
3018334Speterand deleting the temporary files at the end.
3118334Speter
3218334SpeterCC recognizes how to compile each input file by suffixes in the file names.
3318334SpeterOnce it knows which kind of compilation to perform, the procedure for
3418334Spetercompilation is specified by a string called a "spec".  */
3518334Speter
3650599Sobrien#include "config.h"
3750599Sobrien#include "system.h"
3850599Sobrien#include <signal.h>
3918334Speter
4050599Sobrien#include "obstack.h"
4152520Sobrien#include "intl.h"
4252520Sobrien#include "prefix.h"
4318334Speter
4450599Sobrien#ifdef VMS
4550599Sobrien#define exit __posix_exit
4618334Speter#endif
4718334Speter
4818334Speter/* By default there is no special suffix for executables.  */
4950599Sobrien#ifdef EXECUTABLE_SUFFIX
5050599Sobrien#define HAVE_EXECUTABLE_SUFFIX
5150599Sobrien#else
5218334Speter#define EXECUTABLE_SUFFIX ""
5318334Speter#endif
5418334Speter
5550599Sobrien/* By default, the suffix for object files is ".o".  */
5618334Speter#ifdef OBJECT_SUFFIX
5718334Speter#define HAVE_OBJECT_SUFFIX
5818334Speter#else
5918334Speter#define OBJECT_SUFFIX ".o"
6018334Speter#endif
6118334Speter
6218334Speter/* By default, colon separates directories in a path.  */
6318334Speter#ifndef PATH_SEPARATOR
6418334Speter#define PATH_SEPARATOR ':'
6518334Speter#endif
6618334Speter
6718334Speter#ifndef DIR_SEPARATOR
6818334Speter#define DIR_SEPARATOR '/'
6918334Speter#endif
7018334Speter
7152520Sobrien/* Define IS_DIR_SEPARATOR.  */
7252520Sobrien#ifndef DIR_SEPARATOR_2
7352520Sobrien# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
7452520Sobrien#else /* DIR_SEPARATOR_2 */
7552520Sobrien# define IS_DIR_SEPARATOR(ch) \
7652520Sobrien	(((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
7752520Sobrien#endif /* DIR_SEPARATOR_2 */
7852520Sobrien
7918334Speterstatic char dir_separator_str[] = {DIR_SEPARATOR, 0};
8018334Speter
8118334Speter#define obstack_chunk_alloc xmalloc
8218334Speter#define obstack_chunk_free free
8318334Speter
8452520Sobrien#ifndef GET_ENV_PATH_LIST
8552520Sobrien#define GET_ENV_PATH_LIST(VAR,NAME)	do { (VAR) = getenv (NAME); } while (0)
8618334Speter#endif
8718334Speter
8850599Sobrien#ifndef HAVE_KILL
8950599Sobrien#define kill(p,s) raise(s)
9018334Speter#endif
9118334Speter
9218334Speter/* If a stage of compilation returns an exit status >= 1,
9318334Speter   compilation of that file ceases.  */
9418334Speter
9518334Speter#define MIN_FATAL_STATUS 1
9618334Speter
9718334Speter/* Flag saying to print the directories gcc will search through looking for
9818334Speter   programs, libraries, etc.  */
9918334Speter
10018334Speterstatic int print_search_dirs;
10118334Speter
10218334Speter/* Flag saying to print the full filename of this file
10318334Speter   as found through our usual search mechanism.  */
10418334Speter
10552520Sobrienstatic const char *print_file_name = NULL;
10618334Speter
10750599Sobrien/* As print_file_name, but search for executable file.  */
10818334Speter
10952520Sobrienstatic const char *print_prog_name = NULL;
11018334Speter
11118334Speter/* Flag saying to print the relative path we'd use to
11218334Speter   find libgcc.a given the current compiler flags.  */
11318334Speter
11418334Speterstatic int print_multi_directory;
11518334Speter
11618334Speter/* Flag saying to print the list of subdirectories and
11718334Speter   compiler flags used to select them in a standard form.  */
11818334Speter
11918334Speterstatic int print_multi_lib;
12018334Speter
12150599Sobrien/* Flag saying to print the command line options understood by gcc and its
12250599Sobrien   sub-processes.  */
12350599Sobrien
12450599Sobrienstatic int print_help_list;
12550599Sobrien
12618334Speter/* Flag indicating whether we should print the command and arguments */
12718334Speter
12818334Speterstatic int verbose_flag;
12918334Speter
13018334Speter/* Nonzero means write "temp" files in source directory
13118334Speter   and use the source file's name in them, and don't delete them.  */
13218334Speter
13318334Speterstatic int save_temps_flag;
13418334Speter
13518334Speter/* The compiler version.  */
13618334Speter
13718334Speterstatic char *compiler_version;
13818334Speter
13918334Speter/* The target version specified with -V */
14018334Speter
14118334Speterstatic char *spec_version = DEFAULT_TARGET_VERSION;
14218334Speter
14318334Speter/* The target machine specified with -b.  */
14418334Speter
14552520Sobrienstatic const char *spec_machine = DEFAULT_TARGET_MACHINE;
14618334Speter
14718334Speter/* Nonzero if cross-compiling.
14818334Speter   When -b is used, the value comes from the `specs' file.  */
14918334Speter
15018334Speter#ifdef CROSS_COMPILE
15150599Sobrienstatic char *cross_compile = "1";
15218334Speter#else
15350599Sobrienstatic char *cross_compile = "0";
15418334Speter#endif
15518334Speter
15618334Speter/* The number of errors that have occurred; the link phase will not be
15718334Speter   run if this is non-zero.  */
15818334Speterstatic int error_count = 0;
15918334Speter
16018334Speter/* This is the obstack which we use to allocate many strings.  */
16118334Speter
16218334Speterstatic struct obstack obstack;
16318334Speter
16418334Speter/* This is the obstack to build an environment variable to pass to
16518334Speter   collect2 that describes all of the relevant switches of what to
16618334Speter   pass the compiler in building the list of pointers to constructors
16718334Speter   and destructors.  */
16818334Speter
16918334Speterstatic struct obstack collect_obstack;
17018334Speter
17118334Speterextern char *version_string;
17218334Speter
17318334Speter/* Forward declaration for prototypes.  */
17418334Speterstruct path_prefix;
17518334Speter
17650599Sobrienstatic void init_spec		PROTO((void));
17752520Sobrienstatic void read_specs		PROTO((const char *, int));
17852520Sobrienstatic void set_spec		PROTO((const char *, const char *));
17952520Sobrienstatic struct compiler *lookup_compiler PROTO((const char *, size_t, const char *));
18052520Sobrienstatic char *build_search_list	PROTO((struct path_prefix *, const char *, int));
18152520Sobrienstatic void putenv_from_prefixes PROTO((struct path_prefix *, const char *));
18252520Sobrienstatic char *find_a_file	PROTO((struct path_prefix *, const char *, int));
18352520Sobrienstatic void add_prefix		PROTO((struct path_prefix *, const char *,
18452520Sobrien				       const char *, int, int, int *));
18518334Speterstatic char *skip_whitespace	PROTO((char *));
18652520Sobrienstatic void record_temp_file	PROTO((const char *, int, int));
18752520Sobrienstatic void delete_if_ordinary	PROTO((const char *));
18818334Speterstatic void delete_temp_files	PROTO((void));
18918334Speterstatic void delete_failure_queue PROTO((void));
19018334Speterstatic void clear_failure_queue PROTO((void));
19118334Speterstatic int check_live_switch	PROTO((int, int));
19252520Sobrienstatic const char *handle_braces PROTO((const char *));
19352520Sobrienstatic char *save_string	PROTO((const char *, int));
19452520Sobrienextern int do_spec		PROTO((const char *));
19552520Sobrienstatic int do_spec_1		PROTO((const char *, int, const char *));
19652520Sobrienstatic const char *find_file	PROTO((const char *));
19752520Sobrienstatic int is_directory		PROTO((const char *, const char *, int));
19852520Sobrienstatic void validate_switches	PROTO((const char *));
19918334Speterstatic void validate_all_switches PROTO((void));
20050599Sobrienstatic void give_switch		PROTO((int, int, int));
20152520Sobrienstatic int used_arg		PROTO((const char *, int));
20252520Sobrienstatic int default_arg		PROTO((const char *, int));
20318334Speterstatic void set_multilib_dir	PROTO((void));
20418334Speterstatic void print_multilib_info	PROTO((void));
20552520Sobrienstatic void pfatal_with_name	PROTO((const char *)) ATTRIBUTE_NORETURN;
20652520Sobrienstatic void perror_with_name	PROTO((const char *));
20752520Sobrienstatic void pfatal_pexecute	PROTO((const char *, const char *))
20852520Sobrien  ATTRIBUTE_NORETURN;
20952520Sobrienstatic void error		PVPROTO((const char *, ...))
21052520Sobrien  ATTRIBUTE_PRINTF_1;
21152520Sobrienstatic void notice		PVPROTO((const char *, ...))
21252520Sobrien  ATTRIBUTE_PRINTF_1;
21350599Sobrienstatic void display_help 	PROTO((void));
21452520Sobrienstatic void add_preprocessor_option	PROTO ((const char *, int));
21552520Sobrienstatic void add_assembler_option	PROTO ((const char *, int));
21652520Sobrienstatic void add_linker_option		PROTO ((const char *, int));
21752520Sobrienstatic void process_command		PROTO ((int, char **));
21852520Sobrienstatic int execute			PROTO ((void));
21952520Sobrienstatic void unused_prefix_warnings	PROTO ((struct path_prefix *));
22052520Sobrienstatic void clear_args			PROTO ((void));
22152520Sobrienstatic void fatal_error			PROTO ((int));
22218334Speter
22352520Sobrienvoid fancy_abort		PROTO((void)) ATTRIBUTE_NORETURN;
22450599Sobrien
22550599Sobrien/* Called before processing to change/add/remove arguments. */
22652520Sobrienextern void lang_specific_driver PROTO ((void (*) PVPROTO((const char *, ...)),
22752520Sobrien					 int *, char ***, int *));
22850599Sobrien
22950599Sobrien/* Called before linking.  Returns 0 on success and -1 on failure. */
23050599Sobrienextern int lang_specific_pre_link ();
23150599Sobrien
23250599Sobrien/* Number of extra output files that lang_specific_pre_link may generate. */
23350599Sobrienextern int lang_specific_extra_outfiles;
23418334Speter
23518334Speter/* Specs are strings containing lines, each of which (if not blank)
23618334Speteris made up of a program name, and arguments separated by spaces.
23718334SpeterThe program name must be exact and start from root, since no path
23818334Speteris searched and it is unreliable to depend on the current working directory.
23918334SpeterRedirection of input or output is not supported; the subprograms must
24018334Speteraccept filenames saying what files to read and write.
24118334Speter
24218334SpeterIn addition, the specs can contain %-sequences to substitute variable text
24318334Speteror for conditional text.  Here is a table of all defined %-sequences.
24418334SpeterNote that spaces are not generated automatically around the results of
24518334Speterexpanding these sequences; therefore, you can concatenate them together
24618334Speteror with constant text in a single argument.
24718334Speter
24818334Speter %%	substitute one % into the program name or argument.
24918334Speter %i     substitute the name of the input file being processed.
25018334Speter %b     substitute the basename of the input file being processed.
25118334Speter	This is the substring up to (and not including) the last period
25218334Speter	and not including the directory.
25350599Sobrien %gSUFFIX
25450599Sobrien	substitute a file name that has suffix SUFFIX and is chosen
25550599Sobrien	once per compilation, and mark the argument a la %d.  To reduce
25650599Sobrien	exposure to denial-of-service attacks, the file name is now
25750599Sobrien	chosen in a way that is hard to predict even when previously
25850599Sobrien	chosen file names are known.  For example, `%g.s ... %g.o ... %g.s'
25950599Sobrien	might turn into `ccUVUUAU.s ccXYAXZ12.o ccUVUUAU.s'.  SUFFIX matches
26050599Sobrien	the regexp "[.A-Za-z]*" or the special string "%O", which is
26150599Sobrien	treated exactly as if %O had been pre-processed.  Previously, %g
26250599Sobrien	was simply substituted with a file name chosen once per compilation,
26350599Sobrien	without regard to any appended suffix (which was therefore treated
26450599Sobrien	just like ordinary text), making such attacks more likely to succeed.
26550599Sobrien %uSUFFIX
26650599Sobrien	like %g, but generates a new temporary file name even if %uSUFFIX
26750599Sobrien	was already seen.
26850599Sobrien %USUFFIX
26950599Sobrien	substitutes the last file name generated with %uSUFFIX, generating a
27050599Sobrien	new one if there is no such last file name.  In the absence of any
27150599Sobrien	%uSUFFIX, this is just like %gSUFFIX, except they don't share
27250599Sobrien	the same suffix "space", so `%g.s ... %U.s ... %g.s ... %U.s'
27350599Sobrien	would involve the generation of two distinct file names, one
27450599Sobrien	for each `%g.s' and another for each `%U.s'.  Previously, %U was
27550599Sobrien	simply substituted with a file name chosen for the previous %u,
27650599Sobrien	without regard to any appended suffix.
27718334Speter %d	marks the argument containing or following the %d as a
27818334Speter	temporary file name, so that that file will be deleted if CC exits
27918334Speter	successfully.  Unlike %g, this contributes no text to the argument.
28018334Speter %w	marks the argument containing or following the %w as the
28118334Speter	"output file" of this compilation.  This puts the argument
28218334Speter	into the sequence of arguments that %o will substitute later.
28318334Speter %W{...}
28418334Speter	like %{...} but mark last argument supplied within
28518334Speter	as a file to be deleted on failure.
28618334Speter %o	substitutes the names of all the output files, with spaces
28718334Speter	automatically placed around them.  You should write spaces
28818334Speter	around the %o as well or the results are undefined.
28918334Speter	%o is for use in the specs for running the linker.
29018334Speter	Input files whose names have no recognized suffix are not compiled
29118334Speter	at all, but they are included among the output files, so they will
29218334Speter	be linked.
29350599Sobrien %O	substitutes the suffix for object files.  Note that this is
29450599Sobrien	handled specially when it immediately follows %g, %u, or %U,
29550599Sobrien	because of the need for those to form complete file names.  The
29650599Sobrien	handling is such that %O is treated exactly as if it had already
29750599Sobrien	been substituted, except that %g, %u, and %U do not currently
29850599Sobrien	support additional SUFFIX characters following %O as they would
29950599Sobrien	following, for example, `.o'.
30018334Speter %p	substitutes the standard macro predefinitions for the
30118334Speter	current target machine.  Use this when running cpp.
30218334Speter %P	like %p, but puts `__' before and after the name of each macro.
30318334Speter	(Except macros that already have __.)
30418334Speter	This is for ANSI C.
30518334Speter %I	Substitute a -iprefix option made from GCC_EXEC_PREFIX.
30618334Speter %s     current argument is the name of a library or startup file of some sort.
30718334Speter        Search for that file in a standard list of directories
30818334Speter	and substitute the full name found.
30918334Speter %eSTR  Print STR as an error message.  STR is terminated by a newline.
31018334Speter        Use this when inconsistent options are detected.
31118334Speter %x{OPTION}	Accumulate an option for %X.
31218334Speter %X	Output the accumulated linker options specified by compilations.
31318334Speter %Y	Output the accumulated assembler options specified by compilations.
31418334Speter %Z	Output the accumulated preprocessor options specified by compilations.
31518334Speter %v1	Substitute the major version number of GCC.
31618334Speter	(For version 2.5.n, this is 2.)
31718334Speter %v2	Substitute the minor version number of GCC.
31818334Speter	(For version 2.5.n, this is 5.)
31918334Speter %a     process ASM_SPEC as a spec.
32018334Speter        This allows config.h to specify part of the spec for running as.
32118334Speter %A	process ASM_FINAL_SPEC as a spec.  A capital A is actually
32218334Speter	used here.  This can be used to run a post-processor after the
32350599Sobrien	assembler has done its job.
32418334Speter %D	Dump out a -L option for each directory in startfile_prefixes.
32518334Speter	If multilib_dir is set, extra entries are generated with it affixed.
32618334Speter %l     process LINK_SPEC as a spec.
32718334Speter %L     process LIB_SPEC as a spec.
32818334Speter %G     process LIBGCC_SPEC as a spec.
32918334Speter %S     process STARTFILE_SPEC as a spec.  A capital S is actually used here.
33018334Speter %E     process ENDFILE_SPEC as a spec.  A capital E is actually used here.
33118334Speter %c	process SIGNED_CHAR_SPEC as a spec.
33218334Speter %C     process CPP_SPEC as a spec.  A capital C is actually used here.
33318334Speter %1	process CC1_SPEC as a spec.
33418334Speter %2	process CC1PLUS_SPEC as a spec.
33518334Speter %|	output "-" if the input for the current command is coming from a pipe.
33618334Speter %*	substitute the variable part of a matched option.  (See below.)
33718334Speter	Note that each comma in the substituted string is replaced by
33818334Speter	a single space.
33918334Speter %{S}   substitutes the -S switch, if that switch was given to CC.
34018334Speter	If that switch was not specified, this substitutes nothing.
34118334Speter	Here S is a metasyntactic variable.
34218334Speter %{S*}  substitutes all the switches specified to CC whose names start
34318334Speter	with -S.  This is used for -o, -D, -I, etc; switches that take
34418334Speter	arguments.  CC considers `-o foo' as being one switch whose
34518334Speter	name starts with `o'.  %{o*} would substitute this text,
34618334Speter	including the space; thus, two arguments would be generated.
34750599Sobrien %{^S*} likewise, but don't put a blank between a switch and any args.
34818334Speter %{S*:X} substitutes X if one or more switches whose names start with -S are
34918334Speter	specified to CC.  Note that the tail part of the -S option
35018334Speter	(i.e. the part matched by the `*') will be substituted for each
35118334Speter	occurrence of %* within X.
35218334Speter %{S:X} substitutes X, but only if the -S switch was given to CC.
35318334Speter %{!S:X} substitutes X, but only if the -S switch was NOT given to CC.
35418334Speter %{|S:X} like %{S:X}, but if no S switch, substitute `-'.
35518334Speter %{|!S:X} like %{!S:X}, but if there is an S switch, substitute `-'.
35618334Speter %{.S:X} substitutes X, but only if processing a file with suffix S.
35718334Speter %{!.S:X} substitutes X, but only if NOT processing a file with suffix S.
35850599Sobrien %{S|P:X} substitutes X if either -S or -P was given to CC.  This may be
35950599Sobrien	  combined with ! and . as above binding stronger than the OR.
36018334Speter %(Spec) processes a specification defined in a specs file as *Spec:
36118334Speter %[Spec] as above, but put __ around -D arguments
36218334Speter
36318334SpeterThe conditional text X in a %{S:X} or %{!S:X} construct may contain
36418334Speterother nested % constructs or spaces, or even newlines.  They are
36518334Speterprocessed as usual, as described above.
36618334Speter
36718334SpeterThe -O, -f, -m, and -W switches are handled specifically in these
36818334Speterconstructs.  If another value of -O or the negated form of a -f, -m, or
36918334Speter-W switch is found later in the command line, the earlier switch
37018334Spetervalue is ignored, except with {S*} where S is just one letter; this
37118334Speterpasses all matching options.
37218334Speter
37350599SobrienThe character | at the beginning of the predicate text is used to indicate
37450599Sobrienthat a command should be piped to the following command, but only if -pipe
37550599Sobrienis specified.
37618334Speter
37718334SpeterNote that it is built into CC which switches take arguments and which
37818334Speterdo not.  You might think it would be useful to generalize this to
37918334Speterallow each compiler's spec to say which switches take arguments.  But
38018334Speterthis cannot be done in a consistent fashion.  CC cannot even decide
38118334Speterwhich input files have been specified without knowing which switches
38218334Spetertake arguments, and it must know which input files to compile in order
38318334Speterto tell which compilers to run.
38418334Speter
38518334SpeterCC also knows implicitly that arguments starting in `-l' are to be
38618334Spetertreated as compiler output files, and passed to the linker in their
38718334Speterproper position among the other output files.  */
38818334Speter
38918334Speter/* Define the macros used for specs %a, %l, %L, %S, %c, %C, %1.  */
39018334Speter
39118334Speter/* config.h can define ASM_SPEC to provide extra args to the assembler
39218334Speter   or extra switch-translations.  */
39318334Speter#ifndef ASM_SPEC
39418334Speter#define ASM_SPEC ""
39518334Speter#endif
39618334Speter
39718334Speter/* config.h can define ASM_FINAL_SPEC to run a post processor after
39818334Speter   the assembler has run.  */
39918334Speter#ifndef ASM_FINAL_SPEC
40018334Speter#define ASM_FINAL_SPEC ""
40118334Speter#endif
40218334Speter
40318334Speter/* config.h can define CPP_SPEC to provide extra args to the C preprocessor
40418334Speter   or extra switch-translations.  */
40518334Speter#ifndef CPP_SPEC
40618334Speter#define CPP_SPEC ""
40718334Speter#endif
40818334Speter
40918334Speter/* config.h can define CC1_SPEC to provide extra args to cc1 and cc1plus
41018334Speter   or extra switch-translations.  */
41118334Speter#ifndef CC1_SPEC
41218334Speter#define CC1_SPEC ""
41318334Speter#endif
41418334Speter
41518334Speter/* config.h can define CC1PLUS_SPEC to provide extra args to cc1plus
41618334Speter   or extra switch-translations.  */
41718334Speter#ifndef CC1PLUS_SPEC
41818334Speter#define CC1PLUS_SPEC ""
41918334Speter#endif
42018334Speter
42118334Speter/* config.h can define LINK_SPEC to provide extra args to the linker
42218334Speter   or extra switch-translations.  */
42318334Speter#ifndef LINK_SPEC
42418334Speter#define LINK_SPEC ""
42518334Speter#endif
42618334Speter
42718334Speter/* config.h can define LIB_SPEC to override the default libraries.  */
42818334Speter#ifndef LIB_SPEC
42918334Speter#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
43018334Speter#endif
43118334Speter
43218334Speter/* config.h can define LIBGCC_SPEC to override how and when libgcc.a is
43318334Speter   included.  */
43418334Speter#ifndef LIBGCC_SPEC
43518334Speter#if defined(LINK_LIBGCC_SPECIAL) || defined(LINK_LIBGCC_SPECIAL_1)
43618334Speter/* Have gcc do the search for libgcc.a.  */
43750599Sobrien#define LIBGCC_SPEC "libgcc.a%s"
43818334Speter#else
43950599Sobrien#define LIBGCC_SPEC "-lgcc"
44018334Speter#endif
44118334Speter#endif
44218334Speter
44318334Speter/* config.h can define STARTFILE_SPEC to override the default crt0 files.  */
44418334Speter#ifndef STARTFILE_SPEC
44518334Speter#define STARTFILE_SPEC  \
44618334Speter  "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}"
44718334Speter#endif
44818334Speter
44950599Sobrien/* config.h can define SWITCHES_NEED_SPACES to control which options
45050599Sobrien   require spaces between the option and the argument.  */
45118334Speter#ifndef SWITCHES_NEED_SPACES
45218334Speter#define SWITCHES_NEED_SPACES ""
45318334Speter#endif
45418334Speter
45518334Speter/* config.h can define ENDFILE_SPEC to override the default crtn files.  */
45618334Speter#ifndef ENDFILE_SPEC
45718334Speter#define ENDFILE_SPEC ""
45818334Speter#endif
45918334Speter
46018334Speter/* This spec is used for telling cpp whether char is signed or not.  */
46118334Speter#ifndef SIGNED_CHAR_SPEC
46218334Speter/* Use #if rather than ?:
46318334Speter   because MIPS C compiler rejects like ?: in initializers.  */
46418334Speter#if DEFAULT_SIGNED_CHAR
46518334Speter#define SIGNED_CHAR_SPEC "%{funsigned-char:-D__CHAR_UNSIGNED__}"
46618334Speter#else
46718334Speter#define SIGNED_CHAR_SPEC "%{!fsigned-char:-D__CHAR_UNSIGNED__}"
46818334Speter#endif
46918334Speter#endif
47018334Speter
47150599Sobrien#ifndef LINKER_NAME
47250599Sobrien#define LINKER_NAME "collect2"
47318334Speter#endif
47418334Speter
47518334Speterstatic char *cpp_spec = CPP_SPEC;
47618334Speterstatic char *cpp_predefines = CPP_PREDEFINES;
47718334Speterstatic char *cc1_spec = CC1_SPEC;
47818334Speterstatic char *cc1plus_spec = CC1PLUS_SPEC;
47918334Speterstatic char *signed_char_spec = SIGNED_CHAR_SPEC;
48018334Speterstatic char *asm_spec = ASM_SPEC;
48118334Speterstatic char *asm_final_spec = ASM_FINAL_SPEC;
48218334Speterstatic char *link_spec = LINK_SPEC;
48318334Speterstatic char *lib_spec = LIB_SPEC;
48418334Speterstatic char *libgcc_spec = LIBGCC_SPEC;
48518334Speterstatic char *endfile_spec = ENDFILE_SPEC;
48618334Speterstatic char *startfile_spec = STARTFILE_SPEC;
48718334Speterstatic char *switches_need_spaces = SWITCHES_NEED_SPACES;
48850599Sobrienstatic char *linker_name_spec = LINKER_NAME;
48918334Speter
49050599Sobrien/* Some compilers have limits on line lengths, and the multilib_select
49150599Sobrien   and/or multilib_matches strings can be very long, so we build them at
49250599Sobrien   run time.  */
49350599Sobrienstatic struct obstack multilib_obstack;
49450599Sobrienstatic char *multilib_select;
49550599Sobrienstatic char *multilib_matches;
49650599Sobrienstatic char *multilib_defaults;
49750599Sobrien#include "multilib.h"
49850599Sobrien
49950599Sobrien/* Check whether a particular argument is a default argument.  */
50050599Sobrien
50150599Sobrien#ifndef MULTILIB_DEFAULTS
50250599Sobrien#define MULTILIB_DEFAULTS { "" }
50350599Sobrien#endif
50450599Sobrien
50550599Sobrienstatic char *multilib_defaults_raw[] = MULTILIB_DEFAULTS;
50650599Sobrien
50750599Sobrienstruct user_specs {
50850599Sobrien  struct user_specs *next;
50952520Sobrien  const char *filename;
51050599Sobrien};
51150599Sobrien
51250599Sobrienstatic struct user_specs *user_specs_head, *user_specs_tail;
51350599Sobrien
51418334Speter/* This defines which switch letters take arguments.  */
51518334Speter
51650599Sobrien#define DEFAULT_SWITCH_TAKES_ARG(CHAR) \
51718334Speter  ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
51818334Speter   || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
51918334Speter   || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \
52050599Sobrien   || (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'V' \
52150599Sobrien   || (CHAR) == 'B' || (CHAR) == 'b')
52250599Sobrien
52350599Sobrien#ifndef SWITCH_TAKES_ARG
52450599Sobrien#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
52518334Speter#endif
52618334Speter
52718334Speter/* This defines which multi-letter switches take arguments.  */
52818334Speter
52918334Speter#define DEFAULT_WORD_SWITCH_TAKES_ARG(STR)		\
53018334Speter (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext")	\
53118334Speter  || !strcmp (STR, "Tbss") || !strcmp (STR, "include")	\
53218334Speter  || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \
53318334Speter  || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \
53418334Speter  || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \
53550599Sobrien  || !strcmp (STR, "isystem") || !strcmp (STR, "specs"))
53618334Speter
53718334Speter#ifndef WORD_SWITCH_TAKES_ARG
53818334Speter#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
53918334Speter#endif
54018334Speter
54150599Sobrien
54250599Sobrien#ifdef HAVE_EXECUTABLE_SUFFIX
54350599Sobrien/* This defines which switches stop a full compilation.  */
54450599Sobrien#define DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) \
54550599Sobrien  ((CHAR) == 'c' || (CHAR) == 'S')
54650599Sobrien
54750599Sobrien#ifndef SWITCH_CURTAILS_COMPILATION
54850599Sobrien#define SWITCH_CURTAILS_COMPILATION(CHAR) \
54950599Sobrien  DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR)
55050599Sobrien#endif
55150599Sobrien#endif
55250599Sobrien
55318334Speter/* Record the mapping from file suffixes for compilation specs.  */
55418334Speter
55518334Speterstruct compiler
55618334Speter{
55752520Sobrien  const char *suffix;		/* Use this compiler for input files
55818334Speter				   whose names end in this suffix.  */
55918334Speter
56052520Sobrien  const char *spec[4];		/* To use this compiler, concatenate these
56118334Speter				   specs and pass to do_spec.  */
56218334Speter};
56318334Speter
56418334Speter/* Pointer to a vector of `struct compiler' that gives the spec for
56518334Speter   compiling a file, based on its suffix.
56618334Speter   A file that does not end in any of these suffixes will be passed
56718334Speter   unchanged to the loader and nothing else will be done to it.
56818334Speter
56918334Speter   An entry containing two 0s is used to terminate the vector.
57018334Speter
57118334Speter   If multiple entries match a file, the last matching one is used.  */
57218334Speter
57318334Speterstatic struct compiler *compilers;
57418334Speter
57518334Speter/* Number of entries in `compilers', not counting the null terminator.  */
57618334Speter
57718334Speterstatic int n_compilers;
57818334Speter
57918334Speter/* The default list of file name suffixes and their compilation specs.  */
58018334Speter
58118334Speterstatic struct compiler default_compilers[] =
58218334Speter{
58350599Sobrien  /* Add lists of suffixes of known languages here.  If those languages
58450599Sobrien     were not present when we built the driver, we will hit these copies
58550599Sobrien     and be given a more meaningful error than "file not used since
58650599Sobrien     linking is not done".  */
58752520Sobrien  {".m", {"#Objective-C"}},
58852520Sobrien  {".cc", {"#C++"}}, {".cxx", {"#C++"}}, {".cpp", {"#C++"}},
58952520Sobrien  {".c++", {"#C++"}}, {".C", {"#C++"}},
59052520Sobrien  {".ads", {"#Ada"}}, {".adb", {"#Ada"}}, {".ada", {"#Ada"}},
59150599Sobrien  {".f", {"#Fortran"}}, {".for", {"#Fortran"}}, {".F", {"#Fortran"}},
59250599Sobrien  {".fpp", {"#Fortran"}},
59350599Sobrien  {".p", {"#Pascal"}}, {".pas", {"#Pascal"}},
59450599Sobrien  /* Next come the entries for C.  */
59550599Sobrien  {".c", {"@c"}},
59618334Speter  {"@c",
59750599Sobrien   {
59850599Sobrien#if USE_CPPLIB
59952520Sobrien     "%{E|M|MM:cpp -lang-c %{ansi:-std=c89} %{std*} %{nostdinc*}\
60052520Sobrien	%{C} %{v} %{A*} %{I*} %{P} %{$} %I\
60118334Speter	%{C:%{!E:%eGNU C does not support -C without using -E}}\
60218334Speter	%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
60352520Sobrien        %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
60452520Sobrien	%{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
60552520Sobrien	%{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
60650599Sobrien        %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
60752520Sobrien	%{ffast-math:-D__FAST_MATH__}\
60850599Sobrien        %{traditional} %{ftraditional:-traditional}\
60918334Speter        %{traditional-cpp:-traditional}\
61052520Sobrien	%{fleading-underscore} %{fno-leading-underscore}\
61118334Speter	%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
61250599Sobrien        %i %{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}}\n}\
61350599Sobrien      %{!E:%{!M:%{!MM:cc1 %i %1 \
61452520Sobrien                  %{std*} %{nostdinc*} %{A*} %{I*} %I\
61550599Sobrien                  %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
61650599Sobrien                  %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
61752520Sobrien                  %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
61852520Sobrien		  %{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
61952520Sobrien		  %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
62050599Sobrien                  %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
62152520Sobrien		  %{ffast-math:-D__FAST_MATH__}\
62250599Sobrien                  %{H} %C %{D*} %{U*} %{i*} %Z\
62350599Sobrien                  %{ftraditional:-traditional}\
62450599Sobrien                  %{traditional-cpp:-traditional}\
62550599Sobrien		  %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
62652520Sobrien		  %{aux-info*} %{Qn:-fno-ident}\
62752520Sobrien		  %{--help:--help}\
62852520Sobrien		  %{g*} %{O*} %{W*} %{w} %{pedantic*}\
62950599Sobrien		  %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
63050599Sobrien		  %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
63150599Sobrien                  %{!S:as %a %Y\
63250599Sobrien		     %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
63350599Sobrien                     %{!pipe:%g.s} %A\n }}}}"
63450599Sobrien#else /* ! USE_CPPLIB */
63552520Sobrien    "cpp -lang-c %{ansi:-std=c89} %{std*} %{nostdinc*}\
63652520Sobrien	%{C} %{v} %{A*} %{I*} %{P} %{$} %I\
63750599Sobrien	%{C:%{!E:%eGNU C does not support -C without using -E}}\
63850599Sobrien	%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
63952520Sobrien        %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
64052520Sobrien	%{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
64152520Sobrien	%{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
64250599Sobrien        %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
64352520Sobrien	%{ffast-math:-D__FAST_MATH__}\
64450599Sobrien        %{traditional} %{ftraditional:-traditional}\
64550599Sobrien        %{traditional-cpp:-traditional}\
64652520Sobrien	%{fleading-underscore} %{fno-leading-underscore}\
64750599Sobrien	%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
64818334Speter        %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
64918334Speter   "%{!M:%{!MM:%{!E:cc1 %{!pipe:%g.i} %1 \
65050599Sobrien		   %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
65152520Sobrien		   %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*}\
65218334Speter		   %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
65352520Sobrien		   %{aux-info*} %{Qn:-fno-ident}\
65450599Sobrien		   %{--help:--help} \
65518334Speter		   %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
65618334Speter		   %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
65718334Speter              %{!S:as %a %Y\
65818334Speter		      %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
65950599Sobrien                      %{!pipe:%g.s} %A\n }}}}"
66052520Sobrien#endif /* ! USE_CPPLIB */
66150599Sobrien  }},
66218334Speter  {"-",
66352520Sobrien   {"%{E:cpp -lang-c %{ansi:-std=c89} %{std*} %{nostdinc*}\
66452520Sobrien	%{C} %{v} %{A*} %{I*} %{P} %{$} %I\
66518334Speter	%{C:%{!E:%eGNU C does not support -C without using -E}}\
66618334Speter	%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
66752520Sobrien        %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
66852520Sobrien	%{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
66952520Sobrien	%{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
67050599Sobrien        %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
67152520Sobrien	%{ffast-math:-D__FAST_MATH__}\
67250599Sobrien        %{traditional} %{ftraditional:-traditional}\
67318334Speter        %{traditional-cpp:-traditional}\
67452520Sobrien	%{fleading-underscore} %{fno-leading-underscore}\
67518334Speter	%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
67618334Speter        %i %W{o*}}\
67750599Sobrien    %{!E:%e-E required when input is from standard input}"}},
67850599Sobrien  {".h", {"@c-header"}},
67918334Speter  {"@c-header",
68050599Sobrien   {"%{!E:%eCompilation of header file requested} \
68152520Sobrien    cpp %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
68218334Speter	%{C:%{!E:%eGNU C does not support -C without using -E}}\
68352520Sobrien	%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
68452520Sobrien        %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
68552520Sobrien	%{std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
68652520Sobrien	%{!undef:%{!std=*:%p}%{std=gnu*:%p} %P} %{trigraphs}\
68750599Sobrien        %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
68852520Sobrien	%{ffast-math:-D__FAST_MATH__}\
68950599Sobrien        %{traditional} %{ftraditional:-traditional}\
69018334Speter        %{traditional-cpp:-traditional}\
69152520Sobrien	%{fleading-underscore} %{fno-leading-underscore}\
69218334Speter	%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
69350599Sobrien        %i %W{o*}"}},
69450599Sobrien  {".i", {"@cpp-output"}},
69518334Speter  {"@cpp-output",
69650599Sobrien   {"%{!M:%{!MM:%{!E:cc1 %i %1 %{!Q:-quiet} %{d*} %{m*} %{a*}\
69752520Sobrien			%{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*}\
69818334Speter			%{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
69952520Sobrien			%{aux-info*} %{Qn:-fno-ident}\
70018334Speter			%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
70118334Speter			%{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
70218334Speter		     %{!S:as %a %Y\
70318334Speter			     %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
70450599Sobrien			     %{!pipe:%g.s} %A\n }}}}"}},
70550599Sobrien  {".s", {"@assembler"}},
70618334Speter  {"@assembler",
70750599Sobrien   {"%{!M:%{!MM:%{!E:%{!S:as %a %Y\
70818334Speter		            %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
70950599Sobrien			    %i %A\n }}}}"}},
71050599Sobrien  {".S", {"@assembler-with-cpp"}},
71118334Speter  {"@assembler-with-cpp",
71252520Sobrien   {"cpp -lang-asm %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
71318334Speter	%{C:%{!E:%eGNU C does not support -C without using -E}}\
71418334Speter	%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG} %{trigraphs}\
71552520Sobrien        -$ %{!undef:%p %P} -D__ASSEMBLER__ \
71650599Sobrien        %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
71752520Sobrien	%{ffast-math:-D__FAST_MATH__}\
71850599Sobrien        %{traditional} %{ftraditional:-traditional}\
71918334Speter        %{traditional-cpp:-traditional}\
72052520Sobrien	%{fleading-underscore} %{fno-leading-underscore}\
72118334Speter	%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
72218334Speter        %i %{!M:%{!MM:%{!E:%{!pipe:%g.s}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
72350599Sobrien    "%{!M:%{!MM:%{!E:%{!S:as %a %Y\
72418334Speter                    %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
72550599Sobrien		    %{!pipe:%g.s} %A\n }}}}"}},
72618334Speter#include "specs.h"
72718334Speter  /* Mark end of table */
72850599Sobrien  {0, {0}}
72918334Speter};
73018334Speter
73118334Speter/* Number of elements in default_compilers, not counting the terminator.  */
73218334Speter
73318334Speterstatic int n_default_compilers
73418334Speter  = (sizeof default_compilers / sizeof (struct compiler)) - 1;
73518334Speter
73618334Speter/* Here is the spec for running the linker, after compiling all files.  */
73718334Speter
73818334Speter/* -u* was put back because both BSD and SysV seem to support it.  */
73918334Speter/* %{static:} simply prevents an error message if the target machine
74018334Speter   doesn't handle -static.  */
74118334Speter/* We want %{T*} after %{L*} and %D so that it can be used to specify linker
74218334Speter   scripts which exist in user specified directories, or in standard
74318334Speter   directories.  */
74450599Sobrien#ifdef LINK_COMMAND_SPEC
74550599Sobrien/* Provide option to override link_command_spec from machine specific
74650599Sobrien   configuration files.  */
74752520Sobrienstatic const char *link_command_spec =
74850599Sobrien	LINK_COMMAND_SPEC;
74950599Sobrien#else
75018334Speter#ifdef LINK_LIBGCC_SPECIAL
75118334Speter/* Don't generate -L options.  */
75252520Sobrienstatic const char *link_command_spec = "\
75318334Speter%{!fsyntax-only: \
75450599Sobrien %{!c:%{!M:%{!MM:%{!E:%{!S:%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
75518334Speter			%{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
75618334Speter			%{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
75750599Sobrien			%{static:} %{L*} %o\
75818334Speter			%{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
75950599Sobrien			%{!A:%{!nostdlib:%{!nostartfiles:%E}}}\
76050599Sobrien			%{T*}\
76150599Sobrien			\n }}}}}}";
76218334Speter#else
76318334Speter/* Use -L.  */
76452520Sobrienstatic const char *link_command_spec = "\
76518334Speter%{!fsyntax-only: \
76650599Sobrien %{!c:%{!M:%{!MM:%{!E:%{!S:%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
76718334Speter			%{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
76818334Speter			%{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
76950599Sobrien			%{static:} %{L*} %D %o\
77018334Speter			%{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
77150599Sobrien			%{!A:%{!nostdlib:%{!nostartfiles:%E}}}\
77250599Sobrien			%{T*}\
77350599Sobrien			\n }}}}}}";
77418334Speter#endif
77550599Sobrien#endif
77618334Speter
77718334Speter/* A vector of options to give to the linker.
77818334Speter   These options are accumulated by %x,
77918334Speter   and substituted into the linker command with %X.  */
78018334Speterstatic int n_linker_options;
78118334Speterstatic char **linker_options;
78218334Speter
78318334Speter/* A vector of options to give to the assembler.
78418334Speter   These options are accumulated by -Wa,
78518334Speter   and substituted into the assembler command with %Y.  */
78618334Speterstatic int n_assembler_options;
78718334Speterstatic char **assembler_options;
78818334Speter
78918334Speter/* A vector of options to give to the preprocessor.
79018334Speter   These options are accumulated by -Wp,
79118334Speter   and substituted into the preprocessor command with %Z.  */
79218334Speterstatic int n_preprocessor_options;
79318334Speterstatic char **preprocessor_options;
79418334Speter
79518334Speter/* Define how to map long options into short ones.  */
79618334Speter
79718334Speter/* This structure describes one mapping.  */
79818334Speterstruct option_map
79918334Speter{
80018334Speter  /* The long option's name.  */
80152520Sobrien  const char *name;
80218334Speter  /* The equivalent short option.  */
80352520Sobrien  const char *equivalent;
80418334Speter  /* Argument info.  A string of flag chars; NULL equals no options.
80518334Speter     a => argument required.
80618334Speter     o => argument optional.
80718334Speter     j => join argument to equivalent, making one word.
80818334Speter     * => require other text after NAME as an argument.  */
80952520Sobrien  const char *arg_info;
81018334Speter};
81118334Speter
81218334Speter/* This is the table of mappings.  Mappings are tried sequentially
81318334Speter   for each option encountered; the first one that matches, wins.  */
81418334Speter
81518334Speterstruct option_map option_map[] =
81618334Speter {
81718334Speter   {"--all-warnings", "-Wall", 0},
81818334Speter   {"--ansi", "-ansi", 0},
81918334Speter   {"--assemble", "-S", 0},
82018334Speter   {"--assert", "-A", "a"},
82152520Sobrien   {"--classpath", "-fclasspath=", "aj"},
82252520Sobrien   {"--CLASSPATH", "-fCLASSPATH=", "aj"},
82318334Speter   {"--comments", "-C", 0},
82418334Speter   {"--compile", "-c", 0},
82518334Speter   {"--debug", "-g", "oj"},
82650599Sobrien   {"--define-macro", "-D", "aj"},
82718334Speter   {"--dependencies", "-M", 0},
82818334Speter   {"--dump", "-d", "a"},
82918334Speter   {"--dumpbase", "-dumpbase", "a"},
83018334Speter   {"--entry", "-e", 0},
83118334Speter   {"--extra-warnings", "-W", 0},
83218334Speter   {"--for-assembler", "-Wa", "a"},
83318334Speter   {"--for-linker", "-Xlinker", "a"},
83418334Speter   {"--force-link", "-u", "a"},
83518334Speter   {"--imacros", "-imacros", "a"},
83618334Speter   {"--include", "-include", "a"},
83718334Speter   {"--include-barrier", "-I-", 0},
83850599Sobrien   {"--include-directory", "-I", "aj"},
83918334Speter   {"--include-directory-after", "-idirafter", "a"},
84018334Speter   {"--include-prefix", "-iprefix", "a"},
84118334Speter   {"--include-with-prefix", "-iwithprefix", "a"},
84218334Speter   {"--include-with-prefix-before", "-iwithprefixbefore", "a"},
84318334Speter   {"--include-with-prefix-after", "-iwithprefix", "a"},
84418334Speter   {"--language", "-x", "a"},
84518334Speter   {"--library-directory", "-L", "a"},
84618334Speter   {"--machine", "-m", "aj"},
84718334Speter   {"--machine-", "-m", "*j"},
84818334Speter   {"--no-line-commands", "-P", 0},
84918334Speter   {"--no-precompiled-includes", "-noprecomp", 0},
85018334Speter   {"--no-standard-includes", "-nostdinc", 0},
85118334Speter   {"--no-standard-libraries", "-nostdlib", 0},
85218334Speter   {"--no-warnings", "-w", 0},
85318334Speter   {"--optimize", "-O", "oj"},
85418334Speter   {"--output", "-o", "a"},
85552520Sobrien   {"--output-class-directory", "-foutput-class-dir=", "ja"},
85618334Speter   {"--pedantic", "-pedantic", 0},
85718334Speter   {"--pedantic-errors", "-pedantic-errors", 0},
85818334Speter   {"--pipe", "-pipe", 0},
85918334Speter   {"--prefix", "-B", "a"},
86018334Speter   {"--preprocess", "-E", 0},
86118334Speter   {"--print-search-dirs", "-print-search-dirs", 0},
86218334Speter   {"--print-file-name", "-print-file-name=", "aj"},
86318334Speter   {"--print-libgcc-file-name", "-print-libgcc-file-name", 0},
86418334Speter   {"--print-missing-file-dependencies", "-MG", 0},
86518334Speter   {"--print-multi-lib", "-print-multi-lib", 0},
86618334Speter   {"--print-multi-directory", "-print-multi-directory", 0},
86718334Speter   {"--print-prog-name", "-print-prog-name=", "aj"},
86818334Speter   {"--profile", "-p", 0},
86918334Speter   {"--profile-blocks", "-a", 0},
87018334Speter   {"--quiet", "-q", 0},
87118334Speter   {"--save-temps", "-save-temps", 0},
87218334Speter   {"--shared", "-shared", 0},
87318334Speter   {"--silent", "-q", 0},
87450599Sobrien   {"--specs", "-specs=", "aj"},
87518334Speter   {"--static", "-static", 0},
87652520Sobrien   {"--std", "-std=", "aj"},
87718334Speter   {"--symbolic", "-symbolic", 0},
87818334Speter   {"--target", "-b", "a"},
87918334Speter   {"--trace-includes", "-H", 0},
88018334Speter   {"--traditional", "-traditional", 0},
88118334Speter   {"--traditional-cpp", "-traditional-cpp", 0},
88218334Speter   {"--trigraphs", "-trigraphs", 0},
88350599Sobrien   {"--undefine-macro", "-U", "aj"},
88418334Speter   {"--use-version", "-V", "a"},
88518334Speter   {"--user-dependencies", "-MM", 0},
88618334Speter   {"--verbose", "-v", 0},
88718334Speter   {"--version", "-dumpversion", 0},
88818334Speter   {"--warn-", "-W", "*j"},
88918334Speter   {"--write-dependencies", "-MD", 0},
89018334Speter   {"--write-user-dependencies", "-MMD", 0},
89118334Speter   {"--", "-f", "*j"}
89218334Speter };
89318334Speter
89418334Speter/* Translate the options described by *ARGCP and *ARGVP.
89518334Speter   Make a new vector and store it back in *ARGVP,
89618334Speter   and store its length in *ARGVC.  */
89718334Speter
89818334Speterstatic void
89918334Spetertranslate_options (argcp, argvp)
90018334Speter     int *argcp;
90152520Sobrien     const char ***argvp;
90218334Speter{
90352520Sobrien  int i;
90418334Speter  int argc = *argcp;
90552520Sobrien  const char **argv = *argvp;
90652520Sobrien  const char **newv =
90752520Sobrien    (const char **) xmalloc ((argc + 2) * 2 * sizeof (const char *));
90818334Speter  int newindex = 0;
90918334Speter
91018334Speter  i = 0;
91118334Speter  newv[newindex++] = argv[i++];
91218334Speter
91318334Speter  while (i < argc)
91418334Speter    {
91518334Speter      /* Translate -- options.  */
91618334Speter      if (argv[i][0] == '-' && argv[i][1] == '-')
91718334Speter	{
91852520Sobrien	  size_t j;
91918334Speter	  /* Find a mapping that applies to this option.  */
92018334Speter	  for (j = 0; j < sizeof (option_map) / sizeof (option_map[0]); j++)
92118334Speter	    {
92250599Sobrien	      size_t optlen = strlen (option_map[j].name);
92350599Sobrien	      size_t arglen = strlen (argv[i]);
92450599Sobrien	      size_t complen = arglen > optlen ? optlen : arglen;
92552520Sobrien	      const char *arginfo = option_map[j].arg_info;
92618334Speter
92718334Speter	      if (arginfo == 0)
92818334Speter		arginfo = "";
92918334Speter
93018334Speter	      if (!strncmp (argv[i], option_map[j].name, complen))
93118334Speter		{
93252520Sobrien		  const char *arg = 0;
93318334Speter
93418334Speter		  if (arglen < optlen)
93518334Speter		    {
93652520Sobrien		      size_t k;
93718334Speter		      for (k = j + 1;
93818334Speter			   k < sizeof (option_map) / sizeof (option_map[0]);
93918334Speter			   k++)
94018334Speter			if (strlen (option_map[k].name) >= arglen
94118334Speter			    && !strncmp (argv[i], option_map[k].name, arglen))
94218334Speter			  {
94318334Speter			    error ("Ambiguous abbreviation %s", argv[i]);
94418334Speter			    break;
94518334Speter			  }
94618334Speter
94718334Speter		      if (k != sizeof (option_map) / sizeof (option_map[0]))
94818334Speter			break;
94918334Speter		    }
95018334Speter
95118334Speter		  if (arglen > optlen)
95218334Speter		    {
95318334Speter		      /* If the option has an argument, accept that.  */
95418334Speter		      if (argv[i][optlen] == '=')
95518334Speter			arg = argv[i] + optlen + 1;
95618334Speter
95718334Speter		      /* If this mapping requires extra text at end of name,
95818334Speter			 accept that as "argument".  */
95918334Speter		      else if (index (arginfo, '*') != 0)
96018334Speter			arg = argv[i] + optlen;
96118334Speter
96218334Speter		      /* Otherwise, extra text at end means mismatch.
96318334Speter			 Try other mappings.  */
96418334Speter		      else
96518334Speter			continue;
96618334Speter		    }
96718334Speter
96818334Speter		  else if (index (arginfo, '*') != 0)
96918334Speter		    {
97018334Speter		      error ("Incomplete `%s' option", option_map[j].name);
97118334Speter		      break;
97218334Speter		    }
97318334Speter
97418334Speter		  /* Handle arguments.  */
97518334Speter		  if (index (arginfo, 'a') != 0)
97618334Speter		    {
97718334Speter		      if (arg == 0)
97818334Speter			{
97918334Speter			  if (i + 1 == argc)
98018334Speter			    {
98118334Speter			      error ("Missing argument to `%s' option",
98218334Speter				     option_map[j].name);
98318334Speter			      break;
98418334Speter			    }
98518334Speter
98618334Speter			  arg = argv[++i];
98718334Speter			}
98818334Speter		    }
98918334Speter		  else if (index (arginfo, '*') != 0)
99018334Speter		    ;
99118334Speter		  else if (index (arginfo, 'o') == 0)
99218334Speter		    {
99318334Speter		      if (arg != 0)
99418334Speter			error ("Extraneous argument to `%s' option",
99518334Speter			       option_map[j].name);
99618334Speter		      arg = 0;
99718334Speter		    }
99818334Speter
99918334Speter		  /* Store the translation as one argv elt or as two.  */
100018334Speter		  if (arg != 0 && index (arginfo, 'j') != 0)
100150599Sobrien		    newv[newindex++] = concat (option_map[j].equivalent, arg,
100250599Sobrien					       NULL_PTR);
100318334Speter		  else if (arg != 0)
100418334Speter		    {
100518334Speter		      newv[newindex++] = option_map[j].equivalent;
100618334Speter		      newv[newindex++] = arg;
100718334Speter		    }
100818334Speter		  else
100918334Speter		    newv[newindex++] = option_map[j].equivalent;
101018334Speter
101118334Speter		  break;
101218334Speter		}
101318334Speter	    }
101418334Speter	  i++;
101518334Speter	}
101618334Speter
101718334Speter      /* Handle old-fashioned options--just copy them through,
101818334Speter	 with their arguments.  */
101918334Speter      else if (argv[i][0] == '-')
102018334Speter	{
102152520Sobrien	  const char *p = argv[i] + 1;
102218334Speter	  int c = *p;
102318334Speter	  int nskip = 1;
102418334Speter
102518334Speter	  if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
102618334Speter	    nskip += SWITCH_TAKES_ARG (c) - (p[1] != 0);
102718334Speter	  else if (WORD_SWITCH_TAKES_ARG (p))
102818334Speter	    nskip += WORD_SWITCH_TAKES_ARG (p);
102918334Speter	  else if ((c == 'B' || c == 'b' || c == 'V' || c == 'x')
103018334Speter		   && p[1] == 0)
103118334Speter	    nskip += 1;
103218334Speter	  else if (! strcmp (p, "Xlinker"))
103318334Speter	    nskip += 1;
103418334Speter
103518334Speter	  /* Watch out for an option at the end of the command line that
103618334Speter	     is missing arguments, and avoid skipping past the end of the
103718334Speter	     command line.  */
103818334Speter	  if (nskip + i > argc)
103918334Speter	    nskip = argc - i;
104018334Speter
104118334Speter	  while (nskip > 0)
104218334Speter	    {
104318334Speter	      newv[newindex++] = argv[i++];
104418334Speter	      nskip--;
104518334Speter	    }
104618334Speter	}
104718334Speter      else
104818334Speter	/* Ordinary operands, or +e options.  */
104918334Speter	newv[newindex++] = argv[i++];
105018334Speter    }
105118334Speter
105218334Speter  newv[newindex] = 0;
105318334Speter
105418334Speter  *argvp = newv;
105518334Speter  *argcp = newindex;
105618334Speter}
105718334Speter
105818334Speterchar *
105952520Sobrienxstrerror(e)
106018334Speter     int e;
106118334Speter{
106250599Sobrien#ifdef HAVE_STRERROR
106318334Speter
106418334Speter  return strerror(e);
106518334Speter
106618334Speter#else
106718334Speter
106818334Speter  if (!e)
106952520Sobrien    return "errno = 0";
107018334Speter
107118334Speter  if (e > 0 && e < sys_nerr)
107218334Speter    return sys_errlist[e];
107318334Speter
107452520Sobrien  return "errno = ?";
107518334Speter#endif
107618334Speter}
107718334Speter
107818334Speterstatic char *
107918334Speterskip_whitespace (p)
108018334Speter     char *p;
108118334Speter{
108218334Speter  while (1)
108318334Speter    {
108418334Speter      /* A fully-blank line is a delimiter in the SPEC file and shouldn't
108518334Speter	 be considered whitespace.  */
108618334Speter      if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n')
108718334Speter	return p + 1;
108818334Speter      else if (*p == '\n' || *p == ' ' || *p == '\t')
108918334Speter	p++;
109018334Speter      else if (*p == '#')
109118334Speter	{
109218334Speter	  while (*p != '\n') p++;
109318334Speter	  p++;
109418334Speter	}
109518334Speter      else
109618334Speter	break;
109718334Speter    }
109818334Speter
109918334Speter  return p;
110018334Speter}
110118334Speter
110250599Sobrien/* Structure to keep track of the specs that have been defined so far.
110350599Sobrien   These are accessed using %(specname) or %[specname] in a compiler
110450599Sobrien   or link spec.  */
110518334Speter
110618334Speterstruct spec_list
110718334Speter{
110850599Sobrien				/* The following 2 fields must be first */
110950599Sobrien				/* to allow EXTRA_SPECS to be initialized */
111050599Sobrien  char *name;			/* name of the spec.  */
111150599Sobrien  char *ptr;			/* available ptr if no static pointer */
111250599Sobrien
111350599Sobrien				/* The following fields are not initialized */
111450599Sobrien				/* by EXTRA_SPECS */
111550599Sobrien  char **ptr_spec;		/* pointer to the spec itself.  */
111650599Sobrien  struct spec_list *next;	/* Next spec in linked list.  */
111750599Sobrien  int name_len;			/* length of the name */
111850599Sobrien  int alloc_p;			/* whether string was allocated */
111918334Speter};
112018334Speter
112150599Sobrien#define INIT_STATIC_SPEC(NAME,PTR) \
112250599Sobrien{ NAME, NULL_PTR, PTR, (struct spec_list *)0, sizeof (NAME)-1, 0 }
112318334Speter
112450599Sobrien/* List of statically defined specs */
112550599Sobrienstatic struct spec_list static_specs[] = {
112650599Sobrien  INIT_STATIC_SPEC ("asm",			&asm_spec),
112750599Sobrien  INIT_STATIC_SPEC ("asm_final",		&asm_final_spec),
112850599Sobrien  INIT_STATIC_SPEC ("cpp",			&cpp_spec),
112950599Sobrien  INIT_STATIC_SPEC ("cc1",			&cc1_spec),
113050599Sobrien  INIT_STATIC_SPEC ("cc1plus",			&cc1plus_spec),
113150599Sobrien  INIT_STATIC_SPEC ("endfile",			&endfile_spec),
113250599Sobrien  INIT_STATIC_SPEC ("link",			&link_spec),
113350599Sobrien  INIT_STATIC_SPEC ("lib",			&lib_spec),
113450599Sobrien  INIT_STATIC_SPEC ("libgcc",			&libgcc_spec),
113550599Sobrien  INIT_STATIC_SPEC ("startfile",		&startfile_spec),
113650599Sobrien  INIT_STATIC_SPEC ("switches_need_spaces",	&switches_need_spaces),
113750599Sobrien  INIT_STATIC_SPEC ("signed_char",		&signed_char_spec),
113850599Sobrien  INIT_STATIC_SPEC ("predefines",		&cpp_predefines),
113950599Sobrien  INIT_STATIC_SPEC ("cross_compile",		&cross_compile),
114050599Sobrien  INIT_STATIC_SPEC ("version",			&compiler_version),
114150599Sobrien  INIT_STATIC_SPEC ("multilib",			&multilib_select),
114250599Sobrien  INIT_STATIC_SPEC ("multilib_defaults",	&multilib_defaults),
114350599Sobrien  INIT_STATIC_SPEC ("multilib_extra",		&multilib_extra),
114450599Sobrien  INIT_STATIC_SPEC ("multilib_matches",		&multilib_matches),
114550599Sobrien  INIT_STATIC_SPEC ("linker",			&linker_name_spec),
114650599Sobrien};
114750599Sobrien
114850599Sobrien#ifdef EXTRA_SPECS		/* additional specs needed */
114952520Sobrien/* Structure to keep track of just the first two args of a spec_list.
115052520Sobrien   That is all that the EXTRA_SPECS macro gives us. */
115152520Sobrienstruct spec_list_1
115252520Sobrien{
115352520Sobrien  char *name;
115452520Sobrien  char *ptr;
115552520Sobrien};
115652520Sobrien
115752520Sobrienstatic struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
115852520Sobrienstatic struct spec_list * extra_specs = (struct spec_list *)0;
115950599Sobrien#endif
116050599Sobrien
116150599Sobrien/* List of dynamically allocates specs that have been defined so far.  */
116250599Sobrien
116350599Sobrienstatic struct spec_list *specs = (struct spec_list *)0;
116450599Sobrien
116518334Speter
116650599Sobrien/* Initialize the specs lookup routines.  */
116750599Sobrien
116850599Sobrienstatic void
116950599Sobrieninit_spec ()
117050599Sobrien{
117150599Sobrien  struct spec_list *next = (struct spec_list *)0;
117250599Sobrien  struct spec_list *sl   = (struct spec_list *)0;
117350599Sobrien  int i;
117450599Sobrien
117550599Sobrien  if (specs)
117650599Sobrien    return;			/* already initialized */
117750599Sobrien
117850599Sobrien  if (verbose_flag)
117952520Sobrien    notice ("Using builtin specs.\n");
118050599Sobrien
118150599Sobrien#ifdef EXTRA_SPECS
118252520Sobrien  extra_specs = (struct spec_list *)
118352520Sobrien    xmalloc (sizeof(struct spec_list) *
118452520Sobrien	     (sizeof(extra_specs_1)/sizeof(extra_specs_1[0])));
118552520Sobrien  bzero ((PTR) extra_specs, sizeof(struct spec_list) *
118652520Sobrien	 (sizeof(extra_specs_1)/sizeof(extra_specs_1[0])));
118752520Sobrien
118852520Sobrien  for (i = (sizeof(extra_specs_1) / sizeof(extra_specs_1[0])) - 1; i >= 0; i--)
118950599Sobrien    {
119050599Sobrien      sl = &extra_specs[i];
119152520Sobrien      sl->name = extra_specs_1[i].name;
119252520Sobrien      sl->ptr = extra_specs_1[i].ptr;
119350599Sobrien      sl->next = next;
119450599Sobrien      sl->name_len = strlen (sl->name);
119550599Sobrien      sl->ptr_spec = &sl->ptr;
119650599Sobrien      next = sl;
119750599Sobrien    }
119850599Sobrien#endif
119950599Sobrien
120050599Sobrien  for (i = (sizeof (static_specs) / sizeof (static_specs[0])) - 1; i >= 0; i--)
120150599Sobrien    {
120250599Sobrien      sl = &static_specs[i];
120350599Sobrien      sl->next = next;
120450599Sobrien      next = sl;
120550599Sobrien    }
120650599Sobrien
120750599Sobrien  specs = sl;
120850599Sobrien}
120950599Sobrien
121050599Sobrien
121118334Speter/* Change the value of spec NAME to SPEC.  If SPEC is empty, then the spec is
121218334Speter   removed; If the spec starts with a + then SPEC is added to the end of the
121350599Sobrien   current spec.  */
121418334Speter
121518334Speterstatic void
121618334Speterset_spec (name, spec)
121752520Sobrien     const char *name;
121852520Sobrien     const char *spec;
121918334Speter{
122018334Speter  struct spec_list *sl;
122118334Speter  char *old_spec;
122250599Sobrien  int name_len = strlen (name);
122350599Sobrien  int i;
122418334Speter
122550599Sobrien  /* If this is the first call, initialize the statically allocated specs */
122650599Sobrien  if (!specs)
122750599Sobrien    {
122850599Sobrien      struct spec_list *next = (struct spec_list *)0;
122950599Sobrien      for (i = (sizeof (static_specs) / sizeof (static_specs[0])) - 1;
123050599Sobrien	   i >= 0; i--)
123150599Sobrien	{
123250599Sobrien	  sl = &static_specs[i];
123350599Sobrien	  sl->next = next;
123450599Sobrien	  next = sl;
123550599Sobrien	}
123650599Sobrien      specs = sl;
123750599Sobrien    }
123850599Sobrien
123918334Speter  /* See if the spec already exists */
124018334Speter  for (sl = specs; sl; sl = sl->next)
124150599Sobrien    if (name_len == sl->name_len && !strcmp (sl->name, name))
124218334Speter      break;
124318334Speter
124418334Speter  if (!sl)
124518334Speter    {
124618334Speter      /* Not found - make it */
124718334Speter      sl = (struct spec_list *) xmalloc (sizeof (struct spec_list));
124818334Speter      sl->name = save_string (name, strlen (name));
124950599Sobrien      sl->name_len = name_len;
125050599Sobrien      sl->ptr_spec = &sl->ptr;
125150599Sobrien      sl->alloc_p = 0;
125250599Sobrien      *(sl->ptr_spec) = "";
125318334Speter      sl->next = specs;
125418334Speter      specs = sl;
125518334Speter    }
125618334Speter
125750599Sobrien  old_spec = *(sl->ptr_spec);
125852520Sobrien  *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1]))
125950599Sobrien		     ? concat (old_spec, spec + 1, NULL_PTR)
126050599Sobrien		     : save_string (spec, strlen (spec)));
126118334Speter
126250599Sobrien#ifdef DEBUG_SPECS
126350599Sobrien  if (verbose_flag)
126452520Sobrien    notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
126550599Sobrien#endif
126650599Sobrien
126718334Speter  /* Free the old spec */
126850599Sobrien  if (old_spec && sl->alloc_p)
126918334Speter    free (old_spec);
127050599Sobrien
127150599Sobrien  sl->alloc_p = 1;
127218334Speter}
127318334Speter
127418334Speter/* Accumulate a command (program name and args), and run it.  */
127518334Speter
127618334Speter/* Vector of pointers to arguments in the current line of specifications.  */
127718334Speter
127818334Speterstatic char **argbuf;
127918334Speter
128018334Speter/* Number of elements allocated in argbuf.  */
128118334Speter
128218334Speterstatic int argbuf_length;
128318334Speter
128418334Speter/* Number of elements in argbuf currently in use (containing args).  */
128518334Speter
128618334Speterstatic int argbuf_index;
128718334Speter
128850599Sobrien/* We want this on by default all the time now.  */
128950599Sobrien#define MKTEMP_EACH_FILE
129050599Sobrien
129150599Sobrien#ifdef MKTEMP_EACH_FILE
129250599Sobrien
129352520Sobrienextern char *make_temp_file PROTO((const char *));
129450599Sobrien
129518334Speter/* This is the list of suffixes and codes (%g/%u/%U) and the associated
129650599Sobrien   temp file.  */
129718334Speter
129818334Speterstatic struct temp_name {
129952520Sobrien  const char *suffix;	/* suffix associated with the code.  */
130018334Speter  int length;		/* strlen (suffix).  */
130118334Speter  int unique;		/* Indicates whether %g or %u/%U was used.  */
130252520Sobrien  const char *filename;	/* associated filename.  */
130318334Speter  int filename_length;	/* strlen (filename).  */
130418334Speter  struct temp_name *next;
130518334Speter} *temp_names;
130650599Sobrien#endif
130718334Speter
130850599Sobrien
130918334Speter/* Number of commands executed so far.  */
131018334Speter
131118334Speterstatic int execution_count;
131218334Speter
131318334Speter/* Number of commands that exited with a signal.  */
131418334Speter
131518334Speterstatic int signal_count;
131618334Speter
131718334Speter/* Name with which this program was invoked.  */
131818334Speter
131952520Sobrienstatic const char *programname;
132018334Speter
132150599Sobrien/* Structures to keep track of prefixes to try when looking for files.  */
132218334Speter
132318334Speterstruct prefix_list
132418334Speter{
132550599Sobrien  char *prefix;               /* String to prepend to the path.  */
132650599Sobrien  struct prefix_list *next;   /* Next in linked list.  */
132718334Speter  int require_machine_suffix; /* Don't use without machine_suffix.  */
132818334Speter  /* 2 means try both machine_suffix and just_machine_suffix.  */
132918334Speter  int *used_flag_ptr;	      /* 1 if a file was found with this prefix.  */
133018334Speter};
133118334Speter
133218334Speterstruct path_prefix
133318334Speter{
133418334Speter  struct prefix_list *plist;  /* List of prefixes to try */
133518334Speter  int max_len;                /* Max length of a prefix in PLIST */
133652520Sobrien  const char *name;           /* Name of this list (used in config stuff) */
133718334Speter};
133818334Speter
133950599Sobrien/* List of prefixes to try when looking for executables.  */
134018334Speter
134118334Speterstatic struct path_prefix exec_prefixes = { 0, 0, "exec" };
134218334Speter
134350599Sobrien/* List of prefixes to try when looking for startup (crt0) files.  */
134418334Speter
134518334Speterstatic struct path_prefix startfile_prefixes = { 0, 0, "startfile" };
134618334Speter
134718334Speter/* List of prefixes to try when looking for include files.  */
134818334Speter
134918334Speterstatic struct path_prefix include_prefixes = { 0, 0, "include" };
135018334Speter
135118334Speter/* Suffix to attach to directories searched for commands.
135218334Speter   This looks like `MACHINE/VERSION/'.  */
135318334Speter
135452520Sobrienstatic const char *machine_suffix = 0;
135518334Speter
135618334Speter/* Suffix to attach to directories searched for commands.
135718334Speter   This is just `MACHINE/'.  */
135818334Speter
135952520Sobrienstatic const char *just_machine_suffix = 0;
136018334Speter
136118334Speter/* Adjusted value of GCC_EXEC_PREFIX envvar.  */
136218334Speter
136352520Sobrienstatic const char *gcc_exec_prefix;
136418334Speter
136518334Speter/* Default prefixes to attach to command names.  */
136618334Speter
136718334Speter#ifdef CROSS_COMPILE  /* Don't use these prefixes for a cross compiler.  */
136818334Speter#undef MD_EXEC_PREFIX
136918334Speter#undef MD_STARTFILE_PREFIX
137018334Speter#undef MD_STARTFILE_PREFIX_1
137118334Speter#endif
137218334Speter
137318334Speter#ifndef STANDARD_EXEC_PREFIX
137418334Speter#define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/"
137518334Speter#endif /* !defined STANDARD_EXEC_PREFIX */
137618334Speter
137752520Sobrienstatic const char *standard_exec_prefix = STANDARD_EXEC_PREFIX;
137852520Sobrienstatic const char *standard_exec_prefix_1 = "/usr/lib/gcc/";
137918334Speter#ifdef MD_EXEC_PREFIX
138052520Sobrienstatic const char *md_exec_prefix = MD_EXEC_PREFIX;
138118334Speter#endif
138218334Speter
138318334Speter#ifndef STANDARD_STARTFILE_PREFIX
138418334Speter#define STANDARD_STARTFILE_PREFIX "/usr/local/lib/"
138518334Speter#endif /* !defined STANDARD_STARTFILE_PREFIX */
138618334Speter
138718334Speter#ifdef MD_STARTFILE_PREFIX
138852520Sobrienstatic const char *md_startfile_prefix = MD_STARTFILE_PREFIX;
138918334Speter#endif
139018334Speter#ifdef MD_STARTFILE_PREFIX_1
139152520Sobrienstatic const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
139218334Speter#endif
139352520Sobrienstatic const char *standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
139452520Sobrienstatic const char *standard_startfile_prefix_1 = "/lib/";
139552520Sobrienstatic const char *standard_startfile_prefix_2 = "/usr/lib/";
139618334Speter
139718334Speter#ifndef TOOLDIR_BASE_PREFIX
139818334Speter#define TOOLDIR_BASE_PREFIX "/usr/local/"
139918334Speter#endif
140052520Sobrienstatic const char *tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
140152520Sobrienstatic const char *tooldir_prefix;
140218334Speter
140318334Speter/* Subdirectory to use for locating libraries.  Set by
140418334Speter   set_multilib_dir based on the compilation options.  */
140518334Speter
140652520Sobrienstatic const char *multilib_dir;
140718334Speter
140818334Speter/* Clear out the vector of arguments (after a command is executed).  */
140918334Speter
141018334Speterstatic void
141118334Speterclear_args ()
141218334Speter{
141318334Speter  argbuf_index = 0;
141418334Speter}
141518334Speter
141618334Speter/* Add one argument to the vector at the end.
141718334Speter   This is done when a space is seen or at the end of the line.
141818334Speter   If DELETE_ALWAYS is nonzero, the arg is a filename
141918334Speter    and the file should be deleted eventually.
142018334Speter   If DELETE_FAILURE is nonzero, the arg is a filename
142118334Speter    and the file should be deleted if this compilation fails.  */
142218334Speter
142318334Speterstatic void
142418334Speterstore_arg (arg, delete_always, delete_failure)
142518334Speter     char *arg;
142618334Speter     int delete_always, delete_failure;
142718334Speter{
142818334Speter  if (argbuf_index + 1 == argbuf_length)
142950599Sobrien    argbuf
143050599Sobrien      = (char **) xrealloc (argbuf, (argbuf_length *= 2) * sizeof (char *));
143118334Speter
143218334Speter  argbuf[argbuf_index++] = arg;
143318334Speter  argbuf[argbuf_index] = 0;
143418334Speter
143518334Speter  if (delete_always || delete_failure)
143618334Speter    record_temp_file (arg, delete_always, delete_failure);
143718334Speter}
143818334Speter
143950599Sobrien/* Read compilation specs from a file named FILENAME,
144050599Sobrien   replacing the default ones.
144150599Sobrien
144250599Sobrien   A suffix which starts with `*' is a definition for
144350599Sobrien   one of the machine-specific sub-specs.  The "suffix" should be
144450599Sobrien   *asm, *cc1, *cpp, *link, *startfile, *signed_char, etc.
144550599Sobrien   The corresponding spec is stored in asm_spec, etc.,
144650599Sobrien   rather than in the `compilers' vector.
144750599Sobrien
144850599Sobrien   Anything invalid in the file is a fatal error.  */
144950599Sobrien
145050599Sobrienstatic void
145150599Sobrienread_specs (filename, main_p)
145252520Sobrien     const char *filename;
145350599Sobrien     int main_p;
145450599Sobrien{
145550599Sobrien  int desc;
145650599Sobrien  int readlen;
145750599Sobrien  struct stat statbuf;
145850599Sobrien  char *buffer;
145950599Sobrien  register char *p;
146050599Sobrien
146150599Sobrien  if (verbose_flag)
146252520Sobrien    notice ("Reading specs from %s\n", filename);
146350599Sobrien
146450599Sobrien  /* Open and stat the file.  */
146550599Sobrien  desc = open (filename, O_RDONLY, 0);
146650599Sobrien  if (desc < 0)
146750599Sobrien    pfatal_with_name (filename);
146850599Sobrien  if (stat (filename, &statbuf) < 0)
146950599Sobrien    pfatal_with_name (filename);
147050599Sobrien
147150599Sobrien  /* Read contents of file into BUFFER.  */
147250599Sobrien  buffer = xmalloc ((unsigned) statbuf.st_size + 1);
147350599Sobrien  readlen = read (desc, buffer, (unsigned) statbuf.st_size);
147450599Sobrien  if (readlen < 0)
147550599Sobrien    pfatal_with_name (filename);
147650599Sobrien  buffer[readlen] = 0;
147750599Sobrien  close (desc);
147850599Sobrien
147950599Sobrien  /* Scan BUFFER for specs, putting them in the vector.  */
148050599Sobrien  p = buffer;
148150599Sobrien  while (1)
148250599Sobrien    {
148350599Sobrien      char *suffix;
148450599Sobrien      char *spec;
148550599Sobrien      char *in, *out, *p1, *p2, *p3;
148650599Sobrien
148750599Sobrien      /* Advance P in BUFFER to the next nonblank nocomment line.  */
148850599Sobrien      p = skip_whitespace (p);
148950599Sobrien      if (*p == 0)
149050599Sobrien	break;
149150599Sobrien
149250599Sobrien      /* Is this a special command that starts with '%'? */
149350599Sobrien      /* Don't allow this for the main specs file, since it would
149450599Sobrien	 encourage people to overwrite it.  */
149550599Sobrien      if (*p == '%' && !main_p)
149650599Sobrien	{
149750599Sobrien	  p1 = p;
149850599Sobrien	  while (*p && *p != '\n')
149950599Sobrien	    p++;
150050599Sobrien
150150599Sobrien	  p++;			/* Skip '\n' */
150250599Sobrien
150350599Sobrien	  if (!strncmp (p1, "%include", sizeof ("%include")-1)
150450599Sobrien	      && (p1[sizeof "%include" - 1] == ' '
150550599Sobrien		  || p1[sizeof "%include" - 1] == '\t'))
150650599Sobrien	    {
150750599Sobrien	      char *new_filename;
150850599Sobrien
150950599Sobrien	      p1 += sizeof ("%include");
151050599Sobrien	      while (*p1 == ' ' || *p1 == '\t')
151150599Sobrien		p1++;
151250599Sobrien
151350599Sobrien	      if (*p1++ != '<' || p[-2] != '>')
151452520Sobrien		fatal ("specs %%include syntax malformed after %ld characters",
151552520Sobrien		       (long) (p1 - buffer + 1));
151650599Sobrien
151750599Sobrien	      p[-2] = '\0';
151850599Sobrien	      new_filename = find_a_file (&startfile_prefixes, p1, R_OK);
151950599Sobrien	      read_specs (new_filename ? new_filename : p1, FALSE);
152050599Sobrien	      continue;
152150599Sobrien	    }
152250599Sobrien	  else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1)
152350599Sobrien		   && (p1[sizeof "%include_noerr" - 1] == ' '
152450599Sobrien		       || p1[sizeof "%include_noerr" - 1] == '\t'))
152550599Sobrien	    {
152650599Sobrien	      char *new_filename;
152750599Sobrien
152850599Sobrien	      p1 += sizeof "%include_noerr";
152950599Sobrien	      while (*p1 == ' ' || *p1 == '\t') p1++;
153050599Sobrien
153150599Sobrien	      if (*p1++ != '<' || p[-2] != '>')
153252520Sobrien		fatal ("specs %%include syntax malformed after %ld characters",
153352520Sobrien		       (long) (p1 - buffer + 1));
153450599Sobrien
153550599Sobrien	      p[-2] = '\0';
153650599Sobrien	      new_filename = find_a_file (&startfile_prefixes, p1, R_OK);
153750599Sobrien	      if (new_filename)
153850599Sobrien		read_specs (new_filename, FALSE);
153950599Sobrien	      else if (verbose_flag)
154052520Sobrien		notice ("Could not find specs file %s\n", p1);
154150599Sobrien	      continue;
154250599Sobrien	    }
154350599Sobrien	  else if (!strncmp (p1, "%rename", sizeof "%rename" - 1)
154450599Sobrien		   && (p1[sizeof "%rename" - 1] == ' '
154550599Sobrien		       || p1[sizeof "%rename" - 1] == '\t'))
154650599Sobrien	    {
154750599Sobrien	      int name_len;
154850599Sobrien	      struct spec_list *sl;
154950599Sobrien
155050599Sobrien	      /* Get original name */
155150599Sobrien	      p1 += sizeof "%rename";
155250599Sobrien	      while (*p1 == ' ' || *p1 == '\t')
155350599Sobrien		p1++;
155450599Sobrien
155552520Sobrien	      if (! ISALPHA ((unsigned char)*p1))
155652520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
155752520Sobrien		       (long) (p1 - buffer));
155850599Sobrien
155950599Sobrien	      p2 = p1;
156052520Sobrien	      while (*p2 && !ISSPACE ((unsigned char)*p2))
156150599Sobrien		p2++;
156250599Sobrien
156350599Sobrien	      if (*p2 != ' ' && *p2 != '\t')
156452520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
156552520Sobrien		       (long) (p2 - buffer));
156650599Sobrien
156750599Sobrien	      name_len = p2 - p1;
156850599Sobrien	      *p2++ = '\0';
156950599Sobrien	      while (*p2 == ' ' || *p2 == '\t')
157050599Sobrien		p2++;
157150599Sobrien
157252520Sobrien	      if (! ISALPHA ((unsigned char)*p2))
157352520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
157452520Sobrien		       (long) (p2 - buffer));
157550599Sobrien
157650599Sobrien	      /* Get new spec name */
157750599Sobrien	      p3 = p2;
157852520Sobrien	      while (*p3 && !ISSPACE ((unsigned char)*p3))
157950599Sobrien		p3++;
158050599Sobrien
158150599Sobrien	      if (p3 != p-1)
158252520Sobrien		fatal ("specs %%rename syntax malformed after %ld characters",
158352520Sobrien		       (long) (p3 - buffer));
158450599Sobrien	      *p3 = '\0';
158550599Sobrien
158650599Sobrien	      for (sl = specs; sl; sl = sl->next)
158750599Sobrien		if (name_len == sl->name_len && !strcmp (sl->name, p1))
158850599Sobrien		  break;
158950599Sobrien
159050599Sobrien	      if (!sl)
159150599Sobrien		fatal ("specs %s spec was not found to be renamed", p1);
159250599Sobrien
159350599Sobrien	      if (strcmp (p1, p2) == 0)
159450599Sobrien		continue;
159550599Sobrien
159650599Sobrien	      if (verbose_flag)
159750599Sobrien		{
159852520Sobrien		  notice ("rename spec %s to %s\n", p1, p2);
159950599Sobrien#ifdef DEBUG_SPECS
160052520Sobrien		  notice ("spec is '%s'\n\n", *(sl->ptr_spec));
160150599Sobrien#endif
160250599Sobrien		}
160350599Sobrien
160450599Sobrien	      set_spec (p2, *(sl->ptr_spec));
160550599Sobrien	      if (sl->alloc_p)
160650599Sobrien		free (*(sl->ptr_spec));
160750599Sobrien
160850599Sobrien	      *(sl->ptr_spec) = "";
160950599Sobrien	      sl->alloc_p = 0;
161050599Sobrien	      continue;
161150599Sobrien	    }
161250599Sobrien	  else
161352520Sobrien	    fatal ("specs unknown %% command after %ld characters",
161452520Sobrien		   (long) (p1 - buffer));
161550599Sobrien	}
161650599Sobrien
161750599Sobrien      /* Find the colon that should end the suffix.  */
161850599Sobrien      p1 = p;
161950599Sobrien      while (*p1 && *p1 != ':' && *p1 != '\n')
162050599Sobrien	p1++;
162150599Sobrien
162250599Sobrien      /* The colon shouldn't be missing.  */
162350599Sobrien      if (*p1 != ':')
162452520Sobrien	fatal ("specs file malformed after %ld characters",
162552520Sobrien	       (long) (p1 - buffer));
162650599Sobrien
162750599Sobrien      /* Skip back over trailing whitespace.  */
162850599Sobrien      p2 = p1;
162950599Sobrien      while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t'))
163050599Sobrien	p2--;
163150599Sobrien
163250599Sobrien      /* Copy the suffix to a string.  */
163350599Sobrien      suffix = save_string (p, p2 - p);
163450599Sobrien      /* Find the next line.  */
163550599Sobrien      p = skip_whitespace (p1 + 1);
163650599Sobrien      if (p[1] == 0)
163752520Sobrien	fatal ("specs file malformed after %ld characters",
163852520Sobrien	       (long) (p - buffer));
163950599Sobrien
164050599Sobrien      p1 = p;
164150599Sobrien      /* Find next blank line or end of string.  */
164250599Sobrien      while (*p1 && !(*p1 == '\n' && (p1[1] == '\n' || p1[1] == '\0')))
164350599Sobrien	p1++;
164450599Sobrien
164550599Sobrien      /* Specs end at the blank line and do not include the newline.  */
164650599Sobrien      spec = save_string (p, p1 - p);
164750599Sobrien      p = p1;
164850599Sobrien
164950599Sobrien      /* Delete backslash-newline sequences from the spec.  */
165050599Sobrien      in = spec;
165150599Sobrien      out = spec;
165250599Sobrien      while (*in != 0)
165350599Sobrien	{
165450599Sobrien	  if (in[0] == '\\' && in[1] == '\n')
165550599Sobrien	    in += 2;
165650599Sobrien	  else if (in[0] == '#')
165750599Sobrien	    while (*in && *in != '\n')
165850599Sobrien	      in++;
165950599Sobrien
166050599Sobrien	  else
166150599Sobrien	    *out++ = *in++;
166250599Sobrien	}
166350599Sobrien      *out = 0;
166450599Sobrien
166550599Sobrien      if (suffix[0] == '*')
166650599Sobrien	{
166750599Sobrien	  if (! strcmp (suffix, "*link_command"))
166850599Sobrien	    link_command_spec = spec;
166950599Sobrien	  else
167050599Sobrien	    set_spec (suffix + 1, spec);
167150599Sobrien	}
167250599Sobrien      else
167350599Sobrien	{
167450599Sobrien	  /* Add this pair to the vector.  */
167550599Sobrien	  compilers
167650599Sobrien	    = ((struct compiler *)
167750599Sobrien	       xrealloc (compilers,
167850599Sobrien			 (n_compilers + 2) * sizeof (struct compiler)));
167950599Sobrien
168050599Sobrien	  compilers[n_compilers].suffix = suffix;
168150599Sobrien	  bzero ((char *) compilers[n_compilers].spec,
168250599Sobrien		 sizeof compilers[n_compilers].spec);
168350599Sobrien	  compilers[n_compilers].spec[0] = spec;
168450599Sobrien	  n_compilers++;
168550599Sobrien	  bzero ((char *) &compilers[n_compilers],
168650599Sobrien		 sizeof compilers[n_compilers]);
168750599Sobrien	}
168850599Sobrien
168950599Sobrien      if (*suffix == 0)
169050599Sobrien	link_command_spec = spec;
169150599Sobrien    }
169250599Sobrien
169350599Sobrien  if (link_command_spec == 0)
169450599Sobrien    fatal ("spec file has no spec for linking");
169550599Sobrien}
169650599Sobrien
169718334Speter/* Record the names of temporary files we tell compilers to write,
169818334Speter   and delete them at the end of the run.  */
169918334Speter
170018334Speter/* This is the common prefix we use to make temp file names.
170118334Speter   It is chosen once for each run of this program.
170218334Speter   It is substituted into a spec by %g.
170318334Speter   Thus, all temp file names contain this prefix.
170418334Speter   In practice, all temp file names start with this prefix.
170518334Speter
170618334Speter   This prefix comes from the envvar TMPDIR if it is defined;
170718334Speter   otherwise, from the P_tmpdir macro if that is defined;
170850599Sobrien   otherwise, in /usr/tmp or /tmp;
170950599Sobrien   or finally the current directory if all else fails.  */
171018334Speter
171152520Sobrienstatic const char *temp_filename;
171218334Speter
171318334Speter/* Length of the prefix.  */
171418334Speter
171518334Speterstatic int temp_filename_length;
171618334Speter
171718334Speter/* Define the list of temporary files to delete.  */
171818334Speter
171918334Speterstruct temp_file
172018334Speter{
172152520Sobrien  const char *name;
172218334Speter  struct temp_file *next;
172318334Speter};
172418334Speter
172518334Speter/* Queue of files to delete on success or failure of compilation.  */
172618334Speterstatic struct temp_file *always_delete_queue;
172718334Speter/* Queue of files to delete on failure of compilation.  */
172818334Speterstatic struct temp_file *failure_delete_queue;
172918334Speter
173018334Speter/* Record FILENAME as a file to be deleted automatically.
173118334Speter   ALWAYS_DELETE nonzero means delete it if all compilation succeeds;
173218334Speter   otherwise delete it in any case.
173318334Speter   FAIL_DELETE nonzero means delete it if a compilation step fails;
173418334Speter   otherwise delete it in any case.  */
173518334Speter
173618334Speterstatic void
173718334Speterrecord_temp_file (filename, always_delete, fail_delete)
173852520Sobrien     const char *filename;
173918334Speter     int always_delete;
174018334Speter     int fail_delete;
174118334Speter{
174218334Speter  register char *name;
174318334Speter  name = xmalloc (strlen (filename) + 1);
174418334Speter  strcpy (name, filename);
174518334Speter
174618334Speter  if (always_delete)
174718334Speter    {
174818334Speter      register struct temp_file *temp;
174918334Speter      for (temp = always_delete_queue; temp; temp = temp->next)
175018334Speter	if (! strcmp (name, temp->name))
175118334Speter	  goto already1;
175250599Sobrien
175318334Speter      temp = (struct temp_file *) xmalloc (sizeof (struct temp_file));
175418334Speter      temp->next = always_delete_queue;
175518334Speter      temp->name = name;
175618334Speter      always_delete_queue = temp;
175750599Sobrien
175818334Speter    already1:;
175918334Speter    }
176018334Speter
176118334Speter  if (fail_delete)
176218334Speter    {
176318334Speter      register struct temp_file *temp;
176418334Speter      for (temp = failure_delete_queue; temp; temp = temp->next)
176518334Speter	if (! strcmp (name, temp->name))
176618334Speter	  goto already2;
176750599Sobrien
176818334Speter      temp = (struct temp_file *) xmalloc (sizeof (struct temp_file));
176918334Speter      temp->next = failure_delete_queue;
177018334Speter      temp->name = name;
177118334Speter      failure_delete_queue = temp;
177250599Sobrien
177318334Speter    already2:;
177418334Speter    }
177518334Speter}
177618334Speter
177718334Speter/* Delete all the temporary files whose names we previously recorded.  */
177818334Speter
177918334Speterstatic void
178018334Speterdelete_if_ordinary (name)
178152520Sobrien     const char *name;
178218334Speter{
178318334Speter  struct stat st;
178418334Speter#ifdef DEBUG
178518334Speter  int i, c;
178618334Speter
178718334Speter  printf ("Delete %s? (y or n) ", name);
178818334Speter  fflush (stdout);
178918334Speter  i = getchar ();
179018334Speter  if (i != '\n')
179150599Sobrien    while ((c = getchar ()) != '\n' && c != EOF)
179250599Sobrien      ;
179350599Sobrien
179418334Speter  if (i == 'y' || i == 'Y')
179518334Speter#endif /* DEBUG */
179618334Speter    if (stat (name, &st) >= 0 && S_ISREG (st.st_mode))
179718334Speter      if (unlink (name) < 0)
179818334Speter	if (verbose_flag)
179918334Speter	  perror_with_name (name);
180018334Speter}
180118334Speter
180218334Speterstatic void
180318334Speterdelete_temp_files ()
180418334Speter{
180518334Speter  register struct temp_file *temp;
180618334Speter
180718334Speter  for (temp = always_delete_queue; temp; temp = temp->next)
180818334Speter    delete_if_ordinary (temp->name);
180918334Speter  always_delete_queue = 0;
181018334Speter}
181118334Speter
181218334Speter/* Delete all the files to be deleted on error.  */
181318334Speter
181418334Speterstatic void
181518334Speterdelete_failure_queue ()
181618334Speter{
181718334Speter  register struct temp_file *temp;
181818334Speter
181918334Speter  for (temp = failure_delete_queue; temp; temp = temp->next)
182018334Speter    delete_if_ordinary (temp->name);
182118334Speter}
182218334Speter
182318334Speterstatic void
182418334Speterclear_failure_queue ()
182518334Speter{
182618334Speter  failure_delete_queue = 0;
182718334Speter}
182818334Speter
182918334Speter/* Routine to add variables to the environment.  We do this to pass
183018334Speter   the pathname of the gcc driver, and the directories search to the
183118334Speter   collect2 program, which is being run as ld.  This way, we can be
183218334Speter   sure of executing the right compiler when collect2 wants to build
183318334Speter   constructors and destructors.  Since the environment variables we
183418334Speter   use come from an obstack, we don't have to worry about allocating
183518334Speter   space for them.  */
183618334Speter
183718334Speter#ifndef HAVE_PUTENV
183818334Speter
183918334Spetervoid
184018334Speterputenv (str)
184118334Speter     char *str;
184218334Speter{
184318334Speter#ifndef VMS			/* nor about VMS */
184418334Speter
184518334Speter  extern char **environ;
184618334Speter  char **old_environ = environ;
184718334Speter  char **envp;
184818334Speter  int num_envs = 0;
184918334Speter  int name_len = 1;
185050599Sobrien  int str_len = strlen (str);
185118334Speter  char *p = str;
185218334Speter  int ch;
185318334Speter
185418334Speter  while ((ch = *p++) != '\0' && ch != '=')
185518334Speter    name_len++;
185618334Speter
185718334Speter  if (!ch)
185818334Speter    abort ();
185918334Speter
186018334Speter  /* Search for replacing an existing environment variable, and
186118334Speter     count the number of total environment variables.  */
186218334Speter  for (envp = old_environ; *envp; envp++)
186318334Speter    {
186418334Speter      num_envs++;
186518334Speter      if (!strncmp (str, *envp, name_len))
186618334Speter	{
186718334Speter	  *envp = str;
186818334Speter	  return;
186918334Speter	}
187018334Speter    }
187118334Speter
187218334Speter  /* Add a new environment variable */
187318334Speter  environ = (char **) xmalloc (sizeof (char *) * (num_envs+2));
187418334Speter  *environ = str;
187552520Sobrien  memcpy ((char *) (environ + 1), (char *) old_environ,
187618334Speter	 sizeof (char *) * (num_envs+1));
187718334Speter
187818334Speter#endif	/* VMS */
187918334Speter}
188018334Speter
188118334Speter#endif	/* HAVE_PUTENV */
188218334Speter
188318334Speter
188418334Speter/* Build a list of search directories from PATHS.
188518334Speter   PREFIX is a string to prepend to the list.
188618334Speter   If CHECK_DIR_P is non-zero we ensure the directory exists.
188718334Speter   This is used mostly by putenv_from_prefixes so we use `collect_obstack'.
188818334Speter   It is also used by the --print-search-dirs flag.  */
188918334Speter
189018334Speterstatic char *
189118334Speterbuild_search_list (paths, prefix, check_dir_p)
189218334Speter     struct path_prefix *paths;
189352520Sobrien     const char *prefix;
189418334Speter     int check_dir_p;
189518334Speter{
189618334Speter  int suffix_len = (machine_suffix) ? strlen (machine_suffix) : 0;
189718334Speter  int just_suffix_len
189818334Speter    = (just_machine_suffix) ? strlen (just_machine_suffix) : 0;
189918334Speter  int first_time = TRUE;
190018334Speter  struct prefix_list *pprefix;
190118334Speter
190218334Speter  obstack_grow (&collect_obstack, prefix, strlen (prefix));
190318334Speter
190418334Speter  for (pprefix = paths->plist; pprefix != 0; pprefix = pprefix->next)
190518334Speter    {
190618334Speter      int len = strlen (pprefix->prefix);
190718334Speter
190818334Speter      if (machine_suffix
190950599Sobrien	  && (! check_dir_p
191018334Speter	      || is_directory (pprefix->prefix, machine_suffix, 0)))
191118334Speter	{
191218334Speter	  if (!first_time)
191318334Speter	    obstack_1grow (&collect_obstack, PATH_SEPARATOR);
191418334Speter
191518334Speter	  first_time = FALSE;
191618334Speter	  obstack_grow (&collect_obstack, pprefix->prefix, len);
191718334Speter	  obstack_grow (&collect_obstack, machine_suffix, suffix_len);
191818334Speter	}
191918334Speter
192018334Speter      if (just_machine_suffix
192118334Speter	  && pprefix->require_machine_suffix == 2
192250599Sobrien	  && (! check_dir_p
192318334Speter	      || is_directory (pprefix->prefix, just_machine_suffix, 0)))
192418334Speter	{
192550599Sobrien	  if (! first_time)
192618334Speter	    obstack_1grow (&collect_obstack, PATH_SEPARATOR);
192718334Speter
192818334Speter	  first_time = FALSE;
192918334Speter	  obstack_grow (&collect_obstack, pprefix->prefix, len);
193018334Speter	  obstack_grow (&collect_obstack, just_machine_suffix,
193118334Speter			just_suffix_len);
193218334Speter	}
193318334Speter
193450599Sobrien      if (! pprefix->require_machine_suffix)
193518334Speter	{
193650599Sobrien	  if (! first_time)
193718334Speter	    obstack_1grow (&collect_obstack, PATH_SEPARATOR);
193818334Speter
193918334Speter	  first_time = FALSE;
194018334Speter	  obstack_grow (&collect_obstack, pprefix->prefix, len);
194118334Speter	}
194218334Speter    }
194350599Sobrien
194418334Speter  obstack_1grow (&collect_obstack, '\0');
194518334Speter  return obstack_finish (&collect_obstack);
194618334Speter}
194718334Speter
194850599Sobrien/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
194950599Sobrien   for collect.  */
195018334Speter
195118334Speterstatic void
195218334Speterputenv_from_prefixes (paths, env_var)
195318334Speter     struct path_prefix *paths;
195452520Sobrien     const char *env_var;
195518334Speter{
195618334Speter  putenv (build_search_list (paths, env_var, 1));
195718334Speter}
195818334Speter
195918334Speter/* Search for NAME using the prefix list PREFIXES.  MODE is passed to
196018334Speter   access to check permissions.
196150599Sobrien   Return 0 if not found, otherwise return its name, allocated with malloc.  */
196218334Speter
196318334Speterstatic char *
196418334Speterfind_a_file (pprefix, name, mode)
196518334Speter     struct path_prefix *pprefix;
196652520Sobrien     const char *name;
196718334Speter     int mode;
196818334Speter{
196918334Speter  char *temp;
197052520Sobrien  const char *file_suffix = ((mode & X_OK) != 0 ? EXECUTABLE_SUFFIX : "");
197118334Speter  struct prefix_list *pl;
197218334Speter  int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1;
197318334Speter
197452520Sobrien#ifdef DEFAULT_ASSEMBLER
197552520Sobrien  if (! strcmp(name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0) {
197652520Sobrien    name = DEFAULT_ASSEMBLER;
197752520Sobrien    len = strlen(name)+1;
197852520Sobrien    temp = xmalloc (len);
197952520Sobrien    strcpy (temp, name);
198052520Sobrien    return temp;
198152520Sobrien  }
198252520Sobrien#endif
198352520Sobrien
198452520Sobrien#ifdef DEFAULT_LINKER
198552520Sobrien  if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0) {
198652520Sobrien    name = DEFAULT_LINKER;
198752520Sobrien    len = strlen(name)+1;
198852520Sobrien    temp = xmalloc (len);
198952520Sobrien    strcpy (temp, name);
199052520Sobrien    return temp;
199152520Sobrien  }
199252520Sobrien#endif
199352520Sobrien
199418334Speter  if (machine_suffix)
199518334Speter    len += strlen (machine_suffix);
199618334Speter
199718334Speter  temp = xmalloc (len);
199818334Speter
199918334Speter  /* Determine the filename to execute (special case for absolute paths).  */
200018334Speter
200152520Sobrien  if (IS_DIR_SEPARATOR (*name)
200252520Sobrien#ifdef HAVE_DOS_BASED_FILESYSTEM
200350599Sobrien      /* Check for disk name on MS-DOS-based systems.  */
200452520Sobrien      || (name[0] && name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
200552520Sobrien#endif
200652520Sobrien      )
200718334Speter    {
200852520Sobrien      if (access (name, mode) == 0)
200918334Speter	{
201018334Speter	  strcpy (temp, name);
201118334Speter	  return temp;
201218334Speter	}
201318334Speter    }
201418334Speter  else
201518334Speter    for (pl = pprefix->plist; pl; pl = pl->next)
201618334Speter      {
201718334Speter	if (machine_suffix)
201818334Speter	  {
201918334Speter	    /* Some systems have a suffix for executable files.
202018334Speter	       So try appending that first.  */
202118334Speter	    if (file_suffix[0] != 0)
202218334Speter	      {
202318334Speter		strcpy (temp, pl->prefix);
202418334Speter		strcat (temp, machine_suffix);
202518334Speter		strcat (temp, name);
202618334Speter		strcat (temp, file_suffix);
202718334Speter		if (access (temp, mode) == 0)
202818334Speter		  {
202918334Speter		    if (pl->used_flag_ptr != 0)
203018334Speter		      *pl->used_flag_ptr = 1;
203118334Speter		    return temp;
203218334Speter		  }
203318334Speter	      }
203418334Speter
203518334Speter	    /* Now try just the name.  */
203618334Speter	    strcpy (temp, pl->prefix);
203718334Speter	    strcat (temp, machine_suffix);
203818334Speter	    strcat (temp, name);
203918334Speter	    if (access (temp, mode) == 0)
204018334Speter	      {
204118334Speter		if (pl->used_flag_ptr != 0)
204218334Speter		  *pl->used_flag_ptr = 1;
204318334Speter		return temp;
204418334Speter	      }
204518334Speter	  }
204618334Speter
204718334Speter	/* Certain prefixes are tried with just the machine type,
204818334Speter	   not the version.  This is used for finding as, ld, etc.  */
204918334Speter	if (just_machine_suffix && pl->require_machine_suffix == 2)
205018334Speter	  {
205118334Speter	    /* Some systems have a suffix for executable files.
205218334Speter	       So try appending that first.  */
205318334Speter	    if (file_suffix[0] != 0)
205418334Speter	      {
205518334Speter		strcpy (temp, pl->prefix);
205618334Speter		strcat (temp, just_machine_suffix);
205718334Speter		strcat (temp, name);
205818334Speter		strcat (temp, file_suffix);
205918334Speter		if (access (temp, mode) == 0)
206018334Speter		  {
206118334Speter		    if (pl->used_flag_ptr != 0)
206218334Speter		      *pl->used_flag_ptr = 1;
206318334Speter		    return temp;
206418334Speter		  }
206518334Speter	      }
206618334Speter
206718334Speter	    strcpy (temp, pl->prefix);
206818334Speter	    strcat (temp, just_machine_suffix);
206918334Speter	    strcat (temp, name);
207018334Speter	    if (access (temp, mode) == 0)
207118334Speter	      {
207218334Speter		if (pl->used_flag_ptr != 0)
207318334Speter		  *pl->used_flag_ptr = 1;
207418334Speter		return temp;
207518334Speter	      }
207618334Speter	  }
207718334Speter
207818334Speter	/* Certain prefixes can't be used without the machine suffix
207918334Speter	   when the machine or version is explicitly specified.  */
208050599Sobrien	if (! pl->require_machine_suffix)
208118334Speter	  {
208218334Speter	    /* Some systems have a suffix for executable files.
208318334Speter	       So try appending that first.  */
208418334Speter	    if (file_suffix[0] != 0)
208518334Speter	      {
208618334Speter		strcpy (temp, pl->prefix);
208718334Speter		strcat (temp, name);
208818334Speter		strcat (temp, file_suffix);
208918334Speter		if (access (temp, mode) == 0)
209018334Speter		  {
209118334Speter		    if (pl->used_flag_ptr != 0)
209218334Speter		      *pl->used_flag_ptr = 1;
209318334Speter		    return temp;
209418334Speter		  }
209518334Speter	      }
209618334Speter
209718334Speter	    strcpy (temp, pl->prefix);
209818334Speter	    strcat (temp, name);
209918334Speter	    if (access (temp, mode) == 0)
210018334Speter	      {
210118334Speter		if (pl->used_flag_ptr != 0)
210218334Speter		  *pl->used_flag_ptr = 1;
210318334Speter		return temp;
210418334Speter	      }
210518334Speter	  }
210618334Speter      }
210718334Speter
210818334Speter  free (temp);
210918334Speter  return 0;
211018334Speter}
211118334Speter
211218334Speter/* Add an entry for PREFIX in PLIST.  If FIRST is set, it goes
211318334Speter   at the start of the list, otherwise it goes at the end.
211418334Speter
211518334Speter   If WARN is nonzero, we will warn if no file is found
211618334Speter   through this prefix.  WARN should point to an int
211718334Speter   which will be set to 1 if this entry is used.
211818334Speter
211950599Sobrien   COMPONENT is the value to be passed to update_path.
212050599Sobrien
212118334Speter   REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without
212218334Speter   the complete value of machine_suffix.
212318334Speter   2 means try both machine_suffix and just_machine_suffix.  */
212418334Speter
212518334Speterstatic void
212650599Sobrienadd_prefix (pprefix, prefix, component, first, require_machine_suffix, warn)
212718334Speter     struct path_prefix *pprefix;
212852520Sobrien     const char *prefix;
212952520Sobrien     const char *component;
213018334Speter     int first;
213118334Speter     int require_machine_suffix;
213218334Speter     int *warn;
213318334Speter{
213418334Speter  struct prefix_list *pl, **prev;
213518334Speter  int len;
213618334Speter
213750599Sobrien  if (! first && pprefix->plist)
213818334Speter    {
213918334Speter      for (pl = pprefix->plist; pl->next; pl = pl->next)
214018334Speter	;
214118334Speter      prev = &pl->next;
214218334Speter    }
214318334Speter  else
214418334Speter    prev = &pprefix->plist;
214518334Speter
214618334Speter  /* Keep track of the longest prefix */
214718334Speter
214850599Sobrien  prefix = update_path (prefix, component);
214918334Speter  len = strlen (prefix);
215018334Speter  if (len > pprefix->max_len)
215118334Speter    pprefix->max_len = len;
215218334Speter
215318334Speter  pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
215418334Speter  pl->prefix = save_string (prefix, len);
215518334Speter  pl->require_machine_suffix = require_machine_suffix;
215618334Speter  pl->used_flag_ptr = warn;
215718334Speter  if (warn)
215818334Speter    *warn = 0;
215918334Speter
216018334Speter  if (*prev)
216118334Speter    pl->next = *prev;
216218334Speter  else
216318334Speter    pl->next = (struct prefix_list *) 0;
216418334Speter  *prev = pl;
216518334Speter}
216618334Speter
216718334Speter/* Print warnings for any prefixes in the list PPREFIX that were not used.  */
216818334Speter
216918334Speterstatic void
217018334Speterunused_prefix_warnings (pprefix)
217118334Speter     struct path_prefix *pprefix;
217218334Speter{
217318334Speter  struct prefix_list *pl = pprefix->plist;
217418334Speter
217518334Speter  while (pl)
217618334Speter    {
217718334Speter      if (pl->used_flag_ptr != 0 && !*pl->used_flag_ptr)
217818334Speter	{
217950599Sobrien	  if (pl->require_machine_suffix && machine_suffix)
218050599Sobrien	    error ("file path prefix `%s%s' never used", pl->prefix,
218150599Sobrien		   machine_suffix);
218250599Sobrien	  else
218350599Sobrien	    error ("file path prefix `%s' never used", pl->prefix);
218450599Sobrien
218518334Speter	  /* Prevent duplicate warnings.  */
218618334Speter	  *pl->used_flag_ptr = 1;
218718334Speter	}
218818334Speter
218918334Speter      pl = pl->next;
219018334Speter    }
219118334Speter}
219218334Speter
219318334Speter
219418334Speter/* Execute the command specified by the arguments on the current line of spec.
219518334Speter   When using pipes, this includes several piped-together commands
219618334Speter   with `|' between them.
219718334Speter
219818334Speter   Return 0 if successful, -1 if failed.  */
219918334Speter
220018334Speterstatic int
220118334Speterexecute ()
220218334Speter{
220318334Speter  int i;
220418334Speter  int n_commands;		/* # of command.  */
220518334Speter  char *string;
220618334Speter  struct command
220718334Speter    {
220852520Sobrien      const char *prog;		/* program name.  */
220952520Sobrien      char **argv;	/* vector of args.  */
221018334Speter      int pid;			/* pid of process for this command.  */
221118334Speter    };
221218334Speter
221318334Speter  struct command *commands;	/* each command buffer with above info.  */
221418334Speter
221518334Speter  /* Count # of piped commands.  */
221618334Speter  for (n_commands = 1, i = 0; i < argbuf_index; i++)
221718334Speter    if (strcmp (argbuf[i], "|") == 0)
221818334Speter      n_commands++;
221918334Speter
222018334Speter  /* Get storage for each command.  */
222118334Speter  commands
222218334Speter    = (struct command *) alloca (n_commands * sizeof (struct command));
222318334Speter
222418334Speter  /* Split argbuf into its separate piped processes,
222518334Speter     and record info about each one.
222618334Speter     Also search for the programs that are to be run.  */
222718334Speter
222818334Speter  commands[0].prog = argbuf[0]; /* first command.  */
222918334Speter  commands[0].argv = &argbuf[0];
223018334Speter  string = find_a_file (&exec_prefixes, commands[0].prog, X_OK);
223150599Sobrien
223218334Speter  if (string)
223318334Speter    commands[0].argv[0] = string;
223418334Speter
223518334Speter  for (n_commands = 1, i = 0; i < argbuf_index; i++)
223618334Speter    if (strcmp (argbuf[i], "|") == 0)
223718334Speter      {				/* each command.  */
223852520Sobrien#if defined (__MSDOS__) || defined (OS2) || defined (VMS)
223950599Sobrien        fatal ("-pipe not supported");
224018334Speter#endif
224118334Speter	argbuf[i] = 0;	/* termination of command args.  */
224218334Speter	commands[n_commands].prog = argbuf[i + 1];
224318334Speter	commands[n_commands].argv = &argbuf[i + 1];
224418334Speter	string = find_a_file (&exec_prefixes, commands[n_commands].prog, X_OK);
224518334Speter	if (string)
224618334Speter	  commands[n_commands].argv[0] = string;
224718334Speter	n_commands++;
224818334Speter      }
224918334Speter
225018334Speter  argbuf[argbuf_index] = 0;
225118334Speter
225218334Speter  /* If -v, print what we are about to do, and maybe query.  */
225318334Speter
225418334Speter  if (verbose_flag)
225518334Speter    {
225650599Sobrien      /* For help listings, put a blank line between sub-processes.  */
225750599Sobrien      if (print_help_list)
225850599Sobrien	fputc ('\n', stderr);
225950599Sobrien
226018334Speter      /* Print each piped command as a separate line.  */
226118334Speter      for (i = 0; i < n_commands ; i++)
226218334Speter	{
226318334Speter	  char **j;
226418334Speter
226518334Speter	  for (j = commands[i].argv; *j; j++)
226618334Speter	    fprintf (stderr, " %s", *j);
226718334Speter
226818334Speter	  /* Print a pipe symbol after all but the last command.  */
226918334Speter	  if (i + 1 != n_commands)
227018334Speter	    fprintf (stderr, " |");
227118334Speter	  fprintf (stderr, "\n");
227218334Speter	}
227318334Speter      fflush (stderr);
227418334Speter#ifdef DEBUG
227552520Sobrien      notice ("\nGo ahead? (y or n) ");
227618334Speter      fflush (stderr);
227718334Speter      i = getchar ();
227818334Speter      if (i != '\n')
227950599Sobrien	while (getchar () != '\n')
228050599Sobrien	  ;
228150599Sobrien
228218334Speter      if (i != 'y' && i != 'Y')
228318334Speter	return 0;
228418334Speter#endif /* DEBUG */
228518334Speter    }
228618334Speter
228718334Speter  /* Run each piped subprocess.  */
228818334Speter
228918334Speter  for (i = 0; i < n_commands; i++)
229018334Speter    {
229150599Sobrien      char *errmsg_fmt, *errmsg_arg;
229218334Speter      char *string = commands[i].argv[0];
229318334Speter
229450599Sobrien      commands[i].pid = pexecute (string, commands[i].argv,
229550599Sobrien				  programname, temp_filename,
229650599Sobrien				  &errmsg_fmt, &errmsg_arg,
229750599Sobrien				  ((i == 0 ? PEXECUTE_FIRST : 0)
229850599Sobrien				   | (i + 1 == n_commands ? PEXECUTE_LAST : 0)
229950599Sobrien				   | (string == commands[i].prog
230050599Sobrien				      ? PEXECUTE_SEARCH : 0)
230150599Sobrien				   | (verbose_flag ? PEXECUTE_VERBOSE : 0)));
230218334Speter
230350599Sobrien      if (commands[i].pid == -1)
230450599Sobrien	pfatal_pexecute (errmsg_fmt, errmsg_arg);
230550599Sobrien
230618334Speter      if (string != commands[i].prog)
230718334Speter	free (string);
230818334Speter    }
230918334Speter
231018334Speter  execution_count++;
231118334Speter
231218334Speter  /* Wait for all the subprocesses to finish.
231318334Speter     We don't care what order they finish in;
231418334Speter     we know that N_COMMANDS waits will get them all.
231518334Speter     Ignore subprocesses that we don't know about,
231618334Speter     since they can be spawned by the process that exec'ed us.  */
231718334Speter
231818334Speter  {
231918334Speter    int ret_code = 0;
232018334Speter
232118334Speter    for (i = 0; i < n_commands; )
232218334Speter      {
232318334Speter	int j;
232418334Speter	int status;
232518334Speter	int pid;
232618334Speter
232750599Sobrien	pid = pwait (commands[i].pid, &status, 0);
232818334Speter	if (pid < 0)
232918334Speter	  abort ();
233018334Speter
233118334Speter	for (j = 0; j < n_commands; j++)
233218334Speter	  if (commands[j].pid == pid)
233318334Speter	    {
233418334Speter	      i++;
233518334Speter	      if (status != 0)
233618334Speter		{
233718334Speter		  if (WIFSIGNALED (status))
233818334Speter		    {
233918334Speter		      fatal ("Internal compiler error: program %s got fatal signal %d",
234018334Speter			     commands[j].prog, WTERMSIG (status));
234118334Speter		      signal_count++;
234218334Speter		      ret_code = -1;
234318334Speter		    }
234418334Speter		  else if (WIFEXITED (status)
234518334Speter			   && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
234618334Speter		    ret_code = -1;
234718334Speter		}
234818334Speter	      break;
234918334Speter	    }
235018334Speter      }
235118334Speter    return ret_code;
235218334Speter  }
235318334Speter}
235418334Speter
235518334Speter/* Find all the switches given to us
235618334Speter   and make a vector describing them.
235718334Speter   The elements of the vector are strings, one per switch given.
235818334Speter   If a switch uses following arguments, then the `part1' field
235918334Speter   is the switch itself and the `args' field
236018334Speter   is a null-terminated vector containing the following arguments.
236118334Speter   The `live_cond' field is 1 if the switch is true in a conditional spec,
236218334Speter   -1 if false (overridden by a later switch), and is initialized to zero.
236352520Sobrien   The `validated' field is nonzero if any spec has looked at this switch;
236418334Speter   if it remains zero at the end of the run, it must be meaningless.  */
236518334Speter
236618334Speterstruct switchstr
236718334Speter{
236852520Sobrien  const char *part1;
236918334Speter  char **args;
237018334Speter  int live_cond;
237152520Sobrien  int validated;
237218334Speter};
237318334Speter
237418334Speterstatic struct switchstr *switches;
237518334Speter
237618334Speterstatic int n_switches;
237718334Speter
237818334Speterstruct infile
237918334Speter{
238052520Sobrien  const char *name;
238152520Sobrien  const char *language;
238218334Speter};
238318334Speter
238418334Speter/* Also a vector of input files specified.  */
238518334Speter
238618334Speterstatic struct infile *infiles;
238718334Speter
238818334Speterstatic int n_infiles;
238918334Speter
239052520Sobrien/* This counts the number of libraries added by lang_specific_driver, so that
239150599Sobrien   we can tell if there were any user supplied any files or libraries.  */
239250599Sobrien
239350599Sobrienstatic int added_libraries;
239450599Sobrien
239518334Speter/* And a vector of corresponding output files is made up later.  */
239618334Speter
239752520Sobrienstatic const char **outfiles;
239818334Speter
239950599Sobrien/* Used to track if none of the -B paths are used.  */
240050599Sobrienstatic int warn_B;
240150599Sobrien
240250599Sobrien/* Used to track if standard path isn't used and -b or -V is specified.  */
240350599Sobrienstatic int warn_std;
240450599Sobrien
240550599Sobrien/* Gives value to pass as "warn" to add_prefix for standard prefixes.  */
240650599Sobrienstatic int *warn_std_ptr = 0;
240750599Sobrien
240853878Sobrien#if defined(FREEBSD_NATIVE)
240953878Sobrien#include <objformat.h>
241053878Sobrien
241153878Sobrientypedef enum { OBJFMT_UNKNOWN, OBJFMT_AOUT, OBJFMT_ELF } objf_t;
241253878Sobrien
241353878Sobrienstatic objf_t objformat = OBJFMT_UNKNOWN;
241450599Sobrien#endif
241550599Sobrien
241650599Sobrien#if defined(HAVE_OBJECT_SUFFIX) || defined(HAVE_EXECUTABLE_SUFFIX)
241750599Sobrien
241850599Sobrien/* Convert NAME to a new name if it is the standard suffix.  DO_EXE
241950599Sobrien   is true if we should look for an executable suffix as well.  */
242050599Sobrien
242150599Sobrienstatic char *
242250599Sobrienconvert_filename (name, do_exe)
242350599Sobrien     char *name;
242450599Sobrien     int do_exe;
242550599Sobrien{
242650599Sobrien  int i;
242752520Sobrien  int len;
242850599Sobrien
242952520Sobrien  if (name == NULL)
243052520Sobrien    return NULL;
243152520Sobrien
243252520Sobrien  len = strlen (name);
243352520Sobrien
243450599Sobrien#ifdef HAVE_OBJECT_SUFFIX
243550599Sobrien  /* Convert x.o to x.obj if OBJECT_SUFFIX is ".obj".  */
243650599Sobrien  if (len > 2
243750599Sobrien      && name[len - 2] == '.'
243850599Sobrien      && name[len - 1] == 'o')
243950599Sobrien    {
244050599Sobrien      obstack_grow (&obstack, name, len - 2);
244150599Sobrien      obstack_grow0 (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX));
244250599Sobrien      name = obstack_finish (&obstack);
244350599Sobrien    }
244450599Sobrien#endif
244550599Sobrien
244650599Sobrien#ifdef HAVE_EXECUTABLE_SUFFIX
244750599Sobrien  /* If there is no filetype, make it the executable suffix (which includes
244850599Sobrien     the ".").  But don't get confused if we have just "-o".  */
244950599Sobrien  if (! do_exe || EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-'))
245050599Sobrien    return name;
245150599Sobrien
245250599Sobrien  for (i = len - 1; i >= 0; i--)
245352520Sobrien    if (IS_DIR_SEPARATOR (name[i]))
245450599Sobrien      break;
245550599Sobrien
245650599Sobrien  for (i++; i < len; i++)
245750599Sobrien    if (name[i] == '.')
245850599Sobrien      return name;
245950599Sobrien
246050599Sobrien  obstack_grow (&obstack, name, len);
246150599Sobrien  obstack_grow0 (&obstack, EXECUTABLE_SUFFIX, strlen (EXECUTABLE_SUFFIX));
246250599Sobrien  name = obstack_finish (&obstack);
246350599Sobrien#endif
246450599Sobrien
246550599Sobrien  return name;
246650599Sobrien}
246750599Sobrien#endif
246850599Sobrien
246950599Sobrien/* Display the command line switches accepted by gcc.  */
247050599Sobrienstatic void
247150599Sobriendisplay_help ()
247250599Sobrien{
247350599Sobrien  printf ("Usage: %s [options] file...\n", programname);
247450599Sobrien  printf ("Options:\n");
247550599Sobrien
247650599Sobrien  printf ("  --help                   Display this information\n");
247750599Sobrien  if (! verbose_flag)
247850599Sobrien    printf ("  (Use '-v --help' to display command line options of sub-processes)\n");
247950599Sobrien  printf ("  -dumpspecs               Display all of the built in spec strings\n");
248050599Sobrien  printf ("  -dumpversion             Display the version of the compiler\n");
248150599Sobrien  printf ("  -dumpmachine             Display the compiler's target processor\n");
248250599Sobrien  printf ("  -print-search-dirs       Display the directories in the compiler's search path\n");
248350599Sobrien  printf ("  -print-libgcc-file-name  Display the name of the compiler's companion library\n");
248450599Sobrien  printf ("  -print-file-name=<lib>   Display the full path to library <lib>\n");
248550599Sobrien  printf ("  -print-prog-name=<prog>  Display the full path to compiler component <prog>\n");
248650599Sobrien  printf ("  -print-multi-directory   Display the root directory for versions of libgcc\n");
248750599Sobrien  printf ("  -print-multi-lib         Display the mapping between command line options and\n");
248850599Sobrien  printf ("                            multiple library search directories\n");
248950599Sobrien  printf ("  -Wa,<options>            Pass comma-separated <options> on to the assembler\n");
249050599Sobrien  printf ("  -Wp,<options>            Pass comma-separated <options> on to the preprocessor\n");
249150599Sobrien  printf ("  -Wl,<options>            Pass comma-separated <options> on to the linker\n");
249250599Sobrien  printf ("  -Xlinker <arg>           Pass <arg> on to the linker\n");
249350599Sobrien  printf ("  -save-temps              Do not delete intermediate files\n");
249450599Sobrien  printf ("  -pipe                    Use pipes rather than intermediate files\n");
249550599Sobrien  printf ("  -specs=<file>            Override builtin specs with the contents of <file>\n");
249652520Sobrien  printf ("  -std=<standard>          Assume that the input sources are for <standard>\n");
249750599Sobrien  printf ("  -B <directory>           Add <directory> to the compiler's search paths\n");
249850599Sobrien  printf ("  -b <machine>             Run gcc for target <machine>, if installed\n");
249950599Sobrien  printf ("  -V <version>             Run gcc version number <version>, if installed\n");
250050599Sobrien  printf ("  -v                       Display the programs invoked by the compiler\n");
250150599Sobrien  printf ("  -E                       Preprocess only; do not compile, assemble or link\n");
250250599Sobrien  printf ("  -S                       Compile only; do not assemble or link\n");
250350599Sobrien  printf ("  -c                       Compile and assemble, but do not link\n");
250450599Sobrien  printf ("  -o <file>                Place the output into <file>\n");
250550599Sobrien  printf ("  -x <language>            Specify the language of the following input files\n");
250650599Sobrien  printf ("                            Permissable languages include: c c++ assembler none\n");
250750599Sobrien  printf ("                            'none' means revert to the default behaviour of\n");
250850599Sobrien  printf ("                            guessing the language based on the file's extension\n");
250950599Sobrien
251050599Sobrien  printf ("\nOptions starting with -g, -f, -m, -O or -W are automatically passed on to\n");
251150599Sobrien  printf ("the various sub-processes invoked by %s.  In order to pass other options\n",
251250599Sobrien	  programname);
251350599Sobrien  printf ("on to these processes the -W<letter> options must be used.\n");
251450599Sobrien
251550599Sobrien  /* The rest of the options are displayed by invocations of the various
251650599Sobrien     sub-processes.  */
251750599Sobrien}
251850599Sobrien
251950599Sobrienstatic void
252050599Sobrienadd_preprocessor_option (option, len)
252152520Sobrien     const char * option;
252252520Sobrien     int len;
252350599Sobrien{
252452520Sobrien  n_preprocessor_options++;
252550599Sobrien
252652520Sobrien  if (! preprocessor_options)
252752520Sobrien    preprocessor_options
252852520Sobrien      = (char **) xmalloc (n_preprocessor_options * sizeof (char *));
252952520Sobrien  else
253052520Sobrien    preprocessor_options
253152520Sobrien      = (char **) xrealloc (preprocessor_options,
253252520Sobrien			    n_preprocessor_options * sizeof (char *));
253350599Sobrien
253452520Sobrien  preprocessor_options [n_preprocessor_options - 1] =
253552520Sobrien    save_string (option, len);
253650599Sobrien}
253750599Sobrien
253850599Sobrienstatic void
253950599Sobrienadd_assembler_option (option, len)
254052520Sobrien     const char * option;
254152520Sobrien     int len;
254252520Sobrien{
254352520Sobrien  n_assembler_options++;
254452520Sobrien
254552520Sobrien  if (! assembler_options)
254652520Sobrien    assembler_options
254752520Sobrien      = (char **) xmalloc (n_assembler_options * sizeof (char *));
254852520Sobrien  else
254952520Sobrien    assembler_options
255052520Sobrien      = (char **) xrealloc (assembler_options,
255152520Sobrien			    n_assembler_options * sizeof (char *));
255252520Sobrien
255352520Sobrien  assembler_options [n_assembler_options - 1] = save_string (option, len);
255450599Sobrien}
255550599Sobrien
255650599Sobrienstatic void
255750599Sobrienadd_linker_option (option, len)
255852520Sobrien     const char * option;
255952520Sobrien     int    len;
256052520Sobrien{
256152520Sobrien  n_linker_options++;
256252520Sobrien
256352520Sobrien  if (! linker_options)
256452520Sobrien    linker_options
256552520Sobrien      = (char **) xmalloc (n_linker_options * sizeof (char *));
256652520Sobrien  else
256752520Sobrien    linker_options
256852520Sobrien      = (char **) xrealloc (linker_options,
256952520Sobrien			    n_linker_options * sizeof (char *));
257052520Sobrien
257152520Sobrien  linker_options [n_linker_options - 1] = save_string (option, len);
257250599Sobrien}
257350599Sobrien
257418334Speter/* Create the vector `switches' and its contents.
257518334Speter   Store its length in `n_switches'.  */
257618334Speter
257718334Speterstatic void
257818334Speterprocess_command (argc, argv)
257918334Speter     int argc;
258018334Speter     char **argv;
258118334Speter{
258218334Speter  register int i;
258352520Sobrien  const char *temp;
258452520Sobrien  char *temp1;
258518334Speter  char *spec_lang = 0;
258618334Speter  int last_language_n_infiles;
258750599Sobrien  int have_c = 0;
258850599Sobrien  int have_o = 0;
258950599Sobrien  int lang_n_infiles = 0;
259018334Speter
259152520Sobrien  GET_ENV_PATH_LIST (gcc_exec_prefix, "GCC_EXEC_PREFIX");
259218334Speter
259318334Speter  n_switches = 0;
259418334Speter  n_infiles = 0;
259550599Sobrien  added_libraries = 0;
259618334Speter
259718334Speter  /* Figure compiler version from version string.  */
259818334Speter
259952520Sobrien  compiler_version = temp1 =
260052520Sobrien    save_string (version_string, strlen (version_string));
260152520Sobrien  for (; *temp1; ++temp1)
260218334Speter    {
260352520Sobrien      if (*temp1 == ' ')
260418334Speter	{
260552520Sobrien	  *temp1 = '\0';
260618334Speter	  break;
260718334Speter	}
260818334Speter    }
260918334Speter
261018334Speter  /* Set up the default search paths.  */
261118334Speter
261218334Speter  if (gcc_exec_prefix)
261318334Speter    {
261450599Sobrien      int len = strlen (gcc_exec_prefix);
261552520Sobrien      if (len > (int) sizeof ("/lib/gcc-lib/")-1
261652520Sobrien	  && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1])))
261750599Sobrien	{
261850599Sobrien	  temp = gcc_exec_prefix + len - sizeof ("/lib/gcc-lib/") + 1;
261952520Sobrien	  if (IS_DIR_SEPARATOR (*temp)
262050599Sobrien	      && strncmp (temp+1, "lib", 3) == 0
262152520Sobrien	      && IS_DIR_SEPARATOR (temp[4])
262250599Sobrien	      && strncmp (temp+5, "gcc-lib", 7) == 0)
262350599Sobrien	    len -= sizeof ("/lib/gcc-lib/") - 1;
262450599Sobrien	}
262550599Sobrien
262650599Sobrien      set_std_prefix (gcc_exec_prefix, len);
262750599Sobrien      add_prefix (&exec_prefixes, gcc_exec_prefix, "GCC", 0, 0, NULL_PTR);
262850599Sobrien      add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC", 0, 0, NULL_PTR);
262918334Speter    }
263018334Speter
263118334Speter  /* COMPILER_PATH and LIBRARY_PATH have values
263218334Speter     that are lists of directory names with colons.  */
263318334Speter
263452520Sobrien  GET_ENV_PATH_LIST (temp, "COMPILER_PATH");
263518334Speter  if (temp)
263618334Speter    {
263752520Sobrien      const char *startp, *endp;
263818334Speter      char *nstore = (char *) alloca (strlen (temp) + 3);
263918334Speter
264018334Speter      startp = endp = temp;
264118334Speter      while (1)
264218334Speter	{
264318334Speter	  if (*endp == PATH_SEPARATOR || *endp == 0)
264418334Speter	    {
264518334Speter	      strncpy (nstore, startp, endp-startp);
264618334Speter	      if (endp == startp)
264750599Sobrien		strcpy (nstore, concat (".", dir_separator_str, NULL_PTR));
264852520Sobrien	      else if (!IS_DIR_SEPARATOR (endp[-1]))
264918334Speter		{
265018334Speter		  nstore[endp-startp] = DIR_SEPARATOR;
265118334Speter		  nstore[endp-startp+1] = 0;
265218334Speter		}
265318334Speter	      else
265418334Speter		nstore[endp-startp] = 0;
265550599Sobrien	      add_prefix (&exec_prefixes, nstore, 0, 0, 0, NULL_PTR);
265650599Sobrien	      add_prefix (&include_prefixes,
265750599Sobrien			  concat (nstore, "include", NULL_PTR),
265850599Sobrien			  0, 0, 0, NULL_PTR);
265918334Speter	      if (*endp == 0)
266018334Speter		break;
266118334Speter	      endp = startp = endp + 1;
266218334Speter	    }
266318334Speter	  else
266418334Speter	    endp++;
266518334Speter	}
266618334Speter    }
266718334Speter
266852520Sobrien  GET_ENV_PATH_LIST (temp, "LIBRARY_PATH");
266955220Sobrien  if (temp)
267018334Speter    {
267152520Sobrien      const char *startp, *endp;
267218334Speter      char *nstore = (char *) alloca (strlen (temp) + 3);
267318334Speter
267418334Speter      startp = endp = temp;
267518334Speter      while (1)
267618334Speter	{
267718334Speter	  if (*endp == PATH_SEPARATOR || *endp == 0)
267818334Speter	    {
267918334Speter	      strncpy (nstore, startp, endp-startp);
268018334Speter	      if (endp == startp)
268150599Sobrien		strcpy (nstore, concat (".", dir_separator_str, NULL_PTR));
268252520Sobrien	      else if (!IS_DIR_SEPARATOR (endp[-1]))
268318334Speter		{
268418334Speter		  nstore[endp-startp] = DIR_SEPARATOR;
268518334Speter		  nstore[endp-startp+1] = 0;
268618334Speter		}
268718334Speter	      else
268818334Speter		nstore[endp-startp] = 0;
268950599Sobrien	      add_prefix (&startfile_prefixes, nstore, NULL_PTR,
269050599Sobrien			  0, 0, NULL_PTR);
269118334Speter	      if (*endp == 0)
269218334Speter		break;
269318334Speter	      endp = startp = endp + 1;
269418334Speter	    }
269518334Speter	  else
269618334Speter	    endp++;
269718334Speter	}
269818334Speter    }
269918334Speter
270018334Speter  /* Use LPATH like LIBRARY_PATH (for the CMU build program).  */
270152520Sobrien  GET_ENV_PATH_LIST (temp, "LPATH");
270250599Sobrien  if (temp && *cross_compile == '0')
270318334Speter    {
270452520Sobrien      const char *startp, *endp;
270518334Speter      char *nstore = (char *) alloca (strlen (temp) + 3);
270618334Speter
270718334Speter      startp = endp = temp;
270818334Speter      while (1)
270918334Speter	{
271018334Speter	  if (*endp == PATH_SEPARATOR || *endp == 0)
271118334Speter	    {
271218334Speter	      strncpy (nstore, startp, endp-startp);
271318334Speter	      if (endp == startp)
271450599Sobrien		strcpy (nstore, concat (".", dir_separator_str, NULL_PTR));
271552520Sobrien	      else if (!IS_DIR_SEPARATOR (endp[-1]))
271618334Speter		{
271718334Speter		  nstore[endp-startp] = DIR_SEPARATOR;
271818334Speter		  nstore[endp-startp+1] = 0;
271918334Speter		}
272018334Speter	      else
272118334Speter		nstore[endp-startp] = 0;
272250599Sobrien	      add_prefix (&startfile_prefixes, nstore, NULL_PTR,
272350599Sobrien			  0, 0, NULL_PTR);
272418334Speter	      if (*endp == 0)
272518334Speter		break;
272618334Speter	      endp = startp = endp + 1;
272718334Speter	    }
272818334Speter	  else
272918334Speter	    endp++;
273018334Speter	}
273118334Speter    }
273218334Speter
273353878Sobrien#if defined(FREEBSD_NATIVE)
273434229Speter  {
273553878Sobrien    char buf[64];
273653878Sobrien    if (getobjformat (buf, sizeof buf, &argc, argv))
273753878Sobrien      if (strcmp (buf, "aout") == 0)
273853878Sobrien        objformat = OBJFMT_AOUT;
273953878Sobrien      else if (strcmp (buf, "elf") == 0)
274053878Sobrien        objformat = OBJFMT_ELF;
274134229Speter      else
274253878Sobrien        fprintf(stderr, "Unrecognized object format: %s\n", buf);
274334229Speter  }
274434229Speter#endif
274550599Sobrien
274618334Speter  /* Convert new-style -- options to old-style.  */
274718334Speter  translate_options (&argc, &argv);
274818334Speter
274950599Sobrien  /* Do language-specific adjustment/addition of flags.  */
275050599Sobrien  lang_specific_driver (fatal, &argc, &argv, &added_libraries);
275150599Sobrien
275218334Speter  /* Scan argv twice.  Here, the first time, just count how many switches
275318334Speter     there will be in their vector, and how many input files in theirs.
275418334Speter     Here we also parse the switches that cc itself uses (e.g. -v).  */
275518334Speter
275618334Speter  for (i = 1; i < argc; i++)
275718334Speter    {
275818334Speter      if (! strcmp (argv[i], "-dumpspecs"))
275918334Speter	{
276050599Sobrien	  struct spec_list *sl;
276150599Sobrien	  init_spec ();
276250599Sobrien	  for (sl = specs; sl; sl = sl->next)
276350599Sobrien	    printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec));
276452520Sobrien          if (link_command_spec)
276552520Sobrien            printf ("*link_command:\n%s\n\n", link_command_spec);
276618334Speter	  exit (0);
276718334Speter	}
276818334Speter      else if (! strcmp (argv[i], "-dumpversion"))
276918334Speter	{
277050599Sobrien	  printf ("%s\n", spec_version);
277118334Speter	  exit (0);
277218334Speter	}
277318334Speter      else if (! strcmp (argv[i], "-dumpmachine"))
277418334Speter	{
277518334Speter	  printf ("%s\n", spec_machine);
277618334Speter	  exit  (0);
277718334Speter	}
277850599Sobrien      else if (strcmp (argv[i], "-fhelp") == 0)
277950599Sobrien	{
278050599Sobrien	  /* translate_options () has turned --help into -fhelp.  */
278150599Sobrien	  print_help_list = 1;
278250599Sobrien
278350599Sobrien	  /* We will be passing a dummy file on to the sub-processes.  */
278450599Sobrien	  n_infiles++;
278550599Sobrien	  n_switches++;
278650599Sobrien
278750599Sobrien	  add_preprocessor_option ("--help", 6);
278850599Sobrien	  add_assembler_option ("--help", 6);
278950599Sobrien	  add_linker_option ("--help", 6);
279050599Sobrien	}
279118334Speter      else if (! strcmp (argv[i], "-print-search-dirs"))
279218334Speter	print_search_dirs = 1;
279318334Speter      else if (! strcmp (argv[i], "-print-libgcc-file-name"))
279418334Speter	print_file_name = "libgcc.a";
279518334Speter      else if (! strncmp (argv[i], "-print-file-name=", 17))
279618334Speter	print_file_name = argv[i] + 17;
279718334Speter      else if (! strncmp (argv[i], "-print-prog-name=", 17))
279818334Speter	print_prog_name = argv[i] + 17;
279918334Speter      else if (! strcmp (argv[i], "-print-multi-lib"))
280018334Speter	print_multi_lib = 1;
280118334Speter      else if (! strcmp (argv[i], "-print-multi-directory"))
280218334Speter	print_multi_directory = 1;
280318334Speter      else if (! strncmp (argv[i], "-Wa,", 4))
280418334Speter	{
280518334Speter	  int prev, j;
280618334Speter	  /* Pass the rest of this option to the assembler.  */
280718334Speter
280818334Speter	  /* Split the argument at commas.  */
280918334Speter	  prev = 4;
281018334Speter	  for (j = 4; argv[i][j]; j++)
281118334Speter	    if (argv[i][j] == ',')
281218334Speter	      {
281350599Sobrien		add_assembler_option (argv[i] + prev, j - prev);
281418334Speter		prev = j + 1;
281518334Speter	      }
281650599Sobrien
281718334Speter	  /* Record the part after the last comma.  */
281850599Sobrien	  add_assembler_option (argv[i] + prev, j - prev);
281918334Speter	}
282018334Speter      else if (! strncmp (argv[i], "-Wp,", 4))
282118334Speter	{
282218334Speter	  int prev, j;
282318334Speter	  /* Pass the rest of this option to the preprocessor.  */
282418334Speter
282518334Speter	  /* Split the argument at commas.  */
282618334Speter	  prev = 4;
282718334Speter	  for (j = 4; argv[i][j]; j++)
282818334Speter	    if (argv[i][j] == ',')
282918334Speter	      {
283050599Sobrien		add_preprocessor_option (argv[i] + prev, j - prev);
283118334Speter		prev = j + 1;
283218334Speter	      }
283350599Sobrien
283418334Speter	  /* Record the part after the last comma.  */
283550599Sobrien	  add_preprocessor_option (argv[i] + prev, j - prev);
283618334Speter	}
283718334Speter      else if (argv[i][0] == '+' && argv[i][1] == 'e')
283818334Speter	/* The +e options to the C++ front-end.  */
283918334Speter	n_switches++;
284018334Speter      else if (strncmp (argv[i], "-Wl,", 4) == 0)
284118334Speter	{
284218334Speter	  int j;
284318334Speter	  /* Split the argument at commas.  */
284418334Speter	  for (j = 3; argv[i][j]; j++)
284518334Speter	    n_infiles += (argv[i][j] == ',');
284618334Speter	}
284718334Speter      else if (strcmp (argv[i], "-Xlinker") == 0)
284818334Speter	{
284918334Speter	  if (i + 1 == argc)
285018334Speter	    fatal ("argument to `-Xlinker' is missing");
285118334Speter
285218334Speter	  n_infiles++;
285318334Speter	  i++;
285418334Speter	}
285518334Speter      else if (strncmp (argv[i], "-l", 2) == 0)
285618334Speter	n_infiles++;
285750599Sobrien      else if (strcmp (argv[i], "-save-temps") == 0)
285850599Sobrien	{
285950599Sobrien	  save_temps_flag = 1;
286050599Sobrien	  n_switches++;
286150599Sobrien	}
286250599Sobrien      else if (strcmp (argv[i], "-specs") == 0)
286350599Sobrien	{
286450599Sobrien	  struct user_specs *user = (struct user_specs *)
286550599Sobrien	    xmalloc (sizeof (struct user_specs));
286650599Sobrien	  if (++i >= argc)
286750599Sobrien	    fatal ("argument to `-specs' is missing");
286850599Sobrien
286950599Sobrien	  user->next = (struct user_specs *)0;
287050599Sobrien	  user->filename = argv[i];
287150599Sobrien	  if (user_specs_tail)
287250599Sobrien	    user_specs_tail->next = user;
287350599Sobrien	  else
287450599Sobrien	    user_specs_head = user;
287550599Sobrien	  user_specs_tail = user;
287650599Sobrien	}
287750599Sobrien      else if (strncmp (argv[i], "-specs=", 7) == 0)
287850599Sobrien	{
287950599Sobrien	  struct user_specs *user = (struct user_specs *)
288050599Sobrien	    xmalloc (sizeof (struct user_specs));
288150599Sobrien	  if (strlen (argv[i]) == 7)
288250599Sobrien	    fatal ("argument to `-specs=' is missing");
288350599Sobrien
288450599Sobrien	  user->next = (struct user_specs *)0;
288550599Sobrien	  user->filename = argv[i]+7;
288650599Sobrien	  if (user_specs_tail)
288750599Sobrien	    user_specs_tail->next = user;
288850599Sobrien	  else
288950599Sobrien	    user_specs_head = user;
289050599Sobrien	  user_specs_tail = user;
289150599Sobrien	}
289218334Speter      else if (argv[i][0] == '-' && argv[i][1] != 0)
289318334Speter	{
289418334Speter	  register char *p = &argv[i][1];
289518334Speter	  register int c = *p;
289618334Speter
289718334Speter	  switch (c)
289818334Speter	    {
289918334Speter	    case 'b':
290050599Sobrien              n_switches++;
290118334Speter	      if (p[1] == 0 && i + 1 == argc)
290218334Speter		fatal ("argument to `-b' is missing");
290318334Speter	      if (p[1] == 0)
290418334Speter		spec_machine = argv[++i];
290518334Speter	      else
290618334Speter		spec_machine = p + 1;
290750599Sobrien
290850599Sobrien	      warn_std_ptr = &warn_std;
290918334Speter	      break;
291018334Speter
291118334Speter	    case 'B':
291218334Speter	      {
291318334Speter		char *value;
291418334Speter		if (p[1] == 0 && i + 1 == argc)
291518334Speter		  fatal ("argument to `-B' is missing");
291618334Speter		if (p[1] == 0)
291718334Speter		  value = argv[++i];
291818334Speter		else
291918334Speter		  value = p + 1;
292050599Sobrien		add_prefix (&exec_prefixes, value, NULL_PTR, 1, 0, &warn_B);
292150599Sobrien		add_prefix (&startfile_prefixes, value, NULL_PTR,
292250599Sobrien			    1, 0, &warn_B);
292350599Sobrien		add_prefix (&include_prefixes, concat (value, "include",
292450599Sobrien						       NULL_PTR),
292550599Sobrien			    NULL_PTR, 1, 0, NULL_PTR);
292618334Speter
292718334Speter		/* As a kludge, if the arg is "[foo/]stageN/", just add
292818334Speter		   "[foo/]include" to the include prefix.  */
292918334Speter		{
293018334Speter		  int len = strlen (value);
293118334Speter		  if ((len == 7
293218334Speter		       || (len > 7
293352520Sobrien			   && (IS_DIR_SEPARATOR (value[len - 8]))))
293418334Speter		      && strncmp (value + len - 7, "stage", 5) == 0
293550599Sobrien		      && ISDIGIT (value[len - 2])
293652520Sobrien		      && (IS_DIR_SEPARATOR (value[len - 1])))
293718334Speter		    {
293818334Speter		      if (len == 7)
293950599Sobrien			add_prefix (&include_prefixes, "include", NULL_PTR,
294050599Sobrien				    1, 0, NULL_PTR);
294118334Speter		      else
294218334Speter			{
294318334Speter			  char *string = xmalloc (len + 1);
294418334Speter			  strncpy (string, value, len-7);
294550599Sobrien			  strcpy (string+len-7, "include");
294650599Sobrien			  add_prefix (&include_prefixes, string, NULL_PTR,
294750599Sobrien				      1, 0, NULL_PTR);
294818334Speter			}
294918334Speter		    }
295018334Speter		}
295150599Sobrien                n_switches++;
295218334Speter	      }
295318334Speter	      break;
295418334Speter
295518334Speter	    case 'v':	/* Print our subcommands and print versions.  */
295618334Speter	      n_switches++;
295718334Speter	      /* If they do anything other than exactly `-v', don't set
295818334Speter		 verbose_flag; rather, continue on to give the error.  */
295918334Speter	      if (p[1] != 0)
296018334Speter		break;
296118334Speter	      verbose_flag++;
296218334Speter	      break;
296318334Speter
296418334Speter	    case 'V':
296550599Sobrien	      n_switches++;
296618334Speter	      if (p[1] == 0 && i + 1 == argc)
296718334Speter		fatal ("argument to `-V' is missing");
296818334Speter	      if (p[1] == 0)
296918334Speter		spec_version = argv[++i];
297018334Speter	      else
297118334Speter		spec_version = p + 1;
297218334Speter	      compiler_version = spec_version;
297350599Sobrien	      warn_std_ptr = &warn_std;
297450599Sobrien
297550599Sobrien	      /* Validate the version number.  Use the same checks
297650599Sobrien		 done when inserting it into a spec.
297750599Sobrien
297850599Sobrien		 The format of the version string is
297950599Sobrien		 ([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)?  */
298050599Sobrien	      {
298152520Sobrien		const char *v = compiler_version;
298250599Sobrien
298350599Sobrien		/* Ignore leading non-digits.  i.e. "foo-" in "foo-2.7.2".  */
298450599Sobrien		while (! ISDIGIT (*v))
298550599Sobrien		  v++;
298650599Sobrien
298750599Sobrien		if (v > compiler_version && v[-1] != '-')
298850599Sobrien		  fatal ("invalid version number format");
298950599Sobrien
299050599Sobrien		/* Set V after the first period.  */
299150599Sobrien		while (ISDIGIT (*v))
299250599Sobrien		  v++;
299350599Sobrien
299450599Sobrien		if (*v != '.')
299550599Sobrien		  fatal ("invalid version number format");
299650599Sobrien
299750599Sobrien		v++;
299850599Sobrien		while (ISDIGIT (*v))
299950599Sobrien		  v++;
300050599Sobrien
300150599Sobrien		if (*v != 0 && *v != ' ' && *v != '.' && *v != '-')
300250599Sobrien		  fatal ("invalid version number format");
300350599Sobrien	      }
300418334Speter	      break;
300518334Speter
300650599Sobrien	    case 'S':
300750599Sobrien	    case 'c':
300850599Sobrien	      if (p[1] == 0)
300918334Speter		{
301050599Sobrien		  have_c = 1;
301118334Speter		  n_switches++;
301218334Speter		  break;
301318334Speter		}
301450599Sobrien	      goto normal_switch;
301550599Sobrien
301650599Sobrien	    case 'o':
301750599Sobrien	      have_o = 1;
301850599Sobrien#if defined(HAVE_EXECUTABLE_SUFFIX)
301950599Sobrien	      if (! have_c)
302050599Sobrien		{
302150599Sobrien		  int skip;
302250599Sobrien
302350599Sobrien		  /* Forward scan, just in case -S or -c is specified
302450599Sobrien		     after -o.  */
302550599Sobrien		  int j = i + 1;
302650599Sobrien		  if (p[1] == 0)
302750599Sobrien		    ++j;
302850599Sobrien		  while (j < argc)
302950599Sobrien		    {
303050599Sobrien		      if (argv[j][0] == '-')
303150599Sobrien			{
303250599Sobrien			  if (SWITCH_CURTAILS_COMPILATION (argv[j][1])
303350599Sobrien			      && argv[j][2] == 0)
303450599Sobrien			    {
303550599Sobrien			      have_c = 1;
303650599Sobrien			      break;
303750599Sobrien			    }
303850599Sobrien			  else if (skip = SWITCH_TAKES_ARG (argv[j][1]))
303950599Sobrien			    j += skip - (argv[j][2] != 0);
304050599Sobrien			  else if (skip = WORD_SWITCH_TAKES_ARG (argv[j] + 1))
304150599Sobrien			    j += skip;
304250599Sobrien			}
304350599Sobrien		      j++;
304450599Sobrien		    }
304550599Sobrien		}
304650599Sobrien#endif
304750599Sobrien#if defined(HAVE_EXECUTABLE_SUFFIX) || defined(HAVE_OBJECT_SUFFIX)
304850599Sobrien	      if (p[1] == 0)
304950599Sobrien		argv[i+1] = convert_filename (argv[i+1], ! have_c);
305050599Sobrien	      else
305150599Sobrien		argv[i] = convert_filename (argv[i], ! have_c);
305250599Sobrien#endif
305350599Sobrien	      goto normal_switch;
305450599Sobrien
305518334Speter	    default:
305650599Sobrien	    normal_switch:
305718334Speter	      n_switches++;
305818334Speter
305918334Speter	      if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
306018334Speter		i += SWITCH_TAKES_ARG (c) - (p[1] != 0);
306118334Speter	      else if (WORD_SWITCH_TAKES_ARG (p))
306218334Speter		i += WORD_SWITCH_TAKES_ARG (p);
306318334Speter	    }
306418334Speter	}
306518334Speter      else
306650599Sobrien	{
306750599Sobrien	  n_infiles++;
306850599Sobrien	  lang_n_infiles++;
306950599Sobrien	}
307018334Speter    }
307118334Speter
307250599Sobrien  if (have_c && have_o && lang_n_infiles > 1)
307350599Sobrien    fatal ("cannot specify -o with -c or -S and multiple compilations");
307450599Sobrien
307518334Speter  /* Set up the search paths before we go looking for config files.  */
307618334Speter
307718334Speter  /* These come before the md prefixes so that we will find gcc's subcommands
307818334Speter     (such as cpp) rather than those of the host system.  */
307918334Speter  /* Use 2 as fourth arg meaning try just the machine as a suffix,
308018334Speter     as well as trying the machine and the version.  */
308118346Speter#ifdef FREEBSD_NATIVE
308253878Sobrien  switch (objformat)
308353878Sobrien    {
308453878Sobrien    case OBJFMT_AOUT:
308553878Sobrien      n_switches++;		/* add implied -maout */
308655220Sobrien      add_prefix (&exec_prefixes, PREFIX"/libexec/aout/", "BINUTILS",
308753878Sobrien		  0, 0, NULL_PTR);
308853878Sobrien      break;
308953878Sobrien    case OBJFMT_ELF:
309055220Sobrien      add_prefix (&exec_prefixes, PREFIX"/libexec/elf/", "BINUTILS",
309153878Sobrien		  0, 0, NULL_PTR);
309253878Sobrien      break;
309354778Sobrien    case OBJFMT_UNKNOWN:
309454778Sobrien      fatal ("object format unknown");
309553878Sobrien    }
309618346Speter#else /* not FREEBSD_NATIVE */
309718334Speter#ifndef OS2
309850599Sobrien  add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS",
309950599Sobrien	      0, 2, warn_std_ptr);
310050599Sobrien  add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS",
310150599Sobrien	      0, 2, warn_std_ptr);
310218334Speter#endif
310318334Speter
310450599Sobrien  add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS",
310550599Sobrien	      0, 1, warn_std_ptr);
310650599Sobrien  add_prefix (&startfile_prefixes, standard_exec_prefix_1, "BINUTILS",
310750599Sobrien	      0, 1, warn_std_ptr);
310818346Speter#endif /* FREEBSD_NATIVE */
310918334Speter
311050599Sobrien  tooldir_prefix = concat (tooldir_base_prefix, spec_machine,
311150599Sobrien			   dir_separator_str, NULL_PTR);
311218334Speter
311318334Speter  /* If tooldir is relative, base it on exec_prefixes.  A relative
311418334Speter     tooldir lets us move the installed tree as a unit.
311518334Speter
311618334Speter     If GCC_EXEC_PREFIX is defined, then we want to add two relative
311718334Speter     directories, so that we can search both the user specified directory
311818334Speter     and the standard place.  */
311918334Speter
312052520Sobrien  if (!IS_DIR_SEPARATOR (*tooldir_prefix))
312118334Speter    {
312218334Speter      if (gcc_exec_prefix)
312318334Speter	{
312418334Speter	  char *gcc_exec_tooldir_prefix
312550599Sobrien	    = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
312650599Sobrien		      spec_version, dir_separator_str, tooldir_prefix, NULL_PTR);
312718334Speter
312818334Speter	  add_prefix (&exec_prefixes,
312950599Sobrien		      concat (gcc_exec_tooldir_prefix, "bin",
313050599Sobrien			      dir_separator_str, NULL_PTR),
313150599Sobrien		      NULL_PTR, 0, 0, NULL_PTR);
313218334Speter	  add_prefix (&startfile_prefixes,
313350599Sobrien		      concat (gcc_exec_tooldir_prefix, "lib",
313450599Sobrien			      dir_separator_str, NULL_PTR),
313550599Sobrien		      NULL_PTR, 0, 0, NULL_PTR);
313618334Speter	}
313718334Speter
313850599Sobrien      tooldir_prefix = concat (standard_exec_prefix, spec_machine,
313950599Sobrien			       dir_separator_str, spec_version,
314050599Sobrien			       dir_separator_str, tooldir_prefix, NULL_PTR);
314118334Speter    }
314218334Speter
314318346Speter#ifndef FREEBSD_NATIVE
314418334Speter  add_prefix (&exec_prefixes,
314550599Sobrien              concat (tooldir_prefix, "bin", dir_separator_str, NULL_PTR),
314650599Sobrien	      "BINUTILS", 0, 0, NULL_PTR);
314718334Speter  add_prefix (&startfile_prefixes,
314850599Sobrien	      concat (tooldir_prefix, "lib", dir_separator_str, NULL_PTR),
314950599Sobrien	      "BINUTILS", 0, 0, NULL_PTR);
315018346Speter#endif /* FREEBSD_NATIVE */
315118334Speter
315218334Speter  /* More prefixes are enabled in main, after we read the specs file
315318334Speter     and determine whether this is cross-compilation or not.  */
315418334Speter
315518334Speter
315618334Speter  /* Then create the space for the vectors and scan again.  */
315718334Speter
315818334Speter  switches = ((struct switchstr *)
315918334Speter	      xmalloc ((n_switches + 1) * sizeof (struct switchstr)));
316018334Speter  infiles = (struct infile *) xmalloc ((n_infiles + 1) * sizeof (struct infile));
316118334Speter  n_switches = 0;
316218334Speter  n_infiles = 0;
316318334Speter  last_language_n_infiles = -1;
316418334Speter
316518334Speter  /* This, time, copy the text of each switch and store a pointer
316618334Speter     to the copy in the vector of switches.
316718334Speter     Store all the infiles in their vector.  */
316818334Speter
316953878Sobrien#if defined(FREEBSD_NATIVE)
317053878Sobrien  switch (objformat)
317153878Sobrien    {
317253878Sobrien    case OBJFMT_AOUT:
317353878Sobrien      switches[n_switches].part1 = "maout";
317453878Sobrien      switches[n_switches].args = 0;
317553878Sobrien      switches[n_switches].live_cond = 0;
317653878Sobrien      switches[n_switches].validated = 0;
317753878Sobrien      n_switches++;
317853878Sobrien      putenv("OBJFORMAT=aout");
317953878Sobrien      break;
318053878Sobrien    case OBJFMT_ELF:
318153878Sobrien      putenv("OBJFORMAT=elf");
318253878Sobrien      break;
318354778Sobrien    case OBJFMT_UNKNOWN:
318454778Sobrien      fatal ("object format unknown");
318553878Sobrien    }
318634229Speter#endif
318734229Speter
318818334Speter  for (i = 1; i < argc; i++)
318918334Speter    {
319018334Speter      /* Just skip the switches that were handled by the preceding loop.  */
319118334Speter      if (! strncmp (argv[i], "-Wa,", 4))
319218334Speter	;
319318334Speter      else if (! strncmp (argv[i], "-Wp,", 4))
319418334Speter	;
319518334Speter      else if (! strcmp (argv[i], "-print-search-dirs"))
319618334Speter	;
319718334Speter      else if (! strcmp (argv[i], "-print-libgcc-file-name"))
319818334Speter	;
319918334Speter      else if (! strncmp (argv[i], "-print-file-name=", 17))
320018334Speter	;
320118334Speter      else if (! strncmp (argv[i], "-print-prog-name=", 17))
320218334Speter	;
320318334Speter      else if (! strcmp (argv[i], "-print-multi-lib"))
320418334Speter	;
320518334Speter      else if (! strcmp (argv[i], "-print-multi-directory"))
320618334Speter	;
320750599Sobrien      else if (strcmp (argv[i], "-fhelp") == 0)
320850599Sobrien	{
320950599Sobrien	  if (verbose_flag)
321050599Sobrien	    {
321150599Sobrien	      /* Create a dummy input file, so that we can pass --help on to
321250599Sobrien		 the various sub-processes.  */
321350599Sobrien	      infiles[n_infiles].language = "c";
321450599Sobrien	      infiles[n_infiles++].name   = "help-dummy";
321550599Sobrien
321650599Sobrien	      /* Preserve the --help switch so that it can be caught by the
321750599Sobrien		 cc1 spec string.  */
321850599Sobrien	      switches[n_switches].part1     = "--help";
321950599Sobrien	      switches[n_switches].args      = 0;
322050599Sobrien	      switches[n_switches].live_cond = 0;
322152520Sobrien	      switches[n_switches].validated     = 0;
322250599Sobrien
322350599Sobrien	      n_switches++;
322450599Sobrien	    }
322550599Sobrien	}
322618334Speter      else if (argv[i][0] == '+' && argv[i][1] == 'e')
322718334Speter	{
322818334Speter	  /* Compensate for the +e options to the C++ front-end;
322918334Speter	     they're there simply for cfront call-compatibility.  We do
323018334Speter	     some magic in default_compilers to pass them down properly.
323118334Speter	     Note we deliberately start at the `+' here, to avoid passing
323218334Speter	     -e0 or -e1 down into the linker.  */
323318334Speter	  switches[n_switches].part1 = &argv[i][0];
323418334Speter	  switches[n_switches].args = 0;
323518334Speter	  switches[n_switches].live_cond = 0;
323652520Sobrien	  switches[n_switches].validated = 0;
323718334Speter	  n_switches++;
323818334Speter	}
323918334Speter      else if (strncmp (argv[i], "-Wl,", 4) == 0)
324018334Speter	{
324118334Speter	  int prev, j;
324218334Speter	  /* Split the argument at commas.  */
324318334Speter	  prev = 4;
324418334Speter	  for (j = 4; argv[i][j]; j++)
324518334Speter	    if (argv[i][j] == ',')
324618334Speter	      {
324750599Sobrien		infiles[n_infiles].language = "*";
324818334Speter		infiles[n_infiles++].name
324918334Speter		  = save_string (argv[i] + prev, j - prev);
325018334Speter		prev = j + 1;
325118334Speter	      }
325218334Speter	  /* Record the part after the last comma.  */
325350599Sobrien	  infiles[n_infiles].language = "*";
325418334Speter	  infiles[n_infiles++].name = argv[i] + prev;
325518334Speter	}
325618334Speter      else if (strcmp (argv[i], "-Xlinker") == 0)
325718334Speter	{
325850599Sobrien	  infiles[n_infiles].language = "*";
325918334Speter	  infiles[n_infiles++].name = argv[++i];
326018334Speter	}
326118334Speter      else if (strncmp (argv[i], "-l", 2) == 0)
326218334Speter	{
326350599Sobrien	  infiles[n_infiles].language = "*";
326418334Speter	  infiles[n_infiles++].name = argv[i];
326518334Speter	}
326650599Sobrien      else if (strcmp (argv[i], "-specs") == 0)
326750599Sobrien	i++;
326850599Sobrien      else if (strncmp (argv[i], "-specs=", 7) == 0)
326950599Sobrien	;
327050599Sobrien      /* -save-temps overrides -pipe, so that temp files are produced */
327150599Sobrien      else if (save_temps_flag && strcmp (argv[i], "-pipe") == 0)
327250599Sobrien	error ("Warning: -pipe ignored since -save-temps specified");
327318334Speter      else if (argv[i][0] == '-' && argv[i][1] != 0)
327418334Speter	{
327518334Speter	  register char *p = &argv[i][1];
327618334Speter	  register int c = *p;
327718334Speter
327818334Speter	  if (c == 'x')
327918334Speter	    {
328018334Speter	      if (p[1] == 0 && i + 1 == argc)
328118334Speter		fatal ("argument to `-x' is missing");
328218334Speter	      if (p[1] == 0)
328318334Speter		spec_lang = argv[++i];
328418334Speter	      else
328518334Speter		spec_lang = p + 1;
328618334Speter	      if (! strcmp (spec_lang, "none"))
328718334Speter		/* Suppress the warning if -xnone comes after the last input
328818334Speter		   file, because alternate command interfaces like g++ might
328918334Speter		   find it useful to place -xnone after each input file.  */
329018334Speter		spec_lang = 0;
329118334Speter	      else
329218334Speter		last_language_n_infiles = n_infiles;
329318334Speter	      continue;
329418334Speter	    }
329518334Speter	  switches[n_switches].part1 = p;
329618334Speter	  /* Deal with option arguments in separate argv elements.  */
329718334Speter	  if ((SWITCH_TAKES_ARG (c) > (p[1] != 0))
329818334Speter	      || WORD_SWITCH_TAKES_ARG (p))
329918334Speter	    {
330018334Speter	      int j = 0;
330118334Speter	      int n_args = WORD_SWITCH_TAKES_ARG (p);
330218334Speter
330318334Speter	      if (n_args == 0)
330418334Speter		{
330518334Speter		  /* Count only the option arguments in separate argv elements.  */
330618334Speter		  n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0);
330718334Speter		}
330818334Speter	      if (i + n_args >= argc)
330918334Speter		fatal ("argument to `-%s' is missing", p);
331018334Speter	      switches[n_switches].args
331118334Speter		= (char **) xmalloc ((n_args + 1) * sizeof (char *));
331218334Speter	      while (j < n_args)
331318334Speter		switches[n_switches].args[j++] = argv[++i];
331418334Speter	      /* Null-terminate the vector.  */
331518334Speter	      switches[n_switches].args[j] = 0;
331618334Speter	    }
331750599Sobrien	  else if (index (switches_need_spaces, c))
331818334Speter	    {
331950599Sobrien	      /* On some systems, ld cannot handle some options without
332050599Sobrien		 a space.  So split the option from its argument.  */
332150599Sobrien	      char *part1 = (char *) xmalloc (2);
332250599Sobrien	      part1[0] = c;
332350599Sobrien	      part1[1] = '\0';
332450599Sobrien
332550599Sobrien	      switches[n_switches].part1 = part1;
332618334Speter	      switches[n_switches].args = (char **) xmalloc (2 * sizeof (char *));
332718334Speter	      switches[n_switches].args[0] = xmalloc (strlen (p));
332818334Speter	      strcpy (switches[n_switches].args[0], &p[1]);
332918334Speter	      switches[n_switches].args[1] = 0;
333018334Speter	    }
333118334Speter	  else
333218334Speter	    switches[n_switches].args = 0;
333318334Speter
333418334Speter	  switches[n_switches].live_cond = 0;
333552520Sobrien	  switches[n_switches].validated = 0;
333618334Speter	  /* This is always valid, since gcc.c itself understands it.  */
333718334Speter	  if (!strcmp (p, "save-temps"))
333852520Sobrien	    switches[n_switches].validated = 1;
333950599Sobrien          else
334050599Sobrien            {
334150599Sobrien              char ch = switches[n_switches].part1[0];
334250599Sobrien              if (ch == 'V' || ch == 'b' || ch == 'B')
334352520Sobrien                switches[n_switches].validated = 1;
334450599Sobrien            }
334518334Speter	  n_switches++;
334618334Speter	}
334718334Speter      else
334818334Speter	{
334918334Speter#ifdef HAVE_OBJECT_SUFFIX
335050599Sobrien	  argv[i] = convert_filename (argv[i], 0);
335118334Speter#endif
335218334Speter
335318334Speter	  if (strcmp (argv[i], "-") != 0 && access (argv[i], R_OK) < 0)
335418334Speter	    {
335518334Speter	      perror_with_name (argv[i]);
335618334Speter	      error_count++;
335718334Speter	    }
335818334Speter	  else
335918334Speter	    {
336018334Speter	      infiles[n_infiles].language = spec_lang;
336118334Speter	      infiles[n_infiles++].name = argv[i];
336218334Speter	    }
336318334Speter	}
336418334Speter    }
336518334Speter
336618334Speter  if (n_infiles == last_language_n_infiles && spec_lang != 0)
336718334Speter    error ("Warning: `-x %s' after last input file has no effect", spec_lang);
336818334Speter
336918334Speter  switches[n_switches].part1 = 0;
337018334Speter  infiles[n_infiles].name = 0;
337118334Speter}
337218334Speter
337318334Speter/* Process a spec string, accumulating and running commands.  */
337418334Speter
337518334Speter/* These variables describe the input file name.
337618334Speter   input_file_number is the index on outfiles of this file,
337718334Speter   so that the output file name can be stored for later use by %o.
337818334Speter   input_basename is the start of the part of the input file
337918334Speter   sans all directory names, and basename_length is the number
338018334Speter   of characters starting there excluding the suffix .c or whatever.  */
338118334Speter
338252520Sobrienconst char *input_filename;
338318334Speterstatic int input_file_number;
338450599Sobriensize_t input_filename_length;
338518334Speterstatic int basename_length;
338652520Sobrienstatic const char *input_basename;
338752520Sobrienstatic const char *input_suffix;
338818334Speter
338918334Speter/* These are variables used within do_spec and do_spec_1.  */
339018334Speter
339118334Speter/* Nonzero if an arg has been started and not yet terminated
339218334Speter   (with space, tab or newline).  */
339318334Speterstatic int arg_going;
339418334Speter
339518334Speter/* Nonzero means %d or %g has been seen; the next arg to be terminated
339618334Speter   is a temporary file name.  */
339718334Speterstatic int delete_this_arg;
339818334Speter
339918334Speter/* Nonzero means %w has been seen; the next arg to be terminated
340018334Speter   is the output file name of this compilation.  */
340118334Speterstatic int this_is_output_file;
340218334Speter
340318334Speter/* Nonzero means %s has been seen; the next arg to be terminated
340418334Speter   is the name of a library file and we should try the standard
340518334Speter   search dirs for it.  */
340618334Speterstatic int this_is_library_file;
340718334Speter
340818334Speter/* Nonzero means that the input of this command is coming from a pipe.  */
340918334Speterstatic int input_from_pipe;
341018334Speter
341118334Speter/* Process the spec SPEC and run the commands specified therein.
341218334Speter   Returns 0 if the spec is successfully processed; -1 if failed.  */
341318334Speter
341450599Sobrienint
341518334Speterdo_spec (spec)
341652520Sobrien     const char *spec;
341718334Speter{
341818334Speter  int value;
341918334Speter
342018334Speter  clear_args ();
342118334Speter  arg_going = 0;
342218334Speter  delete_this_arg = 0;
342318334Speter  this_is_output_file = 0;
342418334Speter  this_is_library_file = 0;
342518334Speter  input_from_pipe = 0;
342618334Speter
342718334Speter  value = do_spec_1 (spec, 0, NULL_PTR);
342818334Speter
342918334Speter  /* Force out any unfinished command.
343018334Speter     If -pipe, this forces out the last command if it ended in `|'.  */
343118334Speter  if (value == 0)
343218334Speter    {
343318334Speter      if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
343418334Speter	argbuf_index--;
343518334Speter
343618334Speter      if (argbuf_index > 0)
343718334Speter	value = execute ();
343818334Speter    }
343918334Speter
344018334Speter  return value;
344118334Speter}
344218334Speter
344318334Speter/* Process the sub-spec SPEC as a portion of a larger spec.
344418334Speter   This is like processing a whole spec except that we do
344518334Speter   not initialize at the beginning and we do not supply a
344618334Speter   newline by default at the end.
344718334Speter   INSWITCH nonzero means don't process %-sequences in SPEC;
344818334Speter   in this case, % is treated as an ordinary character.
344918334Speter   This is used while substituting switches.
345018334Speter   INSWITCH nonzero also causes SPC not to terminate an argument.
345118334Speter
345218334Speter   Value is zero unless a line was finished
345318334Speter   and the command on that line reported an error.  */
345418334Speter
345518334Speterstatic int
345618334Speterdo_spec_1 (spec, inswitch, soft_matched_part)
345752520Sobrien     const char *spec;
345818334Speter     int inswitch;
345952520Sobrien     const char *soft_matched_part;
346018334Speter{
346152520Sobrien  register const char *p = spec;
346218334Speter  register int c;
346318334Speter  int i;
346452520Sobrien  const char *string;
346518334Speter  int value;
346618334Speter
346750599Sobrien  while ((c = *p++))
346818334Speter    /* If substituting a switch, treat all chars like letters.
346918334Speter       Otherwise, NL, SPC, TAB and % are special.  */
347018334Speter    switch (inswitch ? 'a' : c)
347118334Speter      {
347218334Speter      case '\n':
347318334Speter	/* End of line: finish any pending argument,
347418334Speter	   then run the pending command if one has been started.  */
347518334Speter	if (arg_going)
347618334Speter	  {
347718334Speter	    obstack_1grow (&obstack, 0);
347818334Speter	    string = obstack_finish (&obstack);
347918334Speter	    if (this_is_library_file)
348018334Speter	      string = find_file (string);
348118334Speter	    store_arg (string, delete_this_arg, this_is_output_file);
348218334Speter	    if (this_is_output_file)
348318334Speter	      outfiles[input_file_number] = string;
348418334Speter	  }
348518334Speter	arg_going = 0;
348618334Speter
348718334Speter	if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
348818334Speter	  {
348918334Speter	    for (i = 0; i < n_switches; i++)
349018334Speter	      if (!strcmp (switches[i].part1, "pipe"))
349118334Speter		break;
349218334Speter
349318334Speter	    /* A `|' before the newline means use a pipe here,
349418334Speter	       but only if -pipe was specified.
349518334Speter	       Otherwise, execute now and don't pass the `|' as an arg.  */
349618334Speter	    if (i < n_switches)
349718334Speter	      {
349818334Speter		input_from_pipe = 1;
349952520Sobrien		switches[i].validated = 1;
350018334Speter		break;
350118334Speter	      }
350218334Speter	    else
350318334Speter	      argbuf_index--;
350418334Speter	  }
350518334Speter
350618334Speter	if (argbuf_index > 0)
350718334Speter	  {
350818334Speter	    value = execute ();
350918334Speter	    if (value)
351018334Speter	      return value;
351118334Speter	  }
351218334Speter	/* Reinitialize for a new command, and for a new argument.  */
351318334Speter	clear_args ();
351418334Speter	arg_going = 0;
351518334Speter	delete_this_arg = 0;
351618334Speter	this_is_output_file = 0;
351718334Speter	this_is_library_file = 0;
351818334Speter	input_from_pipe = 0;
351918334Speter	break;
352018334Speter
352118334Speter      case '|':
352218334Speter	/* End any pending argument.  */
352318334Speter	if (arg_going)
352418334Speter	  {
352518334Speter	    obstack_1grow (&obstack, 0);
352618334Speter	    string = obstack_finish (&obstack);
352718334Speter	    if (this_is_library_file)
352818334Speter	      string = find_file (string);
352918334Speter	    store_arg (string, delete_this_arg, this_is_output_file);
353018334Speter	    if (this_is_output_file)
353118334Speter	      outfiles[input_file_number] = string;
353218334Speter	  }
353318334Speter
353418334Speter	/* Use pipe */
353518334Speter	obstack_1grow (&obstack, c);
353618334Speter	arg_going = 1;
353718334Speter	break;
353818334Speter
353918334Speter      case '\t':
354018334Speter      case ' ':
354118334Speter	/* Space or tab ends an argument if one is pending.  */
354218334Speter	if (arg_going)
354318334Speter	  {
354418334Speter	    obstack_1grow (&obstack, 0);
354518334Speter	    string = obstack_finish (&obstack);
354618334Speter	    if (this_is_library_file)
354718334Speter	      string = find_file (string);
354818334Speter	    store_arg (string, delete_this_arg, this_is_output_file);
354918334Speter	    if (this_is_output_file)
355018334Speter	      outfiles[input_file_number] = string;
355118334Speter	  }
355218334Speter	/* Reinitialize for a new argument.  */
355318334Speter	arg_going = 0;
355418334Speter	delete_this_arg = 0;
355518334Speter	this_is_output_file = 0;
355618334Speter	this_is_library_file = 0;
355718334Speter	break;
355818334Speter
355918334Speter      case '%':
356018334Speter	switch (c = *p++)
356118334Speter	  {
356218334Speter	  case 0:
356318334Speter	    fatal ("Invalid specification!  Bug in cc.");
356418334Speter
356518334Speter	  case 'b':
356618334Speter	    obstack_grow (&obstack, input_basename, basename_length);
356718334Speter	    arg_going = 1;
356818334Speter	    break;
356918334Speter
357018334Speter	  case 'd':
357118334Speter	    delete_this_arg = 2;
357218334Speter	    break;
357318334Speter
357418334Speter	  /* Dump out the directories specified with LIBRARY_PATH,
357518334Speter	     followed by the absolute directories
357618334Speter	     that we search for startfiles.  */
357718334Speter	  case 'D':
357818334Speter	    {
357918334Speter	      struct prefix_list *pl = startfile_prefixes.plist;
358050599Sobrien	      size_t bufsize = 100;
358118334Speter	      char *buffer = (char *) xmalloc (bufsize);
358218334Speter	      int idx;
358318334Speter
358418334Speter	      for (; pl; pl = pl->next)
358518334Speter		{
358618334Speter#ifdef RELATIVE_PREFIX_NOT_LINKDIR
358718334Speter		  /* Used on systems which record the specified -L dirs
358818334Speter		     and use them to search for dynamic linking.  */
358918334Speter		  /* Relative directories always come from -B,
359018334Speter		     and it is better not to use them for searching
359118334Speter		     at run time.  In particular, stage1 loses  */
359252520Sobrien		  if (!IS_DIR_SEPARATOR (pl->prefix[0]))
359318334Speter		    continue;
359418334Speter#endif
359518334Speter		  /* Try subdirectory if there is one.  */
359618334Speter		  if (multilib_dir != NULL)
359718334Speter		    {
359818334Speter		      if (machine_suffix)
359918334Speter			{
360018334Speter			  if (strlen (pl->prefix) + strlen (machine_suffix)
360118334Speter			      >= bufsize)
360218334Speter			    bufsize = (strlen (pl->prefix)
360318334Speter				       + strlen (machine_suffix)) * 2 + 1;
360418334Speter			  buffer = (char *) xrealloc (buffer, bufsize);
360518334Speter			  strcpy (buffer, pl->prefix);
360618334Speter			  strcat (buffer, machine_suffix);
360718334Speter			  if (is_directory (buffer, multilib_dir, 1))
360818334Speter			    {
360918334Speter			      do_spec_1 ("-L", 0, NULL_PTR);
361018334Speter#ifdef SPACE_AFTER_L_OPTION
361118334Speter			      do_spec_1 (" ", 0, NULL_PTR);
361218334Speter#endif
361318334Speter			      do_spec_1 (buffer, 1, NULL_PTR);
361418334Speter			      do_spec_1 (multilib_dir, 1, NULL_PTR);
361518334Speter			      /* Make this a separate argument.  */
361618334Speter			      do_spec_1 (" ", 0, NULL_PTR);
361718334Speter			    }
361818334Speter			}
361918334Speter		      if (!pl->require_machine_suffix)
362018334Speter			{
362118334Speter			  if (is_directory (pl->prefix, multilib_dir, 1))
362218334Speter			    {
362318334Speter			      do_spec_1 ("-L", 0, NULL_PTR);
362418334Speter#ifdef SPACE_AFTER_L_OPTION
362518334Speter			      do_spec_1 (" ", 0, NULL_PTR);
362618334Speter#endif
362718334Speter			      do_spec_1 (pl->prefix, 1, NULL_PTR);
362818334Speter			      do_spec_1 (multilib_dir, 1, NULL_PTR);
362918334Speter			      /* Make this a separate argument.  */
363018334Speter			      do_spec_1 (" ", 0, NULL_PTR);
363118334Speter			    }
363218334Speter			}
363318334Speter		    }
363418334Speter		  if (machine_suffix)
363518334Speter		    {
363618334Speter		      if (is_directory (pl->prefix, machine_suffix, 1))
363718334Speter			{
363818334Speter			  do_spec_1 ("-L", 0, NULL_PTR);
363918334Speter#ifdef SPACE_AFTER_L_OPTION
364018334Speter			  do_spec_1 (" ", 0, NULL_PTR);
364118334Speter#endif
364218334Speter			  do_spec_1 (pl->prefix, 1, NULL_PTR);
364318334Speter			  /* Remove slash from machine_suffix.  */
364418334Speter			  if (strlen (machine_suffix) >= bufsize)
364518334Speter			    bufsize = strlen (machine_suffix) * 2 + 1;
364618334Speter			  buffer = (char *) xrealloc (buffer, bufsize);
364718334Speter			  strcpy (buffer, machine_suffix);
364818334Speter			  idx = strlen (buffer);
364952520Sobrien			  if (IS_DIR_SEPARATOR (buffer[idx - 1]))
365018334Speter			    buffer[idx - 1] = 0;
365118334Speter			  do_spec_1 (buffer, 1, NULL_PTR);
365218334Speter			  /* Make this a separate argument.  */
365318334Speter			  do_spec_1 (" ", 0, NULL_PTR);
365418334Speter			}
365518334Speter		    }
365618334Speter		  if (!pl->require_machine_suffix)
365718334Speter		    {
365818334Speter		      if (is_directory (pl->prefix, "", 1))
365918334Speter			{
366018334Speter			  do_spec_1 ("-L", 0, NULL_PTR);
366118334Speter#ifdef SPACE_AFTER_L_OPTION
366218334Speter			  do_spec_1 (" ", 0, NULL_PTR);
366318334Speter#endif
366418334Speter			  /* Remove slash from pl->prefix.  */
366518334Speter			  if (strlen (pl->prefix) >= bufsize)
366618334Speter			    bufsize = strlen (pl->prefix) * 2 + 1;
366718334Speter			  buffer = (char *) xrealloc (buffer, bufsize);
366818334Speter			  strcpy (buffer, pl->prefix);
366918334Speter			  idx = strlen (buffer);
367052520Sobrien			  if (IS_DIR_SEPARATOR (buffer[idx - 1]))
367118334Speter			    buffer[idx - 1] = 0;
367218334Speter			  do_spec_1 (buffer, 1, NULL_PTR);
367318334Speter			  /* Make this a separate argument.  */
367418334Speter			  do_spec_1 (" ", 0, NULL_PTR);
367518334Speter			}
367618334Speter		    }
367718334Speter		}
367818334Speter	      free (buffer);
367918334Speter	    }
368018334Speter	    break;
368118334Speter
368218334Speter	  case 'e':
368352520Sobrien	    /* %efoo means report an error with `foo' as error message
368418334Speter	       and don't execute any more commands for this file.  */
368518334Speter	    {
368652520Sobrien	      const char *q = p;
368718334Speter	      char *buf;
368818334Speter	      while (*p != 0 && *p != '\n') p++;
368918334Speter	      buf = (char *) alloca (p - q + 1);
369018334Speter	      strncpy (buf, q, p - q);
369118334Speter	      buf[p - q] = 0;
369252520Sobrien	      error (buf);
369318334Speter	      return -1;
369418334Speter	    }
369518334Speter	    break;
369618334Speter
369718334Speter	  case 'g':
369818334Speter	  case 'u':
369918334Speter	  case 'U':
370018334Speter	    if (save_temps_flag)
370118334Speter	      {
370218334Speter		obstack_grow (&obstack, input_basename, basename_length);
370318334Speter		delete_this_arg = 0;
370418334Speter	      }
370518334Speter	    else
370618334Speter	      {
370718334Speter#ifdef MKTEMP_EACH_FILE
370818334Speter		/* ??? This has a problem: the total number of
370918334Speter		   values mktemp can return is limited.
371018334Speter		   That matters for the names of object files.
371118334Speter		   In 2.4, do something about that.  */
371218334Speter		struct temp_name *t;
371350599Sobrien		int suffix_length;
371452520Sobrien		const char *suffix = p;
371518334Speter
371650599Sobrien		if (p[0] == '%' && p[1] == 'O')
371750599Sobrien		  {
371850599Sobrien		    p += 2;
371950599Sobrien		    /* We don't support extra suffix characters after %O.  */
372052520Sobrien		    if (*p == '.' || ISALPHA ((unsigned char)*p))
372150599Sobrien		      abort ();
372250599Sobrien		    suffix = OBJECT_SUFFIX;
372350599Sobrien		    suffix_length = strlen (OBJECT_SUFFIX);
372450599Sobrien		  }
372550599Sobrien		else
372650599Sobrien		  {
372752520Sobrien		    while (*p == '.' || ISALPHA ((unsigned char)*p))
372850599Sobrien		      p++;
372950599Sobrien		    suffix_length = p - suffix;
373050599Sobrien		  }
373150599Sobrien
373218334Speter		/* See if we already have an association of %g/%u/%U and
373318334Speter		   suffix.  */
373418334Speter		for (t = temp_names; t; t = t->next)
373550599Sobrien		  if (t->length == suffix_length
373650599Sobrien		      && strncmp (t->suffix, suffix, suffix_length) == 0
373718334Speter		      && t->unique == (c != 'g'))
373818334Speter		    break;
373918334Speter
374018334Speter		/* Make a new association if needed.  %u requires one.  */
374118334Speter		if (t == 0 || c == 'u')
374218334Speter		  {
374318334Speter		    if (t == 0)
374418334Speter		      {
374518334Speter			t = (struct temp_name *) xmalloc (sizeof (struct temp_name));
374618334Speter			t->next = temp_names;
374718334Speter			temp_names = t;
374818334Speter		      }
374950599Sobrien		    t->length = suffix_length;
375050599Sobrien		    t->suffix = save_string (suffix, suffix_length);
375118334Speter		    t->unique = (c != 'g');
375250599Sobrien		    temp_filename = make_temp_file (t->suffix);
375350599Sobrien		    temp_filename_length = strlen (temp_filename);
375418334Speter		    t->filename = temp_filename;
375518334Speter		    t->filename_length = temp_filename_length;
375618334Speter		  }
375718334Speter
375818334Speter		obstack_grow (&obstack, t->filename, t->filename_length);
375918334Speter		delete_this_arg = 1;
376018334Speter#else
376118334Speter		obstack_grow (&obstack, temp_filename, temp_filename_length);
376218334Speter		if (c == 'u' || c == 'U')
376318334Speter		  {
376418334Speter		    static int unique;
376518334Speter		    char buff[9];
376618334Speter		    if (c == 'u')
376718334Speter		      unique++;
376818334Speter		    sprintf (buff, "%d", unique);
376918334Speter		    obstack_grow (&obstack, buff, strlen (buff));
377018334Speter		  }
377118334Speter#endif
377218334Speter		delete_this_arg = 1;
377318334Speter	      }
377418334Speter	    arg_going = 1;
377518334Speter	    break;
377618334Speter
377718334Speter	  case 'i':
377818334Speter	    obstack_grow (&obstack, input_filename, input_filename_length);
377918334Speter	    arg_going = 1;
378018334Speter	    break;
378118334Speter
378218334Speter	  case 'I':
378318334Speter	    {
378418334Speter	      struct prefix_list *pl = include_prefixes.plist;
378518334Speter
378618334Speter	      if (gcc_exec_prefix)
378718334Speter		{
378818334Speter		  do_spec_1 ("-iprefix", 1, NULL_PTR);
378918334Speter		  /* Make this a separate argument.  */
379018334Speter		  do_spec_1 (" ", 0, NULL_PTR);
379118334Speter		  do_spec_1 (gcc_exec_prefix, 1, NULL_PTR);
379218334Speter		  do_spec_1 (" ", 0, NULL_PTR);
379318334Speter		}
379418334Speter
379518334Speter	      for (; pl; pl = pl->next)
379618334Speter		{
379718334Speter		  do_spec_1 ("-isystem", 1, NULL_PTR);
379818334Speter		  /* Make this a separate argument.  */
379918334Speter		  do_spec_1 (" ", 0, NULL_PTR);
380018334Speter		  do_spec_1 (pl->prefix, 1, NULL_PTR);
380118334Speter		  do_spec_1 (" ", 0, NULL_PTR);
380218334Speter		}
380318334Speter	    }
380418334Speter	    break;
380518334Speter
380618334Speter	  case 'o':
380752520Sobrien	    {
380852520Sobrien	      int max = n_infiles;
380952520Sobrien	      max += lang_specific_extra_outfiles;
381018334Speter
381152520Sobrien	      for (i = 0; i < max; i++)
381252520Sobrien		if (outfiles[i])
381352520Sobrien		  store_arg (outfiles[i], 0, 0);
381452520Sobrien	      break;
381552520Sobrien	    }
381652520Sobrien
381718334Speter	  case 'O':
381818334Speter	    obstack_grow (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX));
381918334Speter	    arg_going = 1;
382018334Speter	    break;
382118334Speter
382218334Speter	  case 's':
382318334Speter	    this_is_library_file = 1;
382418334Speter	    break;
382518334Speter
382618334Speter	  case 'w':
382718334Speter	    this_is_output_file = 1;
382818334Speter	    break;
382918334Speter
383018334Speter	  case 'W':
383118334Speter	    {
383250599Sobrien	      int cur_index = argbuf_index;
383318334Speter	      /* Handle the {...} following the %W.  */
383418334Speter	      if (*p != '{')
383518334Speter		abort ();
383618334Speter	      p = handle_braces (p + 1);
383718334Speter	      if (p == 0)
383818334Speter		return -1;
383918334Speter	      /* If any args were output, mark the last one for deletion
384018334Speter		 on failure.  */
384150599Sobrien	      if (argbuf_index != cur_index)
384218334Speter		record_temp_file (argbuf[argbuf_index - 1], 0, 1);
384318334Speter	      break;
384418334Speter	    }
384518334Speter
384618334Speter	  /* %x{OPTION} records OPTION for %X to output.  */
384718334Speter	  case 'x':
384818334Speter	    {
384952520Sobrien	      const char *p1 = p;
385018334Speter	      char *string;
385118334Speter
385218334Speter	      /* Skip past the option value and make a copy.  */
385318334Speter	      if (*p != '{')
385418334Speter		abort ();
385518334Speter	      while (*p++ != '}')
385618334Speter		;
385718334Speter	      string = save_string (p1 + 1, p - p1 - 2);
385818334Speter
385918334Speter	      /* See if we already recorded this option.  */
386018334Speter	      for (i = 0; i < n_linker_options; i++)
386118334Speter		if (! strcmp (string, linker_options[i]))
386218334Speter		  {
386318334Speter		    free (string);
386418334Speter		    return 0;
386518334Speter		  }
386618334Speter
386718334Speter	      /* This option is new; add it.  */
386850599Sobrien	      add_linker_option (string, strlen (string));
386918334Speter	    }
387018334Speter	    break;
387118334Speter
387218334Speter	  /* Dump out the options accumulated previously using %x.  */
387318334Speter	  case 'X':
387418334Speter	    for (i = 0; i < n_linker_options; i++)
387518334Speter	      {
387618334Speter		do_spec_1 (linker_options[i], 1, NULL_PTR);
387718334Speter		/* Make each accumulated option a separate argument.  */
387818334Speter		do_spec_1 (" ", 0, NULL_PTR);
387918334Speter	      }
388018334Speter	    break;
388118334Speter
388218334Speter	  /* Dump out the options accumulated previously using -Wa,.  */
388318334Speter	  case 'Y':
388418334Speter	    for (i = 0; i < n_assembler_options; i++)
388518334Speter	      {
388618334Speter		do_spec_1 (assembler_options[i], 1, NULL_PTR);
388718334Speter		/* Make each accumulated option a separate argument.  */
388818334Speter		do_spec_1 (" ", 0, NULL_PTR);
388918334Speter	      }
389018334Speter	    break;
389118334Speter
389218334Speter	  /* Dump out the options accumulated previously using -Wp,.  */
389318334Speter	  case 'Z':
389418334Speter	    for (i = 0; i < n_preprocessor_options; i++)
389518334Speter	      {
389618334Speter		do_spec_1 (preprocessor_options[i], 1, NULL_PTR);
389718334Speter		/* Make each accumulated option a separate argument.  */
389818334Speter		do_spec_1 (" ", 0, NULL_PTR);
389918334Speter	      }
390018334Speter	    break;
390118334Speter
390218334Speter	    /* Here are digits and numbers that just process
390318334Speter	       a certain constant string as a spec.  */
390418334Speter
390518334Speter	  case '1':
390618334Speter	    value = do_spec_1 (cc1_spec, 0, NULL_PTR);
390718334Speter	    if (value != 0)
390818334Speter	      return value;
390918334Speter	    break;
391018334Speter
391118334Speter	  case '2':
391218334Speter	    value = do_spec_1 (cc1plus_spec, 0, NULL_PTR);
391318334Speter	    if (value != 0)
391418334Speter	      return value;
391518334Speter	    break;
391618334Speter
391718334Speter	  case 'a':
391818334Speter	    value = do_spec_1 (asm_spec, 0, NULL_PTR);
391918334Speter	    if (value != 0)
392018334Speter	      return value;
392118334Speter	    break;
392218334Speter
392318334Speter	  case 'A':
392418334Speter	    value = do_spec_1 (asm_final_spec, 0, NULL_PTR);
392518334Speter	    if (value != 0)
392618334Speter	      return value;
392718334Speter	    break;
392818334Speter
392918334Speter	  case 'c':
393018334Speter	    value = do_spec_1 (signed_char_spec, 0, NULL_PTR);
393118334Speter	    if (value != 0)
393218334Speter	      return value;
393318334Speter	    break;
393418334Speter
393518334Speter	  case 'C':
393618334Speter	    value = do_spec_1 (cpp_spec, 0, NULL_PTR);
393718334Speter	    if (value != 0)
393818334Speter	      return value;
393918334Speter	    break;
394018334Speter
394118334Speter	  case 'E':
394218334Speter	    value = do_spec_1 (endfile_spec, 0, NULL_PTR);
394318334Speter	    if (value != 0)
394418334Speter	      return value;
394518334Speter	    break;
394618334Speter
394718334Speter	  case 'l':
394818334Speter	    value = do_spec_1 (link_spec, 0, NULL_PTR);
394918334Speter	    if (value != 0)
395018334Speter	      return value;
395118334Speter	    break;
395218334Speter
395318334Speter	  case 'L':
395418334Speter	    value = do_spec_1 (lib_spec, 0, NULL_PTR);
395518334Speter	    if (value != 0)
395618334Speter	      return value;
395718334Speter	    break;
395818334Speter
395918334Speter	  case 'G':
396018334Speter	    value = do_spec_1 (libgcc_spec, 0, NULL_PTR);
396118334Speter	    if (value != 0)
396218334Speter	      return value;
396318334Speter	    break;
396418334Speter
396518334Speter	  case 'p':
396618334Speter	    {
396718334Speter	      char *x = (char *) alloca (strlen (cpp_predefines) + 1);
396818334Speter	      char *buf = x;
396918334Speter	      char *y;
397018334Speter
397118334Speter	      /* Copy all of the -D options in CPP_PREDEFINES into BUF.  */
397218334Speter	      y = cpp_predefines;
397318334Speter	      while (*y != 0)
397418334Speter		{
397518334Speter		  if (! strncmp (y, "-D", 2))
397618334Speter		    /* Copy the whole option.  */
397718334Speter		    while (*y && *y != ' ' && *y != '\t')
397818334Speter		      *x++ = *y++;
397918334Speter		  else if (*y == ' ' || *y == '\t')
398018334Speter		    /* Copy whitespace to the result.  */
398118334Speter		    *x++ = *y++;
398218334Speter		  /* Don't copy other options.  */
398318334Speter		  else
398418334Speter		    y++;
398518334Speter		}
398618334Speter
398718334Speter	      *x = 0;
398818334Speter
398918334Speter	      value = do_spec_1 (buf, 0, NULL_PTR);
399018334Speter	      if (value != 0)
399118334Speter		return value;
399218334Speter	    }
399318334Speter	    break;
399418334Speter
399518334Speter	  case 'P':
399618334Speter	    {
399718334Speter	      char *x = (char *) alloca (strlen (cpp_predefines) * 4 + 1);
399818334Speter	      char *buf = x;
399918334Speter	      char *y;
400018334Speter
400118334Speter	      /* Copy all of CPP_PREDEFINES into BUF,
400218334Speter		 but put __ after every -D and at the end of each arg.  */
400318334Speter	      y = cpp_predefines;
400418334Speter	      while (*y != 0)
400518334Speter		{
400618334Speter		  if (! strncmp (y, "-D", 2))
400718334Speter		    {
400818334Speter		      int flag = 0;
400918334Speter
401018334Speter		      *x++ = *y++;
401118334Speter		      *x++ = *y++;
401218334Speter
401318334Speter		      if (*y != '_'
401452520Sobrien			  || (*(y+1) != '_'
401552520Sobrien			      && ! ISUPPER ((unsigned char)*(y+1))))
401618334Speter		        {
401718334Speter			  /* Stick __ at front of macro name.  */
401818334Speter			  *x++ = '_';
401918334Speter			  *x++ = '_';
402018334Speter			  /* Arrange to stick __ at the end as well.  */
402118334Speter			  flag = 1;
402218334Speter			}
402318334Speter
402418334Speter		      /* Copy the macro name.  */
402518334Speter		      while (*y && *y != '=' && *y != ' ' && *y != '\t')
402618334Speter			*x++ = *y++;
402718334Speter
402818334Speter		      if (flag)
402918334Speter		        {
403018334Speter			  *x++ = '_';
403118334Speter			  *x++ = '_';
403218334Speter			}
403318334Speter
403418334Speter		      /* Copy the value given, if any.  */
403518334Speter		      while (*y && *y != ' ' && *y != '\t')
403618334Speter			*x++ = *y++;
403718334Speter		    }
403818334Speter		  else if (*y == ' ' || *y == '\t')
403918334Speter		    /* Copy whitespace to the result.  */
404018334Speter		    *x++ = *y++;
404118334Speter		  /* Don't copy -A options  */
404218334Speter		  else
404318334Speter		    y++;
404418334Speter		}
404518334Speter	      *x++ = ' ';
404618334Speter
404718334Speter	      /* Copy all of CPP_PREDEFINES into BUF,
404818334Speter		 but put __ after every -D.  */
404918334Speter	      y = cpp_predefines;
405018334Speter	      while (*y != 0)
405118334Speter		{
405218334Speter		  if (! strncmp (y, "-D", 2))
405318334Speter		    {
405418334Speter		      y += 2;
405518334Speter
405618334Speter		      if (*y != '_'
405752520Sobrien			  || (*(y+1) != '_'
405852520Sobrien			      && ! ISUPPER ((unsigned char)*(y+1))))
405918334Speter		        {
406018334Speter			  /* Stick -D__ at front of macro name.  */
406118334Speter			  *x++ = '-';
406218334Speter			  *x++ = 'D';
406318334Speter			  *x++ = '_';
406418334Speter			  *x++ = '_';
406518334Speter
406618334Speter			  /* Copy the macro name.  */
406718334Speter			  while (*y && *y != '=' && *y != ' ' && *y != '\t')
406818334Speter			    *x++ = *y++;
406918334Speter
407018334Speter			  /* Copy the value given, if any.  */
407118334Speter			  while (*y && *y != ' ' && *y != '\t')
407218334Speter			    *x++ = *y++;
407318334Speter			}
407418334Speter		      else
407518334Speter			{
407618334Speter			  /* Do not copy this macro - we have just done it before */
407718334Speter			  while (*y && *y != ' ' && *y != '\t')
407818334Speter			    y++;
407918334Speter			}
408018334Speter		    }
408118334Speter		  else if (*y == ' ' || *y == '\t')
408218334Speter		    /* Copy whitespace to the result.  */
408318334Speter		    *x++ = *y++;
408418334Speter		  /* Don't copy -A options  */
408518334Speter		  else
408618334Speter		    y++;
408718334Speter		}
408818334Speter	      *x++ = ' ';
408918334Speter
409018334Speter	      /* Copy all of the -A options in CPP_PREDEFINES into BUF.  */
409118334Speter	      y = cpp_predefines;
409218334Speter	      while (*y != 0)
409318334Speter		{
409418334Speter		  if (! strncmp (y, "-A", 2))
409518334Speter		    /* Copy the whole option.  */
409618334Speter		    while (*y && *y != ' ' && *y != '\t')
409718334Speter		      *x++ = *y++;
409818334Speter		  else if (*y == ' ' || *y == '\t')
409918334Speter		    /* Copy whitespace to the result.  */
410018334Speter		    *x++ = *y++;
410118334Speter		  /* Don't copy other options.  */
410218334Speter		  else
410318334Speter		    y++;
410418334Speter		}
410518334Speter
410618334Speter	      *x = 0;
410718334Speter
410818334Speter	      value = do_spec_1 (buf, 0, NULL_PTR);
410918334Speter	      if (value != 0)
411018334Speter		return value;
411118334Speter	    }
411218334Speter	    break;
411318334Speter
411418334Speter	  case 'S':
411518334Speter	    value = do_spec_1 (startfile_spec, 0, NULL_PTR);
411618334Speter	    if (value != 0)
411718334Speter	      return value;
411818334Speter	    break;
411918334Speter
412018334Speter	    /* Here we define characters other than letters and digits.  */
412118334Speter
412218334Speter	  case '{':
412318334Speter	    p = handle_braces (p);
412418334Speter	    if (p == 0)
412518334Speter	      return -1;
412618334Speter	    break;
412718334Speter
412818334Speter	  case '%':
412918334Speter	    obstack_1grow (&obstack, '%');
413018334Speter	    break;
413118334Speter
413218334Speter	  case '*':
413318334Speter	    do_spec_1 (soft_matched_part, 1, NULL_PTR);
413418334Speter	    do_spec_1 (" ", 0, NULL_PTR);
413518334Speter	    break;
413618334Speter
413718334Speter	    /* Process a string found as the value of a spec given by name.
413818334Speter	       This feature allows individual machine descriptions
413918334Speter	       to add and use their own specs.
414018334Speter	       %[...] modifies -D options the way %P does;
414118334Speter	       %(...) uses the spec unmodified.  */
414250599Sobrien	  case '[':
414350599Sobrien	    error ("Warning: use of obsolete %%[ operator in specs");
414418334Speter	  case '(':
414518334Speter	    {
414652520Sobrien	      const char *name = p;
414718334Speter	      struct spec_list *sl;
414818334Speter	      int len;
414918334Speter
415018334Speter	      /* The string after the S/P is the name of a spec that is to be
415150599Sobrien		 processed.  */
415218334Speter	      while (*p && *p != ')' && *p != ']')
415318334Speter		p++;
415418334Speter
415518334Speter	      /* See if it's in the list */
415618334Speter	      for (len = p - name, sl = specs; sl; sl = sl->next)
415750599Sobrien		if (sl->name_len == len && !strncmp (sl->name, name, len))
415818334Speter		  {
415950599Sobrien		    name = *(sl->ptr_spec);
416050599Sobrien#ifdef DEBUG_SPECS
416152520Sobrien		    notice ("Processing spec %c%s%c, which is '%s'\n",
416252520Sobrien			    c, sl->name, (c == '(') ? ')' : ']', name);
416350599Sobrien#endif
416418334Speter		    break;
416518334Speter		  }
416618334Speter
416718334Speter	      if (sl)
416818334Speter		{
416918334Speter		  if (c == '(')
417018334Speter		    {
417118334Speter		      value = do_spec_1 (name, 0, NULL_PTR);
417218334Speter		      if (value != 0)
417318334Speter			return value;
417418334Speter		    }
417518334Speter		  else
417618334Speter		    {
417718334Speter		      char *x = (char *) alloca (strlen (name) * 2 + 1);
417818334Speter		      char *buf = x;
417952520Sobrien		      const char *y = name;
418050599Sobrien		      int flag = 0;
418118334Speter
418218334Speter		      /* Copy all of NAME into BUF, but put __ after
418318334Speter			 every -D and at the end of each arg,  */
418418334Speter		      while (1)
418518334Speter			{
418618334Speter			  if (! strncmp (y, "-D", 2))
418718334Speter			    {
418818334Speter			      *x++ = '-';
418918334Speter			      *x++ = 'D';
419018334Speter			      *x++ = '_';
419118334Speter			      *x++ = '_';
419218334Speter			      y += 2;
419350599Sobrien			      flag = 1;
419450599Sobrien			      continue;
419518334Speter			    }
419650599Sobrien                          else if (flag && (*y == ' ' || *y == '\t' || *y == '='
419750599Sobrien                                            || *y == '}' || *y == 0))
419818334Speter			    {
419918334Speter			      *x++ = '_';
420018334Speter			      *x++ = '_';
420150599Sobrien			      flag = 0;
420218334Speter			    }
420350599Sobrien                          if (*y == 0)
420450599Sobrien			    break;
420518334Speter			  else
420618334Speter			    *x++ = *y++;
420718334Speter			}
420818334Speter		      *x = 0;
420918334Speter
421018334Speter		      value = do_spec_1 (buf, 0, NULL_PTR);
421118334Speter		      if (value != 0)
421218334Speter			return value;
421318334Speter		    }
421418334Speter		}
421518334Speter
421618334Speter	      /* Discard the closing paren or bracket.  */
421718334Speter	      if (*p)
421818334Speter		p++;
421918334Speter	    }
422018334Speter	    break;
422118334Speter
422218334Speter	  case 'v':
422318334Speter	    {
422418334Speter	      int c1 = *p++;  /* Select first or second version number.  */
422518334Speter	      char *v = compiler_version;
422618346Speter	      char *q;
422750599Sobrien
422850599Sobrien	      /* The format of the version string is
422950599Sobrien		 ([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)?  */
423050599Sobrien
423150599Sobrien	      /* Ignore leading non-digits.  i.e. "foo-" in "foo-2.7.2".  */
423250599Sobrien	      while (! ISDIGIT (*v))
423350599Sobrien		v++;
423450599Sobrien	      if (v > compiler_version && v[-1] != '-')
423550599Sobrien		abort ();
423650599Sobrien
423718334Speter	      /* If desired, advance to second version number.  */
423818334Speter	      if (c1 == '2')
423918334Speter		{
424050599Sobrien		  /* Set V after the first period.  */
424150599Sobrien		  while (ISDIGIT (*v))
424218334Speter		    v++;
424350599Sobrien		  if (*v != '.')
424450599Sobrien		    abort ();
424550599Sobrien		  v++;
424618334Speter		}
424750599Sobrien
424818334Speter	      /* Set Q at the next period or at the end.  */
424918334Speter	      q = v;
425050599Sobrien	      while (ISDIGIT (*q))
425118334Speter		q++;
425250599Sobrien	      if (*q != 0 && *q != ' ' && *q != '.' && *q != '-')
425350599Sobrien		abort ();
425450599Sobrien
425518334Speter	      /* Put that part into the command.  */
425618334Speter	      obstack_grow (&obstack, v, q - v);
425718334Speter	      arg_going = 1;
425818334Speter	    }
425918334Speter	    break;
426018334Speter
426118334Speter	  case '|':
426218334Speter	    if (input_from_pipe)
426318334Speter	      do_spec_1 ("-", 0, NULL_PTR);
426418334Speter	    break;
426518334Speter
426618334Speter	  default:
426718334Speter	    abort ();
426818334Speter	  }
426918334Speter	break;
427018334Speter
427118334Speter      case '\\':
427218334Speter	/* Backslash: treat next character as ordinary.  */
427318334Speter	c = *p++;
427418334Speter
427518334Speter	/* fall through */
427618334Speter      default:
427718334Speter	/* Ordinary character: put it into the current argument.  */
427818334Speter	obstack_1grow (&obstack, c);
427918334Speter	arg_going = 1;
428018334Speter      }
428118334Speter
428218334Speter  return 0;		/* End of string */
428318334Speter}
428418334Speter
428518334Speter/* Return 0 if we call do_spec_1 and that returns -1.  */
428618334Speter
428752520Sobrienstatic const char *
428818334Speterhandle_braces (p)
428952520Sobrien     register const char *p;
429018334Speter{
429152520Sobrien  const char *filter, *body = NULL, *endbody = NULL;
429250599Sobrien  int pipe_p = 0;
429350599Sobrien  int negate;
429450599Sobrien  int suffix;
429550599Sobrien  int include_blanks = 1;
429618334Speter
429750599Sobrien  if (*p == '^')
429850599Sobrien    /* A '^' after the open-brace means to not give blanks before args.  */
429950599Sobrien    include_blanks = 0, ++p;
430050599Sobrien
430118334Speter  if (*p == '|')
430218334Speter    /* A `|' after the open-brace means,
430318334Speter       if the test fails, output a single minus sign rather than nothing.
430418334Speter       This is used in %{|!pipe:...}.  */
430550599Sobrien    pipe_p = 1, ++p;
430618334Speter
430750599Sobriennext_member:
430850599Sobrien  negate = suffix = 0;
430950599Sobrien
431018334Speter  if (*p == '!')
431118334Speter    /* A `!' after the open-brace negates the condition:
431218334Speter       succeed if the specified switch is not present.  */
431318334Speter    negate = 1, ++p;
431418334Speter
431518334Speter  if (*p == '.')
431618334Speter    /* A `.' after the open-brace means test against the current suffix.  */
431718334Speter    {
431850599Sobrien      if (pipe_p)
431918334Speter	abort ();
432018334Speter
432118334Speter      suffix = 1;
432218334Speter      ++p;
432318334Speter    }
432418334Speter
432518334Speter  filter = p;
432650599Sobrien  while (*p != ':' && *p != '}' && *p != '|') p++;
432750599Sobrien
432850599Sobrien  if (*p == '|' && pipe_p)
432950599Sobrien    abort ();
433050599Sobrien
433150599Sobrien  if (!body)
433218334Speter    {
433350599Sobrien      if (*p != '}')
433450599Sobrien        {
433550599Sobrien	  register int count = 1;
433652520Sobrien	  register const char *q = p;
433750599Sobrien
433850599Sobrien	  while (*q++ != ':') continue;
433950599Sobrien	  body = q;
434050599Sobrien
434150599Sobrien	  while (count > 0)
434250599Sobrien	    {
434350599Sobrien	      if (*q == '{')
434450599Sobrien	        count++;
434550599Sobrien	      else if (*q == '}')
434650599Sobrien	        count--;
434750599Sobrien	      else if (*q == 0)
434850599Sobrien	        abort ();
434950599Sobrien	      q++;
435050599Sobrien	    }
435150599Sobrien	  endbody = q;
435218334Speter	}
435350599Sobrien      else
435450599Sobrien	body = p, endbody = p+1;
435518334Speter    }
435618334Speter
435718334Speter  if (suffix)
435818334Speter    {
435918334Speter      int found = (input_suffix != 0
436052520Sobrien		   && (long) strlen (input_suffix) == (long)(p - filter)
436118334Speter		   && strncmp (input_suffix, filter, p - filter) == 0);
436218334Speter
436350599Sobrien      if (body[0] == '}')
436418334Speter	abort ();
436518334Speter
436618334Speter      if (negate != found
436750599Sobrien	  && do_spec_1 (save_string (body, endbody-body-1), 0, NULL_PTR) < 0)
436818334Speter	return 0;
436918334Speter    }
437018334Speter  else if (p[-1] == '*' && p[0] == '}')
437118334Speter    {
437218334Speter      /* Substitute all matching switches as separate args.  */
437318334Speter      register int i;
437418334Speter      --p;
437518334Speter      for (i = 0; i < n_switches; i++)
437618334Speter	if (!strncmp (switches[i].part1, filter, p - filter)
437718334Speter	    && check_live_switch (i, p - filter))
437850599Sobrien	  give_switch (i, 0, include_blanks);
437918334Speter    }
438018334Speter  else
438118334Speter    {
438218334Speter      /* Test for presence of the specified switch.  */
438318334Speter      register int i;
438418334Speter      int present = 0;
438518334Speter
438618334Speter      /* If name specified ends in *, as in {x*:...},
438718334Speter	 check for %* and handle that case.  */
438818334Speter      if (p[-1] == '*' && !negate)
438918334Speter	{
439018334Speter	  int substitution;
439152520Sobrien	  const char *r = body;
439218334Speter
439318334Speter	  /* First see whether we have %*.  */
439418334Speter	  substitution = 0;
439550599Sobrien	  while (r < endbody)
439618334Speter	    {
439718334Speter	      if (*r == '%' && r[1] == '*')
439818334Speter		substitution = 1;
439918334Speter	      r++;
440018334Speter	    }
440118334Speter	  /* If we do, handle that case.  */
440218334Speter	  if (substitution)
440318334Speter	    {
440418334Speter	      /* Substitute all matching switches as separate args.
440518334Speter		 But do this by substituting for %*
440618334Speter		 in the text that follows the colon.  */
440718334Speter
440818334Speter	      unsigned hard_match_len = p - filter - 1;
440950599Sobrien	      char *string = save_string (body, endbody - body - 1);
441018334Speter
441118334Speter	      for (i = 0; i < n_switches; i++)
441218334Speter		if (!strncmp (switches[i].part1, filter, hard_match_len)
441318334Speter		    && check_live_switch (i, -1))
441418334Speter		  {
441518334Speter		    do_spec_1 (string, 0, &switches[i].part1[hard_match_len]);
441618334Speter		    /* Pass any arguments this switch has.  */
441750599Sobrien		    give_switch (i, 1, 1);
441818334Speter		  }
441918334Speter
442050599Sobrien	      /* We didn't match.  Try again.  */
442150599Sobrien	      if (*p++ == '|')
442250599Sobrien		goto next_member;
442350599Sobrien	      return endbody;
442418334Speter	    }
442518334Speter	}
442618334Speter
442718334Speter      /* If name specified ends in *, as in {x*:...},
442818334Speter	 check for presence of any switch name starting with x.  */
442918334Speter      if (p[-1] == '*')
443018334Speter	{
443118334Speter	  for (i = 0; i < n_switches; i++)
443218334Speter	    {
443318334Speter	      unsigned hard_match_len = p - filter - 1;
443418334Speter
443518334Speter	      if (!strncmp (switches[i].part1, filter, hard_match_len)
443618334Speter		  && check_live_switch (i, hard_match_len))
443718334Speter		{
443818334Speter		  present = 1;
443918334Speter		}
444018334Speter	    }
444118334Speter	}
444218334Speter      /* Otherwise, check for presence of exact name specified.  */
444318334Speter      else
444418334Speter	{
444518334Speter	  for (i = 0; i < n_switches; i++)
444618334Speter	    {
444718334Speter	      if (!strncmp (switches[i].part1, filter, p - filter)
444818334Speter		  && switches[i].part1[p - filter] == 0
444918334Speter		  && check_live_switch (i, -1))
445018334Speter		{
445118334Speter		  present = 1;
445218334Speter		  break;
445318334Speter		}
445418334Speter	    }
445518334Speter	}
445618334Speter
445750599Sobrien      /* If it is as desired (present for %{s...}, absent for %{!s...})
445818334Speter	 then substitute either the switch or the specified
445918334Speter	 conditional text.  */
446018334Speter      if (present != negate)
446118334Speter	{
446218334Speter	  if (*p == '}')
446318334Speter	    {
446450599Sobrien	      give_switch (i, 0, include_blanks);
446518334Speter	    }
446618334Speter	  else
446718334Speter	    {
446850599Sobrien	      if (do_spec_1 (save_string (body, endbody - body - 1),
446950599Sobrien			     0, NULL_PTR) < 0)
447018334Speter		return 0;
447118334Speter	    }
447218334Speter	}
447350599Sobrien      else if (pipe_p)
447418334Speter	{
447518334Speter	  /* Here if a %{|...} conditional fails: output a minus sign,
447618334Speter	     which means "standard output" or "standard input".  */
447718334Speter	  do_spec_1 ("-", 0, NULL_PTR);
447850599Sobrien	  return endbody;
447918334Speter	}
448018334Speter    }
448118334Speter
448250599Sobrien  /* We didn't match; try again.  */
448350599Sobrien  if (*p++ == '|')
448450599Sobrien    goto next_member;
448550599Sobrien
448650599Sobrien  return endbody;
448718334Speter}
448818334Speter
448918334Speter/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch
449018334Speter   on the command line.  PREFIX_LENGTH is the length of XXX in an {XXX*}
449118334Speter   spec, or -1 if either exact match or %* is used.
449218334Speter
449318334Speter   A -O switch is obsoleted by a later -O switch.  A -f, -m, or -W switch
449418334Speter   whose value does not begin with "no-" is obsoleted by the same value
449518334Speter   with the "no-", similarly for a switch with the "no-" prefix.  */
449618334Speter
449718334Speterstatic int
449818334Spetercheck_live_switch (switchnum, prefix_length)
449918334Speter     int switchnum;
450018334Speter     int prefix_length;
450118334Speter{
450252520Sobrien  const char *name = switches[switchnum].part1;
450318334Speter  int i;
450418334Speter
450518334Speter  /* In the common case of {<at-most-one-letter>*}, a negating
450618334Speter     switch would always match, so ignore that case.  We will just
450718334Speter     send the conflicting switches to the compiler phase.  */
450818334Speter  if (prefix_length >= 0 && prefix_length <= 1)
450918334Speter    return 1;
451018334Speter
451118334Speter  /* If we already processed this switch and determined if it was
451218334Speter     live or not, return our past determination.  */
451318334Speter  if (switches[switchnum].live_cond != 0)
451418334Speter    return switches[switchnum].live_cond > 0;
451518334Speter
451618334Speter  /* Now search for duplicate in a manner that depends on the name.  */
451718334Speter  switch (*name)
451818334Speter    {
451918334Speter    case 'O':
452018334Speter	for (i = switchnum + 1; i < n_switches; i++)
452118334Speter	  if (switches[i].part1[0] == 'O')
452218334Speter	    {
452352520Sobrien	      switches[switchnum].validated = 1;
452418334Speter	      switches[switchnum].live_cond = -1;
452518334Speter	      return 0;
452618334Speter	    }
452718334Speter      break;
452818334Speter
452918334Speter    case 'W':  case 'f':  case 'm':
453018334Speter      if (! strncmp (name + 1, "no-", 3))
453118334Speter	{
453250599Sobrien	  /* We have Xno-YYY, search for XYYY.  */
453318334Speter	  for (i = switchnum + 1; i < n_switches; i++)
453418334Speter	    if (switches[i].part1[0] == name[0]
453518334Speter		&& ! strcmp (&switches[i].part1[1], &name[4]))
453618334Speter	    {
453752520Sobrien	      switches[switchnum].validated = 1;
453818334Speter	      switches[switchnum].live_cond = -1;
453918334Speter	      return 0;
454018334Speter	    }
454118334Speter	}
454218334Speter      else
454318334Speter	{
454418334Speter	  /* We have XYYY, search for Xno-YYY.  */
454518334Speter	  for (i = switchnum + 1; i < n_switches; i++)
454618334Speter	    if (switches[i].part1[0] == name[0]
454718334Speter		&& switches[i].part1[1] == 'n'
454818334Speter		&& switches[i].part1[2] == 'o'
454918334Speter		&& switches[i].part1[3] == '-'
455018334Speter		&& !strcmp (&switches[i].part1[4], &name[1]))
455118334Speter	    {
455252520Sobrien	      switches[switchnum].validated = 1;
455318334Speter	      switches[switchnum].live_cond = -1;
455418334Speter	      return 0;
455518334Speter	    }
455618334Speter	}
455718334Speter      break;
455818334Speter    }
455918334Speter
456018334Speter  /* Otherwise the switch is live.  */
456118334Speter  switches[switchnum].live_cond = 1;
456218334Speter  return 1;
456318334Speter}
456418334Speter
456518334Speter/* Pass a switch to the current accumulating command
456618334Speter   in the same form that we received it.
456718334Speter   SWITCHNUM identifies the switch; it is an index into
456818334Speter   the vector of switches gcc received, which is `switches'.
456918334Speter   This cannot fail since it never finishes a command line.
457018334Speter
457150599Sobrien   If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument.
457218334Speter
457350599Sobrien   If INCLUDE_BLANKS is nonzero, then we include blanks before each argument
457450599Sobrien   of the switch.  */
457550599Sobrien
457618334Speterstatic void
457750599Sobriengive_switch (switchnum, omit_first_word, include_blanks)
457818334Speter     int switchnum;
457918334Speter     int omit_first_word;
458050599Sobrien     int include_blanks;
458118334Speter{
458218334Speter  if (!omit_first_word)
458318334Speter    {
458418334Speter      do_spec_1 ("-", 0, NULL_PTR);
458518334Speter      do_spec_1 (switches[switchnum].part1, 1, NULL_PTR);
458618334Speter    }
458750599Sobrien
458818334Speter  if (switches[switchnum].args != 0)
458918334Speter    {
459018334Speter      char **p;
459118334Speter      for (p = switches[switchnum].args; *p; p++)
459218334Speter	{
459350599Sobrien	  if (include_blanks)
459450599Sobrien	    do_spec_1 (" ", 0, NULL_PTR);
459518334Speter	  do_spec_1 (*p, 1, NULL_PTR);
459618334Speter	}
459718334Speter    }
459850599Sobrien
459950599Sobrien  do_spec_1 (" ", 0, NULL_PTR);
460052520Sobrien  switches[switchnum].validated = 1;
460118334Speter}
460218334Speter
460318334Speter/* Search for a file named NAME trying various prefixes including the
460418334Speter   user's -B prefix and some standard ones.
460518334Speter   Return the absolute file name found.  If nothing is found, return NAME.  */
460618334Speter
460752520Sobrienstatic const char *
460818334Speterfind_file (name)
460952520Sobrien     const char *name;
461018334Speter{
461118334Speter  char *newname;
461218334Speter
461318334Speter  /* Try multilib_dir if it is defined.  */
461418334Speter  if (multilib_dir != NULL)
461518334Speter    {
461618334Speter      char *try;
461718334Speter
461818334Speter      try = (char *) alloca (strlen (multilib_dir) + strlen (name) + 2);
461918334Speter      strcpy (try, multilib_dir);
462018334Speter      strcat (try, dir_separator_str);
462118334Speter      strcat (try, name);
462218334Speter
462318334Speter      newname = find_a_file (&startfile_prefixes, try, R_OK);
462418334Speter
462518334Speter      /* If we don't find it in the multi library dir, then fall
462618334Speter	 through and look for it in the normal places.  */
462718334Speter      if (newname != NULL)
462818334Speter	return newname;
462918334Speter    }
463018334Speter
463118334Speter  newname = find_a_file (&startfile_prefixes, name, R_OK);
463218334Speter  return newname ? newname : name;
463318334Speter}
463418334Speter
463518334Speter/* Determine whether a directory exists.  If LINKER, return 0 for
463618334Speter   certain fixed names not needed by the linker.  If not LINKER, it is
463718334Speter   only important to return 0 if the host machine has a small ARG_MAX
463818334Speter   limit.  */
463918334Speter
464018334Speterstatic int
464118334Speteris_directory (path1, path2, linker)
464252520Sobrien     const char *path1;
464352520Sobrien     const char *path2;
464418334Speter     int linker;
464518334Speter{
464618334Speter  int len1 = strlen (path1);
464718334Speter  int len2 = strlen (path2);
464818334Speter  char *path = (char *) alloca (3 + len1 + len2);
464918334Speter  char *cp;
465018334Speter  struct stat st;
465118334Speter
465218334Speter#ifndef SMALL_ARG_MAX
465318334Speter  if (! linker)
465418334Speter    return 1;
465518334Speter#endif
465618334Speter
465718334Speter  /* Construct the path from the two parts.  Ensure the string ends with "/.".
465818334Speter     The resulting path will be a directory even if the given path is a
465918334Speter     symbolic link.  */
466052520Sobrien  memcpy (path, path1, len1);
466152520Sobrien  memcpy (path + len1, path2, len2);
466218334Speter  cp = path + len1 + len2;
466352520Sobrien  if (!IS_DIR_SEPARATOR (cp[-1]))
466418334Speter    *cp++ = DIR_SEPARATOR;
466518334Speter  *cp++ = '.';
466618334Speter  *cp = '\0';
466718334Speter
466851232Sbde#ifndef FREEBSD_NATIVE
466918334Speter  /* Exclude directories that the linker is known to search.  */
467018334Speter  if (linker
467118334Speter      && ((cp - path == 6
467250599Sobrien	   && strcmp (path, concat (dir_separator_str, "lib",
467350599Sobrien				    dir_separator_str, ".", NULL_PTR)) == 0)
467418334Speter	  || (cp - path == 10
467550599Sobrien	      && strcmp (path, concat (dir_separator_str, "usr",
467650599Sobrien				       dir_separator_str, "lib",
467750599Sobrien				       dir_separator_str, ".", NULL_PTR)) == 0)))
467818334Speter    return 0;
467951232Sbde#endif /* FREEBSD_NATIVE */
468018334Speter
468118334Speter  return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
468218334Speter}
468318334Speter
468418334Speter/* On fatal signals, delete all the temporary files.  */
468518334Speter
468618334Speterstatic void
468718334Speterfatal_error (signum)
468818334Speter     int signum;
468918334Speter{
469018334Speter  signal (signum, SIG_DFL);
469118334Speter  delete_failure_queue ();
469218334Speter  delete_temp_files ();
469318334Speter  /* Get the same signal again, this time not handled,
469418334Speter     so its normal effect occurs.  */
469518334Speter  kill (getpid (), signum);
469618334Speter}
469718334Speter
469818334Speterint
469918334Spetermain (argc, argv)
470018334Speter     int argc;
470118334Speter     char **argv;
470218334Speter{
470350599Sobrien  register size_t i;
470450599Sobrien  size_t j;
470518334Speter  int value;
470618334Speter  int linker_was_run = 0;
470718334Speter  char *explicit_link_files;
470818334Speter  char *specs_file;
470952520Sobrien  const char *p;
471050599Sobrien  struct user_specs *uptr;
471118334Speter
471218334Speter  p = argv[0] + strlen (argv[0]);
471352520Sobrien  while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
471452520Sobrien    --p;
471518334Speter  programname = p;
471618334Speter
471752520Sobrien#ifdef HAVE_LC_MESSAGES
471852520Sobrien  setlocale (LC_MESSAGES, "");
471952520Sobrien#endif
472052520Sobrien  (void) bindtextdomain (PACKAGE, localedir);
472152520Sobrien  (void) textdomain (PACKAGE);
472252520Sobrien
472318334Speter  if (signal (SIGINT, SIG_IGN) != SIG_IGN)
472418334Speter    signal (SIGINT, fatal_error);
472518334Speter#ifdef SIGHUP
472618334Speter  if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
472718334Speter    signal (SIGHUP, fatal_error);
472818334Speter#endif
472918334Speter  if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
473018334Speter    signal (SIGTERM, fatal_error);
473118334Speter#ifdef SIGPIPE
473218334Speter  if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
473318334Speter    signal (SIGPIPE, fatal_error);
473418334Speter#endif
473518334Speter
473618334Speter  argbuf_length = 10;
473718334Speter  argbuf = (char **) xmalloc (argbuf_length * sizeof (char *));
473818334Speter
473918334Speter  obstack_init (&obstack);
474018334Speter
474150599Sobrien  /* Build multilib_select, et. al from the separate lines that make up each
474250599Sobrien     multilib selection.  */
474350599Sobrien  {
474450599Sobrien    char **q = multilib_raw;
474550599Sobrien    int need_space;
474650599Sobrien
474750599Sobrien    obstack_init (&multilib_obstack);
474850599Sobrien    while ((p = *q++) != (char *) 0)
474950599Sobrien      obstack_grow (&multilib_obstack, p, strlen (p));
475050599Sobrien
475150599Sobrien    obstack_1grow (&multilib_obstack, 0);
475250599Sobrien    multilib_select = obstack_finish (&multilib_obstack);
475350599Sobrien
475450599Sobrien    q = multilib_matches_raw;
475550599Sobrien    while ((p = *q++) != (char *) 0)
475650599Sobrien      obstack_grow (&multilib_obstack, p, strlen (p));
475750599Sobrien
475850599Sobrien    obstack_1grow (&multilib_obstack, 0);
475950599Sobrien    multilib_matches = obstack_finish (&multilib_obstack);
476050599Sobrien
476150599Sobrien    need_space = FALSE;
476250599Sobrien    for (i = 0;
476350599Sobrien	 i < sizeof (multilib_defaults_raw) / sizeof (multilib_defaults_raw[0]);
476450599Sobrien	 i++)
476550599Sobrien      {
476650599Sobrien	if (need_space)
476750599Sobrien	  obstack_1grow (&multilib_obstack, ' ');
476850599Sobrien	obstack_grow (&multilib_obstack,
476950599Sobrien		      multilib_defaults_raw[i],
477050599Sobrien		      strlen (multilib_defaults_raw[i]));
477150599Sobrien	need_space = TRUE;
477250599Sobrien      }
477350599Sobrien
477450599Sobrien    obstack_1grow (&multilib_obstack, 0);
477550599Sobrien    multilib_defaults = obstack_finish (&multilib_obstack);
477650599Sobrien  }
477750599Sobrien
477818334Speter  /* Set up to remember the pathname of gcc and any options
477918334Speter     needed for collect.  We use argv[0] instead of programname because
478018334Speter     we need the complete pathname.  */
478118334Speter  obstack_init (&collect_obstack);
478218334Speter  obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=")-1);
478318334Speter  obstack_grow (&collect_obstack, argv[0], strlen (argv[0])+1);
478418334Speter  putenv (obstack_finish (&collect_obstack));
478518334Speter
478618334Speter#ifdef INIT_ENVIRONMENT
478718334Speter  /* Set up any other necessary machine specific environment variables.  */
478818334Speter  putenv (INIT_ENVIRONMENT);
478918334Speter#endif
479018334Speter
479118334Speter  /* Choose directory for temp files.  */
479218334Speter
479350599Sobrien#ifndef MKTEMP_EACH_FILE
479450599Sobrien  temp_filename = choose_temp_base ();
479550599Sobrien  temp_filename_length = strlen (temp_filename);
479650599Sobrien#endif
479718334Speter
479818334Speter  /* Make a table of what switches there are (switches, n_switches).
479918334Speter     Make a table of specified input files (infiles, n_infiles).
480018334Speter     Decode switches that are handled locally.  */
480118334Speter
480218334Speter  process_command (argc, argv);
480318334Speter
480450599Sobrien  {
480550599Sobrien    int first_time;
480650599Sobrien
480750599Sobrien    /* Build COLLECT_GCC_OPTIONS to have all of the options specified to
480850599Sobrien       the compiler.  */
480950599Sobrien    obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
481050599Sobrien		  sizeof ("COLLECT_GCC_OPTIONS=")-1);
481150599Sobrien
481250599Sobrien    first_time = TRUE;
481352520Sobrien    for (i = 0; (int)i < n_switches; i++)
481450599Sobrien      {
481550599Sobrien	char **args;
481652520Sobrien	const char *p, *q;
481750599Sobrien	if (!first_time)
481850599Sobrien	  obstack_grow (&collect_obstack, " ", 1);
481950599Sobrien
482050599Sobrien	first_time = FALSE;
482150599Sobrien	obstack_grow (&collect_obstack, "'-", 2);
482250599Sobrien        q = switches[i].part1;
482350599Sobrien	while ((p = index (q,'\'')))
482450599Sobrien          {
482550599Sobrien            obstack_grow (&collect_obstack, q, p-q);
482650599Sobrien            obstack_grow (&collect_obstack, "'\\''", 4);
482750599Sobrien            q = ++p;
482850599Sobrien          }
482950599Sobrien        obstack_grow (&collect_obstack, q, strlen (q));
483050599Sobrien	obstack_grow (&collect_obstack, "'", 1);
483150599Sobrien
483250599Sobrien	for (args = switches[i].args; args && *args; args++)
483350599Sobrien	  {
483450599Sobrien	    obstack_grow (&collect_obstack, " '", 2);
483550599Sobrien	    q = *args;
483650599Sobrien	    while ((p = index (q,'\'')))
483750599Sobrien	      {
483850599Sobrien		obstack_grow (&collect_obstack, q, p-q);
483950599Sobrien		obstack_grow (&collect_obstack, "'\\''", 4);
484050599Sobrien		q = ++p;
484150599Sobrien	      }
484250599Sobrien	    obstack_grow (&collect_obstack, q, strlen (q));
484350599Sobrien	    obstack_grow (&collect_obstack, "'", 1);
484450599Sobrien	  }
484550599Sobrien      }
484650599Sobrien    obstack_grow (&collect_obstack, "\0", 1);
484750599Sobrien    putenv (obstack_finish (&collect_obstack));
484850599Sobrien  }
484950599Sobrien
485018334Speter  /* Initialize the vector of specs to just the default.
485118334Speter     This means one element containing 0s, as a terminator.  */
485218334Speter
485318334Speter  compilers = (struct compiler *) xmalloc (sizeof default_compilers);
485418334Speter  bcopy ((char *) default_compilers, (char *) compilers,
485518334Speter	 sizeof default_compilers);
485618334Speter  n_compilers = n_default_compilers;
485718334Speter
485818334Speter  /* Read specs from a file if there is one.  */
485918334Speter
486018346Speter#ifndef FREEBSD_NATIVE
486150599Sobrien  machine_suffix = concat (spec_machine, dir_separator_str,
486250599Sobrien			   spec_version, dir_separator_str, NULL_PTR);
486350599Sobrien  just_machine_suffix = concat (spec_machine, dir_separator_str, NULL_PTR);
486450599Sobrien#else /* FREEBSD_NATIVE */
486550599Sobrien  just_machine_suffix = "";
486650599Sobrien#endif /* FREEBSD_NATIVE */
486718334Speter
486818334Speter  specs_file = find_a_file (&startfile_prefixes, "specs", R_OK);
486918334Speter  /* Read the specs file unless it is a default one.  */
487018334Speter  if (specs_file != 0 && strcmp (specs_file, "specs"))
487150599Sobrien    read_specs (specs_file, TRUE);
487250599Sobrien  else
487350599Sobrien    init_spec ();
487418334Speter
487550599Sobrien  /* We need to check standard_exec_prefix/just_machine_suffix/specs
487650599Sobrien     for any override of as, ld and libraries. */
487750599Sobrien  specs_file = (char *) alloca (strlen (standard_exec_prefix)
487850599Sobrien				+ strlen (just_machine_suffix)
487950599Sobrien				+ sizeof ("specs"));
488050599Sobrien
488150599Sobrien  strcpy (specs_file, standard_exec_prefix);
488250599Sobrien  strcat (specs_file, just_machine_suffix);
488350599Sobrien  strcat (specs_file, "specs");
488450599Sobrien  if (access (specs_file, R_OK) == 0)
488550599Sobrien    read_specs (specs_file, TRUE);
488650599Sobrien
488718334Speter  /* If not cross-compiling, look for startfiles in the standard places.  */
488850599Sobrien  if (*cross_compile == '0')
488918334Speter    {
489018334Speter#ifdef MD_EXEC_PREFIX
489150599Sobrien      add_prefix (&exec_prefixes, md_exec_prefix, "GCC", 0, 0, NULL_PTR);
489250599Sobrien      add_prefix (&startfile_prefixes, md_exec_prefix, "GCC", 0, 0, NULL_PTR);
489318334Speter#endif
489418334Speter
489518334Speter#ifdef MD_STARTFILE_PREFIX
489650599Sobrien      add_prefix (&startfile_prefixes, md_startfile_prefix, "GCC",
489750599Sobrien		  0, 0, NULL_PTR);
489818334Speter#endif
489918334Speter
490018334Speter#ifdef MD_STARTFILE_PREFIX_1
490150599Sobrien      add_prefix (&startfile_prefixes, md_startfile_prefix_1, "GCC",
490250599Sobrien		  0, 0, NULL_PTR);
490318334Speter#endif
490418334Speter
490518334Speter      /* If standard_startfile_prefix is relative, base it on
490618334Speter	 standard_exec_prefix.  This lets us move the installed tree
490718334Speter	 as a unit.  If GCC_EXEC_PREFIX is defined, base
490818334Speter	 standard_startfile_prefix on that as well.  */
490952520Sobrien      if (IS_DIR_SEPARATOR (*standard_startfile_prefix)
491052520Sobrien	    || *standard_startfile_prefix == '$'
491152520Sobrien#ifdef HAVE_DOS_BASED_FILESYSTEM
491252520Sobrien  	    /* Check for disk name on MS-DOS-based systems.  */
491350599Sobrien          || (standard_startfile_prefix[1] == ':'
491452520Sobrien	      && (IS_DIR_SEPARATOR (standard_startfile_prefix[2])))
491550599Sobrien#endif
491650599Sobrien	  )
491750599Sobrien	add_prefix (&startfile_prefixes, standard_startfile_prefix, "BINUTILS",
491850599Sobrien		    0, 0, NULL_PTR);
491918334Speter      else
492018334Speter	{
492118334Speter	  if (gcc_exec_prefix)
492218334Speter	    add_prefix (&startfile_prefixes,
492350599Sobrien			concat (gcc_exec_prefix, machine_suffix,
492450599Sobrien				standard_startfile_prefix, NULL_PTR),
492550599Sobrien			NULL_PTR, 0, 0, NULL_PTR);
492618334Speter	  add_prefix (&startfile_prefixes,
492750599Sobrien		      concat (standard_exec_prefix,
492850599Sobrien			      machine_suffix,
492950599Sobrien			      standard_startfile_prefix, NULL_PTR),
493050599Sobrien		      NULL_PTR, 0, 0, NULL_PTR);
493118334Speter	}
493218334Speter
493318346Speter#ifndef FREEBSD_NATIVE
493450599Sobrien      add_prefix (&startfile_prefixes, standard_startfile_prefix_1,
493550599Sobrien		  "BINUTILS", 0, 0, NULL_PTR);
493650599Sobrien      add_prefix (&startfile_prefixes, standard_startfile_prefix_2,
493750599Sobrien		  "BINUTILS", 0, 0, NULL_PTR);
493818334Speter#if 0 /* Can cause surprises, and one can use -B./ instead.  */
493950599Sobrien      add_prefix (&startfile_prefixes, "./", NULL_PTR, 0, 1, NULL_PTR);
494018334Speter#endif
494118346Speter#endif /* FREEBSD_NATIVE */
494218334Speter    }
494318334Speter  else
494418334Speter    {
494552520Sobrien      if (!IS_DIR_SEPARATOR (*standard_startfile_prefix) && gcc_exec_prefix)
494618334Speter	add_prefix (&startfile_prefixes,
494750599Sobrien		    concat (gcc_exec_prefix, machine_suffix,
494850599Sobrien			    standard_startfile_prefix, NULL_PTR),
494950599Sobrien		    "BINUTILS", 0, 0, NULL_PTR);
495018334Speter    }
495118334Speter
495252520Sobrien  /* Process any user specified specs in the order given on the command
495352520Sobrien     line.  */
495452520Sobrien  for (uptr = user_specs_head; uptr; uptr = uptr->next)
495552520Sobrien    {
495652520Sobrien      char *filename = find_a_file (&startfile_prefixes, uptr->filename, R_OK);
495752520Sobrien      read_specs (filename ? filename : uptr->filename, FALSE);
495852520Sobrien    }
495952520Sobrien
496018334Speter  /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake.  */
496118334Speter  if (gcc_exec_prefix)
496218334Speter    {
496318334Speter      char * temp = (char *) xmalloc (strlen (gcc_exec_prefix)
496418334Speter				      + strlen (spec_version)
496518334Speter				      + strlen (spec_machine) + 3);
496618334Speter      strcpy (temp, gcc_exec_prefix);
496718334Speter      strcat (temp, spec_machine);
496818334Speter      strcat (temp, dir_separator_str);
496918334Speter      strcat (temp, spec_version);
497018334Speter      strcat (temp, dir_separator_str);
497118334Speter      gcc_exec_prefix = temp;
497218334Speter    }
497318334Speter
497418334Speter  /* Now we have the specs.
497518334Speter     Set the `valid' bits for switches that match anything in any spec.  */
497618334Speter
497718334Speter  validate_all_switches ();
497818334Speter
497918334Speter  /* Now that we have the switches and the specs, set
498018334Speter     the subdirectory based on the options.  */
498118334Speter  set_multilib_dir ();
498218334Speter
498318334Speter  /* Warn about any switches that no pass was interested in.  */
498418334Speter
498552520Sobrien  for (i = 0; (int)i < n_switches; i++)
498652520Sobrien    if (! switches[i].validated)
498718334Speter      error ("unrecognized option `-%s'", switches[i].part1);
498818334Speter
498918334Speter  /* Obey some of the options.  */
499018334Speter
499118334Speter  if (print_search_dirs)
499218334Speter    {
499318334Speter      printf ("install: %s%s\n", standard_exec_prefix, machine_suffix);
499418334Speter      printf ("programs: %s\n", build_search_list (&exec_prefixes, "", 0));
499518334Speter      printf ("libraries: %s\n", build_search_list (&startfile_prefixes, "", 0));
499618334Speter      exit (0);
499718334Speter    }
499818334Speter
499918334Speter  if (print_file_name)
500018334Speter    {
500118334Speter      printf ("%s\n", find_file (print_file_name));
500218334Speter      exit (0);
500318334Speter    }
500418334Speter
500518334Speter  if (print_prog_name)
500618334Speter    {
500718334Speter      char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK);
500818334Speter      printf ("%s\n", (newname ? newname : print_prog_name));
500918334Speter      exit (0);
501018334Speter    }
501118334Speter
501218334Speter  if (print_multi_lib)
501318334Speter    {
501418334Speter      print_multilib_info ();
501518334Speter      exit (0);
501618334Speter    }
501718334Speter
501818334Speter  if (print_multi_directory)
501918334Speter    {
502018334Speter      if (multilib_dir == NULL)
502118334Speter	printf (".\n");
502218334Speter      else
502318334Speter	printf ("%s\n", multilib_dir);
502418334Speter      exit (0);
502518334Speter    }
502618334Speter
502750599Sobrien  if (print_help_list)
502850599Sobrien    {
502950599Sobrien      display_help ();
503050599Sobrien
503150599Sobrien      if (! verbose_flag)
503250599Sobrien	{
503352520Sobrien	  printf ("\nFor bug reporting instructions, please see:\n");
503457849Sobrien	  printf ("%s.\n", GCCBUGURL);
503550599Sobrien
503650599Sobrien	  exit (0);
503750599Sobrien	}
503850599Sobrien
503950599Sobrien      /* We do not exit here.  Instead we have created a fake input file
504050599Sobrien	 called 'help-dummy' which needs to be compiled, and we pass this
504150599Sobrien	 on the the various sub-processes, along with the --help switch.  */
504250599Sobrien    }
504350599Sobrien
504418334Speter  if (verbose_flag)
504518334Speter    {
504650599Sobrien      int n;
504750599Sobrien
504850599Sobrien      /* compiler_version is truncated at the first space when initialized
504950599Sobrien	 from version string, so truncate version_string at the first space
505050599Sobrien	 before comparing.  */
505150599Sobrien      for (n = 0; version_string[n]; n++)
505250599Sobrien	if (version_string[n] == ' ')
505350599Sobrien	  break;
505450599Sobrien
505550599Sobrien      if (! strncmp (version_string, compiler_version, n)
505650599Sobrien	  && compiler_version[n] == 0)
505752520Sobrien	notice ("gcc version %s\n", version_string);
505818334Speter      else
505952520Sobrien	notice ("gcc driver version %s executing gcc version %s\n",
506052520Sobrien		version_string, compiler_version);
506118334Speter
506218334Speter      if (n_infiles == 0)
506318334Speter	exit (0);
506418334Speter    }
506518334Speter
506650599Sobrien  if (n_infiles == added_libraries)
506718346Speter    fatal ("No input files specified");
506818334Speter
506918334Speter  /* Make a place to record the compiler output file names
507018334Speter     that correspond to the input files.  */
507118334Speter
507250599Sobrien  i = n_infiles;
507350599Sobrien  i += lang_specific_extra_outfiles;
507452520Sobrien  outfiles = (const char **) xmalloc (i * sizeof (char *));
507552520Sobrien  bzero ((char *) outfiles, i * sizeof (char *));
507618334Speter
507718334Speter  /* Record which files were specified explicitly as link input.  */
507818334Speter
507918334Speter  explicit_link_files = xmalloc (n_infiles);
508018334Speter  bzero (explicit_link_files, n_infiles);
508118334Speter
508252520Sobrien  for (i = 0; (int)i < n_infiles; i++)
508318334Speter    {
508418334Speter      register struct compiler *cp = 0;
508518334Speter      int this_file_error = 0;
508618334Speter
508718334Speter      /* Tell do_spec what to substitute for %i.  */
508818334Speter
508918334Speter      input_filename = infiles[i].name;
509018334Speter      input_filename_length = strlen (input_filename);
509118334Speter      input_file_number = i;
509218334Speter
509318334Speter      /* Use the same thing in %o, unless cp->spec says otherwise.  */
509418334Speter
509518334Speter      outfiles[i] = input_filename;
509618334Speter
509718334Speter      /* Figure out which compiler from the file's suffix.  */
509818334Speter
509918334Speter      cp = lookup_compiler (infiles[i].name, input_filename_length,
510018334Speter			    infiles[i].language);
510118334Speter
510218334Speter      if (cp)
510318334Speter	{
510418334Speter	  /* Ok, we found an applicable compiler.  Run its spec.  */
510518334Speter	  /* First say how much of input_filename to substitute for %b  */
510652520Sobrien	  register const char *p;
510718334Speter	  int len;
510818334Speter
510950599Sobrien	  if (cp->spec[0][0] == '#')
511050599Sobrien	    error ("%s: %s compiler not installed on this system",
511150599Sobrien		   input_filename, &cp->spec[0][1]);
511250599Sobrien
511318334Speter	  input_basename = input_filename;
511418334Speter	  for (p = input_filename; *p; p++)
511552520Sobrien	    if (IS_DIR_SEPARATOR (*p))
511618334Speter	      input_basename = p + 1;
511718334Speter
511818334Speter	  /* Find a suffix starting with the last period,
511918334Speter	     and set basename_length to exclude that suffix.  */
512018334Speter	  basename_length = strlen (input_basename);
512118334Speter	  p = input_basename + basename_length;
512218334Speter	  while (p != input_basename && *p != '.') --p;
512318334Speter	  if (*p == '.' && p != input_basename)
512418334Speter	    {
512518334Speter	      basename_length = p - input_basename;
512618334Speter	      input_suffix = p + 1;
512718334Speter	    }
512818334Speter	  else
512918334Speter	    input_suffix = "";
513018334Speter
513118334Speter	  len = 0;
513218334Speter	  for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++)
513318334Speter	    if (cp->spec[j])
513418334Speter	      len += strlen (cp->spec[j]);
513518334Speter
513652520Sobrien	  {
513752520Sobrien	    char *p1 = (char *) xmalloc (len + 1);
513852520Sobrien
513952520Sobrien	    len = 0;
514052520Sobrien	    for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++)
514152520Sobrien	      if (cp->spec[j])
514252520Sobrien		{
514352520Sobrien		  strcpy (p1 + len, cp->spec[j]);
514452520Sobrien		  len += strlen (cp->spec[j]);
514552520Sobrien		}
514652520Sobrien
514752520Sobrien	    value = do_spec (p1);
514852520Sobrien	    free (p1);
514952520Sobrien	  }
515018334Speter	  if (value < 0)
515118334Speter	    this_file_error = 1;
515218334Speter	}
515318334Speter
515418334Speter      /* If this file's name does not contain a recognized suffix,
515518334Speter	 record it as explicit linker input.  */
515618334Speter
515718334Speter      else
515818334Speter	explicit_link_files[i] = 1;
515918334Speter
516018334Speter      /* Clear the delete-on-failure queue, deleting the files in it
516118334Speter	 if this compilation failed.  */
516218334Speter
516318334Speter      if (this_file_error)
516418334Speter	{
516518334Speter	  delete_failure_queue ();
516618334Speter	  error_count++;
516718334Speter	}
516818334Speter      /* If this compilation succeeded, don't delete those files later.  */
516918334Speter      clear_failure_queue ();
517018334Speter    }
517118334Speter
517252520Sobrien  if (error_count == 0)
517352520Sobrien    {
517452520Sobrien      /* Make sure INPUT_FILE_NUMBER points to first available open
517552520Sobrien	 slot.  */
517652520Sobrien      input_file_number = n_infiles;
517752520Sobrien      if (lang_specific_pre_link ())
517852520Sobrien	error_count++;
517952520Sobrien    }
518050599Sobrien
518118334Speter  /* Run ld to link all the compiler output files.  */
518218334Speter
518318334Speter  if (error_count == 0)
518418334Speter    {
518518334Speter      int tmp = execution_count;
518618334Speter
518750599Sobrien      /* We'll use ld if we can't find collect2. */
518850599Sobrien      if (! strcmp (linker_name_spec, "collect2"))
518950599Sobrien	{
519050599Sobrien	  char *s = find_a_file (&exec_prefixes, "collect2", X_OK);
519150599Sobrien	  if (s == NULL)
519250599Sobrien	    linker_name_spec = "ld";
519350599Sobrien	}
519418334Speter      /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
519518334Speter	 for collect.  */
519618334Speter      putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH=");
519718334Speter      putenv_from_prefixes (&startfile_prefixes, "LIBRARY_PATH=");
519818334Speter
519918334Speter      value = do_spec (link_command_spec);
520018334Speter      if (value < 0)
520118334Speter	error_count = 1;
520218334Speter      linker_was_run = (tmp != execution_count);
520318334Speter    }
520418334Speter
520518334Speter  /* Warn if a -B option was specified but the prefix was never used.  */
520618334Speter  unused_prefix_warnings (&exec_prefixes);
520718334Speter  unused_prefix_warnings (&startfile_prefixes);
520818334Speter
520918334Speter  /* If options said don't run linker,
521018334Speter     complain about input files to be given to the linker.  */
521118334Speter
521218334Speter  if (! linker_was_run && error_count == 0)
521352520Sobrien    for (i = 0; (int)i < n_infiles; i++)
521418334Speter      if (explicit_link_files[i])
521518334Speter	error ("%s: linker input file unused since linking not done",
521618334Speter	       outfiles[i]);
521718334Speter
521818334Speter  /* Delete some or all of the temporary files we made.  */
521918334Speter
522018334Speter  if (error_count)
522118334Speter    delete_failure_queue ();
522218334Speter  delete_temp_files ();
522318334Speter
522450599Sobrien  if (print_help_list)
522550599Sobrien    {
522652520Sobrien      printf ("\nFor bug reporting instructions, please see:\n");
522757849Sobrien      printf ("%s\n", GCCBUGURL);
522850599Sobrien    }
522950599Sobrien
523018334Speter  exit (error_count > 0 ? (signal_count ? 2 : 1) : 0);
523118334Speter  /* NOTREACHED */
523218334Speter  return 0;
523318334Speter}
523418334Speter
523518334Speter/* Find the proper compilation spec for the file name NAME,
523618334Speter   whose length is LENGTH.  LANGUAGE is the specified language,
523750599Sobrien   or 0 if this file is to be passed to the linker.  */
523818334Speter
523918334Speterstatic struct compiler *
524018334Speterlookup_compiler (name, length, language)
524152520Sobrien     const char *name;
524250599Sobrien     size_t length;
524352520Sobrien     const char *language;
524418334Speter{
524518334Speter  struct compiler *cp;
524618334Speter
524750599Sobrien  /* If this was specified by the user to be a linker input, indicate that. */
524850599Sobrien  if (language != 0 && language[0] == '*')
524950599Sobrien    return 0;
525050599Sobrien
525150599Sobrien  /* Otherwise, look for the language, if one is spec'd.  */
525218334Speter  if (language != 0)
525318334Speter    {
525418334Speter      for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
525550599Sobrien	if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language))
525650599Sobrien	  return cp;
525750599Sobrien
525818334Speter      error ("language %s not recognized", language);
525950599Sobrien      return 0;
526018334Speter    }
526118334Speter
526218334Speter  /* Look for a suffix.  */
526318334Speter  for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
526418334Speter    {
526518334Speter      if (/* The suffix `-' matches only the file name `-'.  */
526618334Speter	  (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
526750599Sobrien	  || (strlen (cp->suffix) < length
526850599Sobrien	      /* See if the suffix matches the end of NAME.  */
526918334Speter#ifdef OS2
527050599Sobrien	      && ((!strcmp (cp->suffix,
527150599Sobrien			   name + length - strlen (cp->suffix))
527250599Sobrien		   || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
527350599Sobrien		  && !strcasecmp (cp->suffix,
527450599Sobrien				  name + length - strlen (cp->suffix)))
527518334Speter#else
527650599Sobrien	      && !strcmp (cp->suffix,
527750599Sobrien			  name + length - strlen (cp->suffix))
527818334Speter#endif
527950599Sobrien	 ))
528018334Speter	{
528118334Speter	  if (cp->spec[0][0] == '@')
528218334Speter	    {
528318334Speter	      struct compiler *new;
528450599Sobrien
528518334Speter	      /* An alias entry maps a suffix to a language.
528618334Speter		 Search for the language; pass 0 for NAME and LENGTH
528718334Speter		 to avoid infinite recursion if language not found.
528818334Speter		 Construct the new compiler spec.  */
528918334Speter	      language = cp->spec[0] + 1;
529018334Speter	      new = (struct compiler *) xmalloc (sizeof (struct compiler));
529118334Speter	      new->suffix = cp->suffix;
529218334Speter	      bcopy ((char *) lookup_compiler (NULL_PTR, 0, language)->spec,
529318334Speter		     (char *) new->spec, sizeof new->spec);
529418334Speter	      return new;
529518334Speter	    }
529650599Sobrien
529718334Speter	  /* A non-alias entry: return it.  */
529818334Speter	  return cp;
529918334Speter	}
530018334Speter    }
530118334Speter
530218334Speter  return 0;
530318334Speter}
530418334Speter
530552520SobrienPTR
530618334Speterxmalloc (size)
530752520Sobrien  size_t size;
530818334Speter{
530952520Sobrien  register PTR value = (PTR) malloc (size);
531018334Speter  if (value == 0)
531118334Speter    fatal ("virtual memory exhausted");
531218334Speter  return value;
531318334Speter}
531418334Speter
531552520SobrienPTR
531652520Sobrienxrealloc (old, size)
531752520Sobrien  PTR old;
531852520Sobrien  size_t size;
531918334Speter{
532052520Sobrien  register PTR ptr;
532152520Sobrien  if (old)
532252520Sobrien    ptr = (PTR) realloc (old, size);
532352520Sobrien  else
532452520Sobrien    ptr = (PTR) malloc (size);
532552520Sobrien  if (ptr == 0)
532618334Speter    fatal ("virtual memory exhausted");
532752520Sobrien  return ptr;
532818334Speter}
532918334Speter
533018334Speterstatic char *
533118334Spetersave_string (s, len)
533252520Sobrien  const char *s;
533352520Sobrien  int len;
533418334Speter{
533518334Speter  register char *result = xmalloc (len + 1);
533618334Speter
533718334Speter  bcopy (s, result, len);
533818334Speter  result[len] = 0;
533918334Speter  return result;
534018334Speter}
534118334Speter
534218334Speterstatic void
534318334Speterpfatal_with_name (name)
534452520Sobrien     const char *name;
534518334Speter{
534652520Sobrien  perror_with_name (name);
534752520Sobrien  delete_temp_files ();
534852520Sobrien  exit (1);
534918334Speter}
535018334Speter
535118334Speterstatic void
535218334Speterperror_with_name (name)
535352520Sobrien     const char *name;
535418334Speter{
535552520Sobrien  error ("%s: %s", name, xstrerror (errno));
535618334Speter}
535718334Speter
535818334Speterstatic void
535950599Sobrienpfatal_pexecute (errmsg_fmt, errmsg_arg)
536052520Sobrien     const char *errmsg_fmt;
536152520Sobrien     const char *errmsg_arg;
536218334Speter{
536350599Sobrien  if (errmsg_arg)
536450599Sobrien    {
536552520Sobrien      int save_errno = errno;
536652520Sobrien
536750599Sobrien      /* Space for trailing '\0' is in %s.  */
536850599Sobrien      char *msg = xmalloc (strlen (errmsg_fmt) + strlen (errmsg_arg));
536950599Sobrien      sprintf (msg, errmsg_fmt, errmsg_arg);
537050599Sobrien      errmsg_fmt = msg;
537152520Sobrien
537252520Sobrien      errno = save_errno;
537350599Sobrien    }
537450599Sobrien
537552520Sobrien  pfatal_with_name (errmsg_fmt);
537618334Speter}
537718334Speter
537818334Speter/* More 'friendly' abort that prints the line and file.
537918334Speter   config.h can #define abort fancy_abort if you like that sort of thing.  */
538018334Speter
538118334Spetervoid
538218334Speterfancy_abort ()
538318334Speter{
538418334Speter  fatal ("Internal gcc abort.");
538518334Speter}
538618334Speter
538718334Speter/* Output an error message and exit */
538818334Speter
538952520Sobrienvoid
539052520Sobrienfatal VPROTO((const char *msgid, ...))
539118334Speter{
539252520Sobrien#ifndef ANSI_PROTOTYPES
539352520Sobrien  const char *msgid;
539418334Speter#endif
539518334Speter  va_list ap;
539618334Speter
539752520Sobrien  VA_START (ap, msgid);
539818334Speter
539952520Sobrien#ifndef ANSI_PROTOTYPES
540052520Sobrien  msgid = va_arg (ap, const char *);
540118334Speter#endif
540218334Speter
540318334Speter  fprintf (stderr, "%s: ", programname);
540452520Sobrien  vfprintf (stderr, _(msgid), ap);
540518334Speter  va_end (ap);
540618334Speter  fprintf (stderr, "\n");
540718334Speter  delete_temp_files ();
540818334Speter  exit (1);
540918334Speter}
541018334Speter
541118334Speterstatic void
541252520Sobrienerror VPROTO((const char *msgid, ...))
541318334Speter{
541452520Sobrien#ifndef ANSI_PROTOTYPES
541552520Sobrien  const char *msgid;
541618334Speter#endif
541718334Speter  va_list ap;
541818334Speter
541952520Sobrien  VA_START (ap, msgid);
542018334Speter
542152520Sobrien#ifndef ANSI_PROTOTYPES
542252520Sobrien  msgid = va_arg (ap, const char *);
542318334Speter#endif
542418334Speter
542518334Speter  fprintf (stderr, "%s: ", programname);
542652520Sobrien  vfprintf (stderr, _(msgid), ap);
542718334Speter  va_end (ap);
542818334Speter
542918334Speter  fprintf (stderr, "\n");
543018334Speter}
543152520Sobrien
543252520Sobrienstatic void
543352520Sobriennotice VPROTO((const char *msgid, ...))
543452520Sobrien{
543552520Sobrien#ifndef ANSI_PROTOTYPES
543652520Sobrien  const char *msgid;
543752520Sobrien#endif
543852520Sobrien  va_list ap;
543952520Sobrien
544052520Sobrien  VA_START (ap, msgid);
544152520Sobrien
544252520Sobrien#ifndef ANSI_PROTOTYPES
544352520Sobrien  msgid = va_arg (ap, const char *);
544452520Sobrien#endif
544552520Sobrien
544652520Sobrien  vfprintf (stderr, _(msgid), ap);
544752520Sobrien  va_end (ap);
544852520Sobrien}
544952520Sobrien
545018334Speter
545118334Speterstatic void
545218334Spetervalidate_all_switches ()
545318334Speter{
545418334Speter  struct compiler *comp;
545552520Sobrien  register const char *p;
545618334Speter  register char c;
545718334Speter  struct spec_list *spec;
545818334Speter
545918334Speter  for (comp = compilers; comp->spec[0]; comp++)
546018334Speter    {
546150599Sobrien      size_t i;
546218334Speter      for (i = 0; i < sizeof comp->spec / sizeof comp->spec[0] && comp->spec[i]; i++)
546318334Speter	{
546418334Speter	  p = comp->spec[i];
546550599Sobrien	  while ((c = *p++))
546618334Speter	    if (c == '%' && *p == '{')
546718334Speter	      /* We have a switch spec.  */
546818334Speter	      validate_switches (p + 1);
546918334Speter	}
547018334Speter    }
547118334Speter
547250599Sobrien  /* look through the linked list of specs read from the specs file */
547318334Speter  for (spec = specs; spec ; spec = spec->next)
547418334Speter    {
547550599Sobrien      p = *(spec->ptr_spec);
547650599Sobrien      while ((c = *p++))
547718334Speter	if (c == '%' && *p == '{')
547818334Speter	  /* We have a switch spec.  */
547918334Speter	  validate_switches (p + 1);
548018334Speter    }
548118334Speter
548218334Speter  p = link_command_spec;
548350599Sobrien  while ((c = *p++))
548418334Speter    if (c == '%' && *p == '{')
548518334Speter      /* We have a switch spec.  */
548618334Speter      validate_switches (p + 1);
548718334Speter}
548818334Speter
548918334Speter/* Look at the switch-name that comes after START
549018334Speter   and mark as valid all supplied switches that match it.  */
549118334Speter
549218334Speterstatic void
549318334Spetervalidate_switches (start)
549452520Sobrien     const char *start;
549518334Speter{
549652520Sobrien  register const char *p = start;
549752520Sobrien  const char *filter;
549818334Speter  register int i;
549918334Speter  int suffix = 0;
550018334Speter
550118334Speter  if (*p == '|')
550218334Speter    ++p;
550318334Speter
550418334Speter  if (*p == '!')
550518334Speter    ++p;
550618334Speter
550718334Speter  if (*p == '.')
550818334Speter    suffix = 1, ++p;
550918334Speter
551018334Speter  filter = p;
551118334Speter  while (*p != ':' && *p != '}') p++;
551218334Speter
551318334Speter  if (suffix)
551418334Speter    ;
551518334Speter  else if (p[-1] == '*')
551618334Speter    {
551718334Speter      /* Mark all matching switches as valid.  */
551818334Speter      --p;
551918334Speter      for (i = 0; i < n_switches; i++)
552018334Speter	if (!strncmp (switches[i].part1, filter, p - filter))
552152520Sobrien	  switches[i].validated = 1;
552218334Speter    }
552318334Speter  else
552418334Speter    {
552518334Speter      /* Mark an exact matching switch as valid.  */
552618334Speter      for (i = 0; i < n_switches; i++)
552718334Speter	{
552818334Speter	  if (!strncmp (switches[i].part1, filter, p - filter)
552918334Speter	      && switches[i].part1[p - filter] == 0)
553052520Sobrien	    switches[i].validated = 1;
553118334Speter	}
553218334Speter    }
553318334Speter}
553418334Speter
553550599Sobrien/* Check whether a particular argument was used.  The first time we
553650599Sobrien   canonicalize the switches to keep only the ones we care about.  */
553718334Speter
553818334Speterstatic int
553918334Speterused_arg (p, len)
554052520Sobrien     const char *p;
554118334Speter     int len;
554218334Speter{
554350599Sobrien  struct mswitchstr {
554450599Sobrien    char *str;
554550599Sobrien    char *replace;
554650599Sobrien    int len;
554750599Sobrien    int rep_len;
554850599Sobrien  };
554918334Speter
555050599Sobrien  static struct mswitchstr *mswitches;
555150599Sobrien  static int n_mswitches;
555250599Sobrien  int i, j;
555350599Sobrien
555450599Sobrien  if (!mswitches)
555550599Sobrien    {
555650599Sobrien      struct mswitchstr *matches;
555750599Sobrien      char *q;
555850599Sobrien      int cnt = 0;
555950599Sobrien
556050599Sobrien      /* Break multilib_matches into the component strings of string and replacement
556150599Sobrien         string */
556250599Sobrien      for (q = multilib_matches; *q != '\0'; q++)
556350599Sobrien	if (*q == ';')
556450599Sobrien	  cnt++;
556550599Sobrien
556650599Sobrien      matches = (struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt);
556750599Sobrien      i = 0;
556850599Sobrien      q = multilib_matches;
556950599Sobrien      while (*q != '\0')
557050599Sobrien	{
557150599Sobrien	  matches[i].str = q;
557250599Sobrien	  while (*q != ' ')
557350599Sobrien	    {
557450599Sobrien	      if (*q == '\0')
557550599Sobrien		abort ();
557650599Sobrien	      q++;
557750599Sobrien	    }
557850599Sobrien	  *q = '\0';
557950599Sobrien	  matches[i].len = q - matches[i].str;
558050599Sobrien
558150599Sobrien	  matches[i].replace = ++q;
558250599Sobrien	  while (*q != ';' && *q != '\0')
558350599Sobrien	    {
558450599Sobrien	      if (*q == ' ')
558550599Sobrien		abort ();
558650599Sobrien	      q++;
558750599Sobrien	    }
558850599Sobrien	  matches[i].rep_len = q - matches[i].replace;
558950599Sobrien	  i++;
559050599Sobrien	  if (*q == ';')
559150599Sobrien	    *q++ = '\0';
559250599Sobrien	  else
559350599Sobrien	    break;
559450599Sobrien	}
559550599Sobrien
559650599Sobrien      /* Now build a list of the replacement string for switches that we care
559750599Sobrien	 about.  Make sure we allocate at least one entry.  This prevents
559850599Sobrien	 xmalloc from calling fatal, and prevents us from re-executing this
559950599Sobrien	 block of code.  */
560050599Sobrien      mswitches
560150599Sobrien	= (struct mswitchstr *) xmalloc ((sizeof (struct mswitchstr))
560250599Sobrien					 * (n_switches ? n_switches : 1));
560350599Sobrien      for (i = 0; i < n_switches; i++)
560450599Sobrien	{
560550599Sobrien	  int xlen = strlen (switches[i].part1);
560650599Sobrien	  for (j = 0; j < cnt; j++)
560750599Sobrien	    if (xlen == matches[j].len && ! strcmp (switches[i].part1, matches[j].str))
560850599Sobrien	      {
560950599Sobrien		mswitches[n_mswitches].str = matches[j].replace;
561050599Sobrien		mswitches[n_mswitches].len = matches[j].rep_len;
561150599Sobrien		mswitches[n_mswitches].replace = (char *)0;
561250599Sobrien		mswitches[n_mswitches].rep_len = 0;
561350599Sobrien		n_mswitches++;
561450599Sobrien		break;
561550599Sobrien	      }
561650599Sobrien	}
561750599Sobrien    }
561850599Sobrien
561950599Sobrien  for (i = 0; i < n_mswitches; i++)
562050599Sobrien    if (len == mswitches[i].len && ! strncmp (p, mswitches[i].str, len))
562118334Speter      return 1;
562250599Sobrien
562318334Speter  return 0;
562418334Speter}
562518334Speter
562618334Speterstatic int
562718334Speterdefault_arg (p, len)
562852520Sobrien     const char *p;
562918334Speter     int len;
563018334Speter{
563150599Sobrien  char *start, *end;
563218334Speter
563350599Sobrien  for (start = multilib_defaults; *start != '\0'; start = end+1)
563450599Sobrien    {
563550599Sobrien      while (*start == ' ' || *start == '\t')
563650599Sobrien	start++;
563718334Speter
563850599Sobrien      if (*start == '\0')
563950599Sobrien	break;
564050599Sobrien
564150599Sobrien      for (end = start+1; *end != ' ' && *end != '\t' && *end != '\0'; end++)
564250599Sobrien	;
564350599Sobrien
564450599Sobrien      if ((end - start) == len && strncmp (p, start, len) == 0)
564550599Sobrien	return 1;
564650599Sobrien
564750599Sobrien      if (*end == '\0')
564850599Sobrien	break;
564950599Sobrien    }
565050599Sobrien
565118334Speter  return 0;
565218334Speter}
565318334Speter
565418334Speter/* Work out the subdirectory to use based on the
565518334Speter   options.  The format of multilib_select is a list of elements.
565618334Speter   Each element is a subdirectory name followed by a list of options
565718334Speter   followed by a semicolon.  gcc will consider each line in turn.  If
565818334Speter   none of the options beginning with an exclamation point are
565918334Speter   present, and all of the other options are present, that
566018334Speter   subdirectory will be used.  */
566118334Speter
566218334Speterstatic void
566318334Speterset_multilib_dir ()
566418334Speter{
566518334Speter  char *p = multilib_select;
566618334Speter  int this_path_len;
566718334Speter  char *this_path, *this_arg;
566818334Speter  int not_arg;
566918334Speter  int ok;
567018334Speter
567118334Speter  while (*p != '\0')
567218334Speter    {
567318334Speter      /* Ignore newlines.  */
567418334Speter      if (*p == '\n')
567518334Speter	{
567618334Speter	  ++p;
567718334Speter	  continue;
567818334Speter	}
567918334Speter
568018334Speter      /* Get the initial path.  */
568118334Speter      this_path = p;
568218334Speter      while (*p != ' ')
568318334Speter	{
568418334Speter	  if (*p == '\0')
568518334Speter	    abort ();
568618334Speter	  ++p;
568718334Speter	}
568818334Speter      this_path_len = p - this_path;
568918334Speter
569018334Speter      /* Check the arguments.  */
569118334Speter      ok = 1;
569218334Speter      ++p;
569318334Speter      while (*p != ';')
569418334Speter	{
569518334Speter	  if (*p == '\0')
569618334Speter	    abort ();
569718334Speter
569818334Speter	  if (! ok)
569918334Speter	    {
570018334Speter	      ++p;
570118334Speter	      continue;
570218334Speter	    }
570318334Speter
570418334Speter	  this_arg = p;
570518334Speter	  while (*p != ' ' && *p != ';')
570618334Speter	    {
570718334Speter	      if (*p == '\0')
570818334Speter		abort ();
570918334Speter	      ++p;
571018334Speter	    }
571118334Speter
571218334Speter	  if (*this_arg != '!')
571318334Speter	    not_arg = 0;
571418334Speter	  else
571518334Speter	    {
571618334Speter	      not_arg = 1;
571718334Speter	      ++this_arg;
571818334Speter	    }
571918334Speter
572018334Speter	  /* If this is a default argument, we can just ignore it.
572118334Speter	     This is true even if this_arg begins with '!'.  Beginning
572218334Speter	     with '!' does not mean that this argument is necessarily
572318334Speter	     inappropriate for this library: it merely means that
572418334Speter	     there is a more specific library which uses this
572518334Speter	     argument.  If this argument is a default, we need not
572618334Speter	     consider that more specific library.  */
572718334Speter	  if (! default_arg (this_arg, p - this_arg))
572818334Speter	    {
572918334Speter	      ok = used_arg (this_arg, p - this_arg);
573018334Speter	      if (not_arg)
573118334Speter		ok = ! ok;
573218334Speter	    }
573318334Speter
573418334Speter	  if (*p == ' ')
573518334Speter	    ++p;
573618334Speter	}
573718334Speter
573818334Speter      if (ok)
573918334Speter	{
574018334Speter	  if (this_path_len != 1
574118334Speter	      || this_path[0] != '.')
574218334Speter	    {
574352520Sobrien	      char * new_multilib_dir = xmalloc (this_path_len + 1);
574452520Sobrien	      strncpy (new_multilib_dir, this_path, this_path_len);
574552520Sobrien	      new_multilib_dir[this_path_len] = '\0';
574652520Sobrien	      multilib_dir = new_multilib_dir;
574718334Speter	    }
574818334Speter	  break;
574918334Speter	}
575018334Speter
575118334Speter      ++p;
575218334Speter    }
575318334Speter}
575418334Speter
575518334Speter/* Print out the multiple library subdirectory selection
575618334Speter   information.  This prints out a series of lines.  Each line looks
575718334Speter   like SUBDIRECTORY;@OPTION@OPTION, with as many options as is
575818334Speter   required.  Only the desired options are printed out, the negative
575918334Speter   matches.  The options are print without a leading dash.  There are
576018334Speter   no spaces to make it easy to use the information in the shell.
576118334Speter   Each subdirectory is printed only once.  This assumes the ordering
576218334Speter   generated by the genmultilib script.  */
576318334Speter
576418334Speterstatic void
576518334Speterprint_multilib_info ()
576618334Speter{
576718334Speter  char *p = multilib_select;
576818334Speter  char *last_path = 0, *this_path;
576918334Speter  int skip;
577018334Speter  int last_path_len = 0;
577118334Speter
577218334Speter  while (*p != '\0')
577318334Speter    {
577418334Speter      /* Ignore newlines.  */
577518334Speter      if (*p == '\n')
577618334Speter	{
577718334Speter	  ++p;
577818334Speter	  continue;
577918334Speter	}
578018334Speter
578118334Speter      /* Get the initial path.  */
578218334Speter      this_path = p;
578318334Speter      while (*p != ' ')
578418334Speter	{
578518334Speter	  if (*p == '\0')
578618334Speter	    abort ();
578718334Speter	  ++p;
578818334Speter	}
578918334Speter
579018334Speter      /* If this is a duplicate, skip it.  */
579118334Speter      skip = (last_path != 0 && p - this_path == last_path_len
579218334Speter	      && ! strncmp (last_path, this_path, last_path_len));
579318334Speter
579418334Speter      last_path = this_path;
579518334Speter      last_path_len = p - this_path;
579618334Speter
579718334Speter      /* If this directory requires any default arguments, we can skip
579818334Speter	 it.  We will already have printed a directory identical to
579918334Speter	 this one which does not require that default argument.  */
580018334Speter      if (! skip)
580118334Speter	{
580218334Speter	  char *q;
580318334Speter
580418334Speter	  q = p + 1;
580518334Speter	  while (*q != ';')
580618334Speter	    {
580718334Speter	      char *arg;
580818334Speter
580918334Speter	      if (*q == '\0')
581018334Speter		abort ();
581118334Speter
581218334Speter	      if (*q == '!')
581318334Speter		arg = NULL;
581418334Speter	      else
581518334Speter		arg = q;
581618334Speter
581718334Speter	      while (*q != ' ' && *q != ';')
581818334Speter		{
581918334Speter		  if (*q == '\0')
582018334Speter		    abort ();
582118334Speter		  ++q;
582218334Speter		}
582318334Speter
582418334Speter	      if (arg != NULL
582518334Speter		  && default_arg (arg, q - arg))
582618334Speter		{
582718334Speter		  skip = 1;
582818334Speter		  break;
582918334Speter		}
583018334Speter
583118334Speter	      if (*q == ' ')
583218334Speter		++q;
583318334Speter	    }
583418334Speter	}
583518334Speter
583618334Speter      if (! skip)
583718334Speter	{
583818334Speter	  char *p1;
583918334Speter
584018334Speter	  for (p1 = last_path; p1 < p; p1++)
584118334Speter	    putchar (*p1);
584218334Speter	  putchar (';');
584318334Speter	}
584418334Speter
584518334Speter      ++p;
584618334Speter      while (*p != ';')
584718334Speter	{
584818334Speter	  int use_arg;
584918334Speter
585018334Speter	  if (*p == '\0')
585118334Speter	    abort ();
585218334Speter
585318334Speter	  if (skip)
585418334Speter	    {
585518334Speter	      ++p;
585618334Speter	      continue;
585718334Speter	    }
585818334Speter
585918334Speter	  use_arg = *p != '!';
586018334Speter
586118334Speter	  if (use_arg)
586218334Speter	    putchar ('@');
586318334Speter
586418334Speter	  while (*p != ' ' && *p != ';')
586518334Speter	    {
586618334Speter	      if (*p == '\0')
586718334Speter		abort ();
586818334Speter	      if (use_arg)
586918334Speter		putchar (*p);
587018334Speter	      ++p;
587118334Speter	    }
587218334Speter
587318334Speter	  if (*p == ' ')
587418334Speter	    ++p;
587518334Speter	}
587618334Speter
587718334Speter      if (! skip)
587850599Sobrien	{
587950599Sobrien	  /* If there are extra options, print them now */
588050599Sobrien	  if (multilib_extra && *multilib_extra)
588150599Sobrien	    {
588250599Sobrien	      int print_at = TRUE;
588350599Sobrien	      char *q;
588418334Speter
588550599Sobrien	      for (q = multilib_extra; *q != '\0'; q++)
588650599Sobrien		{
588750599Sobrien		  if (*q == ' ')
588850599Sobrien		    print_at = TRUE;
588950599Sobrien		  else
589050599Sobrien		    {
589150599Sobrien		      if (print_at)
589250599Sobrien			putchar ('@');
589350599Sobrien		      putchar (*q);
589450599Sobrien		      print_at = FALSE;
589550599Sobrien		    }
589650599Sobrien		}
589750599Sobrien	    }
589850599Sobrien	  putchar ('\n');
589950599Sobrien	}
590050599Sobrien
590118334Speter      ++p;
590218334Speter    }
590318334Speter}
5904