gcc.c revision 18346
118334Speter/* Compiler driver program that can handle many languages.
218334Speter   Copyright (C) 1987, 89, 92, 93, 94, 1995 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
2418334Speter/* This program is the user interface to the C compiler and possibly to
2518334Speterother compilers.  It is used because compilation is a complicated procedure
2618334Speterwhich involves running several programs and passing temporary files between
2718334Speterthem, forwarding the users switches to those programs selectively,
2818334Speterand deleting the temporary files at the end.
2918334Speter
3018334SpeterCC recognizes how to compile each input file by suffixes in the file names.
3118334SpeterOnce it knows which kind of compilation to perform, the procedure for
3218334Spetercompilation is specified by a string called a "spec".  */
3318334Speter
3418334Speter#include <sys/types.h>
3518346Speter#include <sys/wait.h>
3618334Speter#include <ctype.h>
3718334Speter#include <signal.h>
3818334Speter#include <sys/stat.h>
3918334Speter#include <errno.h>
4018334Speter
4118334Speter#ifndef _WIN32
4218334Speter#include <sys/file.h>   /* May get R_OK, etc. on some systems.  */
4318334Speter#else
4418334Speter#include <process.h>
4518334Speterint __spawnv ();
4618334Speterint __spawnvp ();
4718334Speter#endif
4818334Speter
4918334Speter#include "config.h"
5018334Speter#include "obstack.h"
5118334Speter#ifdef __STDC__
5218334Speter#include <stdarg.h>
5318334Speter#else
5418334Speter#include <varargs.h>
5518334Speter#endif
5618334Speter#include <stdio.h>
5718346Speter#include <stdlib.h>
5818346Speter#include <unistd.h>
5918346Speter#include <string.h>
6018334Speter
6118334Speter/* Include multi-lib information.  */
6218334Speter#include "multilib.h"
6318334Speter
6418334Speter#ifndef R_OK
6518334Speter#define R_OK 4
6618334Speter#define W_OK 2
6718334Speter#define X_OK 1
6818334Speter#endif
6918334Speter
7018334Speter#ifndef WIFSIGNALED
7118334Speter#define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)
7218334Speter#endif
7318334Speter#ifndef WTERMSIG
7418334Speter#define WTERMSIG(S) ((S) & 0x7f)
7518334Speter#endif
7618334Speter#ifndef WIFEXITED
7718334Speter#define WIFEXITED(S) (((S) & 0xff) == 0)
7818334Speter#endif
7918334Speter#ifndef WEXITSTATUS
8018334Speter#define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
8118334Speter#endif
8218334Speter
8318334Speter/* Add prototype support.  */
8418334Speter#ifndef PROTO
8518334Speter#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
8618334Speter#define PROTO(ARGS) ARGS
8718334Speter#else
8818334Speter#define PROTO(ARGS) ()
8918334Speter#endif
9018334Speter#endif
9118334Speter
9218334Speter#ifndef VPROTO
9318334Speter#ifdef __STDC__
9418334Speter#define PVPROTO(ARGS)		ARGS
9518334Speter#define VPROTO(ARGS)		ARGS
9618334Speter#define VA_START(va_list,var)	va_start(va_list,var)
9718334Speter#else
9818334Speter#define PVPROTO(ARGS)		()
9918334Speter#define VPROTO(ARGS)		(va_alist) va_dcl
10018334Speter#define VA_START(va_list,var)	va_start(va_list)
10118334Speter#endif
10218334Speter#endif
10318334Speter
10418334Speter/* Define a generic NULL if one hasn't already been defined.  */
10518334Speter
10618334Speter#ifndef NULL
10718334Speter#define NULL 0
10818334Speter#endif
10918334Speter
11018334Speter/* Define O_RDONLY if the system hasn't defined it for us. */
11118334Speter#ifndef O_RDONLY
11218334Speter#define O_RDONLY 0
11318334Speter#endif
11418334Speter
11518334Speter#ifndef GENERIC_PTR
11618334Speter#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
11718334Speter#define GENERIC_PTR void *
11818334Speter#else
11918334Speter#define GENERIC_PTR char *
12018334Speter#endif
12118334Speter#endif
12218334Speter
12318334Speter#ifndef NULL_PTR
12418334Speter#define NULL_PTR ((GENERIC_PTR)0)
12518334Speter#endif
12618334Speter
12718334Speter#ifdef USG
12818334Speter#define vfork fork
12918334Speter#endif /* USG */
13018334Speter
13118334Speter/* On MSDOS, write temp files in current dir
13218334Speter   because there's no place else we can expect to use.  */
13318334Speter#ifdef __MSDOS__
13418334Speter#ifndef P_tmpdir
13518334Speter#define P_tmpdir "."
13618334Speter#endif
13718334Speter#endif
13818334Speter
13918334Speter/* Test if something is a normal file.  */
14018334Speter#ifndef S_ISREG
14118334Speter#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
14218334Speter#endif
14318334Speter
14418334Speter/* Test if something is a directory.  */
14518334Speter#ifndef S_ISDIR
14618334Speter#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
14718334Speter#endif
14818334Speter
14918334Speter/* By default there is no special suffix for executables.  */
15018334Speter#ifndef EXECUTABLE_SUFFIX
15118334Speter#define EXECUTABLE_SUFFIX ""
15218334Speter#endif
15318334Speter
15418334Speter/* By default, the suffix for object files is ".o". */
15518334Speter#ifdef OBJECT_SUFFIX
15618334Speter#define HAVE_OBJECT_SUFFIX
15718334Speter#else
15818334Speter#define OBJECT_SUFFIX ".o"
15918334Speter#endif
16018334Speter
16118334Speter/* By default, colon separates directories in a path.  */
16218334Speter#ifndef PATH_SEPARATOR
16318334Speter#define PATH_SEPARATOR ':'
16418334Speter#endif
16518334Speter
16618334Speter#ifndef DIR_SEPARATOR
16718334Speter#define DIR_SEPARATOR '/'
16818334Speter#endif
16918334Speter
17018334Speterstatic char dir_separator_str[] = {DIR_SEPARATOR, 0};
17118334Speter
17218334Speter#define obstack_chunk_alloc xmalloc
17318334Speter#define obstack_chunk_free free
17418334Speter
17518334Speterextern void free ();
17618334Speterextern char *getenv ();
17718334Speter
17818334Speter#ifndef errno
17918334Speterextern int errno;
18018334Speter#endif
18118334Speter
18218334Speterextern int sys_nerr;
18318334Speter#ifndef HAVE_STRERROR
18418334Speter#if defined(bsd4_4)
18518334Speterextern const char *const sys_errlist[];
18618334Speter#else
18718334Speterextern char *sys_errlist[];
18818334Speter#endif
18918334Speter#else
19018334Speterextern char *strerror();
19118334Speter#endif
19218334Speter
19318334Speterextern int execv (), execvp ();
19418334Speter
19518334Speter/* If a stage of compilation returns an exit status >= 1,
19618334Speter   compilation of that file ceases.  */
19718334Speter
19818334Speter#define MIN_FATAL_STATUS 1
19918334Speter
20018334Speter/* Flag saying to print the directories gcc will search through looking for
20118334Speter   programs, libraries, etc.  */
20218334Speter
20318334Speterstatic int print_search_dirs;
20418334Speter
20518334Speter/* Flag saying to print the full filename of this file
20618334Speter   as found through our usual search mechanism.  */
20718334Speter
20818334Speterstatic char *print_file_name = NULL;
20918334Speter
21018334Speter/* As print_file_name, but search for executable file. */
21118334Speter
21218334Speterstatic char *print_prog_name = NULL;
21318334Speter
21418334Speter/* Flag saying to print the relative path we'd use to
21518334Speter   find libgcc.a given the current compiler flags.  */
21618334Speter
21718334Speterstatic int print_multi_directory;
21818334Speter
21918334Speter/* Flag saying to print the list of subdirectories and
22018334Speter   compiler flags used to select them in a standard form.  */
22118334Speter
22218334Speterstatic int print_multi_lib;
22318334Speter
22418334Speter/* Flag indicating whether we should print the command and arguments */
22518334Speter
22618334Speterstatic int verbose_flag;
22718334Speter
22818334Speter/* Nonzero means write "temp" files in source directory
22918334Speter   and use the source file's name in them, and don't delete them.  */
23018334Speter
23118334Speterstatic int save_temps_flag;
23218334Speter
23318334Speter/* The compiler version.  */
23418334Speter
23518334Speterstatic char *compiler_version;
23618334Speter
23718334Speter/* The target version specified with -V */
23818334Speter
23918334Speterstatic char *spec_version = DEFAULT_TARGET_VERSION;
24018334Speter
24118334Speter/* The target machine specified with -b.  */
24218334Speter
24318334Speterstatic char *spec_machine = DEFAULT_TARGET_MACHINE;
24418334Speter
24518334Speter/* Nonzero if cross-compiling.
24618334Speter   When -b is used, the value comes from the `specs' file.  */
24718334Speter
24818334Speter#ifdef CROSS_COMPILE
24918334Speterstatic int cross_compile = 1;
25018334Speter#else
25118334Speterstatic int cross_compile = 0;
25218334Speter#endif
25318334Speter
25418334Speter/* The number of errors that have occurred; the link phase will not be
25518334Speter   run if this is non-zero.  */
25618334Speterstatic int error_count = 0;
25718334Speter
25818334Speter/* This is the obstack which we use to allocate many strings.  */
25918334Speter
26018334Speterstatic struct obstack obstack;
26118334Speter
26218334Speter/* This is the obstack to build an environment variable to pass to
26318334Speter   collect2 that describes all of the relevant switches of what to
26418334Speter   pass the compiler in building the list of pointers to constructors
26518334Speter   and destructors.  */
26618334Speter
26718334Speterstatic struct obstack collect_obstack;
26818334Speter
26918334Speterextern char *version_string;
27018334Speter
27118334Speter/* Forward declaration for prototypes.  */
27218334Speterstruct path_prefix;
27318334Speter
27418334Speterstatic void set_spec		PROTO((char *, char *));
27518334Speterstatic struct compiler *lookup_compiler PROTO((char *, int, char *));
27618334Speterstatic char *build_search_list	PROTO((struct path_prefix *, char *, int));
27718334Speterstatic void putenv_from_prefixes PROTO((struct path_prefix *, char *));
27818334Speterstatic char *find_a_file	PROTO((struct path_prefix *, char *, int));
27918334Speterstatic void add_prefix		PROTO((struct path_prefix *, char *, int, int, int *));
28018334Speterstatic char *skip_whitespace	PROTO((char *));
28118334Speterstatic void record_temp_file	PROTO((char *, int, int));
28218334Speterstatic void delete_if_ordinary	PROTO((char *));
28318334Speterstatic void delete_temp_files	PROTO((void));
28418334Speterstatic void delete_failure_queue PROTO((void));
28518334Speterstatic void clear_failure_queue PROTO((void));
28618334Speterstatic char *choose_temp_base_try PROTO((char *, char *));
28718334Speterstatic void choose_temp_base	PROTO((void));
28818334Speterstatic int check_live_switch	PROTO((int, int));
28918334Speterstatic char *handle_braces	PROTO((char *));
29018334Speterstatic char *save_string	PROTO((char *, int));
29118334Speterstatic char *concat		PROTO((char *, char *));
29218334Speterstatic char *concat3		PROTO((char *, char *, char *));
29318334Speterstatic char *concat4		PROTO((char *, char *, char *, char *));
29418334Speterstatic char *concat6		PROTO((char *, char *, char *, char *, char *, \
29518334Speter                                       char *));
29618334Speterstatic int do_spec		PROTO((char *));
29718334Speterstatic int do_spec_1		PROTO((char *, int, char *));
29818334Speterstatic char *find_file		PROTO((char *));
29918334Speterstatic int is_directory		PROTO((char *, char *, int));
30018334Speterstatic void validate_switches	PROTO((char *));
30118334Speterstatic void validate_all_switches PROTO((void));
30218334Speterstatic void give_switch		PROTO((int, int));
30318334Speterstatic int used_arg		PROTO((char *, int));
30418334Speterstatic int default_arg		PROTO((char *, int));
30518334Speterstatic void set_multilib_dir	PROTO((void));
30618334Speterstatic void print_multilib_info	PROTO((void));
30718334Speterstatic void pfatal_with_name	PROTO((char *));
30818334Speterstatic void perror_with_name	PROTO((char *));
30918334Speterstatic void perror_exec		PROTO((char *));
31018334Speter#ifdef HAVE_VPRINTF
31118334Speterstatic void fatal		PVPROTO((char *, ...));
31218334Speterstatic void error		PVPROTO((char *, ...));
31318334Speter#else
31418334Speter/* We must not provide any prototype here, even if ANSI C.  */
31518334Speterstatic void fatal		PROTO(());
31618334Speterstatic void error		PROTO(());
31718334Speter#endif
31818334Speter
31918334Spetervoid fancy_abort ();
32018334Speterchar *xmalloc ();
32118334Speterchar *xrealloc ();
32218334Speter
32318334Speter/* Specs are strings containing lines, each of which (if not blank)
32418334Speteris made up of a program name, and arguments separated by spaces.
32518334SpeterThe program name must be exact and start from root, since no path
32618334Speteris searched and it is unreliable to depend on the current working directory.
32718334SpeterRedirection of input or output is not supported; the subprograms must
32818334Speteraccept filenames saying what files to read and write.
32918334Speter
33018334SpeterIn addition, the specs can contain %-sequences to substitute variable text
33118334Speteror for conditional text.  Here is a table of all defined %-sequences.
33218334SpeterNote that spaces are not generated automatically around the results of
33318334Speterexpanding these sequences; therefore, you can concatenate them together
33418334Speteror with constant text in a single argument.
33518334Speter
33618334Speter %%	substitute one % into the program name or argument.
33718334Speter %i     substitute the name of the input file being processed.
33818334Speter %b     substitute the basename of the input file being processed.
33918334Speter	This is the substring up to (and not including) the last period
34018334Speter	and not including the directory.
34118334Speter %g     substitute the temporary-file-name-base.  This is a string chosen
34218334Speter	once per compilation.  Different temporary file names are made by
34318334Speter	concatenation of constant strings on the end, as in `%g.s'.
34418334Speter	%g also has the same effect of %d.
34518334Speter %u	like %g, but make the temporary file name unique.
34618334Speter %U	returns the last file name generated with %u.
34718334Speter %d	marks the argument containing or following the %d as a
34818334Speter	temporary file name, so that that file will be deleted if CC exits
34918334Speter	successfully.  Unlike %g, this contributes no text to the argument.
35018334Speter %w	marks the argument containing or following the %w as the
35118334Speter	"output file" of this compilation.  This puts the argument
35218334Speter	into the sequence of arguments that %o will substitute later.
35318334Speter %W{...}
35418334Speter	like %{...} but mark last argument supplied within
35518334Speter	as a file to be deleted on failure.
35618334Speter %o	substitutes the names of all the output files, with spaces
35718334Speter	automatically placed around them.  You should write spaces
35818334Speter	around the %o as well or the results are undefined.
35918334Speter	%o is for use in the specs for running the linker.
36018334Speter	Input files whose names have no recognized suffix are not compiled
36118334Speter	at all, but they are included among the output files, so they will
36218334Speter	be linked.
36318334Speter %O	substitutes the suffix for object files.
36418334Speter %p	substitutes the standard macro predefinitions for the
36518334Speter	current target machine.  Use this when running cpp.
36618334Speter %P	like %p, but puts `__' before and after the name of each macro.
36718334Speter	(Except macros that already have __.)
36818334Speter	This is for ANSI C.
36918334Speter %I	Substitute a -iprefix option made from GCC_EXEC_PREFIX.
37018334Speter %s     current argument is the name of a library or startup file of some sort.
37118334Speter        Search for that file in a standard list of directories
37218334Speter	and substitute the full name found.
37318334Speter %eSTR  Print STR as an error message.  STR is terminated by a newline.
37418334Speter        Use this when inconsistent options are detected.
37518334Speter %x{OPTION}	Accumulate an option for %X.
37618334Speter %X	Output the accumulated linker options specified by compilations.
37718334Speter %Y	Output the accumulated assembler options specified by compilations.
37818334Speter %Z	Output the accumulated preprocessor options specified by compilations.
37918334Speter %v1	Substitute the major version number of GCC.
38018334Speter	(For version 2.5.n, this is 2.)
38118334Speter %v2	Substitute the minor version number of GCC.
38218334Speter	(For version 2.5.n, this is 5.)
38318334Speter %a     process ASM_SPEC as a spec.
38418334Speter        This allows config.h to specify part of the spec for running as.
38518334Speter %A	process ASM_FINAL_SPEC as a spec.  A capital A is actually
38618334Speter	used here.  This can be used to run a post-processor after the
38718334Speter	assembler has done it's job.
38818334Speter %D	Dump out a -L option for each directory in startfile_prefixes.
38918334Speter	If multilib_dir is set, extra entries are generated with it affixed.
39018334Speter %l     process LINK_SPEC as a spec.
39118334Speter %L     process LIB_SPEC as a spec.
39218334Speter %G     process LIBGCC_SPEC as a spec.
39318334Speter %S     process STARTFILE_SPEC as a spec.  A capital S is actually used here.
39418334Speter %E     process ENDFILE_SPEC as a spec.  A capital E is actually used here.
39518334Speter %c	process SIGNED_CHAR_SPEC as a spec.
39618334Speter %C     process CPP_SPEC as a spec.  A capital C is actually used here.
39718334Speter %1	process CC1_SPEC as a spec.
39818334Speter %2	process CC1PLUS_SPEC as a spec.
39918334Speter %|	output "-" if the input for the current command is coming from a pipe.
40018334Speter %*	substitute the variable part of a matched option.  (See below.)
40118334Speter	Note that each comma in the substituted string is replaced by
40218334Speter	a single space.
40318334Speter %{S}   substitutes the -S switch, if that switch was given to CC.
40418334Speter	If that switch was not specified, this substitutes nothing.
40518334Speter	Here S is a metasyntactic variable.
40618334Speter %{S*}  substitutes all the switches specified to CC whose names start
40718334Speter	with -S.  This is used for -o, -D, -I, etc; switches that take
40818334Speter	arguments.  CC considers `-o foo' as being one switch whose
40918334Speter	name starts with `o'.  %{o*} would substitute this text,
41018334Speter	including the space; thus, two arguments would be generated.
41118334Speter %{S*:X} substitutes X if one or more switches whose names start with -S are
41218334Speter	specified to CC.  Note that the tail part of the -S option
41318334Speter	(i.e. the part matched by the `*') will be substituted for each
41418334Speter	occurrence of %* within X.
41518334Speter %{S:X} substitutes X, but only if the -S switch was given to CC.
41618334Speter %{!S:X} substitutes X, but only if the -S switch was NOT given to CC.
41718334Speter %{|S:X} like %{S:X}, but if no S switch, substitute `-'.
41818334Speter %{|!S:X} like %{!S:X}, but if there is an S switch, substitute `-'.
41918334Speter %{.S:X} substitutes X, but only if processing a file with suffix S.
42018334Speter %{!.S:X} substitutes X, but only if NOT processing a file with suffix S.
42118334Speter %(Spec) processes a specification defined in a specs file as *Spec:
42218334Speter %[Spec] as above, but put __ around -D arguments
42318334Speter
42418334SpeterThe conditional text X in a %{S:X} or %{!S:X} construct may contain
42518334Speterother nested % constructs or spaces, or even newlines.  They are
42618334Speterprocessed as usual, as described above.
42718334Speter
42818334SpeterThe -O, -f, -m, and -W switches are handled specifically in these
42918334Speterconstructs.  If another value of -O or the negated form of a -f, -m, or
43018334Speter-W switch is found later in the command line, the earlier switch
43118334Spetervalue is ignored, except with {S*} where S is just one letter; this
43218334Speterpasses all matching options.
43318334Speter
43418334SpeterThe character | is used to indicate that a command should be piped to
43518334Speterthe following command, but only if -pipe is specified.
43618334Speter
43718334SpeterNote that it is built into CC which switches take arguments and which
43818334Speterdo not.  You might think it would be useful to generalize this to
43918334Speterallow each compiler's spec to say which switches take arguments.  But
44018334Speterthis cannot be done in a consistent fashion.  CC cannot even decide
44118334Speterwhich input files have been specified without knowing which switches
44218334Spetertake arguments, and it must know which input files to compile in order
44318334Speterto tell which compilers to run.
44418334Speter
44518334SpeterCC also knows implicitly that arguments starting in `-l' are to be
44618334Spetertreated as compiler output files, and passed to the linker in their
44718334Speterproper position among the other output files.  */
44818334Speter
44918334Speter/* Define the macros used for specs %a, %l, %L, %S, %c, %C, %1.  */
45018334Speter
45118334Speter/* config.h can define ASM_SPEC to provide extra args to the assembler
45218334Speter   or extra switch-translations.  */
45318334Speter#ifndef ASM_SPEC
45418334Speter#define ASM_SPEC ""
45518334Speter#endif
45618334Speter
45718334Speter/* config.h can define ASM_FINAL_SPEC to run a post processor after
45818334Speter   the assembler has run.  */
45918334Speter#ifndef ASM_FINAL_SPEC
46018334Speter#define ASM_FINAL_SPEC ""
46118334Speter#endif
46218334Speter
46318334Speter/* config.h can define CPP_SPEC to provide extra args to the C preprocessor
46418334Speter   or extra switch-translations.  */
46518334Speter#ifndef CPP_SPEC
46618334Speter#define CPP_SPEC ""
46718334Speter#endif
46818334Speter
46918334Speter/* config.h can define CC1_SPEC to provide extra args to cc1 and cc1plus
47018334Speter   or extra switch-translations.  */
47118334Speter#ifndef CC1_SPEC
47218334Speter#define CC1_SPEC ""
47318334Speter#endif
47418334Speter
47518334Speter/* config.h can define CC1PLUS_SPEC to provide extra args to cc1plus
47618334Speter   or extra switch-translations.  */
47718334Speter#ifndef CC1PLUS_SPEC
47818334Speter#define CC1PLUS_SPEC ""
47918334Speter#endif
48018334Speter
48118334Speter/* config.h can define LINK_SPEC to provide extra args to the linker
48218334Speter   or extra switch-translations.  */
48318334Speter#ifndef LINK_SPEC
48418334Speter#define LINK_SPEC ""
48518334Speter#endif
48618334Speter
48718334Speter/* config.h can define LIB_SPEC to override the default libraries.  */
48818334Speter#ifndef LIB_SPEC
48918334Speter#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
49018334Speter#endif
49118334Speter
49218334Speter/* config.h can define LIBGCC_SPEC to override how and when libgcc.a is
49318334Speter   included.  */
49418334Speter#ifndef LIBGCC_SPEC
49518334Speter#if defined(LINK_LIBGCC_SPECIAL) || defined(LINK_LIBGCC_SPECIAL_1)
49618334Speter/* Have gcc do the search for libgcc.a.  */
49718334Speter#define LIBGCC_SPEC "%{!shared:libgcc.a%s}"
49818334Speter#else
49918334Speter#define LIBGCC_SPEC "%{!shared:-lgcc}"
50018334Speter#endif
50118334Speter#endif
50218334Speter
50318334Speter/* config.h can define STARTFILE_SPEC to override the default crt0 files.  */
50418334Speter#ifndef STARTFILE_SPEC
50518334Speter#define STARTFILE_SPEC  \
50618334Speter  "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}"
50718334Speter#endif
50818334Speter
50918334Speter/* config.h can define SWITCHES_NEED_SPACES to control passing -o and -L.
51018334Speter   Make the string nonempty to require spaces there.  */
51118334Speter#ifndef SWITCHES_NEED_SPACES
51218334Speter#define SWITCHES_NEED_SPACES ""
51318334Speter#endif
51418334Speter
51518334Speter/* config.h can define ENDFILE_SPEC to override the default crtn files.  */
51618334Speter#ifndef ENDFILE_SPEC
51718334Speter#define ENDFILE_SPEC ""
51818334Speter#endif
51918334Speter
52018334Speter/* This spec is used for telling cpp whether char is signed or not.  */
52118334Speter#ifndef SIGNED_CHAR_SPEC
52218334Speter/* Use #if rather than ?:
52318334Speter   because MIPS C compiler rejects like ?: in initializers.  */
52418334Speter#if DEFAULT_SIGNED_CHAR
52518334Speter#define SIGNED_CHAR_SPEC "%{funsigned-char:-D__CHAR_UNSIGNED__}"
52618334Speter#else
52718334Speter#define SIGNED_CHAR_SPEC "%{!fsigned-char:-D__CHAR_UNSIGNED__}"
52818334Speter#endif
52918334Speter#endif
53018334Speter
53118334Speter/* MULTILIB_SELECT comes from multilib.h.  It gives a
53218334Speter   string interpreted by set_multilib_dir to select a library
53318334Speter   subdirectory based on the compiler options.  */
53418334Speter#ifndef MULTILIB_SELECT
53518334Speter#define MULTILIB_SELECT ". ;"
53618334Speter#endif
53718334Speter
53818334Speterstatic char *cpp_spec = CPP_SPEC;
53918334Speterstatic char *cpp_predefines = CPP_PREDEFINES;
54018334Speterstatic char *cc1_spec = CC1_SPEC;
54118334Speterstatic char *cc1plus_spec = CC1PLUS_SPEC;
54218334Speterstatic char *signed_char_spec = SIGNED_CHAR_SPEC;
54318334Speterstatic char *asm_spec = ASM_SPEC;
54418334Speterstatic char *asm_final_spec = ASM_FINAL_SPEC;
54518334Speterstatic char *link_spec = LINK_SPEC;
54618334Speterstatic char *lib_spec = LIB_SPEC;
54718334Speterstatic char *libgcc_spec = LIBGCC_SPEC;
54818334Speterstatic char *endfile_spec = ENDFILE_SPEC;
54918334Speterstatic char *startfile_spec = STARTFILE_SPEC;
55018334Speterstatic char *switches_need_spaces = SWITCHES_NEED_SPACES;
55118334Speterstatic char *multilib_select = MULTILIB_SELECT;
55218334Speter
55318334Speter/* This defines which switch letters take arguments.  */
55418334Speter
55518334Speter#ifndef SWITCH_TAKES_ARG
55618334Speter#define SWITCH_TAKES_ARG(CHAR)      \
55718334Speter  ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
55818334Speter   || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
55918334Speter   || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \
56018334Speter   || (CHAR) == 'L' || (CHAR) == 'A')
56118334Speter#endif
56218334Speter
56318334Speter/* This defines which multi-letter switches take arguments.  */
56418334Speter
56518334Speter#define DEFAULT_WORD_SWITCH_TAKES_ARG(STR)		\
56618334Speter (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext")	\
56718334Speter  || !strcmp (STR, "Tbss") || !strcmp (STR, "include")	\
56818334Speter  || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \
56918334Speter  || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \
57018334Speter  || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \
57118334Speter  || !strcmp (STR, "isystem"))
57218334Speter
57318334Speter#ifndef WORD_SWITCH_TAKES_ARG
57418334Speter#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
57518334Speter#endif
57618334Speter
57718334Speter/* Record the mapping from file suffixes for compilation specs.  */
57818334Speter
57918334Speterstruct compiler
58018334Speter{
58118334Speter  char *suffix;			/* Use this compiler for input files
58218334Speter				   whose names end in this suffix.  */
58318334Speter
58418334Speter  char *spec[4];		/* To use this compiler, concatenate these
58518334Speter				   specs and pass to do_spec.  */
58618334Speter};
58718334Speter
58818334Speter/* Pointer to a vector of `struct compiler' that gives the spec for
58918334Speter   compiling a file, based on its suffix.
59018334Speter   A file that does not end in any of these suffixes will be passed
59118334Speter   unchanged to the loader and nothing else will be done to it.
59218334Speter
59318334Speter   An entry containing two 0s is used to terminate the vector.
59418334Speter
59518334Speter   If multiple entries match a file, the last matching one is used.  */
59618334Speter
59718334Speterstatic struct compiler *compilers;
59818334Speter
59918334Speter/* Number of entries in `compilers', not counting the null terminator.  */
60018334Speter
60118334Speterstatic int n_compilers;
60218334Speter
60318334Speter/* The default list of file name suffixes and their compilation specs.  */
60418334Speter
60518334Speterstatic struct compiler default_compilers[] =
60618334Speter{
60718334Speter  {".c", "@c"},
60818334Speter  {"@c",
60918334Speter   "cpp -lang-c%{ansi:89} %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
61018334Speter	%{C:%{!E:%eGNU C does not support -C without using -E}}\
61118334Speter	%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
61218334Speter        -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
61318334Speter	%{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
61418334Speter	%{!undef:%{!ansi:%p} %P} %{trigraphs} \
61518334Speter        %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
61618334Speter        %{traditional-cpp:-traditional}\
61718334Speter	%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
61818334Speter        %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
61918334Speter   "%{!M:%{!MM:%{!E:cc1 %{!pipe:%g.i} %1 \
62018334Speter		   %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a}\
62118334Speter		   %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
62218334Speter		   %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
62318334Speter		   %{aux-info*}\
62418334Speter		   %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
62518334Speter		   %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
62618334Speter              %{!S:as %a %Y\
62718334Speter		      %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
62818334Speter                      %{!pipe:%g.s} %A\n }}}}"},
62918334Speter  {"-",
63018334Speter   "%{E:cpp -lang-c%{ansi:89} %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
63118334Speter	%{C:%{!E:%eGNU C does not support -C without using -E}}\
63218334Speter	%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
63318334Speter        -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
63418334Speter	%{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
63518334Speter	%{!undef:%{!ansi:%p} %P} %{trigraphs}\
63618334Speter        %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
63718334Speter        %{traditional-cpp:-traditional}\
63818334Speter	%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
63918334Speter        %i %W{o*}}\
64018334Speter    %{!E:%e-E required when input is from standard input}"},
64118334Speter  {".m", "@objective-c"},
64218334Speter  {"@objective-c",
64318334Speter   "cpp -lang-objc %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
64418334Speter	%{C:%{!E:%eGNU C does not support -C without using -E}}\
64518334Speter	%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
64618334Speter        -undef -D__OBJC__ -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
64718334Speter	 %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
64818334Speter	%{!undef:%{!ansi:%p} %P} %{trigraphs}\
64918334Speter        %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
65018334Speter        %{traditional-cpp:-traditional}\
65118334Speter	%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
65218334Speter        %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
65318334Speter   "%{!M:%{!MM:%{!E:cc1obj %{!pipe:%g.i} %1 \
65418334Speter		   %{!Q:-quiet} -dumpbase %b.m %{d*} %{m*} %{a}\
65518334Speter		   %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
65618334Speter		   %{traditional} %{v:-version} %{pg:-p} %{p} %{f*} \
65718334Speter    		   -lang-objc %{gen-decls} \
65818334Speter		   %{aux-info*}\
65918334Speter		   %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
66018334Speter		   %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
66118334Speter              %{!S:as %a %Y\
66218334Speter		      %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
66318334Speter                      %{!pipe:%g.s} %A\n }}}}"},
66418334Speter  {".h", "@c-header"},
66518334Speter  {"@c-header",
66618334Speter   "%{!E:%eCompilation of header file requested} \
66718334Speter    cpp %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
66818334Speter	%{C:%{!E:%eGNU C does not support -C without using -E}}\
66918334Speter	 %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
67018334Speter        -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
67118334Speter	 %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
67218334Speter	%{!undef:%{!ansi:%p} %P} %{trigraphs}\
67318334Speter        %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
67418334Speter        %{traditional-cpp:-traditional}\
67518334Speter	%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
67618334Speter        %i %W{o*}"},
67718334Speter  {".i", "@cpp-output"},
67818334Speter  {"@cpp-output",
67918334Speter   "%{!M:%{!MM:%{!E:cc1 %i %1 %{!Q:-quiet} %{d*} %{m*} %{a}\
68018334Speter			%{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi}\
68118334Speter			%{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
68218334Speter			%{aux-info*}\
68318334Speter			%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
68418334Speter			%{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
68518334Speter		     %{!S:as %a %Y\
68618334Speter			     %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
68718334Speter			     %{!pipe:%g.s} %A\n }}}}"},
68818334Speter  {".s", "@assembler"},
68918334Speter  {"@assembler",
69018334Speter   "%{!M:%{!MM:%{!E:%{!S:as %a %Y\
69118334Speter		            %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
69218334Speter			    %i %A\n }}}}"},
69318334Speter  {".S", "@assembler-with-cpp"},
69418334Speter  {"@assembler-with-cpp",
69518334Speter   "cpp -lang-asm %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
69618334Speter	%{C:%{!E:%eGNU C does not support -C without using -E}}\
69718334Speter	%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG} %{trigraphs}\
69818334Speter        -undef -$ %{!undef:%p %P} -D__ASSEMBLER__ \
69918334Speter        %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\
70018334Speter        %{traditional-cpp:-traditional}\
70118334Speter	%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
70218334Speter        %i %{!M:%{!MM:%{!E:%{!pipe:%g.s}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
70318334Speter   "%{!M:%{!MM:%{!E:%{!S:as %a %Y\
70418334Speter                    %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
70518334Speter		    %{!pipe:%g.s} %A\n }}}}"},
70618334Speter#include "specs.h"
70718334Speter  /* Mark end of table */
70818334Speter  {0, 0}
70918334Speter};
71018334Speter
71118334Speter/* Number of elements in default_compilers, not counting the terminator.  */
71218334Speter
71318334Speterstatic int n_default_compilers
71418334Speter  = (sizeof default_compilers / sizeof (struct compiler)) - 1;
71518334Speter
71618334Speter/* Here is the spec for running the linker, after compiling all files.  */
71718334Speter
71818334Speter/* -u* was put back because both BSD and SysV seem to support it.  */
71918334Speter/* %{static:} simply prevents an error message if the target machine
72018334Speter   doesn't handle -static.  */
72118334Speter/* We want %{T*} after %{L*} and %D so that it can be used to specify linker
72218334Speter   scripts which exist in user specified directories, or in standard
72318334Speter   directories.  */
72418334Speter#ifdef LINK_LIBGCC_SPECIAL
72518334Speter/* Don't generate -L options.  */
72618334Speterstatic char *link_command_spec = "\
72718334Speter%{!fsyntax-only: \
72818334Speter %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
72918334Speter			%{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
73018334Speter			%{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
73118334Speter			%{static:} %{L*} %{T*} %o\
73218334Speter			%{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
73318334Speter			%{!A:%{!nostdlib:%{!nostartfiles:%E}}}\n }}}}}}";
73418334Speter#else
73518334Speter/* Use -L.  */
73618334Speterstatic char *link_command_spec = "\
73718334Speter%{!fsyntax-only: \
73818334Speter %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
73918334Speter			%{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
74018334Speter			%{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
74118334Speter			%{static:} %{L*} %D %{T*} %o\
74218334Speter			%{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
74318334Speter			%{!A:%{!nostdlib:%{!nostartfiles:%E}}}\n }}}}}}";
74418334Speter#endif
74518334Speter
74618334Speter/* A vector of options to give to the linker.
74718334Speter   These options are accumulated by %x,
74818334Speter   and substituted into the linker command with %X.  */
74918334Speterstatic int n_linker_options;
75018334Speterstatic char **linker_options;
75118334Speter
75218334Speter/* A vector of options to give to the assembler.
75318334Speter   These options are accumulated by -Wa,
75418334Speter   and substituted into the assembler command with %Y.  */
75518334Speterstatic int n_assembler_options;
75618334Speterstatic char **assembler_options;
75718334Speter
75818334Speter/* A vector of options to give to the preprocessor.
75918334Speter   These options are accumulated by -Wp,
76018334Speter   and substituted into the preprocessor command with %Z.  */
76118334Speterstatic int n_preprocessor_options;
76218334Speterstatic char **preprocessor_options;
76318334Speter
76418334Speter/* Define how to map long options into short ones.  */
76518334Speter
76618334Speter/* This structure describes one mapping.  */
76718334Speterstruct option_map
76818334Speter{
76918334Speter  /* The long option's name.  */
77018334Speter  char *name;
77118334Speter  /* The equivalent short option.  */
77218334Speter  char *equivalent;
77318334Speter  /* Argument info.  A string of flag chars; NULL equals no options.
77418334Speter     a => argument required.
77518334Speter     o => argument optional.
77618334Speter     j => join argument to equivalent, making one word.
77718334Speter     * => require other text after NAME as an argument.  */
77818334Speter  char *arg_info;
77918334Speter};
78018334Speter
78118334Speter/* This is the table of mappings.  Mappings are tried sequentially
78218334Speter   for each option encountered; the first one that matches, wins.  */
78318334Speter
78418334Speterstruct option_map option_map[] =
78518334Speter {
78618334Speter   {"--all-warnings", "-Wall", 0},
78718334Speter   {"--ansi", "-ansi", 0},
78818334Speter   {"--assemble", "-S", 0},
78918334Speter   {"--assert", "-A", "a"},
79018334Speter   {"--comments", "-C", 0},
79118334Speter   {"--compile", "-c", 0},
79218334Speter   {"--debug", "-g", "oj"},
79318334Speter   {"--define-macro", "-D", "a"},
79418334Speter   {"--dependencies", "-M", 0},
79518334Speter   {"--dump", "-d", "a"},
79618334Speter   {"--dumpbase", "-dumpbase", "a"},
79718334Speter   {"--entry", "-e", 0},
79818334Speter   {"--extra-warnings", "-W", 0},
79918334Speter   {"--for-assembler", "-Wa", "a"},
80018334Speter   {"--for-linker", "-Xlinker", "a"},
80118334Speter   {"--force-link", "-u", "a"},
80218334Speter   {"--imacros", "-imacros", "a"},
80318334Speter   {"--include", "-include", "a"},
80418334Speter   {"--include-barrier", "-I-", 0},
80518334Speter   {"--include-directory", "-I", "a"},
80618334Speter   {"--include-directory-after", "-idirafter", "a"},
80718334Speter   {"--include-prefix", "-iprefix", "a"},
80818334Speter   {"--include-with-prefix", "-iwithprefix", "a"},
80918334Speter   {"--include-with-prefix-before", "-iwithprefixbefore", "a"},
81018334Speter   {"--include-with-prefix-after", "-iwithprefix", "a"},
81118334Speter   {"--language", "-x", "a"},
81218334Speter   {"--library-directory", "-L", "a"},
81318334Speter   {"--machine", "-m", "aj"},
81418334Speter   {"--machine-", "-m", "*j"},
81518334Speter   {"--no-line-commands", "-P", 0},
81618334Speter   {"--no-precompiled-includes", "-noprecomp", 0},
81718334Speter   {"--no-standard-includes", "-nostdinc", 0},
81818334Speter   {"--no-standard-libraries", "-nostdlib", 0},
81918334Speter   {"--no-warnings", "-w", 0},
82018334Speter   {"--optimize", "-O", "oj"},
82118334Speter   {"--output", "-o", "a"},
82218334Speter   {"--pedantic", "-pedantic", 0},
82318334Speter   {"--pedantic-errors", "-pedantic-errors", 0},
82418334Speter   {"--pipe", "-pipe", 0},
82518334Speter   {"--prefix", "-B", "a"},
82618334Speter   {"--preprocess", "-E", 0},
82718334Speter   {"--print-search-dirs", "-print-search-dirs", 0},
82818334Speter   {"--print-file-name", "-print-file-name=", "aj"},
82918334Speter   {"--print-libgcc-file-name", "-print-libgcc-file-name", 0},
83018334Speter   {"--print-missing-file-dependencies", "-MG", 0},
83118334Speter   {"--print-multi-lib", "-print-multi-lib", 0},
83218334Speter   {"--print-multi-directory", "-print-multi-directory", 0},
83318334Speter   {"--print-prog-name", "-print-prog-name=", "aj"},
83418334Speter   {"--profile", "-p", 0},
83518334Speter   {"--profile-blocks", "-a", 0},
83618334Speter   {"--quiet", "-q", 0},
83718334Speter   {"--save-temps", "-save-temps", 0},
83818334Speter   {"--shared", "-shared", 0},
83918334Speter   {"--silent", "-q", 0},
84018334Speter   {"--static", "-static", 0},
84118334Speter   {"--symbolic", "-symbolic", 0},
84218334Speter   {"--target", "-b", "a"},
84318334Speter   {"--trace-includes", "-H", 0},
84418334Speter   {"--traditional", "-traditional", 0},
84518334Speter   {"--traditional-cpp", "-traditional-cpp", 0},
84618334Speter   {"--trigraphs", "-trigraphs", 0},
84718334Speter   {"--undefine-macro", "-U", "a"},
84818334Speter   {"--use-version", "-V", "a"},
84918334Speter   {"--user-dependencies", "-MM", 0},
85018334Speter   {"--verbose", "-v", 0},
85118334Speter   {"--version", "-dumpversion", 0},
85218334Speter   {"--warn-", "-W", "*j"},
85318334Speter   {"--write-dependencies", "-MD", 0},
85418334Speter   {"--write-user-dependencies", "-MMD", 0},
85518334Speter   {"--", "-f", "*j"}
85618334Speter };
85718334Speter
85818334Speter/* Translate the options described by *ARGCP and *ARGVP.
85918334Speter   Make a new vector and store it back in *ARGVP,
86018334Speter   and store its length in *ARGVC.  */
86118334Speter
86218334Speterstatic void
86318334Spetertranslate_options (argcp, argvp)
86418334Speter     int *argcp;
86518334Speter     char ***argvp;
86618334Speter{
86718334Speter  int i, j, k;
86818334Speter  int argc = *argcp;
86918334Speter  char **argv = *argvp;
87018334Speter  char **newv = (char **) xmalloc ((argc + 2) * 2 * sizeof (char *));
87118334Speter  int newindex = 0;
87218334Speter
87318334Speter  i = 0;
87418334Speter  newv[newindex++] = argv[i++];
87518334Speter
87618334Speter  while (i < argc)
87718334Speter    {
87818334Speter      /* Translate -- options.  */
87918334Speter      if (argv[i][0] == '-' && argv[i][1] == '-')
88018334Speter	{
88118334Speter	  /* Find a mapping that applies to this option.  */
88218334Speter	  for (j = 0; j < sizeof (option_map) / sizeof (option_map[0]); j++)
88318334Speter	    {
88418334Speter	      int optlen = strlen (option_map[j].name);
88518334Speter	      int arglen = strlen (argv[i]);
88618334Speter	      int complen = arglen > optlen ? optlen : arglen;
88718334Speter	      char *arginfo = option_map[j].arg_info;
88818334Speter
88918334Speter	      if (arginfo == 0)
89018334Speter		arginfo = "";
89118334Speter
89218334Speter	      if (!strncmp (argv[i], option_map[j].name, complen))
89318334Speter		{
89418334Speter		  char *arg = 0;
89518334Speter
89618334Speter		  if (arglen < optlen)
89718334Speter		    {
89818334Speter		      for (k = j + 1;
89918334Speter			   k < sizeof (option_map) / sizeof (option_map[0]);
90018334Speter			   k++)
90118334Speter			if (strlen (option_map[k].name) >= arglen
90218334Speter			    && !strncmp (argv[i], option_map[k].name, arglen))
90318334Speter			  {
90418334Speter			    error ("Ambiguous abbreviation %s", argv[i]);
90518334Speter			    break;
90618334Speter			  }
90718334Speter
90818334Speter		      if (k != sizeof (option_map) / sizeof (option_map[0]))
90918334Speter			break;
91018334Speter		    }
91118334Speter
91218334Speter		  if (arglen > optlen)
91318334Speter		    {
91418334Speter		      /* If the option has an argument, accept that.  */
91518334Speter		      if (argv[i][optlen] == '=')
91618334Speter			arg = argv[i] + optlen + 1;
91718334Speter
91818334Speter		      /* If this mapping requires extra text at end of name,
91918334Speter			 accept that as "argument".  */
92018334Speter		      else if (index (arginfo, '*') != 0)
92118334Speter			arg = argv[i] + optlen;
92218334Speter
92318334Speter		      /* Otherwise, extra text at end means mismatch.
92418334Speter			 Try other mappings.  */
92518334Speter		      else
92618334Speter			continue;
92718334Speter		    }
92818334Speter
92918334Speter		  else if (index (arginfo, '*') != 0)
93018334Speter		    {
93118334Speter		      error ("Incomplete `%s' option", option_map[j].name);
93218334Speter		      break;
93318334Speter		    }
93418334Speter
93518334Speter		  /* Handle arguments.  */
93618334Speter		  if (index (arginfo, 'a') != 0)
93718334Speter		    {
93818334Speter		      if (arg == 0)
93918334Speter			{
94018334Speter			  if (i + 1 == argc)
94118334Speter			    {
94218334Speter			      error ("Missing argument to `%s' option",
94318334Speter				     option_map[j].name);
94418334Speter			      break;
94518334Speter			    }
94618334Speter
94718334Speter			  arg = argv[++i];
94818334Speter			}
94918334Speter		    }
95018334Speter		  else if (index (arginfo, '*') != 0)
95118334Speter		    ;
95218334Speter		  else if (index (arginfo, 'o') == 0)
95318334Speter		    {
95418334Speter		      if (arg != 0)
95518334Speter			error ("Extraneous argument to `%s' option",
95618334Speter			       option_map[j].name);
95718334Speter		      arg = 0;
95818334Speter		    }
95918334Speter
96018334Speter		  /* Store the translation as one argv elt or as two.  */
96118334Speter		  if (arg != 0 && index (arginfo, 'j') != 0)
96218334Speter		    newv[newindex++] = concat (option_map[j].equivalent, arg);
96318334Speter		  else if (arg != 0)
96418334Speter		    {
96518334Speter		      newv[newindex++] = option_map[j].equivalent;
96618334Speter		      newv[newindex++] = arg;
96718334Speter		    }
96818334Speter		  else
96918334Speter		    newv[newindex++] = option_map[j].equivalent;
97018334Speter
97118334Speter		  break;
97218334Speter		}
97318334Speter	    }
97418334Speter	  i++;
97518334Speter	}
97618334Speter
97718334Speter      /* Handle old-fashioned options--just copy them through,
97818334Speter	 with their arguments.  */
97918334Speter      else if (argv[i][0] == '-')
98018334Speter	{
98118334Speter	  char *p = argv[i] + 1;
98218334Speter	  int c = *p;
98318334Speter	  int nskip = 1;
98418334Speter
98518334Speter	  if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
98618334Speter	    nskip += SWITCH_TAKES_ARG (c) - (p[1] != 0);
98718334Speter	  else if (WORD_SWITCH_TAKES_ARG (p))
98818334Speter	    nskip += WORD_SWITCH_TAKES_ARG (p);
98918334Speter	  else if ((c == 'B' || c == 'b' || c == 'V' || c == 'x')
99018334Speter		   && p[1] == 0)
99118334Speter	    nskip += 1;
99218334Speter	  else if (! strcmp (p, "Xlinker"))
99318334Speter	    nskip += 1;
99418334Speter
99518334Speter	  /* Watch out for an option at the end of the command line that
99618334Speter	     is missing arguments, and avoid skipping past the end of the
99718334Speter	     command line.  */
99818334Speter	  if (nskip + i > argc)
99918334Speter	    nskip = argc - i;
100018334Speter
100118334Speter	  while (nskip > 0)
100218334Speter	    {
100318334Speter	      newv[newindex++] = argv[i++];
100418334Speter	      nskip--;
100518334Speter	    }
100618334Speter	}
100718334Speter      else
100818334Speter	/* Ordinary operands, or +e options.  */
100918334Speter	newv[newindex++] = argv[i++];
101018334Speter    }
101118334Speter
101218334Speter  newv[newindex] = 0;
101318334Speter
101418334Speter  *argvp = newv;
101518334Speter  *argcp = newindex;
101618334Speter}
101718334Speter
101818334Speterchar *
101918334Spetermy_strerror(e)
102018334Speter     int e;
102118334Speter{
102218334Speter
102318334Speter#ifdef HAVE_STRERROR
102418334Speter  return strerror(e);
102518334Speter
102618334Speter#else
102718334Speter
102818334Speter  static char buffer[30];
102918334Speter  if (!e)
103018334Speter    return "";
103118334Speter
103218334Speter  if (e > 0 && e < sys_nerr)
103318334Speter    return sys_errlist[e];
103418334Speter
103518334Speter  sprintf (buffer, "Unknown error %d", e);
103618334Speter  return buffer;
103718334Speter#endif
103818334Speter}
103918334Speter
104018334Speter/* Read compilation specs from a file named FILENAME,
104118334Speter   replacing the default ones.
104218334Speter
104318334Speter   A suffix which starts with `*' is a definition for
104418334Speter   one of the machine-specific sub-specs.  The "suffix" should be
104518334Speter   *asm, *cc1, *cpp, *link, *startfile, *signed_char, etc.
104618334Speter   The corresponding spec is stored in asm_spec, etc.,
104718334Speter   rather than in the `compilers' vector.
104818334Speter
104918334Speter   Anything invalid in the file is a fatal error.  */
105018334Speter
105118334Speterstatic void
105218334Speterread_specs (filename)
105318334Speter     char *filename;
105418334Speter{
105518334Speter  int desc;
105618334Speter  int readlen;
105718334Speter  struct stat statbuf;
105818334Speter  char *buffer;
105918334Speter  register char *p;
106018334Speter
106118334Speter  if (verbose_flag)
106218334Speter    fprintf (stderr, "Reading specs from %s\n", filename);
106318334Speter
106418334Speter  /* Open and stat the file.  */
106518334Speter  desc = open (filename, O_RDONLY, 0);
106618334Speter  if (desc < 0)
106718334Speter    pfatal_with_name (filename);
106818334Speter  if (stat (filename, &statbuf) < 0)
106918334Speter    pfatal_with_name (filename);
107018334Speter
107118334Speter  /* Read contents of file into BUFFER.  */
107218334Speter  buffer = xmalloc ((unsigned) statbuf.st_size + 1);
107318334Speter  readlen = read (desc, buffer, (unsigned) statbuf.st_size);
107418334Speter  if (readlen < 0)
107518334Speter    pfatal_with_name (filename);
107618334Speter  buffer[readlen] = 0;
107718334Speter  close (desc);
107818334Speter
107918334Speter  /* Scan BUFFER for specs, putting them in the vector.  */
108018334Speter  p = buffer;
108118334Speter  while (1)
108218334Speter    {
108318334Speter      char *suffix;
108418334Speter      char *spec;
108518334Speter      char *in, *out, *p1, *p2;
108618334Speter
108718334Speter      /* Advance P in BUFFER to the next nonblank nocomment line.  */
108818334Speter      p = skip_whitespace (p);
108918334Speter      if (*p == 0)
109018334Speter	break;
109118334Speter
109218334Speter      /* Find the colon that should end the suffix.  */
109318334Speter      p1 = p;
109418334Speter      while (*p1 && *p1 != ':' && *p1 != '\n') p1++;
109518334Speter      /* The colon shouldn't be missing.  */
109618334Speter      if (*p1 != ':')
109718334Speter	fatal ("specs file malformed after %d characters", p1 - buffer);
109818334Speter      /* Skip back over trailing whitespace.  */
109918334Speter      p2 = p1;
110018334Speter      while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t')) p2--;
110118334Speter      /* Copy the suffix to a string.  */
110218334Speter      suffix = save_string (p, p2 - p);
110318334Speter      /* Find the next line.  */
110418334Speter      p = skip_whitespace (p1 + 1);
110518334Speter      if (p[1] == 0)
110618334Speter	fatal ("specs file malformed after %d characters", p - buffer);
110718334Speter      p1 = p;
110818334Speter      /* Find next blank line.  */
110918334Speter      while (*p1 && !(*p1 == '\n' && p1[1] == '\n')) p1++;
111018334Speter      /* Specs end at the blank line and do not include the newline.  */
111118334Speter      spec = save_string (p, p1 - p);
111218334Speter      p = p1;
111318334Speter
111418334Speter      /* Delete backslash-newline sequences from the spec.  */
111518334Speter      in = spec;
111618334Speter      out = spec;
111718334Speter      while (*in != 0)
111818334Speter	{
111918334Speter	  if (in[0] == '\\' && in[1] == '\n')
112018334Speter	    in += 2;
112118334Speter	  else if (in[0] == '#')
112218334Speter	    {
112318334Speter	      while (*in && *in != '\n') in++;
112418334Speter	    }
112518334Speter	  else
112618334Speter	    *out++ = *in++;
112718334Speter	}
112818334Speter      *out = 0;
112918334Speter
113018334Speter      if (suffix[0] == '*')
113118334Speter	{
113218334Speter	  if (! strcmp (suffix, "*link_command"))
113318334Speter	    link_command_spec = spec;
113418334Speter	  else
113518334Speter	    set_spec (suffix + 1, spec);
113618334Speter	}
113718334Speter      else
113818334Speter	{
113918334Speter	  /* Add this pair to the vector.  */
114018334Speter	  compilers
114118334Speter	    = ((struct compiler *)
114218334Speter	       xrealloc (compilers, (n_compilers + 2) * sizeof (struct compiler)));
114318334Speter	  compilers[n_compilers].suffix = suffix;
114418334Speter	  bzero ((char *) compilers[n_compilers].spec,
114518334Speter		 sizeof compilers[n_compilers].spec);
114618334Speter	  compilers[n_compilers].spec[0] = spec;
114718334Speter	  n_compilers++;
114818334Speter	  bzero ((char *) &compilers[n_compilers],
114918334Speter		 sizeof compilers[n_compilers]);
115018334Speter	}
115118334Speter
115218334Speter      if (*suffix == 0)
115318334Speter	link_command_spec = spec;
115418334Speter    }
115518334Speter
115618334Speter  if (link_command_spec == 0)
115718334Speter    fatal ("spec file has no spec for linking");
115818334Speter}
115918334Speter
116018334Speterstatic char *
116118334Speterskip_whitespace (p)
116218334Speter     char *p;
116318334Speter{
116418334Speter  while (1)
116518334Speter    {
116618334Speter      /* A fully-blank line is a delimiter in the SPEC file and shouldn't
116718334Speter	 be considered whitespace.  */
116818334Speter      if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n')
116918334Speter	return p + 1;
117018334Speter      else if (*p == '\n' || *p == ' ' || *p == '\t')
117118334Speter	p++;
117218334Speter      else if (*p == '#')
117318334Speter	{
117418334Speter	  while (*p != '\n') p++;
117518334Speter	  p++;
117618334Speter	}
117718334Speter      else
117818334Speter	break;
117918334Speter    }
118018334Speter
118118334Speter  return p;
118218334Speter}
118318334Speter
118418334Speter/* Structure to keep track of the specs that have been defined so far.  These
118518334Speter   are accessed using %(specname) or %[specname] in a compiler or link spec. */
118618334Speter
118718334Speterstruct spec_list
118818334Speter{
118918334Speter  char *name;                 /* Name of the spec. */
119018334Speter  char *spec;                 /* The spec itself. */
119118334Speter  struct spec_list *next;     /* Next spec in linked list. */
119218334Speter};
119318334Speter
119418334Speter/* List of specs that have been defined so far. */
119518334Speter
119618334Speterstatic struct spec_list *specs = (struct spec_list *) 0;
119718334Speter
119818334Speter/* Change the value of spec NAME to SPEC.  If SPEC is empty, then the spec is
119918334Speter   removed; If the spec starts with a + then SPEC is added to the end of the
120018334Speter   current spec. */
120118334Speter
120218334Speterstatic void
120318334Speterset_spec (name, spec)
120418334Speter     char *name;
120518334Speter     char *spec;
120618334Speter{
120718334Speter  struct spec_list *sl;
120818334Speter  char *old_spec;
120918334Speter
121018334Speter  /* See if the spec already exists */
121118334Speter  for (sl = specs; sl; sl = sl->next)
121218334Speter    if (strcmp (sl->name, name) == 0)
121318334Speter      break;
121418334Speter
121518334Speter  if (!sl)
121618334Speter    {
121718334Speter      /* Not found - make it */
121818334Speter      sl = (struct spec_list *) xmalloc (sizeof (struct spec_list));
121918334Speter      sl->name = save_string (name, strlen (name));
122018334Speter      sl->spec = save_string ("", 0);
122118334Speter      sl->next = specs;
122218334Speter      specs = sl;
122318334Speter    }
122418334Speter
122518334Speter  old_spec = sl->spec;
122618334Speter  if (name && spec[0] == '+' && isspace (spec[1]))
122718334Speter    sl->spec = concat (old_spec, spec + 1);
122818334Speter  else
122918334Speter    sl->spec = save_string (spec, strlen (spec));
123018334Speter
123118334Speter  if (! strcmp (name, "asm"))
123218334Speter    asm_spec = sl->spec;
123318334Speter  else if (! strcmp (name, "asm_final"))
123418334Speter    asm_final_spec = sl->spec;
123518334Speter  else if (! strcmp (name, "cc1"))
123618334Speter    cc1_spec = sl->spec;
123718334Speter  else if (! strcmp (name, "cc1plus"))
123818334Speter    cc1plus_spec = sl->spec;
123918334Speter  else if (! strcmp (name, "cpp"))
124018334Speter    cpp_spec = sl->spec;
124118334Speter  else if (! strcmp (name, "endfile"))
124218334Speter    endfile_spec = sl->spec;
124318334Speter  else if (! strcmp (name, "lib"))
124418334Speter    lib_spec = sl->spec;
124518334Speter  else if (! strcmp (name, "libgcc"))
124618334Speter    libgcc_spec = sl->spec;
124718334Speter  else if (! strcmp (name, "link"))
124818334Speter    link_spec = sl->spec;
124918334Speter  else if (! strcmp (name, "predefines"))
125018334Speter    cpp_predefines = sl->spec;
125118334Speter  else if (! strcmp (name, "signed_char"))
125218334Speter    signed_char_spec = sl->spec;
125318334Speter  else if (! strcmp (name, "startfile"))
125418334Speter    startfile_spec = sl->spec;
125518334Speter  else if (! strcmp (name, "switches_need_spaces"))
125618334Speter    switches_need_spaces = sl->spec;
125718334Speter  else if (! strcmp (name, "cross_compile"))
125818334Speter    cross_compile = atoi (sl->spec);
125918334Speter  else if (! strcmp (name, "multilib"))
126018334Speter    multilib_select = sl->spec;
126118334Speter  /* Free the old spec */
126218334Speter  if (old_spec)
126318334Speter    free (old_spec);
126418334Speter}
126518334Speter
126618334Speter/* Accumulate a command (program name and args), and run it.  */
126718334Speter
126818334Speter/* Vector of pointers to arguments in the current line of specifications.  */
126918334Speter
127018334Speterstatic char **argbuf;
127118334Speter
127218334Speter/* Number of elements allocated in argbuf.  */
127318334Speter
127418334Speterstatic int argbuf_length;
127518334Speter
127618334Speter/* Number of elements in argbuf currently in use (containing args).  */
127718334Speter
127818334Speterstatic int argbuf_index;
127918334Speter
128018334Speter/* This is the list of suffixes and codes (%g/%u/%U) and the associated
128118334Speter   temp file.  Used only if MKTEMP_EACH_FILE.  */
128218334Speter
128318334Speterstatic struct temp_name {
128418334Speter  char *suffix;		/* suffix associated with the code.  */
128518334Speter  int length;		/* strlen (suffix).  */
128618334Speter  int unique;		/* Indicates whether %g or %u/%U was used.  */
128718334Speter  char *filename;	/* associated filename.  */
128818334Speter  int filename_length;	/* strlen (filename).  */
128918334Speter  struct temp_name *next;
129018334Speter} *temp_names;
129118334Speter
129218334Speter/* Number of commands executed so far.  */
129318334Speter
129418334Speterstatic int execution_count;
129518334Speter
129618334Speter/* Number of commands that exited with a signal.  */
129718334Speter
129818334Speterstatic int signal_count;
129918334Speter
130018334Speter/* Name with which this program was invoked.  */
130118334Speter
130218334Speterstatic char *programname;
130318334Speter
130418334Speter/* Structures to keep track of prefixes to try when looking for files. */
130518334Speter
130618334Speterstruct prefix_list
130718334Speter{
130818334Speter  char *prefix;               /* String to prepend to the path. */
130918334Speter  struct prefix_list *next;   /* Next in linked list. */
131018334Speter  int require_machine_suffix; /* Don't use without machine_suffix.  */
131118334Speter  /* 2 means try both machine_suffix and just_machine_suffix.  */
131218334Speter  int *used_flag_ptr;	      /* 1 if a file was found with this prefix.  */
131318334Speter};
131418334Speter
131518334Speterstruct path_prefix
131618334Speter{
131718334Speter  struct prefix_list *plist;  /* List of prefixes to try */
131818334Speter  int max_len;                /* Max length of a prefix in PLIST */
131918334Speter  char *name;                 /* Name of this list (used in config stuff) */
132018334Speter};
132118334Speter
132218334Speter/* List of prefixes to try when looking for executables. */
132318334Speter
132418334Speterstatic struct path_prefix exec_prefixes = { 0, 0, "exec" };
132518334Speter
132618334Speter/* List of prefixes to try when looking for startup (crt0) files. */
132718334Speter
132818334Speterstatic struct path_prefix startfile_prefixes = { 0, 0, "startfile" };
132918334Speter
133018334Speter/* List of prefixes to try when looking for include files.  */
133118334Speter
133218334Speterstatic struct path_prefix include_prefixes = { 0, 0, "include" };
133318334Speter
133418334Speter/* Suffix to attach to directories searched for commands.
133518334Speter   This looks like `MACHINE/VERSION/'.  */
133618334Speter
133718334Speterstatic char *machine_suffix = 0;
133818334Speter
133918334Speter/* Suffix to attach to directories searched for commands.
134018334Speter   This is just `MACHINE/'.  */
134118334Speter
134218334Speterstatic char *just_machine_suffix = 0;
134318334Speter
134418334Speter/* Adjusted value of GCC_EXEC_PREFIX envvar.  */
134518334Speter
134618334Speterstatic char *gcc_exec_prefix;
134718334Speter
134818334Speter/* Default prefixes to attach to command names.  */
134918334Speter
135018334Speter#ifdef CROSS_COMPILE  /* Don't use these prefixes for a cross compiler.  */
135118334Speter#undef MD_EXEC_PREFIX
135218334Speter#undef MD_STARTFILE_PREFIX
135318334Speter#undef MD_STARTFILE_PREFIX_1
135418334Speter#endif
135518334Speter
135618334Speter#ifndef STANDARD_EXEC_PREFIX
135718334Speter#define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/"
135818334Speter#endif /* !defined STANDARD_EXEC_PREFIX */
135918334Speter
136018334Speterstatic char *standard_exec_prefix = STANDARD_EXEC_PREFIX;
136118334Speterstatic char *standard_exec_prefix_1 = "/usr/lib/gcc/";
136218334Speter#ifdef MD_EXEC_PREFIX
136318334Speterstatic char *md_exec_prefix = MD_EXEC_PREFIX;
136418334Speter#endif
136518334Speter
136618334Speter#ifndef STANDARD_STARTFILE_PREFIX
136718334Speter#define STANDARD_STARTFILE_PREFIX "/usr/local/lib/"
136818334Speter#endif /* !defined STANDARD_STARTFILE_PREFIX */
136918334Speter
137018334Speter#ifdef MD_STARTFILE_PREFIX
137118334Speterstatic char *md_startfile_prefix = MD_STARTFILE_PREFIX;
137218334Speter#endif
137318334Speter#ifdef MD_STARTFILE_PREFIX_1
137418334Speterstatic char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
137518334Speter#endif
137618334Speterstatic char *standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
137718334Speterstatic char *standard_startfile_prefix_1 = "/lib/";
137818334Speterstatic char *standard_startfile_prefix_2 = "/usr/lib/";
137918334Speter
138018334Speter#ifndef TOOLDIR_BASE_PREFIX
138118334Speter#define TOOLDIR_BASE_PREFIX "/usr/local/"
138218334Speter#endif
138318334Speterstatic char *tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
138418334Speterstatic char *tooldir_prefix;
138518334Speter
138618334Speter/* Subdirectory to use for locating libraries.  Set by
138718334Speter   set_multilib_dir based on the compilation options.  */
138818334Speter
138918334Speterstatic char *multilib_dir;
139018334Speter
139118334Speter/* Clear out the vector of arguments (after a command is executed).  */
139218334Speter
139318334Speterstatic void
139418334Speterclear_args ()
139518334Speter{
139618334Speter  argbuf_index = 0;
139718334Speter}
139818334Speter
139918334Speter/* Add one argument to the vector at the end.
140018334Speter   This is done when a space is seen or at the end of the line.
140118334Speter   If DELETE_ALWAYS is nonzero, the arg is a filename
140218334Speter    and the file should be deleted eventually.
140318334Speter   If DELETE_FAILURE is nonzero, the arg is a filename
140418334Speter    and the file should be deleted if this compilation fails.  */
140518334Speter
140618334Speterstatic void
140718334Speterstore_arg (arg, delete_always, delete_failure)
140818334Speter     char *arg;
140918334Speter     int delete_always, delete_failure;
141018334Speter{
141118334Speter  if (argbuf_index + 1 == argbuf_length)
141218334Speter    {
141318334Speter      argbuf = (char **) xrealloc (argbuf, (argbuf_length *= 2) * sizeof (char *));
141418334Speter    }
141518334Speter
141618334Speter  argbuf[argbuf_index++] = arg;
141718334Speter  argbuf[argbuf_index] = 0;
141818334Speter
141918334Speter  if (delete_always || delete_failure)
142018334Speter    record_temp_file (arg, delete_always, delete_failure);
142118334Speter}
142218334Speter
142318334Speter/* Record the names of temporary files we tell compilers to write,
142418334Speter   and delete them at the end of the run.  */
142518334Speter
142618334Speter/* This is the common prefix we use to make temp file names.
142718334Speter   It is chosen once for each run of this program.
142818334Speter   It is substituted into a spec by %g.
142918334Speter   Thus, all temp file names contain this prefix.
143018334Speter   In practice, all temp file names start with this prefix.
143118334Speter
143218334Speter   This prefix comes from the envvar TMPDIR if it is defined;
143318334Speter   otherwise, from the P_tmpdir macro if that is defined;
143418334Speter   otherwise, in /usr/tmp or /tmp.  */
143518334Speter
143618334Speterstatic char *temp_filename;
143718334Speter
143818334Speter/* Length of the prefix.  */
143918334Speter
144018334Speterstatic int temp_filename_length;
144118334Speter
144218334Speter/* Define the list of temporary files to delete.  */
144318334Speter
144418334Speterstruct temp_file
144518334Speter{
144618334Speter  char *name;
144718334Speter  struct temp_file *next;
144818334Speter};
144918334Speter
145018334Speter/* Queue of files to delete on success or failure of compilation.  */
145118334Speterstatic struct temp_file *always_delete_queue;
145218334Speter/* Queue of files to delete on failure of compilation.  */
145318334Speterstatic struct temp_file *failure_delete_queue;
145418334Speter
145518334Speter/* Record FILENAME as a file to be deleted automatically.
145618334Speter   ALWAYS_DELETE nonzero means delete it if all compilation succeeds;
145718334Speter   otherwise delete it in any case.
145818334Speter   FAIL_DELETE nonzero means delete it if a compilation step fails;
145918334Speter   otherwise delete it in any case.  */
146018334Speter
146118334Speterstatic void
146218334Speterrecord_temp_file (filename, always_delete, fail_delete)
146318334Speter     char *filename;
146418334Speter     int always_delete;
146518334Speter     int fail_delete;
146618334Speter{
146718334Speter  register char *name;
146818334Speter  name = xmalloc (strlen (filename) + 1);
146918334Speter  strcpy (name, filename);
147018334Speter
147118334Speter  if (always_delete)
147218334Speter    {
147318334Speter      register struct temp_file *temp;
147418334Speter      for (temp = always_delete_queue; temp; temp = temp->next)
147518334Speter	if (! strcmp (name, temp->name))
147618334Speter	  goto already1;
147718334Speter      temp = (struct temp_file *) xmalloc (sizeof (struct temp_file));
147818334Speter      temp->next = always_delete_queue;
147918334Speter      temp->name = name;
148018334Speter      always_delete_queue = temp;
148118334Speter    already1:;
148218334Speter    }
148318334Speter
148418334Speter  if (fail_delete)
148518334Speter    {
148618334Speter      register struct temp_file *temp;
148718334Speter      for (temp = failure_delete_queue; temp; temp = temp->next)
148818334Speter	if (! strcmp (name, temp->name))
148918334Speter	  goto already2;
149018334Speter      temp = (struct temp_file *) xmalloc (sizeof (struct temp_file));
149118334Speter      temp->next = failure_delete_queue;
149218334Speter      temp->name = name;
149318334Speter      failure_delete_queue = temp;
149418334Speter    already2:;
149518334Speter    }
149618334Speter}
149718334Speter
149818334Speter/* Delete all the temporary files whose names we previously recorded.  */
149918334Speter
150018334Speterstatic void
150118334Speterdelete_if_ordinary (name)
150218334Speter     char *name;
150318334Speter{
150418334Speter  struct stat st;
150518334Speter#ifdef DEBUG
150618334Speter  int i, c;
150718334Speter
150818334Speter  printf ("Delete %s? (y or n) ", name);
150918334Speter  fflush (stdout);
151018334Speter  i = getchar ();
151118334Speter  if (i != '\n')
151218334Speter    while ((c = getchar ()) != '\n' && c != EOF) ;
151318334Speter  if (i == 'y' || i == 'Y')
151418334Speter#endif /* DEBUG */
151518334Speter    if (stat (name, &st) >= 0 && S_ISREG (st.st_mode))
151618334Speter      if (unlink (name) < 0)
151718334Speter	if (verbose_flag)
151818334Speter	  perror_with_name (name);
151918334Speter}
152018334Speter
152118334Speterstatic void
152218334Speterdelete_temp_files ()
152318334Speter{
152418334Speter  register struct temp_file *temp;
152518334Speter
152618334Speter  for (temp = always_delete_queue; temp; temp = temp->next)
152718334Speter    delete_if_ordinary (temp->name);
152818334Speter  always_delete_queue = 0;
152918334Speter}
153018334Speter
153118334Speter/* Delete all the files to be deleted on error.  */
153218334Speter
153318334Speterstatic void
153418334Speterdelete_failure_queue ()
153518334Speter{
153618334Speter  register struct temp_file *temp;
153718334Speter
153818334Speter  for (temp = failure_delete_queue; temp; temp = temp->next)
153918334Speter    delete_if_ordinary (temp->name);
154018334Speter}
154118334Speter
154218334Speterstatic void
154318334Speterclear_failure_queue ()
154418334Speter{
154518334Speter  failure_delete_queue = 0;
154618334Speter}
154718334Speter
154818334Speter/* Compute a string to use as the base of all temporary file names.
154918334Speter   It is substituted for %g.  */
155018334Speter
155118334Speterstatic char *
155218334Speterchoose_temp_base_try (try, base)
155318334Speter     char *try;
155418334Speter     char *base;
155518334Speter{
155618334Speter  char *rv;
155718334Speter  if (base)
155818334Speter    rv = base;
155918334Speter  else if (try == (char *)0)
156018334Speter    rv = 0;
156118334Speter  else if (access (try, R_OK | W_OK) != 0)
156218334Speter    rv = 0;
156318334Speter  else
156418334Speter    rv = try;
156518334Speter  return rv;
156618334Speter}
156718334Speter
156818334Speterstatic void
156918334Speterchoose_temp_base ()
157018334Speter{
157118334Speter  char *base = 0;
157218334Speter  int len;
157318334Speter
157418334Speter  base = choose_temp_base_try (getenv ("TMPDIR"), base);
157518334Speter  base = choose_temp_base_try (getenv ("TMP"), base);
157618334Speter  base = choose_temp_base_try (getenv ("TEMP"), base);
157718334Speter
157818334Speter#ifdef P_tmpdir
157918334Speter  base = choose_temp_base_try (P_tmpdir, base);
158018334Speter#endif
158118334Speter
158218334Speter  base = choose_temp_base_try (concat4 (dir_separator_str, "usr",
158318334Speter                                        dir_separator_str, "tmp"),
158418334Speter                                base);
158518334Speter  base = choose_temp_base_try (concat (dir_separator_str, "tmp"), base);
158618334Speter
158718334Speter  /* If all else fails, use the current directory! */
158818334Speter  if (base == (char *)0) base = concat(".", dir_separator_str);
158918334Speter
159018334Speter  len = strlen (base);
159118334Speter  temp_filename = xmalloc (len + strlen (concat (dir_separator_str,
159218334Speter                                                 "ccXXXXXX")) + 1);
159318334Speter  strcpy (temp_filename, base);
159418334Speter  if (len > 0 && temp_filename[len-1] != '/'
159518334Speter      && temp_filename[len-1] != DIR_SEPARATOR)
159618334Speter    temp_filename[len++] = DIR_SEPARATOR;
159718334Speter  strcpy (temp_filename + len, "ccXXXXXX");
159818334Speter
159918334Speter  mktemp (temp_filename);
160018334Speter  temp_filename_length = strlen (temp_filename);
160118334Speter  if (temp_filename_length == 0)
160218334Speter    abort ();
160318334Speter}
160418334Speter
160518334Speter
160618334Speter/* Routine to add variables to the environment.  We do this to pass
160718334Speter   the pathname of the gcc driver, and the directories search to the
160818334Speter   collect2 program, which is being run as ld.  This way, we can be
160918334Speter   sure of executing the right compiler when collect2 wants to build
161018334Speter   constructors and destructors.  Since the environment variables we
161118334Speter   use come from an obstack, we don't have to worry about allocating
161218334Speter   space for them.  */
161318334Speter
161418334Speter#ifndef HAVE_PUTENV
161518334Speter
161618334Spetervoid
161718334Speterputenv (str)
161818334Speter     char *str;
161918334Speter{
162018334Speter#ifndef VMS			/* nor about VMS */
162118334Speter
162218334Speter  extern char **environ;
162318334Speter  char **old_environ = environ;
162418334Speter  char **envp;
162518334Speter  int num_envs = 0;
162618334Speter  int name_len = 1;
162718334Speter  char *p = str;
162818334Speter  int ch;
162918334Speter
163018334Speter  while ((ch = *p++) != '\0' && ch != '=')
163118334Speter    name_len++;
163218334Speter
163318334Speter  if (!ch)
163418334Speter    abort ();
163518334Speter
163618334Speter  /* Search for replacing an existing environment variable, and
163718334Speter     count the number of total environment variables.  */
163818334Speter  for (envp = old_environ; *envp; envp++)
163918334Speter    {
164018334Speter      num_envs++;
164118334Speter      if (!strncmp (str, *envp, name_len))
164218334Speter	{
164318334Speter	  *envp = str;
164418334Speter	  return;
164518334Speter	}
164618334Speter    }
164718334Speter
164818334Speter  /* Add a new environment variable */
164918334Speter  environ = (char **) xmalloc (sizeof (char *) * (num_envs+2));
165018334Speter  *environ = str;
165118334Speter  bcopy ((char *) old_environ, (char *) (environ + 1),
165218334Speter	 sizeof (char *) * (num_envs+1));
165318334Speter
165418334Speter#endif	/* VMS */
165518334Speter}
165618334Speter
165718334Speter#endif	/* HAVE_PUTENV */
165818334Speter
165918334Speter
166018334Speter/* Build a list of search directories from PATHS.
166118334Speter   PREFIX is a string to prepend to the list.
166218334Speter   If CHECK_DIR_P is non-zero we ensure the directory exists.
166318334Speter   This is used mostly by putenv_from_prefixes so we use `collect_obstack'.
166418334Speter   It is also used by the --print-search-dirs flag.  */
166518334Speter
166618334Speterstatic char *
166718334Speterbuild_search_list (paths, prefix, check_dir_p)
166818334Speter     struct path_prefix *paths;
166918334Speter     char *prefix;
167018334Speter     int check_dir_p;
167118334Speter{
167218334Speter  int suffix_len = (machine_suffix) ? strlen (machine_suffix) : 0;
167318334Speter  int just_suffix_len
167418334Speter    = (just_machine_suffix) ? strlen (just_machine_suffix) : 0;
167518334Speter  int first_time = TRUE;
167618334Speter  struct prefix_list *pprefix;
167718334Speter
167818334Speter  obstack_grow (&collect_obstack, prefix, strlen (prefix));
167918334Speter
168018334Speter  for (pprefix = paths->plist; pprefix != 0; pprefix = pprefix->next)
168118334Speter    {
168218334Speter      int len = strlen (pprefix->prefix);
168318334Speter
168418334Speter      if (machine_suffix
168518334Speter	  && (!check_dir_p
168618334Speter	      || is_directory (pprefix->prefix, machine_suffix, 0)))
168718334Speter	{
168818334Speter	  if (!first_time)
168918334Speter	    obstack_1grow (&collect_obstack, PATH_SEPARATOR);
169018334Speter
169118334Speter	  first_time = FALSE;
169218334Speter	  obstack_grow (&collect_obstack, pprefix->prefix, len);
169318334Speter	  obstack_grow (&collect_obstack, machine_suffix, suffix_len);
169418334Speter	}
169518334Speter
169618334Speter      if (just_machine_suffix
169718334Speter	  && pprefix->require_machine_suffix == 2
169818334Speter	  && (!check_dir_p
169918334Speter	      || is_directory (pprefix->prefix, just_machine_suffix, 0)))
170018334Speter	{
170118334Speter	  if (!first_time)
170218334Speter	    obstack_1grow (&collect_obstack, PATH_SEPARATOR);
170318334Speter
170418334Speter	  first_time = FALSE;
170518334Speter	  obstack_grow (&collect_obstack, pprefix->prefix, len);
170618334Speter	  obstack_grow (&collect_obstack, just_machine_suffix,
170718334Speter			just_suffix_len);
170818334Speter	}
170918334Speter
171018334Speter      if (!pprefix->require_machine_suffix)
171118334Speter	{
171218334Speter	  if (!first_time)
171318334Speter	    obstack_1grow (&collect_obstack, PATH_SEPARATOR);
171418334Speter
171518334Speter	  first_time = FALSE;
171618334Speter	  obstack_grow (&collect_obstack, pprefix->prefix, len);
171718334Speter	}
171818334Speter    }
171918334Speter  obstack_1grow (&collect_obstack, '\0');
172018334Speter  return obstack_finish (&collect_obstack);
172118334Speter}
172218334Speter
172318334Speter/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables for collect.  */
172418334Speter
172518334Speterstatic void
172618334Speterputenv_from_prefixes (paths, env_var)
172718334Speter     struct path_prefix *paths;
172818334Speter     char *env_var;
172918334Speter{
173018334Speter  putenv (build_search_list (paths, env_var, 1));
173118334Speter}
173218334Speter
173318334Speter/* Search for NAME using the prefix list PREFIXES.  MODE is passed to
173418334Speter   access to check permissions.
173518334Speter   Return 0 if not found, otherwise return its name, allocated with malloc. */
173618334Speter
173718334Speterstatic char *
173818334Speterfind_a_file (pprefix, name, mode)
173918334Speter     struct path_prefix *pprefix;
174018334Speter     char *name;
174118334Speter     int mode;
174218334Speter{
174318334Speter  char *temp;
174418334Speter  char *file_suffix = ((mode & X_OK) != 0 ? EXECUTABLE_SUFFIX : "");
174518334Speter  struct prefix_list *pl;
174618334Speter  int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1;
174718334Speter
174818334Speter  if (machine_suffix)
174918334Speter    len += strlen (machine_suffix);
175018334Speter
175118334Speter  temp = xmalloc (len);
175218334Speter
175318334Speter  /* Determine the filename to execute (special case for absolute paths).  */
175418334Speter
175518334Speter  if (*name == '/' || *name == DIR_SEPARATOR)
175618334Speter    {
175718334Speter      if (access (name, mode))
175818334Speter	{
175918334Speter	  strcpy (temp, name);
176018334Speter	  return temp;
176118334Speter	}
176218334Speter    }
176318334Speter  else
176418334Speter    for (pl = pprefix->plist; pl; pl = pl->next)
176518334Speter      {
176618334Speter	if (machine_suffix)
176718334Speter	  {
176818334Speter	    /* Some systems have a suffix for executable files.
176918334Speter	       So try appending that first.  */
177018334Speter	    if (file_suffix[0] != 0)
177118334Speter	      {
177218334Speter		strcpy (temp, pl->prefix);
177318334Speter		strcat (temp, machine_suffix);
177418334Speter		strcat (temp, name);
177518334Speter		strcat (temp, file_suffix);
177618334Speter		if (access (temp, mode) == 0)
177718334Speter		  {
177818334Speter		    if (pl->used_flag_ptr != 0)
177918334Speter		      *pl->used_flag_ptr = 1;
178018334Speter		    return temp;
178118334Speter		  }
178218334Speter	      }
178318334Speter
178418334Speter	    /* Now try just the name.  */
178518334Speter	    strcpy (temp, pl->prefix);
178618334Speter	    strcat (temp, machine_suffix);
178718334Speter	    strcat (temp, name);
178818334Speter	    if (access (temp, mode) == 0)
178918334Speter	      {
179018334Speter		if (pl->used_flag_ptr != 0)
179118334Speter		  *pl->used_flag_ptr = 1;
179218334Speter		return temp;
179318334Speter	      }
179418334Speter	  }
179518334Speter
179618334Speter	/* Certain prefixes are tried with just the machine type,
179718334Speter	   not the version.  This is used for finding as, ld, etc.  */
179818334Speter	if (just_machine_suffix && pl->require_machine_suffix == 2)
179918334Speter	  {
180018334Speter	    /* Some systems have a suffix for executable files.
180118334Speter	       So try appending that first.  */
180218334Speter	    if (file_suffix[0] != 0)
180318334Speter	      {
180418334Speter		strcpy (temp, pl->prefix);
180518334Speter		strcat (temp, just_machine_suffix);
180618334Speter		strcat (temp, name);
180718334Speter		strcat (temp, file_suffix);
180818334Speter		if (access (temp, mode) == 0)
180918334Speter		  {
181018334Speter		    if (pl->used_flag_ptr != 0)
181118334Speter		      *pl->used_flag_ptr = 1;
181218334Speter		    return temp;
181318334Speter		  }
181418334Speter	      }
181518334Speter
181618334Speter	    strcpy (temp, pl->prefix);
181718334Speter	    strcat (temp, just_machine_suffix);
181818334Speter	    strcat (temp, name);
181918334Speter	    if (access (temp, mode) == 0)
182018334Speter	      {
182118334Speter		if (pl->used_flag_ptr != 0)
182218334Speter		  *pl->used_flag_ptr = 1;
182318334Speter		return temp;
182418334Speter	      }
182518334Speter	  }
182618334Speter
182718334Speter	/* Certain prefixes can't be used without the machine suffix
182818334Speter	   when the machine or version is explicitly specified.  */
182918334Speter	if (!pl->require_machine_suffix)
183018334Speter	  {
183118334Speter	    /* Some systems have a suffix for executable files.
183218334Speter	       So try appending that first.  */
183318334Speter	    if (file_suffix[0] != 0)
183418334Speter	      {
183518334Speter		strcpy (temp, pl->prefix);
183618334Speter		strcat (temp, name);
183718334Speter		strcat (temp, file_suffix);
183818334Speter		if (access (temp, mode) == 0)
183918334Speter		  {
184018334Speter		    if (pl->used_flag_ptr != 0)
184118334Speter		      *pl->used_flag_ptr = 1;
184218334Speter		    return temp;
184318334Speter		  }
184418334Speter	      }
184518334Speter
184618334Speter	    strcpy (temp, pl->prefix);
184718334Speter	    strcat (temp, name);
184818334Speter	    if (access (temp, mode) == 0)
184918334Speter	      {
185018334Speter		if (pl->used_flag_ptr != 0)
185118334Speter		  *pl->used_flag_ptr = 1;
185218334Speter		return temp;
185318334Speter	      }
185418334Speter	  }
185518334Speter      }
185618334Speter
185718334Speter  free (temp);
185818334Speter  return 0;
185918334Speter}
186018334Speter
186118334Speter/* Add an entry for PREFIX in PLIST.  If FIRST is set, it goes
186218334Speter   at the start of the list, otherwise it goes at the end.
186318334Speter
186418334Speter   If WARN is nonzero, we will warn if no file is found
186518334Speter   through this prefix.  WARN should point to an int
186618334Speter   which will be set to 1 if this entry is used.
186718334Speter
186818334Speter   REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without
186918334Speter   the complete value of machine_suffix.
187018334Speter   2 means try both machine_suffix and just_machine_suffix.  */
187118334Speter
187218334Speterstatic void
187318334Speteradd_prefix (pprefix, prefix, first, require_machine_suffix, warn)
187418334Speter     struct path_prefix *pprefix;
187518334Speter     char *prefix;
187618334Speter     int first;
187718334Speter     int require_machine_suffix;
187818334Speter     int *warn;
187918334Speter{
188018334Speter  struct prefix_list *pl, **prev;
188118334Speter  int len;
188218334Speter
188318334Speter  if (!first && pprefix->plist)
188418334Speter    {
188518334Speter      for (pl = pprefix->plist; pl->next; pl = pl->next)
188618334Speter	;
188718334Speter      prev = &pl->next;
188818334Speter    }
188918334Speter  else
189018334Speter    prev = &pprefix->plist;
189118334Speter
189218334Speter  /* Keep track of the longest prefix */
189318334Speter
189418334Speter  len = strlen (prefix);
189518334Speter  if (len > pprefix->max_len)
189618334Speter    pprefix->max_len = len;
189718334Speter
189818334Speter  pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
189918334Speter  pl->prefix = save_string (prefix, len);
190018334Speter  pl->require_machine_suffix = require_machine_suffix;
190118334Speter  pl->used_flag_ptr = warn;
190218334Speter  if (warn)
190318334Speter    *warn = 0;
190418334Speter
190518334Speter  if (*prev)
190618334Speter    pl->next = *prev;
190718334Speter  else
190818334Speter    pl->next = (struct prefix_list *) 0;
190918334Speter  *prev = pl;
191018334Speter}
191118334Speter
191218334Speter/* Print warnings for any prefixes in the list PPREFIX that were not used.  */
191318334Speter
191418334Speterstatic void
191518334Speterunused_prefix_warnings (pprefix)
191618334Speter     struct path_prefix *pprefix;
191718334Speter{
191818334Speter  struct prefix_list *pl = pprefix->plist;
191918334Speter
192018334Speter  while (pl)
192118334Speter    {
192218334Speter      if (pl->used_flag_ptr != 0 && !*pl->used_flag_ptr)
192318334Speter	{
192418334Speter	  error ("file path prefix `%s' never used",
192518334Speter		 pl->prefix);
192618334Speter	  /* Prevent duplicate warnings.  */
192718334Speter	  *pl->used_flag_ptr = 1;
192818334Speter	}
192918334Speter      pl = pl->next;
193018334Speter    }
193118334Speter}
193218334Speter
193318334Speter/* Get rid of all prefixes built up so far in *PLISTP. */
193418334Speter
193518334Speterstatic void
193618334Speterfree_path_prefix (pprefix)
193718334Speter     struct path_prefix *pprefix;
193818334Speter{
193918334Speter  struct prefix_list *pl = pprefix->plist;
194018334Speter  struct prefix_list *temp;
194118334Speter
194218334Speter  while (pl)
194318334Speter    {
194418334Speter      temp = pl;
194518334Speter      pl = pl->next;
194618334Speter      free (temp->prefix);
194718334Speter      free ((char *) temp);
194818334Speter    }
194918334Speter  pprefix->plist = (struct prefix_list *) 0;
195018334Speter}
195118334Speter
195218334Speter/* stdin file number.  */
195318334Speter#define STDIN_FILE_NO 0
195418334Speter
195518334Speter/* stdout file number.  */
195618334Speter#define STDOUT_FILE_NO 1
195718334Speter
195818334Speter/* value of `pipe': port index for reading.  */
195918334Speter#define READ_PORT 0
196018334Speter
196118334Speter/* value of `pipe': port index for writing.  */
196218334Speter#define WRITE_PORT 1
196318334Speter
196418334Speter/* Pipe waiting from last process, to be used as input for the next one.
196518334Speter   Value is STDIN_FILE_NO if no pipe is waiting
196618334Speter   (i.e. the next command is the first of a group).  */
196718334Speter
196818334Speterstatic int last_pipe_input;
196918334Speter
197018334Speter/* Fork one piped subcommand.  FUNC is the system call to use
197118334Speter   (either execv or execvp).  ARGV is the arg vector to use.
197218334Speter   NOT_LAST is nonzero if this is not the last subcommand
197318334Speter   (i.e. its output should be piped to the next one.)  */
197418334Speter
197518334Speter#ifdef __MSDOS__
197618334Speter
197718334Speter#include <process.h>
197818334Speterstatic int
197918334Speterpexecute (search_flag, program, argv, not_last)
198018334Speter     int search_flag;
198118334Speter     char *program;
198218334Speter     char *argv[];
198318334Speter     int not_last;
198418334Speter{
198518334Speter#ifdef __GO32__
198618334Speter  int i = (search_flag ? spawnv : spawnvp) (1, program, argv);
198718334Speter#else
198818334Speter  char *scmd, *rf;
198918334Speter  FILE *argfile;
199018334Speter  int i, el = search_flag ? 0 : 4;
199118334Speter
199218334Speter  scmd = (char *)malloc (strlen (program) + strlen (temp_filename) + 6 + el);
199318334Speter  rf = scmd + strlen(program) + 2 + el;
199418334Speter  sprintf (scmd, "%s%s @%s.gp", program,
199518334Speter	   (search_flag ? "" : ".exe"), temp_filename);
199618334Speter  argfile = fopen (rf, "w");
199718334Speter  if (argfile == 0)
199818334Speter    pfatal_with_name (rf);
199918334Speter
200018334Speter  for (i=1; argv[i]; i++)
200118334Speter    {
200218334Speter      char *cp;
200318334Speter      for (cp = argv[i]; *cp; cp++)
200418334Speter	{
200518334Speter	  if (*cp == '"' || *cp == '\'' || *cp == '\\' || isspace (*cp))
200618334Speter	    fputc ('\\', argfile);
200718334Speter	  fputc (*cp, argfile);
200818334Speter	}
200918334Speter      fputc ('\n', argfile);
201018334Speter    }
201118334Speter  fclose (argfile);
201218334Speter
201318334Speter  i = system (scmd);
201418334Speter
201518334Speter  remove (rf);
201618334Speter#endif
201718334Speter
201818334Speter  if (i == -1)
201918334Speter    {
202018334Speter      perror_exec (program);
202118334Speter      return MIN_FATAL_STATUS << 8;
202218334Speter    }
202318334Speter  return i << 8;
202418334Speter}
202518334Speter
202618334Speter#endif
202718334Speter
202818334Speter#if !defined(__MSDOS__) && !defined(OS2) && !defined(_WIN32)
202918334Speter
203018334Speterstatic int
203118334Speterpexecute (search_flag, program, argv, not_last)
203218334Speter     int search_flag;
203318334Speter     char *program;
203418334Speter     char *argv[];
203518334Speter     int not_last;
203618334Speter{
203718334Speter  int (*func)() = (search_flag ? execv : execvp);
203818334Speter  int pid;
203918334Speter  int pdes[2];
204018334Speter  int input_desc = last_pipe_input;
204118334Speter  int output_desc = STDOUT_FILE_NO;
204218334Speter  int retries, sleep_interval;
204318334Speter
204418334Speter  /* If this isn't the last process, make a pipe for its output,
204518334Speter     and record it as waiting to be the input to the next process.  */
204618334Speter
204718334Speter  if (not_last)
204818334Speter    {
204918334Speter      if (pipe (pdes) < 0)
205018334Speter	pfatal_with_name ("pipe");
205118334Speter      output_desc = pdes[WRITE_PORT];
205218334Speter      last_pipe_input = pdes[READ_PORT];
205318334Speter    }
205418334Speter  else
205518334Speter    last_pipe_input = STDIN_FILE_NO;
205618334Speter
205718334Speter  /* Fork a subprocess; wait and retry if it fails.  */
205818334Speter  sleep_interval = 1;
205918334Speter  for (retries = 0; retries < 4; retries++)
206018334Speter    {
206118334Speter      pid = vfork ();
206218334Speter      if (pid >= 0)
206318334Speter	break;
206418334Speter      sleep (sleep_interval);
206518334Speter      sleep_interval *= 2;
206618334Speter    }
206718334Speter
206818334Speter  switch (pid)
206918334Speter    {
207018334Speter    case -1:
207118334Speter#ifdef vfork
207218334Speter      pfatal_with_name ("fork");
207318334Speter#else
207418334Speter      pfatal_with_name ("vfork");
207518334Speter#endif
207618334Speter      /* NOTREACHED */
207718334Speter      return 0;
207818334Speter
207918334Speter    case 0: /* child */
208018334Speter      /* Move the input and output pipes into place, if nec.  */
208118334Speter      if (input_desc != STDIN_FILE_NO)
208218334Speter	{
208318334Speter	  close (STDIN_FILE_NO);
208418334Speter	  dup (input_desc);
208518334Speter	  close (input_desc);
208618334Speter	}
208718334Speter      if (output_desc != STDOUT_FILE_NO)
208818334Speter	{
208918334Speter	  close (STDOUT_FILE_NO);
209018334Speter	  dup (output_desc);
209118334Speter	  close (output_desc);
209218334Speter	}
209318334Speter
209418334Speter      /* Close the parent's descs that aren't wanted here.  */
209518334Speter      if (last_pipe_input != STDIN_FILE_NO)
209618334Speter	close (last_pipe_input);
209718334Speter
209818334Speter      /* Exec the program.  */
209918334Speter      (*func) (program, argv);
210018334Speter      perror_exec (program);
210118334Speter      exit (-1);
210218334Speter      /* NOTREACHED */
210318334Speter      return 0;
210418334Speter
210518334Speter    default:
210618334Speter      /* In the parent, after forking.
210718334Speter	 Close the descriptors that we made for this child.  */
210818334Speter      if (input_desc != STDIN_FILE_NO)
210918334Speter	close (input_desc);
211018334Speter      if (output_desc != STDOUT_FILE_NO)
211118334Speter	close (output_desc);
211218334Speter
211318334Speter      /* Return child's process number.  */
211418334Speter      return pid;
211518334Speter    }
211618334Speter}
211718334Speter
211818334Speter#endif /* not __MSDOS__ and not OS2 and not _WIN32 */
211918334Speter
212018334Speter#if defined(OS2)
212118334Speter
212218334Speterstatic int
212318334Speterpexecute (search_flag, program, argv, not_last)
212418334Speter     int search_flag;
212518334Speter     char *program;
212618334Speter     char *argv[];
212718334Speter     int not_last;
212818334Speter{
212918334Speter  return (search_flag ? spawnv : spawnvp) (1, program, argv);
213018334Speter}
213118334Speter#endif /* OS2 */
213218334Speter
213318334Speter#if defined(_WIN32)
213418334Speter
213518334Speterstatic int
213618334Speterpexecute (search_flag, program, argv, not_last)
213718334Speter     int search_flag;
213818334Speter     char *program;
213918334Speter     char *argv[];
214018334Speter     int not_last;
214118334Speter{
214218334Speter  return (search_flag ? __spawnv : __spawnvp) (1, program, argv);
214318334Speter}
214418334Speter#endif /* _WIN32 */
214518334Speter
214618334Speter
214718334Speter/* Execute the command specified by the arguments on the current line of spec.
214818334Speter   When using pipes, this includes several piped-together commands
214918334Speter   with `|' between them.
215018334Speter
215118334Speter   Return 0 if successful, -1 if failed.  */
215218334Speter
215318334Speterstatic int
215418334Speterexecute ()
215518334Speter{
215618334Speter  int i;
215718334Speter  int n_commands;		/* # of command.  */
215818334Speter  char *string;
215918334Speter  struct command
216018334Speter    {
216118334Speter      char *prog;		/* program name.  */
216218334Speter      char **argv;		/* vector of args.  */
216318334Speter      int pid;			/* pid of process for this command.  */
216418334Speter    };
216518334Speter
216618334Speter  struct command *commands;	/* each command buffer with above info.  */
216718334Speter
216818334Speter  /* Count # of piped commands.  */
216918334Speter  for (n_commands = 1, i = 0; i < argbuf_index; i++)
217018334Speter    if (strcmp (argbuf[i], "|") == 0)
217118334Speter      n_commands++;
217218334Speter
217318334Speter  /* Get storage for each command.  */
217418334Speter  commands
217518334Speter    = (struct command *) alloca (n_commands * sizeof (struct command));
217618334Speter
217718334Speter  /* Split argbuf into its separate piped processes,
217818334Speter     and record info about each one.
217918334Speter     Also search for the programs that are to be run.  */
218018334Speter
218118334Speter  commands[0].prog = argbuf[0]; /* first command.  */
218218334Speter  commands[0].argv = &argbuf[0];
218318334Speter  string = find_a_file (&exec_prefixes, commands[0].prog, X_OK);
218418334Speter  if (string)
218518334Speter    commands[0].argv[0] = string;
218618334Speter
218718334Speter  for (n_commands = 1, i = 0; i < argbuf_index; i++)
218818334Speter    if (strcmp (argbuf[i], "|") == 0)
218918334Speter      {				/* each command.  */
219018334Speter#ifdef __MSDOS__
219118334Speter        fatal ("-pipe not supported under MS-DOS");
219218334Speter#endif
219318334Speter	argbuf[i] = 0;	/* termination of command args.  */
219418334Speter	commands[n_commands].prog = argbuf[i + 1];
219518334Speter	commands[n_commands].argv = &argbuf[i + 1];
219618334Speter	string = find_a_file (&exec_prefixes, commands[n_commands].prog, X_OK);
219718334Speter	if (string)
219818334Speter	  commands[n_commands].argv[0] = string;
219918334Speter	n_commands++;
220018334Speter      }
220118334Speter
220218334Speter  argbuf[argbuf_index] = 0;
220318334Speter
220418334Speter  /* If -v, print what we are about to do, and maybe query.  */
220518334Speter
220618334Speter  if (verbose_flag)
220718334Speter    {
220818334Speter      /* Print each piped command as a separate line.  */
220918334Speter      for (i = 0; i < n_commands ; i++)
221018334Speter	{
221118334Speter	  char **j;
221218334Speter
221318334Speter	  for (j = commands[i].argv; *j; j++)
221418334Speter	    fprintf (stderr, " %s", *j);
221518334Speter
221618334Speter	  /* Print a pipe symbol after all but the last command.  */
221718334Speter	  if (i + 1 != n_commands)
221818334Speter	    fprintf (stderr, " |");
221918334Speter	  fprintf (stderr, "\n");
222018334Speter	}
222118334Speter      fflush (stderr);
222218334Speter#ifdef DEBUG
222318334Speter      fprintf (stderr, "\nGo ahead? (y or n) ");
222418334Speter      fflush (stderr);
222518334Speter      i = getchar ();
222618334Speter      if (i != '\n')
222718334Speter	while (getchar () != '\n') ;
222818334Speter      if (i != 'y' && i != 'Y')
222918334Speter	return 0;
223018334Speter#endif /* DEBUG */
223118334Speter    }
223218334Speter
223318334Speter  /* Run each piped subprocess.  */
223418334Speter
223518334Speter  last_pipe_input = STDIN_FILE_NO;
223618334Speter  for (i = 0; i < n_commands; i++)
223718334Speter    {
223818334Speter      char *string = commands[i].argv[0];
223918334Speter
224018334Speter      commands[i].pid = pexecute (string != commands[i].prog,
224118334Speter				  string, commands[i].argv,
224218334Speter				  i + 1 < n_commands);
224318334Speter
224418334Speter      if (string != commands[i].prog)
224518334Speter	free (string);
224618334Speter    }
224718334Speter
224818334Speter  execution_count++;
224918334Speter
225018334Speter  /* Wait for all the subprocesses to finish.
225118334Speter     We don't care what order they finish in;
225218334Speter     we know that N_COMMANDS waits will get them all.
225318334Speter     Ignore subprocesses that we don't know about,
225418334Speter     since they can be spawned by the process that exec'ed us.  */
225518334Speter
225618334Speter  {
225718334Speter    int ret_code = 0;
225818334Speter
225918334Speter    for (i = 0; i < n_commands; )
226018334Speter      {
226118334Speter	int j;
226218334Speter	int status;
226318334Speter	int pid;
226418334Speter
226518334Speter#ifdef __MSDOS__
226618334Speter        status = pid = commands[i].pid;
226718334Speter#else
226818334Speter#ifdef _WIN32
226918334Speter	pid = cwait (&status, commands[i].pid, WAIT_CHILD);
227018334Speter#else
227118334Speter	pid = wait (&status);
227218334Speter#endif
227318334Speter#endif
227418334Speter	if (pid < 0)
227518334Speter	  abort ();
227618334Speter
227718334Speter	for (j = 0; j < n_commands; j++)
227818334Speter	  if (commands[j].pid == pid)
227918334Speter	    {
228018334Speter	      i++;
228118334Speter	      if (status != 0)
228218334Speter		{
228318334Speter		  if (WIFSIGNALED (status))
228418334Speter		    {
228518334Speter		      fatal ("Internal compiler error: program %s got fatal signal %d",
228618334Speter			     commands[j].prog, WTERMSIG (status));
228718334Speter		      signal_count++;
228818334Speter		      ret_code = -1;
228918334Speter		    }
229018334Speter		  else if (WIFEXITED (status)
229118334Speter			   && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
229218334Speter		    ret_code = -1;
229318334Speter		}
229418334Speter	      break;
229518334Speter	    }
229618334Speter      }
229718334Speter    return ret_code;
229818334Speter  }
229918334Speter}
230018334Speter
230118334Speter/* Find all the switches given to us
230218334Speter   and make a vector describing them.
230318334Speter   The elements of the vector are strings, one per switch given.
230418334Speter   If a switch uses following arguments, then the `part1' field
230518334Speter   is the switch itself and the `args' field
230618334Speter   is a null-terminated vector containing the following arguments.
230718334Speter   The `live_cond' field is 1 if the switch is true in a conditional spec,
230818334Speter   -1 if false (overridden by a later switch), and is initialized to zero.
230918334Speter   The `valid' field is nonzero if any spec has looked at this switch;
231018334Speter   if it remains zero at the end of the run, it must be meaningless.  */
231118334Speter
231218334Speterstruct switchstr
231318334Speter{
231418334Speter  char *part1;
231518334Speter  char **args;
231618334Speter  int live_cond;
231718334Speter  int valid;
231818334Speter};
231918334Speter
232018334Speterstatic struct switchstr *switches;
232118334Speter
232218334Speterstatic int n_switches;
232318334Speter
232418334Speterstruct infile
232518334Speter{
232618334Speter  char *name;
232718334Speter  char *language;
232818334Speter};
232918334Speter
233018334Speter/* Also a vector of input files specified.  */
233118334Speter
233218334Speterstatic struct infile *infiles;
233318334Speter
233418334Speterstatic int n_infiles;
233518334Speter
233618334Speter/* And a vector of corresponding output files is made up later.  */
233718334Speter
233818334Speterstatic char **outfiles;
233918334Speter
234018334Speter/* Create the vector `switches' and its contents.
234118334Speter   Store its length in `n_switches'.  */
234218334Speter
234318334Speterstatic void
234418334Speterprocess_command (argc, argv)
234518334Speter     int argc;
234618334Speter     char **argv;
234718334Speter{
234818334Speter  register int i;
234918334Speter  char *temp;
235018334Speter  char *spec_lang = 0;
235118334Speter  int last_language_n_infiles;
235218334Speter
235318334Speter  gcc_exec_prefix = getenv ("GCC_EXEC_PREFIX");
235418334Speter
235518334Speter  n_switches = 0;
235618334Speter  n_infiles = 0;
235718334Speter
235818334Speter  /* Figure compiler version from version string.  */
235918334Speter
236018334Speter  compiler_version = save_string (version_string, strlen (version_string));
236118334Speter  for (temp = compiler_version; *temp; ++temp)
236218334Speter    {
236318334Speter      if (*temp == ' ')
236418334Speter	{
236518334Speter	  *temp = '\0';
236618334Speter	  break;
236718334Speter	}
236818334Speter    }
236918334Speter
237018334Speter  /* Set up the default search paths.  */
237118334Speter
237218334Speter  if (gcc_exec_prefix)
237318334Speter    {
237418334Speter      add_prefix (&exec_prefixes, gcc_exec_prefix, 0, 0, NULL_PTR);
237518334Speter      add_prefix (&startfile_prefixes, gcc_exec_prefix, 0, 0, NULL_PTR);
237618334Speter    }
237718334Speter
237818334Speter  /* COMPILER_PATH and LIBRARY_PATH have values
237918334Speter     that are lists of directory names with colons.  */
238018334Speter
238118334Speter  temp = getenv ("COMPILER_PATH");
238218334Speter  if (temp)
238318334Speter    {
238418334Speter      char *startp, *endp;
238518334Speter      char *nstore = (char *) alloca (strlen (temp) + 3);
238618334Speter
238718334Speter      startp = endp = temp;
238818334Speter      while (1)
238918334Speter	{
239018334Speter	  if (*endp == PATH_SEPARATOR || *endp == 0)
239118334Speter	    {
239218334Speter	      strncpy (nstore, startp, endp-startp);
239318334Speter	      if (endp == startp)
239418334Speter		strcpy (nstore, concat (".", dir_separator_str));
239518334Speter	      else if (endp[-1] != '/' && endp[-1] != DIR_SEPARATOR)
239618334Speter		{
239718334Speter		  nstore[endp-startp] = DIR_SEPARATOR;
239818334Speter		  nstore[endp-startp+1] = 0;
239918334Speter		}
240018334Speter	      else
240118334Speter		nstore[endp-startp] = 0;
240218334Speter	      add_prefix (&exec_prefixes, nstore, 0, 0, NULL_PTR);
240318334Speter	      if (*endp == 0)
240418334Speter		break;
240518334Speter	      endp = startp = endp + 1;
240618334Speter	    }
240718334Speter	  else
240818334Speter	    endp++;
240918334Speter	}
241018334Speter    }
241118334Speter
241218334Speter  temp = getenv ("LIBRARY_PATH");
241318334Speter  if (temp && ! cross_compile)
241418334Speter    {
241518334Speter      char *startp, *endp;
241618334Speter      char *nstore = (char *) alloca (strlen (temp) + 3);
241718334Speter
241818334Speter      startp = endp = temp;
241918334Speter      while (1)
242018334Speter	{
242118334Speter	  if (*endp == PATH_SEPARATOR || *endp == 0)
242218334Speter	    {
242318334Speter	      strncpy (nstore, startp, endp-startp);
242418334Speter	      if (endp == startp)
242518334Speter		strcpy (nstore, concat (".", dir_separator_str));
242618334Speter	      else if (endp[-1] != '/' && endp[-1] != DIR_SEPARATOR)
242718334Speter		{
242818334Speter		  nstore[endp-startp] = DIR_SEPARATOR;
242918334Speter		  nstore[endp-startp+1] = 0;
243018334Speter		}
243118334Speter	      else
243218334Speter		nstore[endp-startp] = 0;
243318334Speter	      add_prefix (&startfile_prefixes, nstore, 0, 0, NULL_PTR);
243418334Speter	      if (*endp == 0)
243518334Speter		break;
243618334Speter	      endp = startp = endp + 1;
243718334Speter	    }
243818334Speter	  else
243918334Speter	    endp++;
244018334Speter	}
244118334Speter    }
244218334Speter
244318334Speter  /* Use LPATH like LIBRARY_PATH (for the CMU build program).  */
244418334Speter  temp = getenv ("LPATH");
244518334Speter  if (temp && ! cross_compile)
244618334Speter    {
244718334Speter      char *startp, *endp;
244818334Speter      char *nstore = (char *) alloca (strlen (temp) + 3);
244918334Speter
245018334Speter      startp = endp = temp;
245118334Speter      while (1)
245218334Speter	{
245318334Speter	  if (*endp == PATH_SEPARATOR || *endp == 0)
245418334Speter	    {
245518334Speter	      strncpy (nstore, startp, endp-startp);
245618334Speter	      if (endp == startp)
245718334Speter		strcpy (nstore, concat (".", dir_separator_str));
245818334Speter	      else if (endp[-1] != '/' && endp[-1] != DIR_SEPARATOR)
245918334Speter		{
246018334Speter		  nstore[endp-startp] = DIR_SEPARATOR;
246118334Speter		  nstore[endp-startp+1] = 0;
246218334Speter		}
246318334Speter	      else
246418334Speter		nstore[endp-startp] = 0;
246518334Speter	      add_prefix (&startfile_prefixes, nstore, 0, 0, NULL_PTR);
246618334Speter	      if (*endp == 0)
246718334Speter		break;
246818334Speter	      endp = startp = endp + 1;
246918334Speter	    }
247018334Speter	  else
247118334Speter	    endp++;
247218334Speter	}
247318334Speter    }
247418334Speter
247518334Speter  /* Convert new-style -- options to old-style.  */
247618334Speter  translate_options (&argc, &argv);
247718334Speter
247818334Speter  /* Scan argv twice.  Here, the first time, just count how many switches
247918334Speter     there will be in their vector, and how many input files in theirs.
248018334Speter     Here we also parse the switches that cc itself uses (e.g. -v).  */
248118334Speter
248218334Speter  for (i = 1; i < argc; i++)
248318334Speter    {
248418334Speter      if (! strcmp (argv[i], "-dumpspecs"))
248518334Speter	{
248618334Speter	  printf ("*asm:\n%s\n\n", asm_spec);
248718334Speter	  printf ("*asm_final:\n%s\n\n", asm_final_spec);
248818334Speter	  printf ("*cpp:\n%s\n\n", cpp_spec);
248918334Speter	  printf ("*cc1:\n%s\n\n", cc1_spec);
249018334Speter	  printf ("*cc1plus:\n%s\n\n", cc1plus_spec);
249118334Speter	  printf ("*endfile:\n%s\n\n", endfile_spec);
249218334Speter	  printf ("*link:\n%s\n\n", link_spec);
249318334Speter	  printf ("*lib:\n%s\n\n", lib_spec);
249418334Speter	  printf ("*libgcc:\n%s\n\n", libgcc_spec);
249518334Speter	  printf ("*startfile:\n%s\n\n", startfile_spec);
249618334Speter	  printf ("*switches_need_spaces:\n%s\n\n", switches_need_spaces);
249718334Speter	  printf ("*signed_char:\n%s\n\n", signed_char_spec);
249818334Speter	  printf ("*predefines:\n%s\n\n", cpp_predefines);
249918334Speter	  printf ("*cross_compile:\n%d\n\n", cross_compile);
250018334Speter	  printf ("*multilib:\n%s\n\n", multilib_select);
250118334Speter
250218334Speter	  exit (0);
250318334Speter	}
250418334Speter      else if (! strcmp (argv[i], "-dumpversion"))
250518334Speter	{
250618334Speter	  printf ("%s\n", version_string);
250718334Speter	  exit (0);
250818334Speter	}
250918334Speter      else if (! strcmp (argv[i], "-dumpmachine"))
251018334Speter	{
251118334Speter	  printf ("%s\n", spec_machine);
251218334Speter	  exit  (0);
251318334Speter	}
251418334Speter      else if (! strcmp (argv[i], "-print-search-dirs"))
251518334Speter	print_search_dirs = 1;
251618334Speter      else if (! strcmp (argv[i], "-print-libgcc-file-name"))
251718334Speter	print_file_name = "libgcc.a";
251818334Speter      else if (! strncmp (argv[i], "-print-file-name=", 17))
251918334Speter	print_file_name = argv[i] + 17;
252018334Speter      else if (! strncmp (argv[i], "-print-prog-name=", 17))
252118334Speter	print_prog_name = argv[i] + 17;
252218334Speter      else if (! strcmp (argv[i], "-print-multi-lib"))
252318334Speter	print_multi_lib = 1;
252418334Speter      else if (! strcmp (argv[i], "-print-multi-directory"))
252518334Speter	print_multi_directory = 1;
252618334Speter      else if (! strncmp (argv[i], "-Wa,", 4))
252718334Speter	{
252818334Speter	  int prev, j;
252918334Speter	  /* Pass the rest of this option to the assembler.  */
253018334Speter
253118334Speter	  n_assembler_options++;
253218334Speter	  if (!assembler_options)
253318334Speter	    assembler_options
253418334Speter	      = (char **) xmalloc (n_assembler_options * sizeof (char **));
253518334Speter	  else
253618334Speter	    assembler_options
253718334Speter	      = (char **) xrealloc (assembler_options,
253818334Speter				    n_assembler_options * sizeof (char **));
253918334Speter
254018334Speter	  /* Split the argument at commas.  */
254118334Speter	  prev = 4;
254218334Speter	  for (j = 4; argv[i][j]; j++)
254318334Speter	    if (argv[i][j] == ',')
254418334Speter	      {
254518334Speter		assembler_options[n_assembler_options - 1]
254618334Speter		  = save_string (argv[i] + prev, j - prev);
254718334Speter		n_assembler_options++;
254818334Speter		assembler_options
254918334Speter		  = (char **) xrealloc (assembler_options,
255018334Speter					n_assembler_options * sizeof (char **));
255118334Speter		prev = j + 1;
255218334Speter	      }
255318334Speter	  /* Record the part after the last comma.  */
255418334Speter	  assembler_options[n_assembler_options - 1] = argv[i] + prev;
255518334Speter	}
255618334Speter      else if (! strncmp (argv[i], "-Wp,", 4))
255718334Speter	{
255818334Speter	  int prev, j;
255918334Speter	  /* Pass the rest of this option to the preprocessor.  */
256018334Speter
256118334Speter	  n_preprocessor_options++;
256218334Speter	  if (!preprocessor_options)
256318334Speter	    preprocessor_options
256418334Speter	      = (char **) xmalloc (n_preprocessor_options * sizeof (char **));
256518334Speter	  else
256618334Speter	    preprocessor_options
256718334Speter	      = (char **) xrealloc (preprocessor_options,
256818334Speter				    n_preprocessor_options * sizeof (char **));
256918334Speter
257018334Speter	  /* Split the argument at commas.  */
257118334Speter	  prev = 4;
257218334Speter	  for (j = 4; argv[i][j]; j++)
257318334Speter	    if (argv[i][j] == ',')
257418334Speter	      {
257518334Speter		preprocessor_options[n_preprocessor_options - 1]
257618334Speter		  = save_string (argv[i] + prev, j - prev);
257718334Speter		n_preprocessor_options++;
257818334Speter		preprocessor_options
257918334Speter		  = (char **) xrealloc (preprocessor_options,
258018334Speter					n_preprocessor_options * sizeof (char **));
258118334Speter		prev = j + 1;
258218334Speter	      }
258318334Speter	  /* Record the part after the last comma.  */
258418334Speter	  preprocessor_options[n_preprocessor_options - 1] = argv[i] + prev;
258518334Speter	}
258618334Speter      else if (argv[i][0] == '+' && argv[i][1] == 'e')
258718334Speter	/* The +e options to the C++ front-end.  */
258818334Speter	n_switches++;
258918334Speter      else if (strncmp (argv[i], "-Wl,", 4) == 0)
259018334Speter	{
259118334Speter	  int j;
259218334Speter	  /* Split the argument at commas.  */
259318334Speter	  for (j = 3; argv[i][j]; j++)
259418334Speter	    n_infiles += (argv[i][j] == ',');
259518334Speter	}
259618334Speter      else if (strcmp (argv[i], "-Xlinker") == 0)
259718334Speter	{
259818334Speter	  if (i + 1 == argc)
259918334Speter	    fatal ("argument to `-Xlinker' is missing");
260018334Speter
260118334Speter	  n_infiles++;
260218334Speter	  i++;
260318334Speter	}
260418334Speter      else if (strncmp (argv[i], "-l", 2) == 0)
260518334Speter	n_infiles++;
260618334Speter      else if (argv[i][0] == '-' && argv[i][1] != 0)
260718334Speter	{
260818334Speter	  register char *p = &argv[i][1];
260918334Speter	  register int c = *p;
261018334Speter
261118334Speter	  switch (c)
261218334Speter	    {
261318334Speter	    case 'b':
261418334Speter	      if (p[1] == 0 && i + 1 == argc)
261518334Speter		fatal ("argument to `-b' is missing");
261618334Speter	      if (p[1] == 0)
261718334Speter		spec_machine = argv[++i];
261818334Speter	      else
261918334Speter		spec_machine = p + 1;
262018334Speter	      break;
262118334Speter
262218334Speter	    case 'B':
262318334Speter	      {
262418334Speter		int *temp = (int *) xmalloc (sizeof (int));
262518334Speter		char *value;
262618334Speter		if (p[1] == 0 && i + 1 == argc)
262718334Speter		  fatal ("argument to `-B' is missing");
262818334Speter		if (p[1] == 0)
262918334Speter		  value = argv[++i];
263018334Speter		else
263118334Speter		  value = p + 1;
263218334Speter		add_prefix (&exec_prefixes, value, 1, 0, temp);
263318334Speter		add_prefix (&startfile_prefixes, value, 1, 0, temp);
263418334Speter		add_prefix (&include_prefixes, concat (value, "include"),
263518334Speter			    1, 0, 0);
263618334Speter
263718334Speter		/* As a kludge, if the arg is "[foo/]stageN/", just add
263818334Speter		   "[foo/]include" to the include prefix.  */
263918334Speter		{
264018334Speter		  int len = strlen (value);
264118334Speter		  if ((len == 7
264218334Speter		       || (len > 7
264318334Speter			   && (value[len - 8] == '/'
264418334Speter			       || value[len - 8] == DIR_SEPARATOR)))
264518334Speter		      && strncmp (value + len - 7, "stage", 5) == 0
264618334Speter		      && isdigit (value[len - 2])
264718334Speter		      && (value[len - 1] == '/'
264818334Speter			  || value[len - 1] == DIR_SEPARATOR))
264918334Speter		    {
265018334Speter		      if (len == 7)
265118334Speter			add_prefix (&include_prefixes, "include", 1, 0, 0);
265218334Speter		      else
265318334Speter			{
265418334Speter			  char *string = xmalloc (len + 1);
265518334Speter			  strncpy (string, value, len-7);
265618334Speter			  strcat (string, "include");
265718334Speter			  add_prefix (&include_prefixes, string, 1, 0, 0);
265818334Speter			}
265918334Speter		    }
266018334Speter		}
266118334Speter	      }
266218334Speter	      break;
266318334Speter
266418334Speter	    case 'v':	/* Print our subcommands and print versions.  */
266518334Speter	      n_switches++;
266618334Speter	      /* If they do anything other than exactly `-v', don't set
266718334Speter		 verbose_flag; rather, continue on to give the error.  */
266818334Speter	      if (p[1] != 0)
266918334Speter		break;
267018334Speter	      verbose_flag++;
267118334Speter	      break;
267218334Speter
267318334Speter	    case 'V':
267418334Speter	      if (p[1] == 0 && i + 1 == argc)
267518334Speter		fatal ("argument to `-V' is missing");
267618334Speter	      if (p[1] == 0)
267718334Speter		spec_version = argv[++i];
267818334Speter	      else
267918334Speter		spec_version = p + 1;
268018334Speter	      compiler_version = spec_version;
268118334Speter	      break;
268218334Speter
268318334Speter	    case 's':
268418334Speter	      if (!strcmp (p, "save-temps"))
268518334Speter		{
268618334Speter		  save_temps_flag = 1;
268718334Speter		  n_switches++;
268818334Speter		  break;
268918334Speter		}
269018334Speter	    default:
269118334Speter	      n_switches++;
269218334Speter
269318334Speter	      if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
269418334Speter		i += SWITCH_TAKES_ARG (c) - (p[1] != 0);
269518334Speter	      else if (WORD_SWITCH_TAKES_ARG (p))
269618334Speter		i += WORD_SWITCH_TAKES_ARG (p);
269718334Speter	    }
269818334Speter	}
269918334Speter      else
270018334Speter	n_infiles++;
270118334Speter    }
270218334Speter
270318334Speter  /* Set up the search paths before we go looking for config files.  */
270418334Speter
270518334Speter  /* These come before the md prefixes so that we will find gcc's subcommands
270618334Speter     (such as cpp) rather than those of the host system.  */
270718334Speter  /* Use 2 as fourth arg meaning try just the machine as a suffix,
270818334Speter     as well as trying the machine and the version.  */
270918346Speter#ifdef FREEBSD_NATIVE
271018346Speter  add_prefix (&exec_prefixes, "/usr/libexec/", 0, 0, NULL_PTR);
271118346Speter  add_prefix (&exec_prefixes, "/usr/bin/", 0, 0, NULL_PTR);
271218346Speter#else /* not FREEBSD_NATIVE */
271318334Speter#ifndef OS2
271418334Speter  add_prefix (&exec_prefixes, standard_exec_prefix, 0, 2, NULL_PTR);
271518334Speter  add_prefix (&exec_prefixes, standard_exec_prefix_1, 0, 2, NULL_PTR);
271618334Speter#endif
271718334Speter
271818334Speter  add_prefix (&startfile_prefixes, standard_exec_prefix, 0, 1, NULL_PTR);
271918334Speter  add_prefix (&startfile_prefixes, standard_exec_prefix_1, 0, 1, NULL_PTR);
272018346Speter#endif /* FREEBSD_NATIVE */
272118334Speter
272218334Speter  tooldir_prefix = concat3 (tooldir_base_prefix, spec_machine,
272318334Speter                            dir_separator_str);
272418334Speter
272518334Speter  /* If tooldir is relative, base it on exec_prefixes.  A relative
272618334Speter     tooldir lets us move the installed tree as a unit.
272718334Speter
272818334Speter     If GCC_EXEC_PREFIX is defined, then we want to add two relative
272918334Speter     directories, so that we can search both the user specified directory
273018334Speter     and the standard place.  */
273118334Speter
273218334Speter  if (*tooldir_prefix != '/' && *tooldir_prefix != DIR_SEPARATOR)
273318334Speter    {
273418334Speter      if (gcc_exec_prefix)
273518334Speter	{
273618334Speter	  char *gcc_exec_tooldir_prefix
273718334Speter	    = concat6 (gcc_exec_prefix, spec_machine, dir_separator_str,
273818334Speter		      spec_version, dir_separator_str, tooldir_prefix);
273918334Speter
274018334Speter	  add_prefix (&exec_prefixes,
274118334Speter		      concat3 (gcc_exec_tooldir_prefix, "bin",
274218334Speter                               dir_separator_str),
274318334Speter		      0, 0, NULL_PTR);
274418334Speter	  add_prefix (&startfile_prefixes,
274518334Speter		      concat3 (gcc_exec_tooldir_prefix, "lib",
274618334Speter                               dir_separator_str),
274718334Speter		      0, 0, NULL_PTR);
274818334Speter	}
274918334Speter
275018334Speter      tooldir_prefix = concat6 (standard_exec_prefix, spec_machine,
275118334Speter			        dir_separator_str, spec_version,
275218334Speter                                dir_separator_str, tooldir_prefix);
275318334Speter    }
275418334Speter
275518346Speter#ifndef FREEBSD_NATIVE
275618334Speter  add_prefix (&exec_prefixes,
275718334Speter              concat3 (tooldir_prefix, "bin", dir_separator_str),
275818334Speter	      0, 0, NULL_PTR);
275918334Speter  add_prefix (&startfile_prefixes,
276018334Speter	      concat3 (tooldir_prefix, "lib", dir_separator_str),
276118334Speter	      0, 0, NULL_PTR);
276218346Speter#endif /* FREEBSD_NATIVE */
276318334Speter
276418334Speter  /* More prefixes are enabled in main, after we read the specs file
276518334Speter     and determine whether this is cross-compilation or not.  */
276618334Speter
276718334Speter
276818334Speter  /* Then create the space for the vectors and scan again.  */
276918334Speter
277018334Speter  switches = ((struct switchstr *)
277118334Speter	      xmalloc ((n_switches + 1) * sizeof (struct switchstr)));
277218334Speter  infiles = (struct infile *) xmalloc ((n_infiles + 1) * sizeof (struct infile));
277318334Speter  n_switches = 0;
277418334Speter  n_infiles = 0;
277518334Speter  last_language_n_infiles = -1;
277618334Speter
277718334Speter  /* This, time, copy the text of each switch and store a pointer
277818334Speter     to the copy in the vector of switches.
277918334Speter     Store all the infiles in their vector.  */
278018334Speter
278118334Speter  for (i = 1; i < argc; i++)
278218334Speter    {
278318334Speter      /* Just skip the switches that were handled by the preceding loop.  */
278418334Speter      if (! strncmp (argv[i], "-Wa,", 4))
278518334Speter	;
278618334Speter      else if (! strncmp (argv[i], "-Wp,", 4))
278718334Speter	;
278818334Speter      else if (! strcmp (argv[i], "-print-search-dirs"))
278918334Speter	;
279018334Speter      else if (! strcmp (argv[i], "-print-libgcc-file-name"))
279118334Speter	;
279218334Speter      else if (! strncmp (argv[i], "-print-file-name=", 17))
279318334Speter	;
279418334Speter      else if (! strncmp (argv[i], "-print-prog-name=", 17))
279518334Speter	;
279618334Speter      else if (! strcmp (argv[i], "-print-multi-lib"))
279718334Speter	;
279818334Speter      else if (! strcmp (argv[i], "-print-multi-directory"))
279918334Speter	;
280018334Speter      else if (argv[i][0] == '+' && argv[i][1] == 'e')
280118334Speter	{
280218334Speter	  /* Compensate for the +e options to the C++ front-end;
280318334Speter	     they're there simply for cfront call-compatibility.  We do
280418334Speter	     some magic in default_compilers to pass them down properly.
280518334Speter	     Note we deliberately start at the `+' here, to avoid passing
280618334Speter	     -e0 or -e1 down into the linker.  */
280718334Speter	  switches[n_switches].part1 = &argv[i][0];
280818334Speter	  switches[n_switches].args = 0;
280918334Speter	  switches[n_switches].live_cond = 0;
281018334Speter	  switches[n_switches].valid = 0;
281118334Speter	  n_switches++;
281218334Speter	}
281318334Speter      else if (strncmp (argv[i], "-Wl,", 4) == 0)
281418334Speter	{
281518334Speter	  int prev, j;
281618334Speter	  /* Split the argument at commas.  */
281718334Speter	  prev = 4;
281818334Speter	  for (j = 4; argv[i][j]; j++)
281918334Speter	    if (argv[i][j] == ',')
282018334Speter	      {
282118334Speter		infiles[n_infiles].language = 0;
282218334Speter		infiles[n_infiles++].name
282318334Speter		  = save_string (argv[i] + prev, j - prev);
282418334Speter		prev = j + 1;
282518334Speter	      }
282618334Speter	  /* Record the part after the last comma.  */
282718334Speter	  infiles[n_infiles].language = 0;
282818334Speter	  infiles[n_infiles++].name = argv[i] + prev;
282918334Speter	}
283018334Speter      else if (strcmp (argv[i], "-Xlinker") == 0)
283118334Speter	{
283218334Speter	  infiles[n_infiles].language = 0;
283318334Speter	  infiles[n_infiles++].name = argv[++i];
283418334Speter	}
283518334Speter      else if (strncmp (argv[i], "-l", 2) == 0)
283618334Speter	{
283718334Speter	  infiles[n_infiles].language = 0;
283818334Speter	  infiles[n_infiles++].name = argv[i];
283918334Speter	}
284018334Speter      else if (argv[i][0] == '-' && argv[i][1] != 0)
284118334Speter	{
284218334Speter	  register char *p = &argv[i][1];
284318334Speter	  register int c = *p;
284418334Speter
284518334Speter	  if (c == 'B' || c == 'b' || c == 'V')
284618334Speter	    {
284718334Speter	      /* Skip a separate arg, if any.  */
284818334Speter	      if (p[1] == 0)
284918334Speter		i++;
285018334Speter	      continue;
285118334Speter	    }
285218334Speter	  if (c == 'x')
285318334Speter	    {
285418334Speter	      if (p[1] == 0 && i + 1 == argc)
285518334Speter		fatal ("argument to `-x' is missing");
285618334Speter	      if (p[1] == 0)
285718334Speter		spec_lang = argv[++i];
285818334Speter	      else
285918334Speter		spec_lang = p + 1;
286018334Speter	      if (! strcmp (spec_lang, "none"))
286118334Speter		/* Suppress the warning if -xnone comes after the last input
286218334Speter		   file, because alternate command interfaces like g++ might
286318334Speter		   find it useful to place -xnone after each input file.  */
286418334Speter		spec_lang = 0;
286518334Speter	      else
286618334Speter		last_language_n_infiles = n_infiles;
286718334Speter	      continue;
286818334Speter	    }
286918334Speter	  switches[n_switches].part1 = p;
287018334Speter	  /* Deal with option arguments in separate argv elements.  */
287118334Speter	  if ((SWITCH_TAKES_ARG (c) > (p[1] != 0))
287218334Speter	      || WORD_SWITCH_TAKES_ARG (p))
287318334Speter	    {
287418334Speter	      int j = 0;
287518334Speter	      int n_args = WORD_SWITCH_TAKES_ARG (p);
287618334Speter
287718334Speter	      if (n_args == 0)
287818334Speter		{
287918334Speter		  /* Count only the option arguments in separate argv elements.  */
288018334Speter		  n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0);
288118334Speter		}
288218334Speter	      if (i + n_args >= argc)
288318334Speter		fatal ("argument to `-%s' is missing", p);
288418334Speter	      switches[n_switches].args
288518334Speter		= (char **) xmalloc ((n_args + 1) * sizeof (char *));
288618334Speter	      while (j < n_args)
288718334Speter		switches[n_switches].args[j++] = argv[++i];
288818334Speter	      /* Null-terminate the vector.  */
288918334Speter	      switches[n_switches].args[j] = 0;
289018334Speter	    }
289118334Speter	  else if (*switches_need_spaces != 0 && (c == 'o' || c == 'L'))
289218334Speter	    {
289318334Speter	      /* On some systems, ld cannot handle -o or -L without space.
289418334Speter		 So split the -o or -L from its argument.  */
289518334Speter	      switches[n_switches].part1 = (c == 'o' ? "o" : "L");
289618334Speter	      switches[n_switches].args = (char **) xmalloc (2 * sizeof (char *));
289718334Speter	      switches[n_switches].args[0] = xmalloc (strlen (p));
289818334Speter	      strcpy (switches[n_switches].args[0], &p[1]);
289918334Speter	      switches[n_switches].args[1] = 0;
290018334Speter	    }
290118334Speter	  else
290218334Speter	    switches[n_switches].args = 0;
290318334Speter
290418334Speter	  switches[n_switches].live_cond = 0;
290518334Speter	  switches[n_switches].valid = 0;
290618334Speter	  /* This is always valid, since gcc.c itself understands it.  */
290718334Speter	  if (!strcmp (p, "save-temps"))
290818334Speter	    switches[n_switches].valid = 1;
290918334Speter	  n_switches++;
291018334Speter	}
291118334Speter      else
291218334Speter	{
291318334Speter#ifdef HAVE_OBJECT_SUFFIX
291418334Speter	  /* Convert x.o to x.obj if OBJECT_SUFFIX is ".obj".  */
291518334Speter	  if (strlen (argv[i]) > 2
291618334Speter	      && argv[i][strlen (argv[i]) - 2] == '.'
291718334Speter	      && argv[i][strlen (argv[i]) - 1] == 'o')
291818334Speter	    {
291918334Speter	      int j;
292018334Speter
292118334Speter	      for (j = 0; j < strlen (argv[i]) - 2; j++)
292218334Speter		obstack_1grow (&obstack, argv[i][j]);
292318334Speter
292418334Speter	      obstack_grow (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX));
292518334Speter	      obstack_1grow (&obstack, 0);
292618334Speter	      argv[i] = obstack_finish (&obstack);
292718334Speter	    }
292818334Speter#endif
292918334Speter
293018334Speter	  if (strcmp (argv[i], "-") != 0 && access (argv[i], R_OK) < 0)
293118334Speter	    {
293218334Speter	      perror_with_name (argv[i]);
293318334Speter	      error_count++;
293418334Speter	    }
293518334Speter	  else
293618334Speter	    {
293718334Speter	      infiles[n_infiles].language = spec_lang;
293818334Speter	      infiles[n_infiles++].name = argv[i];
293918334Speter	    }
294018334Speter	}
294118334Speter    }
294218334Speter
294318334Speter  if (n_infiles == last_language_n_infiles && spec_lang != 0)
294418334Speter    error ("Warning: `-x %s' after last input file has no effect", spec_lang);
294518334Speter
294618334Speter  switches[n_switches].part1 = 0;
294718334Speter  infiles[n_infiles].name = 0;
294818334Speter}
294918334Speter
295018334Speter/* Process a spec string, accumulating and running commands.  */
295118334Speter
295218334Speter/* These variables describe the input file name.
295318334Speter   input_file_number is the index on outfiles of this file,
295418334Speter   so that the output file name can be stored for later use by %o.
295518334Speter   input_basename is the start of the part of the input file
295618334Speter   sans all directory names, and basename_length is the number
295718334Speter   of characters starting there excluding the suffix .c or whatever.  */
295818334Speter
295918334Speterstatic char *input_filename;
296018334Speterstatic int input_file_number;
296118334Speterstatic int input_filename_length;
296218334Speterstatic int basename_length;
296318334Speterstatic char *input_basename;
296418334Speterstatic char *input_suffix;
296518334Speter
296618334Speter/* These are variables used within do_spec and do_spec_1.  */
296718334Speter
296818334Speter/* Nonzero if an arg has been started and not yet terminated
296918334Speter   (with space, tab or newline).  */
297018334Speterstatic int arg_going;
297118334Speter
297218334Speter/* Nonzero means %d or %g has been seen; the next arg to be terminated
297318334Speter   is a temporary file name.  */
297418334Speterstatic int delete_this_arg;
297518334Speter
297618334Speter/* Nonzero means %w has been seen; the next arg to be terminated
297718334Speter   is the output file name of this compilation.  */
297818334Speterstatic int this_is_output_file;
297918334Speter
298018334Speter/* Nonzero means %s has been seen; the next arg to be terminated
298118334Speter   is the name of a library file and we should try the standard
298218334Speter   search dirs for it.  */
298318334Speterstatic int this_is_library_file;
298418334Speter
298518334Speter/* Nonzero means that the input of this command is coming from a pipe.  */
298618334Speterstatic int input_from_pipe;
298718334Speter
298818334Speter/* Process the spec SPEC and run the commands specified therein.
298918334Speter   Returns 0 if the spec is successfully processed; -1 if failed.  */
299018334Speter
299118334Speterstatic int
299218334Speterdo_spec (spec)
299318334Speter     char *spec;
299418334Speter{
299518334Speter  int value;
299618334Speter
299718334Speter  clear_args ();
299818334Speter  arg_going = 0;
299918334Speter  delete_this_arg = 0;
300018334Speter  this_is_output_file = 0;
300118334Speter  this_is_library_file = 0;
300218334Speter  input_from_pipe = 0;
300318334Speter
300418334Speter  value = do_spec_1 (spec, 0, NULL_PTR);
300518334Speter
300618334Speter  /* Force out any unfinished command.
300718334Speter     If -pipe, this forces out the last command if it ended in `|'.  */
300818334Speter  if (value == 0)
300918334Speter    {
301018334Speter      if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
301118334Speter	argbuf_index--;
301218334Speter
301318334Speter      if (argbuf_index > 0)
301418334Speter	value = execute ();
301518334Speter    }
301618334Speter
301718334Speter  return value;
301818334Speter}
301918334Speter
302018334Speter/* Process the sub-spec SPEC as a portion of a larger spec.
302118334Speter   This is like processing a whole spec except that we do
302218334Speter   not initialize at the beginning and we do not supply a
302318334Speter   newline by default at the end.
302418334Speter   INSWITCH nonzero means don't process %-sequences in SPEC;
302518334Speter   in this case, % is treated as an ordinary character.
302618334Speter   This is used while substituting switches.
302718334Speter   INSWITCH nonzero also causes SPC not to terminate an argument.
302818334Speter
302918334Speter   Value is zero unless a line was finished
303018334Speter   and the command on that line reported an error.  */
303118334Speter
303218334Speterstatic int
303318334Speterdo_spec_1 (spec, inswitch, soft_matched_part)
303418334Speter     char *spec;
303518334Speter     int inswitch;
303618334Speter     char *soft_matched_part;
303718334Speter{
303818334Speter  register char *p = spec;
303918334Speter  register int c;
304018334Speter  int i;
304118334Speter  char *string;
304218334Speter  int value;
304318334Speter
304418334Speter  while (c = *p++)
304518334Speter    /* If substituting a switch, treat all chars like letters.
304618334Speter       Otherwise, NL, SPC, TAB and % are special.  */
304718334Speter    switch (inswitch ? 'a' : c)
304818334Speter      {
304918334Speter      case '\n':
305018334Speter	/* End of line: finish any pending argument,
305118334Speter	   then run the pending command if one has been started.  */
305218334Speter	if (arg_going)
305318334Speter	  {
305418334Speter	    obstack_1grow (&obstack, 0);
305518334Speter	    string = obstack_finish (&obstack);
305618334Speter	    if (this_is_library_file)
305718334Speter	      string = find_file (string);
305818334Speter	    store_arg (string, delete_this_arg, this_is_output_file);
305918334Speter	    if (this_is_output_file)
306018334Speter	      outfiles[input_file_number] = string;
306118334Speter	  }
306218334Speter	arg_going = 0;
306318334Speter
306418334Speter	if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
306518334Speter	  {
306618334Speter	    for (i = 0; i < n_switches; i++)
306718334Speter	      if (!strcmp (switches[i].part1, "pipe"))
306818334Speter		break;
306918334Speter
307018334Speter	    /* A `|' before the newline means use a pipe here,
307118334Speter	       but only if -pipe was specified.
307218334Speter	       Otherwise, execute now and don't pass the `|' as an arg.  */
307318334Speter	    if (i < n_switches)
307418334Speter	      {
307518334Speter		input_from_pipe = 1;
307618334Speter		switches[i].valid = 1;
307718334Speter		break;
307818334Speter	      }
307918334Speter	    else
308018334Speter	      argbuf_index--;
308118334Speter	  }
308218334Speter
308318334Speter	if (argbuf_index > 0)
308418334Speter	  {
308518334Speter	    value = execute ();
308618334Speter	    if (value)
308718334Speter	      return value;
308818334Speter	  }
308918334Speter	/* Reinitialize for a new command, and for a new argument.  */
309018334Speter	clear_args ();
309118334Speter	arg_going = 0;
309218334Speter	delete_this_arg = 0;
309318334Speter	this_is_output_file = 0;
309418334Speter	this_is_library_file = 0;
309518334Speter	input_from_pipe = 0;
309618334Speter	break;
309718334Speter
309818334Speter      case '|':
309918334Speter	/* End any pending argument.  */
310018334Speter	if (arg_going)
310118334Speter	  {
310218334Speter	    obstack_1grow (&obstack, 0);
310318334Speter	    string = obstack_finish (&obstack);
310418334Speter	    if (this_is_library_file)
310518334Speter	      string = find_file (string);
310618334Speter	    store_arg (string, delete_this_arg, this_is_output_file);
310718334Speter	    if (this_is_output_file)
310818334Speter	      outfiles[input_file_number] = string;
310918334Speter	  }
311018334Speter
311118334Speter	/* Use pipe */
311218334Speter	obstack_1grow (&obstack, c);
311318334Speter	arg_going = 1;
311418334Speter	break;
311518334Speter
311618334Speter      case '\t':
311718334Speter      case ' ':
311818334Speter	/* Space or tab ends an argument if one is pending.  */
311918334Speter	if (arg_going)
312018334Speter	  {
312118334Speter	    obstack_1grow (&obstack, 0);
312218334Speter	    string = obstack_finish (&obstack);
312318334Speter	    if (this_is_library_file)
312418334Speter	      string = find_file (string);
312518334Speter	    store_arg (string, delete_this_arg, this_is_output_file);
312618334Speter	    if (this_is_output_file)
312718334Speter	      outfiles[input_file_number] = string;
312818334Speter	  }
312918334Speter	/* Reinitialize for a new argument.  */
313018334Speter	arg_going = 0;
313118334Speter	delete_this_arg = 0;
313218334Speter	this_is_output_file = 0;
313318334Speter	this_is_library_file = 0;
313418334Speter	break;
313518334Speter
313618334Speter      case '%':
313718334Speter	switch (c = *p++)
313818334Speter	  {
313918334Speter	  case 0:
314018334Speter	    fatal ("Invalid specification!  Bug in cc.");
314118334Speter
314218334Speter	  case 'b':
314318334Speter	    obstack_grow (&obstack, input_basename, basename_length);
314418334Speter	    arg_going = 1;
314518334Speter	    break;
314618334Speter
314718334Speter	  case 'd':
314818334Speter	    delete_this_arg = 2;
314918334Speter	    break;
315018334Speter
315118334Speter	  /* Dump out the directories specified with LIBRARY_PATH,
315218334Speter	     followed by the absolute directories
315318334Speter	     that we search for startfiles.  */
315418334Speter	  case 'D':
315518334Speter	    {
315618334Speter	      struct prefix_list *pl = startfile_prefixes.plist;
315718334Speter	      int bufsize = 100;
315818334Speter	      char *buffer = (char *) xmalloc (bufsize);
315918334Speter	      int idx;
316018334Speter
316118334Speter	      for (; pl; pl = pl->next)
316218334Speter		{
316318334Speter#ifdef RELATIVE_PREFIX_NOT_LINKDIR
316418334Speter		  /* Used on systems which record the specified -L dirs
316518334Speter		     and use them to search for dynamic linking.  */
316618334Speter		  /* Relative directories always come from -B,
316718334Speter		     and it is better not to use them for searching
316818334Speter		     at run time.  In particular, stage1 loses  */
316918334Speter		  if (pl->prefix[0] != '/' && pl->prefix[0] != DIR_SEPARATOR)
317018334Speter		    continue;
317118334Speter#endif
317218334Speter		  /* Try subdirectory if there is one.  */
317318334Speter		  if (multilib_dir != NULL)
317418334Speter		    {
317518334Speter		      if (machine_suffix)
317618334Speter			{
317718334Speter			  if (strlen (pl->prefix) + strlen (machine_suffix)
317818334Speter			      >= bufsize)
317918334Speter			    bufsize = (strlen (pl->prefix)
318018334Speter				       + strlen (machine_suffix)) * 2 + 1;
318118334Speter			  buffer = (char *) xrealloc (buffer, bufsize);
318218334Speter			  strcpy (buffer, pl->prefix);
318318334Speter			  strcat (buffer, machine_suffix);
318418334Speter			  if (is_directory (buffer, multilib_dir, 1))
318518334Speter			    {
318618334Speter			      do_spec_1 ("-L", 0, NULL_PTR);
318718334Speter#ifdef SPACE_AFTER_L_OPTION
318818334Speter			      do_spec_1 (" ", 0, NULL_PTR);
318918334Speter#endif
319018334Speter			      do_spec_1 (buffer, 1, NULL_PTR);
319118334Speter			      do_spec_1 (multilib_dir, 1, NULL_PTR);
319218334Speter			      /* Make this a separate argument.  */
319318334Speter			      do_spec_1 (" ", 0, NULL_PTR);
319418334Speter			    }
319518334Speter			}
319618334Speter		      if (!pl->require_machine_suffix)
319718334Speter			{
319818334Speter			  if (is_directory (pl->prefix, multilib_dir, 1))
319918334Speter			    {
320018334Speter			      do_spec_1 ("-L", 0, NULL_PTR);
320118334Speter#ifdef SPACE_AFTER_L_OPTION
320218334Speter			      do_spec_1 (" ", 0, NULL_PTR);
320318334Speter#endif
320418334Speter			      do_spec_1 (pl->prefix, 1, NULL_PTR);
320518334Speter			      do_spec_1 (multilib_dir, 1, NULL_PTR);
320618334Speter			      /* Make this a separate argument.  */
320718334Speter			      do_spec_1 (" ", 0, NULL_PTR);
320818334Speter			    }
320918334Speter			}
321018334Speter		    }
321118334Speter		  if (machine_suffix)
321218334Speter		    {
321318334Speter		      if (is_directory (pl->prefix, machine_suffix, 1))
321418334Speter			{
321518334Speter			  do_spec_1 ("-L", 0, NULL_PTR);
321618334Speter#ifdef SPACE_AFTER_L_OPTION
321718334Speter			  do_spec_1 (" ", 0, NULL_PTR);
321818334Speter#endif
321918334Speter			  do_spec_1 (pl->prefix, 1, NULL_PTR);
322018334Speter			  /* Remove slash from machine_suffix.  */
322118334Speter			  if (strlen (machine_suffix) >= bufsize)
322218334Speter			    bufsize = strlen (machine_suffix) * 2 + 1;
322318334Speter			  buffer = (char *) xrealloc (buffer, bufsize);
322418334Speter			  strcpy (buffer, machine_suffix);
322518334Speter			  idx = strlen (buffer);
322618334Speter			  if (buffer[idx - 1] == '/'
322718334Speter			      || buffer[idx - 1] == DIR_SEPARATOR)
322818334Speter			    buffer[idx - 1] = 0;
322918334Speter			  do_spec_1 (buffer, 1, NULL_PTR);
323018334Speter			  /* Make this a separate argument.  */
323118334Speter			  do_spec_1 (" ", 0, NULL_PTR);
323218334Speter			}
323318334Speter		    }
323418334Speter		  if (!pl->require_machine_suffix)
323518334Speter		    {
323618334Speter		      if (is_directory (pl->prefix, "", 1))
323718334Speter			{
323818334Speter			  do_spec_1 ("-L", 0, NULL_PTR);
323918334Speter#ifdef SPACE_AFTER_L_OPTION
324018334Speter			  do_spec_1 (" ", 0, NULL_PTR);
324118334Speter#endif
324218334Speter			  /* Remove slash from pl->prefix.  */
324318334Speter			  if (strlen (pl->prefix) >= bufsize)
324418334Speter			    bufsize = strlen (pl->prefix) * 2 + 1;
324518334Speter			  buffer = (char *) xrealloc (buffer, bufsize);
324618334Speter			  strcpy (buffer, pl->prefix);
324718334Speter			  idx = strlen (buffer);
324818334Speter			  if (buffer[idx - 1] == '/'
324918334Speter			      || buffer[idx - 1] == DIR_SEPARATOR)
325018334Speter			    buffer[idx - 1] = 0;
325118334Speter			  do_spec_1 (buffer, 1, NULL_PTR);
325218334Speter			  /* Make this a separate argument.  */
325318334Speter			  do_spec_1 (" ", 0, NULL_PTR);
325418334Speter			}
325518334Speter		    }
325618334Speter		}
325718334Speter	      free (buffer);
325818334Speter	    }
325918334Speter	    break;
326018334Speter
326118334Speter	  case 'e':
326218334Speter	    /* {...:%efoo} means report an error with `foo' as error message
326318334Speter	       and don't execute any more commands for this file.  */
326418334Speter	    {
326518334Speter	      char *q = p;
326618334Speter	      char *buf;
326718334Speter	      while (*p != 0 && *p != '\n') p++;
326818334Speter	      buf = (char *) alloca (p - q + 1);
326918334Speter	      strncpy (buf, q, p - q);
327018334Speter	      buf[p - q] = 0;
327118334Speter	      error ("%s", buf);
327218334Speter	      return -1;
327318334Speter	    }
327418334Speter	    break;
327518334Speter
327618334Speter	  case 'g':
327718334Speter	  case 'u':
327818334Speter	  case 'U':
327918334Speter	    if (save_temps_flag)
328018334Speter	      {
328118334Speter		obstack_grow (&obstack, input_basename, basename_length);
328218334Speter		delete_this_arg = 0;
328318334Speter	      }
328418334Speter	    else
328518334Speter	      {
328618334Speter#ifdef MKTEMP_EACH_FILE
328718334Speter		/* ??? This has a problem: the total number of
328818334Speter		   values mktemp can return is limited.
328918334Speter		   That matters for the names of object files.
329018334Speter		   In 2.4, do something about that.  */
329118334Speter		struct temp_name *t;
329218334Speter		char *suffix = p;
329318334Speter		while (*p == '.' || isalpha (*p)
329418334Speter		       || (p[0] == '%' && p[1] == 'O'))
329518334Speter		  p++;
329618334Speter
329718334Speter		/* See if we already have an association of %g/%u/%U and
329818334Speter		   suffix.  */
329918334Speter		for (t = temp_names; t; t = t->next)
330018334Speter		  if (t->length == p - suffix
330118334Speter		      && strncmp (t->suffix, suffix, p - suffix) == 0
330218334Speter		      && t->unique == (c != 'g'))
330318334Speter		    break;
330418334Speter
330518334Speter		/* Make a new association if needed.  %u requires one.  */
330618334Speter		if (t == 0 || c == 'u')
330718334Speter		  {
330818334Speter		    if (t == 0)
330918334Speter		      {
331018334Speter			t = (struct temp_name *) xmalloc (sizeof (struct temp_name));
331118334Speter			t->next = temp_names;
331218334Speter			temp_names = t;
331318334Speter		      }
331418334Speter		    t->length = p - suffix;
331518334Speter		    t->suffix = save_string (suffix, p - suffix);
331618334Speter		    t->unique = (c != 'g');
331718334Speter		    choose_temp_base ();
331818334Speter		    t->filename = temp_filename;
331918334Speter		    t->filename_length = temp_filename_length;
332018334Speter		  }
332118334Speter
332218334Speter		obstack_grow (&obstack, t->filename, t->filename_length);
332318334Speter		delete_this_arg = 1;
332418334Speter#else
332518334Speter		obstack_grow (&obstack, temp_filename, temp_filename_length);
332618334Speter		if (c == 'u' || c == 'U')
332718334Speter		  {
332818334Speter		    static int unique;
332918334Speter		    char buff[9];
333018334Speter		    if (c == 'u')
333118334Speter		      unique++;
333218334Speter		    sprintf (buff, "%d", unique);
333318334Speter		    obstack_grow (&obstack, buff, strlen (buff));
333418334Speter		  }
333518334Speter#endif
333618334Speter		delete_this_arg = 1;
333718334Speter	      }
333818334Speter	    arg_going = 1;
333918334Speter	    break;
334018334Speter
334118334Speter	  case 'i':
334218334Speter	    obstack_grow (&obstack, input_filename, input_filename_length);
334318334Speter	    arg_going = 1;
334418334Speter	    break;
334518334Speter
334618334Speter	  case 'I':
334718334Speter	    {
334818334Speter	      struct prefix_list *pl = include_prefixes.plist;
334918334Speter
335018334Speter	      if (gcc_exec_prefix)
335118334Speter		{
335218334Speter		  do_spec_1 ("-iprefix", 1, NULL_PTR);
335318334Speter		  /* Make this a separate argument.  */
335418334Speter		  do_spec_1 (" ", 0, NULL_PTR);
335518334Speter		  do_spec_1 (gcc_exec_prefix, 1, NULL_PTR);
335618334Speter		  do_spec_1 (" ", 0, NULL_PTR);
335718334Speter		}
335818334Speter
335918334Speter	      for (; pl; pl = pl->next)
336018334Speter		{
336118334Speter		  do_spec_1 ("-isystem", 1, NULL_PTR);
336218334Speter		  /* Make this a separate argument.  */
336318334Speter		  do_spec_1 (" ", 0, NULL_PTR);
336418334Speter		  do_spec_1 (pl->prefix, 1, NULL_PTR);
336518334Speter		  do_spec_1 (" ", 0, NULL_PTR);
336618334Speter		}
336718334Speter	    }
336818334Speter	    break;
336918334Speter
337018334Speter	  case 'o':
337118334Speter	    for (i = 0; i < n_infiles; i++)
337218334Speter	      store_arg (outfiles[i], 0, 0);
337318334Speter	    break;
337418334Speter
337518334Speter	  case 'O':
337618334Speter	    obstack_grow (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX));
337718334Speter	    arg_going = 1;
337818334Speter	    break;
337918334Speter
338018334Speter	  case 's':
338118334Speter	    this_is_library_file = 1;
338218334Speter	    break;
338318334Speter
338418334Speter	  case 'w':
338518334Speter	    this_is_output_file = 1;
338618334Speter	    break;
338718334Speter
338818334Speter	  case 'W':
338918334Speter	    {
339018334Speter	      int index = argbuf_index;
339118334Speter	      /* Handle the {...} following the %W.  */
339218334Speter	      if (*p != '{')
339318334Speter		abort ();
339418334Speter	      p = handle_braces (p + 1);
339518334Speter	      if (p == 0)
339618334Speter		return -1;
339718334Speter	      /* If any args were output, mark the last one for deletion
339818334Speter		 on failure.  */
339918334Speter	      if (argbuf_index != index)
340018334Speter		record_temp_file (argbuf[argbuf_index - 1], 0, 1);
340118334Speter	      break;
340218334Speter	    }
340318334Speter
340418334Speter	  /* %x{OPTION} records OPTION for %X to output.  */
340518334Speter	  case 'x':
340618334Speter	    {
340718334Speter	      char *p1 = p;
340818334Speter	      char *string;
340918334Speter
341018334Speter	      /* Skip past the option value and make a copy.  */
341118334Speter	      if (*p != '{')
341218334Speter		abort ();
341318334Speter	      while (*p++ != '}')
341418334Speter		;
341518334Speter	      string = save_string (p1 + 1, p - p1 - 2);
341618334Speter
341718334Speter	      /* See if we already recorded this option.  */
341818334Speter	      for (i = 0; i < n_linker_options; i++)
341918334Speter		if (! strcmp (string, linker_options[i]))
342018334Speter		  {
342118334Speter		    free (string);
342218334Speter		    return 0;
342318334Speter		  }
342418334Speter
342518334Speter	      /* This option is new; add it.  */
342618334Speter	      n_linker_options++;
342718334Speter	      if (!linker_options)
342818334Speter		linker_options
342918334Speter		  = (char **) xmalloc (n_linker_options * sizeof (char **));
343018334Speter	      else
343118334Speter		linker_options
343218334Speter		  = (char **) xrealloc (linker_options,
343318334Speter					n_linker_options * sizeof (char **));
343418334Speter
343518334Speter	      linker_options[n_linker_options - 1] = string;
343618334Speter	    }
343718334Speter	    break;
343818334Speter
343918334Speter	  /* Dump out the options accumulated previously using %x.  */
344018334Speter	  case 'X':
344118334Speter	    for (i = 0; i < n_linker_options; i++)
344218334Speter	      {
344318334Speter		do_spec_1 (linker_options[i], 1, NULL_PTR);
344418334Speter		/* Make each accumulated option a separate argument.  */
344518334Speter		do_spec_1 (" ", 0, NULL_PTR);
344618334Speter	      }
344718334Speter	    break;
344818334Speter
344918334Speter	  /* Dump out the options accumulated previously using -Wa,.  */
345018334Speter	  case 'Y':
345118334Speter	    for (i = 0; i < n_assembler_options; i++)
345218334Speter	      {
345318334Speter		do_spec_1 (assembler_options[i], 1, NULL_PTR);
345418334Speter		/* Make each accumulated option a separate argument.  */
345518334Speter		do_spec_1 (" ", 0, NULL_PTR);
345618334Speter	      }
345718334Speter	    break;
345818334Speter
345918334Speter	  /* Dump out the options accumulated previously using -Wp,.  */
346018334Speter	  case 'Z':
346118334Speter	    for (i = 0; i < n_preprocessor_options; i++)
346218334Speter	      {
346318334Speter		do_spec_1 (preprocessor_options[i], 1, NULL_PTR);
346418334Speter		/* Make each accumulated option a separate argument.  */
346518334Speter		do_spec_1 (" ", 0, NULL_PTR);
346618334Speter	      }
346718334Speter	    break;
346818334Speter
346918334Speter	    /* Here are digits and numbers that just process
347018334Speter	       a certain constant string as a spec.  */
347118334Speter
347218334Speter	  case '1':
347318334Speter	    value = do_spec_1 (cc1_spec, 0, NULL_PTR);
347418334Speter	    if (value != 0)
347518334Speter	      return value;
347618334Speter	    break;
347718334Speter
347818334Speter	  case '2':
347918334Speter	    value = do_spec_1 (cc1plus_spec, 0, NULL_PTR);
348018334Speter	    if (value != 0)
348118334Speter	      return value;
348218334Speter	    break;
348318334Speter
348418334Speter	  case 'a':
348518334Speter	    value = do_spec_1 (asm_spec, 0, NULL_PTR);
348618334Speter	    if (value != 0)
348718334Speter	      return value;
348818334Speter	    break;
348918334Speter
349018334Speter	  case 'A':
349118334Speter	    value = do_spec_1 (asm_final_spec, 0, NULL_PTR);
349218334Speter	    if (value != 0)
349318334Speter	      return value;
349418334Speter	    break;
349518334Speter
349618334Speter	  case 'c':
349718334Speter	    value = do_spec_1 (signed_char_spec, 0, NULL_PTR);
349818334Speter	    if (value != 0)
349918334Speter	      return value;
350018334Speter	    break;
350118334Speter
350218334Speter	  case 'C':
350318334Speter	    value = do_spec_1 (cpp_spec, 0, NULL_PTR);
350418334Speter	    if (value != 0)
350518334Speter	      return value;
350618334Speter	    break;
350718334Speter
350818334Speter	  case 'E':
350918334Speter	    value = do_spec_1 (endfile_spec, 0, NULL_PTR);
351018334Speter	    if (value != 0)
351118334Speter	      return value;
351218334Speter	    break;
351318334Speter
351418334Speter	  case 'l':
351518334Speter	    value = do_spec_1 (link_spec, 0, NULL_PTR);
351618334Speter	    if (value != 0)
351718334Speter	      return value;
351818334Speter	    break;
351918334Speter
352018334Speter	  case 'L':
352118334Speter	    value = do_spec_1 (lib_spec, 0, NULL_PTR);
352218334Speter	    if (value != 0)
352318334Speter	      return value;
352418334Speter	    break;
352518334Speter
352618334Speter	  case 'G':
352718334Speter	    value = do_spec_1 (libgcc_spec, 0, NULL_PTR);
352818334Speter	    if (value != 0)
352918334Speter	      return value;
353018334Speter	    break;
353118334Speter
353218334Speter	  case 'p':
353318334Speter	    {
353418334Speter	      char *x = (char *) alloca (strlen (cpp_predefines) + 1);
353518334Speter	      char *buf = x;
353618334Speter	      char *y;
353718334Speter
353818334Speter	      /* Copy all of the -D options in CPP_PREDEFINES into BUF.  */
353918334Speter	      y = cpp_predefines;
354018334Speter	      while (*y != 0)
354118334Speter		{
354218334Speter		  if (! strncmp (y, "-D", 2))
354318334Speter		    /* Copy the whole option.  */
354418334Speter		    while (*y && *y != ' ' && *y != '\t')
354518334Speter		      *x++ = *y++;
354618334Speter		  else if (*y == ' ' || *y == '\t')
354718334Speter		    /* Copy whitespace to the result.  */
354818334Speter		    *x++ = *y++;
354918334Speter		  /* Don't copy other options.  */
355018334Speter		  else
355118334Speter		    y++;
355218334Speter		}
355318334Speter
355418334Speter	      *x = 0;
355518334Speter
355618334Speter	      value = do_spec_1 (buf, 0, NULL_PTR);
355718334Speter	      if (value != 0)
355818334Speter		return value;
355918334Speter	    }
356018334Speter	    break;
356118334Speter
356218334Speter	  case 'P':
356318334Speter	    {
356418334Speter	      char *x = (char *) alloca (strlen (cpp_predefines) * 4 + 1);
356518334Speter	      char *buf = x;
356618334Speter	      char *y;
356718334Speter
356818334Speter	      /* Copy all of CPP_PREDEFINES into BUF,
356918334Speter		 but put __ after every -D and at the end of each arg.  */
357018334Speter	      y = cpp_predefines;
357118334Speter	      while (*y != 0)
357218334Speter		{
357318334Speter		  if (! strncmp (y, "-D", 2))
357418334Speter		    {
357518334Speter		      int flag = 0;
357618334Speter
357718334Speter		      *x++ = *y++;
357818334Speter		      *x++ = *y++;
357918334Speter
358018334Speter		      if (*y != '_'
358118334Speter			  || (*(y+1) != '_' && ! isupper (*(y+1))))
358218334Speter		        {
358318334Speter			  /* Stick __ at front of macro name.  */
358418334Speter			  *x++ = '_';
358518334Speter			  *x++ = '_';
358618334Speter			  /* Arrange to stick __ at the end as well.  */
358718334Speter			  flag = 1;
358818334Speter			}
358918334Speter
359018334Speter		      /* Copy the macro name.  */
359118334Speter		      while (*y && *y != '=' && *y != ' ' && *y != '\t')
359218334Speter			*x++ = *y++;
359318334Speter
359418334Speter		      if (flag)
359518334Speter		        {
359618334Speter			  *x++ = '_';
359718334Speter			  *x++ = '_';
359818334Speter			}
359918334Speter
360018334Speter		      /* Copy the value given, if any.  */
360118334Speter		      while (*y && *y != ' ' && *y != '\t')
360218334Speter			*x++ = *y++;
360318334Speter		    }
360418334Speter		  else if (*y == ' ' || *y == '\t')
360518334Speter		    /* Copy whitespace to the result.  */
360618334Speter		    *x++ = *y++;
360718334Speter		  /* Don't copy -A options  */
360818334Speter		  else
360918334Speter		    y++;
361018334Speter		}
361118334Speter	      *x++ = ' ';
361218334Speter
361318334Speter	      /* Copy all of CPP_PREDEFINES into BUF,
361418334Speter		 but put __ after every -D.  */
361518334Speter	      y = cpp_predefines;
361618334Speter	      while (*y != 0)
361718334Speter		{
361818334Speter		  if (! strncmp (y, "-D", 2))
361918334Speter		    {
362018334Speter		      y += 2;
362118334Speter
362218334Speter		      if (*y != '_'
362318334Speter			  || (*(y+1) != '_' && ! isupper (*(y+1))))
362418334Speter		        {
362518334Speter			  /* Stick -D__ at front of macro name.  */
362618334Speter			  *x++ = '-';
362718334Speter			  *x++ = 'D';
362818334Speter			  *x++ = '_';
362918334Speter			  *x++ = '_';
363018334Speter
363118334Speter			  /* Copy the macro name.  */
363218334Speter			  while (*y && *y != '=' && *y != ' ' && *y != '\t')
363318334Speter			    *x++ = *y++;
363418334Speter
363518334Speter			  /* Copy the value given, if any.  */
363618334Speter			  while (*y && *y != ' ' && *y != '\t')
363718334Speter			    *x++ = *y++;
363818334Speter			}
363918334Speter		      else
364018334Speter			{
364118334Speter			  /* Do not copy this macro - we have just done it before */
364218334Speter			  while (*y && *y != ' ' && *y != '\t')
364318334Speter			    y++;
364418334Speter			}
364518334Speter		    }
364618334Speter		  else if (*y == ' ' || *y == '\t')
364718334Speter		    /* Copy whitespace to the result.  */
364818334Speter		    *x++ = *y++;
364918334Speter		  /* Don't copy -A options  */
365018334Speter		  else
365118334Speter		    y++;
365218334Speter		}
365318334Speter	      *x++ = ' ';
365418334Speter
365518334Speter	      /* Copy all of the -A options in CPP_PREDEFINES into BUF.  */
365618334Speter	      y = cpp_predefines;
365718334Speter	      while (*y != 0)
365818334Speter		{
365918334Speter		  if (! strncmp (y, "-A", 2))
366018334Speter		    /* Copy the whole option.  */
366118334Speter		    while (*y && *y != ' ' && *y != '\t')
366218334Speter		      *x++ = *y++;
366318334Speter		  else if (*y == ' ' || *y == '\t')
366418334Speter		    /* Copy whitespace to the result.  */
366518334Speter		    *x++ = *y++;
366618334Speter		  /* Don't copy other options.  */
366718334Speter		  else
366818334Speter		    y++;
366918334Speter		}
367018334Speter
367118334Speter	      *x = 0;
367218334Speter
367318334Speter	      value = do_spec_1 (buf, 0, NULL_PTR);
367418334Speter	      if (value != 0)
367518334Speter		return value;
367618334Speter	    }
367718334Speter	    break;
367818334Speter
367918334Speter	  case 'S':
368018334Speter	    value = do_spec_1 (startfile_spec, 0, NULL_PTR);
368118334Speter	    if (value != 0)
368218334Speter	      return value;
368318334Speter	    break;
368418334Speter
368518334Speter	    /* Here we define characters other than letters and digits.  */
368618334Speter
368718334Speter	  case '{':
368818334Speter	    p = handle_braces (p);
368918334Speter	    if (p == 0)
369018334Speter	      return -1;
369118334Speter	    break;
369218334Speter
369318334Speter	  case '%':
369418334Speter	    obstack_1grow (&obstack, '%');
369518334Speter	    break;
369618334Speter
369718334Speter	  case '*':
369818334Speter	    do_spec_1 (soft_matched_part, 1, NULL_PTR);
369918334Speter	    do_spec_1 (" ", 0, NULL_PTR);
370018334Speter	    break;
370118334Speter
370218334Speter	    /* Process a string found as the value of a spec given by name.
370318334Speter	       This feature allows individual machine descriptions
370418334Speter	       to add and use their own specs.
370518334Speter	       %[...] modifies -D options the way %P does;
370618334Speter	       %(...) uses the spec unmodified.  */
370718334Speter	  case '(':
370818334Speter	  case '[':
370918334Speter	    {
371018334Speter	      char *name = p;
371118334Speter	      struct spec_list *sl;
371218334Speter	      int len;
371318334Speter
371418334Speter	      /* The string after the S/P is the name of a spec that is to be
371518334Speter		 processed. */
371618334Speter	      while (*p && *p != ')' && *p != ']')
371718334Speter		p++;
371818334Speter
371918334Speter	      /* See if it's in the list */
372018334Speter	      for (len = p - name, sl = specs; sl; sl = sl->next)
372118334Speter		if (strncmp (sl->name, name, len) == 0 && !sl->name[len])
372218334Speter		  {
372318334Speter		    name = sl->spec;
372418334Speter		    break;
372518334Speter		  }
372618334Speter
372718334Speter	      if (sl)
372818334Speter		{
372918334Speter		  if (c == '(')
373018334Speter		    {
373118334Speter		      value = do_spec_1 (name, 0, NULL_PTR);
373218334Speter		      if (value != 0)
373318334Speter			return value;
373418334Speter		    }
373518334Speter		  else
373618334Speter		    {
373718334Speter		      char *x = (char *) alloca (strlen (name) * 2 + 1);
373818334Speter		      char *buf = x;
373918334Speter		      char *y = name;
374018334Speter
374118334Speter		      /* Copy all of NAME into BUF, but put __ after
374218334Speter			 every -D and at the end of each arg,  */
374318334Speter		      while (1)
374418334Speter			{
374518334Speter			  if (! strncmp (y, "-D", 2))
374618334Speter			    {
374718334Speter			      *x++ = '-';
374818334Speter			      *x++ = 'D';
374918334Speter			      *x++ = '_';
375018334Speter			      *x++ = '_';
375118334Speter			      y += 2;
375218334Speter			    }
375318334Speter			  else if (*y == ' ' || *y == 0)
375418334Speter			    {
375518334Speter			      *x++ = '_';
375618334Speter			      *x++ = '_';
375718334Speter			      if (*y == 0)
375818334Speter				break;
375918334Speter			      else
376018334Speter				*x++ = *y++;
376118334Speter			    }
376218334Speter			  else
376318334Speter			    *x++ = *y++;
376418334Speter			}
376518334Speter		      *x = 0;
376618334Speter
376718334Speter		      value = do_spec_1 (buf, 0, NULL_PTR);
376818334Speter		      if (value != 0)
376918334Speter			return value;
377018334Speter		    }
377118334Speter		}
377218334Speter
377318334Speter	      /* Discard the closing paren or bracket.  */
377418334Speter	      if (*p)
377518334Speter		p++;
377618334Speter	    }
377718334Speter	    break;
377818334Speter
377918334Speter	  case 'v':
378018334Speter	    {
378118334Speter	      int c1 = *p++;  /* Select first or second version number.  */
378218334Speter	      char *v = compiler_version;
378318346Speter	      char *q;
378418334Speter	      /* If desired, advance to second version number.  */
378518334Speter	      if (c1 == '2')
378618334Speter		{
378718334Speter		  /* Set P after the first period.  */
378818334Speter		  while (*v != 0 && *v != ' ' && *v != '.')
378918334Speter		    v++;
379018334Speter		  if (*v == '.')
379118334Speter		    v++;
379218334Speter		}
379318334Speter	      /* Set Q at the next period or at the end.  */
379418334Speter	      q = v;
379518334Speter	      while (*q != 0 && *q != ' ' && *q != '.')
379618334Speter		q++;
379718334Speter	      /* Empty string means zero.  */
379818334Speter	      if (p == q)
379918334Speter		{
380018334Speter		  v = "0";
380118334Speter		  q = v + 1;
380218334Speter		}
380318334Speter	      /* Put that part into the command.  */
380418334Speter	      obstack_grow (&obstack, v, q - v);
380518334Speter	      arg_going = 1;
380618334Speter	    }
380718334Speter	    break;
380818334Speter
380918334Speter	  case '|':
381018334Speter	    if (input_from_pipe)
381118334Speter	      do_spec_1 ("-", 0, NULL_PTR);
381218334Speter	    break;
381318334Speter
381418334Speter	  default:
381518334Speter	    abort ();
381618334Speter	  }
381718334Speter	break;
381818334Speter
381918334Speter      case '\\':
382018334Speter	/* Backslash: treat next character as ordinary.  */
382118334Speter	c = *p++;
382218334Speter
382318334Speter	/* fall through */
382418334Speter      default:
382518334Speter	/* Ordinary character: put it into the current argument.  */
382618334Speter	obstack_1grow (&obstack, c);
382718334Speter	arg_going = 1;
382818334Speter      }
382918334Speter
383018334Speter  return 0;		/* End of string */
383118334Speter}
383218334Speter
383318334Speter/* Return 0 if we call do_spec_1 and that returns -1.  */
383418334Speter
383518334Speterstatic char *
383618334Speterhandle_braces (p)
383718334Speter     register char *p;
383818334Speter{
383918334Speter  register char *q;
384018334Speter  char *filter;
384118334Speter  int pipe = 0;
384218334Speter  int negate = 0;
384318334Speter  int suffix = 0;
384418334Speter
384518334Speter  if (*p == '|')
384618334Speter    /* A `|' after the open-brace means,
384718334Speter       if the test fails, output a single minus sign rather than nothing.
384818334Speter       This is used in %{|!pipe:...}.  */
384918334Speter    pipe = 1, ++p;
385018334Speter
385118334Speter  if (*p == '!')
385218334Speter    /* A `!' after the open-brace negates the condition:
385318334Speter       succeed if the specified switch is not present.  */
385418334Speter    negate = 1, ++p;
385518334Speter
385618334Speter  if (*p == '.')
385718334Speter    /* A `.' after the open-brace means test against the current suffix.  */
385818334Speter    {
385918334Speter      if (pipe)
386018334Speter	abort ();
386118334Speter
386218334Speter      suffix = 1;
386318334Speter      ++p;
386418334Speter    }
386518334Speter
386618334Speter  filter = p;
386718334Speter  while (*p != ':' && *p != '}') p++;
386818334Speter  if (*p != '}')
386918334Speter    {
387018334Speter      register int count = 1;
387118334Speter      q = p + 1;
387218334Speter      while (count > 0)
387318334Speter	{
387418334Speter	  if (*q == '{')
387518334Speter	    count++;
387618334Speter	  else if (*q == '}')
387718334Speter	    count--;
387818334Speter	  else if (*q == 0)
387918334Speter	    abort ();
388018334Speter	  q++;
388118334Speter	}
388218334Speter    }
388318334Speter  else
388418334Speter    q = p + 1;
388518334Speter
388618334Speter  if (suffix)
388718334Speter    {
388818334Speter      int found = (input_suffix != 0
388918334Speter		   && strlen (input_suffix) == p - filter
389018334Speter		   && strncmp (input_suffix, filter, p - filter) == 0);
389118334Speter
389218334Speter      if (p[0] == '}')
389318334Speter	abort ();
389418334Speter
389518334Speter      if (negate != found
389618334Speter	  && do_spec_1 (save_string (p + 1, q - p - 2), 0, NULL_PTR) < 0)
389718334Speter	return 0;
389818334Speter
389918334Speter      return q;
390018334Speter    }
390118334Speter  else if (p[-1] == '*' && p[0] == '}')
390218334Speter    {
390318334Speter      /* Substitute all matching switches as separate args.  */
390418334Speter      register int i;
390518334Speter      --p;
390618334Speter      for (i = 0; i < n_switches; i++)
390718334Speter	if (!strncmp (switches[i].part1, filter, p - filter)
390818334Speter	    && check_live_switch (i, p - filter))
390918334Speter	  give_switch (i, 0);
391018334Speter    }
391118334Speter  else
391218334Speter    {
391318334Speter      /* Test for presence of the specified switch.  */
391418334Speter      register int i;
391518334Speter      int present = 0;
391618334Speter
391718334Speter      /* If name specified ends in *, as in {x*:...},
391818334Speter	 check for %* and handle that case.  */
391918334Speter      if (p[-1] == '*' && !negate)
392018334Speter	{
392118334Speter	  int substitution;
392218334Speter	  char *r = p;
392318334Speter
392418334Speter	  /* First see whether we have %*.  */
392518334Speter	  substitution = 0;
392618334Speter	  while (r < q)
392718334Speter	    {
392818334Speter	      if (*r == '%' && r[1] == '*')
392918334Speter		substitution = 1;
393018334Speter	      r++;
393118334Speter	    }
393218334Speter	  /* If we do, handle that case.  */
393318334Speter	  if (substitution)
393418334Speter	    {
393518334Speter	      /* Substitute all matching switches as separate args.
393618334Speter		 But do this by substituting for %*
393718334Speter		 in the text that follows the colon.  */
393818334Speter
393918334Speter	      unsigned hard_match_len = p - filter - 1;
394018334Speter	      char *string = save_string (p + 1, q - p - 2);
394118334Speter
394218334Speter	      for (i = 0; i < n_switches; i++)
394318334Speter		if (!strncmp (switches[i].part1, filter, hard_match_len)
394418334Speter		    && check_live_switch (i, -1))
394518334Speter		  {
394618334Speter		    do_spec_1 (string, 0, &switches[i].part1[hard_match_len]);
394718334Speter		    /* Pass any arguments this switch has.  */
394818334Speter		    give_switch (i, 1);
394918334Speter		  }
395018334Speter
395118334Speter	      return q;
395218334Speter	    }
395318334Speter	}
395418334Speter
395518334Speter      /* If name specified ends in *, as in {x*:...},
395618334Speter	 check for presence of any switch name starting with x.  */
395718334Speter      if (p[-1] == '*')
395818334Speter	{
395918334Speter	  for (i = 0; i < n_switches; i++)
396018334Speter	    {
396118334Speter	      unsigned hard_match_len = p - filter - 1;
396218334Speter
396318334Speter	      if (!strncmp (switches[i].part1, filter, hard_match_len)
396418334Speter		  && check_live_switch (i, hard_match_len))
396518334Speter		{
396618334Speter		  present = 1;
396718334Speter		}
396818334Speter	    }
396918334Speter	}
397018334Speter      /* Otherwise, check for presence of exact name specified.  */
397118334Speter      else
397218334Speter	{
397318334Speter	  for (i = 0; i < n_switches; i++)
397418334Speter	    {
397518334Speter	      if (!strncmp (switches[i].part1, filter, p - filter)
397618334Speter		  && switches[i].part1[p - filter] == 0
397718334Speter		  && check_live_switch (i, -1))
397818334Speter		{
397918334Speter		  present = 1;
398018334Speter		  break;
398118334Speter		}
398218334Speter	    }
398318334Speter	}
398418334Speter
398518334Speter      /* If it is as desired (present for %{s...}, absent for %{-s...})
398618334Speter	 then substitute either the switch or the specified
398718334Speter	 conditional text.  */
398818334Speter      if (present != negate)
398918334Speter	{
399018334Speter	  if (*p == '}')
399118334Speter	    {
399218334Speter	      give_switch (i, 0);
399318334Speter	    }
399418334Speter	  else
399518334Speter	    {
399618334Speter	      if (do_spec_1 (save_string (p + 1, q - p - 2), 0, NULL_PTR) < 0)
399718334Speter		return 0;
399818334Speter	    }
399918334Speter	}
400018334Speter      else if (pipe)
400118334Speter	{
400218334Speter	  /* Here if a %{|...} conditional fails: output a minus sign,
400318334Speter	     which means "standard output" or "standard input".  */
400418334Speter	  do_spec_1 ("-", 0, NULL_PTR);
400518334Speter	}
400618334Speter    }
400718334Speter
400818334Speter  return q;
400918334Speter}
401018334Speter
401118334Speter/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch
401218334Speter   on the command line.  PREFIX_LENGTH is the length of XXX in an {XXX*}
401318334Speter   spec, or -1 if either exact match or %* is used.
401418334Speter
401518334Speter   A -O switch is obsoleted by a later -O switch.  A -f, -m, or -W switch
401618334Speter   whose value does not begin with "no-" is obsoleted by the same value
401718334Speter   with the "no-", similarly for a switch with the "no-" prefix.  */
401818334Speter
401918334Speterstatic int
402018334Spetercheck_live_switch (switchnum, prefix_length)
402118334Speter     int switchnum;
402218334Speter     int prefix_length;
402318334Speter{
402418334Speter  char *name = switches[switchnum].part1;
402518334Speter  int i;
402618334Speter
402718334Speter  /* In the common case of {<at-most-one-letter>*}, a negating
402818334Speter     switch would always match, so ignore that case.  We will just
402918334Speter     send the conflicting switches to the compiler phase.  */
403018334Speter  if (prefix_length >= 0 && prefix_length <= 1)
403118334Speter    return 1;
403218334Speter
403318334Speter  /* If we already processed this switch and determined if it was
403418334Speter     live or not, return our past determination.  */
403518334Speter  if (switches[switchnum].live_cond != 0)
403618334Speter    return switches[switchnum].live_cond > 0;
403718334Speter
403818334Speter  /* Now search for duplicate in a manner that depends on the name.  */
403918334Speter  switch (*name)
404018334Speter    {
404118334Speter    case 'O':
404218334Speter	for (i = switchnum + 1; i < n_switches; i++)
404318334Speter	  if (switches[i].part1[0] == 'O')
404418334Speter	    {
404518334Speter	      switches[switchnum].valid = 1;
404618334Speter	      switches[switchnum].live_cond = -1;
404718334Speter	      return 0;
404818334Speter	    }
404918334Speter      break;
405018334Speter
405118334Speter    case 'W':  case 'f':  case 'm':
405218334Speter      if (! strncmp (name + 1, "no-", 3))
405318334Speter	{
405418334Speter	  /* We have Xno-YYY, search for XYYY. */
405518334Speter	  for (i = switchnum + 1; i < n_switches; i++)
405618334Speter	    if (switches[i].part1[0] == name[0]
405718334Speter		&& ! strcmp (&switches[i].part1[1], &name[4]))
405818334Speter	    {
405918334Speter	      switches[switchnum].valid = 1;
406018334Speter	      switches[switchnum].live_cond = -1;
406118334Speter	      return 0;
406218334Speter	    }
406318334Speter	}
406418334Speter      else
406518334Speter	{
406618334Speter	  /* We have XYYY, search for Xno-YYY.  */
406718334Speter	  for (i = switchnum + 1; i < n_switches; i++)
406818334Speter	    if (switches[i].part1[0] == name[0]
406918334Speter		&& switches[i].part1[1] == 'n'
407018334Speter		&& switches[i].part1[2] == 'o'
407118334Speter		&& switches[i].part1[3] == '-'
407218334Speter		&& !strcmp (&switches[i].part1[4], &name[1]))
407318334Speter	    {
407418334Speter	      switches[switchnum].valid = 1;
407518334Speter	      switches[switchnum].live_cond = -1;
407618334Speter	      return 0;
407718334Speter	    }
407818334Speter	}
407918334Speter      break;
408018334Speter    }
408118334Speter
408218334Speter  /* Otherwise the switch is live.  */
408318334Speter  switches[switchnum].live_cond = 1;
408418334Speter  return 1;
408518334Speter}
408618334Speter
408718334Speter/* Pass a switch to the current accumulating command
408818334Speter   in the same form that we received it.
408918334Speter   SWITCHNUM identifies the switch; it is an index into
409018334Speter   the vector of switches gcc received, which is `switches'.
409118334Speter   This cannot fail since it never finishes a command line.
409218334Speter
409318334Speter   If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument.  */
409418334Speter
409518334Speterstatic void
409618334Spetergive_switch (switchnum, omit_first_word)
409718334Speter     int switchnum;
409818334Speter     int omit_first_word;
409918334Speter{
410018334Speter  if (!omit_first_word)
410118334Speter    {
410218334Speter      do_spec_1 ("-", 0, NULL_PTR);
410318334Speter      do_spec_1 (switches[switchnum].part1, 1, NULL_PTR);
410418334Speter    }
410518334Speter  do_spec_1 (" ", 0, NULL_PTR);
410618334Speter  if (switches[switchnum].args != 0)
410718334Speter    {
410818334Speter      char **p;
410918334Speter      for (p = switches[switchnum].args; *p; p++)
411018334Speter	{
411118334Speter	  do_spec_1 (*p, 1, NULL_PTR);
411218334Speter	  do_spec_1 (" ", 0, NULL_PTR);
411318334Speter	}
411418334Speter    }
411518334Speter  switches[switchnum].valid = 1;
411618334Speter}
411718334Speter
411818334Speter/* Search for a file named NAME trying various prefixes including the
411918334Speter   user's -B prefix and some standard ones.
412018334Speter   Return the absolute file name found.  If nothing is found, return NAME.  */
412118334Speter
412218334Speterstatic char *
412318334Speterfind_file (name)
412418334Speter     char *name;
412518334Speter{
412618334Speter  char *newname;
412718334Speter
412818334Speter  /* Try multilib_dir if it is defined.  */
412918334Speter  if (multilib_dir != NULL)
413018334Speter    {
413118334Speter      char *try;
413218334Speter
413318334Speter      try = (char *) alloca (strlen (multilib_dir) + strlen (name) + 2);
413418334Speter      strcpy (try, multilib_dir);
413518334Speter      strcat (try, dir_separator_str);
413618334Speter      strcat (try, name);
413718334Speter
413818334Speter      newname = find_a_file (&startfile_prefixes, try, R_OK);
413918334Speter
414018334Speter      /* If we don't find it in the multi library dir, then fall
414118334Speter	 through and look for it in the normal places.  */
414218334Speter      if (newname != NULL)
414318334Speter	return newname;
414418334Speter    }
414518334Speter
414618334Speter  newname = find_a_file (&startfile_prefixes, name, R_OK);
414718334Speter  return newname ? newname : name;
414818334Speter}
414918334Speter
415018334Speter/* Determine whether a directory exists.  If LINKER, return 0 for
415118334Speter   certain fixed names not needed by the linker.  If not LINKER, it is
415218334Speter   only important to return 0 if the host machine has a small ARG_MAX
415318334Speter   limit.  */
415418334Speter
415518334Speterstatic int
415618334Speteris_directory (path1, path2, linker)
415718334Speter     char *path1;
415818334Speter     char *path2;
415918334Speter     int linker;
416018334Speter{
416118334Speter  int len1 = strlen (path1);
416218334Speter  int len2 = strlen (path2);
416318334Speter  char *path = (char *) alloca (3 + len1 + len2);
416418334Speter  char *cp;
416518334Speter  struct stat st;
416618334Speter
416718334Speter#ifndef SMALL_ARG_MAX
416818334Speter  if (! linker)
416918334Speter    return 1;
417018334Speter#endif
417118334Speter
417218334Speter  /* Construct the path from the two parts.  Ensure the string ends with "/.".
417318334Speter     The resulting path will be a directory even if the given path is a
417418334Speter     symbolic link.  */
417518334Speter  bcopy (path1, path, len1);
417618334Speter  bcopy (path2, path + len1, len2);
417718334Speter  cp = path + len1 + len2;
417818334Speter  if (cp[-1] != '/' && cp[-1] != DIR_SEPARATOR)
417918334Speter    *cp++ = DIR_SEPARATOR;
418018334Speter  *cp++ = '.';
418118334Speter  *cp = '\0';
418218334Speter
418318334Speter  /* Exclude directories that the linker is known to search.  */
418418334Speter  if (linker
418518334Speter      && ((cp - path == 6
418618334Speter	   && strcmp (path, concat4 (dir_separator_str, "lib",
418718334Speter                                     dir_separator_str, ".")) == 0)
418818334Speter	  || (cp - path == 10
418918334Speter	      && strcmp (path, concat6 (dir_separator_str, "usr",
419018334Speter                                        dir_separator_str, "lib",
419118334Speter                                        dir_separator_str, ".")) == 0)))
419218334Speter    return 0;
419318334Speter
419418334Speter  return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
419518334Speter}
419618334Speter
419718334Speter/* On fatal signals, delete all the temporary files.  */
419818334Speter
419918334Speterstatic void
420018334Speterfatal_error (signum)
420118334Speter     int signum;
420218334Speter{
420318334Speter  signal (signum, SIG_DFL);
420418334Speter  delete_failure_queue ();
420518334Speter  delete_temp_files ();
420618334Speter  /* Get the same signal again, this time not handled,
420718334Speter     so its normal effect occurs.  */
420818334Speter  kill (getpid (), signum);
420918334Speter}
421018334Speter
421118334Speterint
421218334Spetermain (argc, argv)
421318334Speter     int argc;
421418334Speter     char **argv;
421518334Speter{
421618334Speter  register int i;
421718334Speter  int j;
421818334Speter  int value;
421918334Speter  int linker_was_run = 0;
422018334Speter  char *explicit_link_files;
422118334Speter  char *specs_file;
422218334Speter  char *p;
422318334Speter
422418334Speter  p = argv[0] + strlen (argv[0]);
422518334Speter  while (p != argv[0] && p[-1] != '/' && p[-1] != DIR_SEPARATOR) --p;
422618334Speter  programname = p;
422718334Speter
422818334Speter  if (signal (SIGINT, SIG_IGN) != SIG_IGN)
422918334Speter    signal (SIGINT, fatal_error);
423018334Speter#ifdef SIGHUP
423118334Speter  if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
423218334Speter    signal (SIGHUP, fatal_error);
423318334Speter#endif
423418334Speter  if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
423518334Speter    signal (SIGTERM, fatal_error);
423618334Speter#ifdef SIGPIPE
423718334Speter  if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
423818334Speter    signal (SIGPIPE, fatal_error);
423918334Speter#endif
424018334Speter
424118334Speter  argbuf_length = 10;
424218334Speter  argbuf = (char **) xmalloc (argbuf_length * sizeof (char *));
424318334Speter
424418334Speter  obstack_init (&obstack);
424518334Speter
424618334Speter  /* Set up to remember the pathname of gcc and any options
424718334Speter     needed for collect.  We use argv[0] instead of programname because
424818334Speter     we need the complete pathname.  */
424918334Speter  obstack_init (&collect_obstack);
425018334Speter  obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=")-1);
425118334Speter  obstack_grow (&collect_obstack, argv[0], strlen (argv[0])+1);
425218334Speter  putenv (obstack_finish (&collect_obstack));
425318334Speter
425418334Speter#ifdef INIT_ENVIRONMENT
425518334Speter  /* Set up any other necessary machine specific environment variables.  */
425618334Speter  putenv (INIT_ENVIRONMENT);
425718334Speter#endif
425818334Speter
425918334Speter  /* Choose directory for temp files.  */
426018334Speter
426118334Speter  choose_temp_base ();
426218334Speter
426318334Speter  /* Make a table of what switches there are (switches, n_switches).
426418334Speter     Make a table of specified input files (infiles, n_infiles).
426518334Speter     Decode switches that are handled locally.  */
426618334Speter
426718334Speter  process_command (argc, argv);
426818334Speter
426918334Speter  /* Initialize the vector of specs to just the default.
427018334Speter     This means one element containing 0s, as a terminator.  */
427118334Speter
427218334Speter  compilers = (struct compiler *) xmalloc (sizeof default_compilers);
427318334Speter  bcopy ((char *) default_compilers, (char *) compilers,
427418334Speter	 sizeof default_compilers);
427518334Speter  n_compilers = n_default_compilers;
427618334Speter
427718334Speter  /* Read specs from a file if there is one.  */
427818334Speter
427918346Speter#ifndef FREEBSD_NATIVE
428018334Speter  machine_suffix = concat4 (spec_machine, dir_separator_str,
428118334Speter                            spec_version, dir_separator_str);
428218334Speter  just_machine_suffix = concat (spec_machine, dir_separator_str);
428318346Speter#endif
428418334Speter
428518334Speter  specs_file = find_a_file (&startfile_prefixes, "specs", R_OK);
428618334Speter  /* Read the specs file unless it is a default one.  */
428718334Speter  if (specs_file != 0 && strcmp (specs_file, "specs"))
428818334Speter    read_specs (specs_file);
428918334Speter
429018334Speter  /* If not cross-compiling, look for startfiles in the standard places.  */
429118334Speter  /* The fact that these are done here, after reading the specs file,
429218334Speter     means that it cannot be found in these directories.
429318334Speter     But that's okay.  It should never be there anyway.  */
429418334Speter  if (!cross_compile)
429518334Speter    {
429618334Speter#ifdef MD_EXEC_PREFIX
429718334Speter      add_prefix (&exec_prefixes, md_exec_prefix, 0, 0, NULL_PTR);
429818334Speter      add_prefix (&startfile_prefixes, md_exec_prefix, 0, 0, NULL_PTR);
429918334Speter#endif
430018334Speter
430118334Speter#ifdef MD_STARTFILE_PREFIX
430218334Speter      add_prefix (&startfile_prefixes, md_startfile_prefix, 0, 0, NULL_PTR);
430318334Speter#endif
430418334Speter
430518334Speter#ifdef MD_STARTFILE_PREFIX_1
430618334Speter      add_prefix (&startfile_prefixes, md_startfile_prefix_1, 0, 0, NULL_PTR);
430718334Speter#endif
430818334Speter
430918334Speter      /* If standard_startfile_prefix is relative, base it on
431018334Speter	 standard_exec_prefix.  This lets us move the installed tree
431118334Speter	 as a unit.  If GCC_EXEC_PREFIX is defined, base
431218334Speter	 standard_startfile_prefix on that as well.  */
431318334Speter      if (*standard_startfile_prefix == '/'
431418334Speter	  || *standard_startfile_prefix == DIR_SEPARATOR)
431518334Speter	add_prefix (&startfile_prefixes, standard_startfile_prefix, 0, 0,
431618334Speter		    NULL_PTR);
431718334Speter      else
431818334Speter	{
431918334Speter	  if (gcc_exec_prefix)
432018334Speter	    add_prefix (&startfile_prefixes,
432118334Speter			concat3 (gcc_exec_prefix, machine_suffix,
432218334Speter				 standard_startfile_prefix),
432318334Speter			0, 0, NULL_PTR);
432418334Speter	  add_prefix (&startfile_prefixes,
432518334Speter		      concat3 (standard_exec_prefix,
432618334Speter			       machine_suffix,
432718334Speter			       standard_startfile_prefix),
432818334Speter		      0, 0, NULL_PTR);
432918334Speter	}
433018334Speter
433118346Speter#ifndef FREEBSD_NATIVE
433218334Speter      add_prefix (&startfile_prefixes, standard_startfile_prefix_1, 0, 0,
433318334Speter		  NULL_PTR);
433418334Speter      add_prefix (&startfile_prefixes, standard_startfile_prefix_2, 0, 0,
433518334Speter		  NULL_PTR);
433618334Speter#if 0 /* Can cause surprises, and one can use -B./ instead.  */
433718334Speter      add_prefix (&startfile_prefixes, "./", 0, 1, NULL_PTR);
433818334Speter#endif
433918346Speter#endif /* FREEBSD_NATIVE */
434018346Speter
434118334Speter    }
434218334Speter  else
434318334Speter    {
434418334Speter      if (*standard_startfile_prefix != DIR_SEPARATOR && gcc_exec_prefix)
434518334Speter	add_prefix (&startfile_prefixes,
434618334Speter		    concat3 (gcc_exec_prefix, machine_suffix,
434718334Speter			     standard_startfile_prefix),
434818334Speter		    0, 0, NULL_PTR);
434918334Speter    }
435018334Speter
435118334Speter  /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake.  */
435218334Speter  if (gcc_exec_prefix)
435318334Speter    {
435418334Speter      char * temp = (char *) xmalloc (strlen (gcc_exec_prefix)
435518334Speter				      + strlen (spec_version)
435618334Speter				      + strlen (spec_machine) + 3);
435718334Speter      strcpy (temp, gcc_exec_prefix);
435818334Speter      strcat (temp, spec_machine);
435918334Speter      strcat (temp, dir_separator_str);
436018334Speter      strcat (temp, spec_version);
436118334Speter      strcat (temp, dir_separator_str);
436218334Speter      gcc_exec_prefix = temp;
436318334Speter    }
436418334Speter
436518334Speter  /* Now we have the specs.
436618334Speter     Set the `valid' bits for switches that match anything in any spec.  */
436718334Speter
436818334Speter  validate_all_switches ();
436918334Speter
437018334Speter  /* Now that we have the switches and the specs, set
437118334Speter     the subdirectory based on the options.  */
437218334Speter  set_multilib_dir ();
437318334Speter
437418334Speter  /* Warn about any switches that no pass was interested in.  */
437518334Speter
437618334Speter  for (i = 0; i < n_switches; i++)
437718334Speter    if (! switches[i].valid)
437818334Speter      error ("unrecognized option `-%s'", switches[i].part1);
437918334Speter
438018334Speter  /* Obey some of the options.  */
438118334Speter
438218334Speter  if (print_search_dirs)
438318334Speter    {
438418334Speter      printf ("install: %s%s\n", standard_exec_prefix, machine_suffix);
438518334Speter      printf ("programs: %s\n", build_search_list (&exec_prefixes, "", 0));
438618334Speter      printf ("libraries: %s\n", build_search_list (&startfile_prefixes, "", 0));
438718334Speter      exit (0);
438818334Speter    }
438918334Speter
439018334Speter  if (print_file_name)
439118334Speter    {
439218334Speter      printf ("%s\n", find_file (print_file_name));
439318334Speter      exit (0);
439418334Speter    }
439518334Speter
439618334Speter  if (print_prog_name)
439718334Speter    {
439818334Speter      char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK);
439918334Speter      printf ("%s\n", (newname ? newname : print_prog_name));
440018334Speter      exit (0);
440118334Speter    }
440218334Speter
440318334Speter  if (print_multi_lib)
440418334Speter    {
440518334Speter      print_multilib_info ();
440618334Speter      exit (0);
440718334Speter    }
440818334Speter
440918334Speter  if (print_multi_directory)
441018334Speter    {
441118334Speter      if (multilib_dir == NULL)
441218334Speter	printf (".\n");
441318334Speter      else
441418334Speter	printf ("%s\n", multilib_dir);
441518334Speter      exit (0);
441618334Speter    }
441718334Speter
441818334Speter  if (verbose_flag)
441918334Speter    {
442018334Speter      if (! strcmp (version_string, compiler_version))
442118334Speter	fprintf (stderr, "gcc version %s\n", version_string);
442218334Speter      else
442318334Speter	fprintf (stderr, "gcc driver version %s executing gcc version %s\n",
442418334Speter		 version_string, compiler_version);
442518334Speter
442618334Speter      if (n_infiles == 0)
442718334Speter	exit (0);
442818334Speter    }
442918334Speter
443018334Speter  if (n_infiles == 0)
443118346Speter    fatal ("No input files specified");
443218334Speter
443318334Speter  /* Make a place to record the compiler output file names
443418334Speter     that correspond to the input files.  */
443518334Speter
443618334Speter  outfiles = (char **) xmalloc (n_infiles * sizeof (char *));
443718334Speter  bzero ((char *) outfiles, n_infiles * sizeof (char *));
443818334Speter
443918334Speter  /* Record which files were specified explicitly as link input.  */
444018334Speter
444118334Speter  explicit_link_files = xmalloc (n_infiles);
444218334Speter  bzero (explicit_link_files, n_infiles);
444318334Speter
444418334Speter  for (i = 0; i < n_infiles; i++)
444518334Speter    {
444618334Speter      register struct compiler *cp = 0;
444718334Speter      int this_file_error = 0;
444818334Speter
444918334Speter      /* Tell do_spec what to substitute for %i.  */
445018334Speter
445118334Speter      input_filename = infiles[i].name;
445218334Speter      input_filename_length = strlen (input_filename);
445318334Speter      input_file_number = i;
445418334Speter
445518334Speter      /* Use the same thing in %o, unless cp->spec says otherwise.  */
445618334Speter
445718334Speter      outfiles[i] = input_filename;
445818334Speter
445918334Speter      /* Figure out which compiler from the file's suffix.  */
446018334Speter
446118334Speter      cp = lookup_compiler (infiles[i].name, input_filename_length,
446218334Speter			    infiles[i].language);
446318334Speter
446418334Speter      if (cp)
446518334Speter	{
446618334Speter	  /* Ok, we found an applicable compiler.  Run its spec.  */
446718334Speter	  /* First say how much of input_filename to substitute for %b  */
446818334Speter	  register char *p;
446918334Speter	  int len;
447018334Speter
447118334Speter	  input_basename = input_filename;
447218334Speter	  for (p = input_filename; *p; p++)
447318334Speter	    if (*p == '/' || *p == DIR_SEPARATOR)
447418334Speter	      input_basename = p + 1;
447518334Speter
447618334Speter	  /* Find a suffix starting with the last period,
447718334Speter	     and set basename_length to exclude that suffix.  */
447818334Speter	  basename_length = strlen (input_basename);
447918334Speter	  p = input_basename + basename_length;
448018334Speter	  while (p != input_basename && *p != '.') --p;
448118334Speter	  if (*p == '.' && p != input_basename)
448218334Speter	    {
448318334Speter	      basename_length = p - input_basename;
448418334Speter	      input_suffix = p + 1;
448518334Speter	    }
448618334Speter	  else
448718334Speter	    input_suffix = "";
448818334Speter
448918334Speter	  len = 0;
449018334Speter	  for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++)
449118334Speter	    if (cp->spec[j])
449218334Speter	      len += strlen (cp->spec[j]);
449318334Speter
449418334Speter	  p = (char *) xmalloc (len + 1);
449518334Speter
449618334Speter	  len = 0;
449718334Speter	  for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++)
449818334Speter	    if (cp->spec[j])
449918334Speter	      {
450018334Speter		strcpy (p + len, cp->spec[j]);
450118334Speter		len += strlen (cp->spec[j]);
450218334Speter	      }
450318334Speter
450418334Speter	  value = do_spec (p);
450518334Speter	  free (p);
450618334Speter	  if (value < 0)
450718334Speter	    this_file_error = 1;
450818334Speter	}
450918334Speter
451018334Speter      /* If this file's name does not contain a recognized suffix,
451118334Speter	 record it as explicit linker input.  */
451218334Speter
451318334Speter      else
451418334Speter	explicit_link_files[i] = 1;
451518334Speter
451618334Speter      /* Clear the delete-on-failure queue, deleting the files in it
451718334Speter	 if this compilation failed.  */
451818334Speter
451918334Speter      if (this_file_error)
452018334Speter	{
452118334Speter	  delete_failure_queue ();
452218334Speter	  error_count++;
452318334Speter	}
452418334Speter      /* If this compilation succeeded, don't delete those files later.  */
452518334Speter      clear_failure_queue ();
452618334Speter    }
452718334Speter
452818334Speter  /* Run ld to link all the compiler output files.  */
452918334Speter
453018334Speter  if (error_count == 0)
453118334Speter    {
453218334Speter      int tmp = execution_count;
453318334Speter      int i;
453418334Speter      int first_time;
453518334Speter
453618334Speter      /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
453718334Speter	 for collect.  */
453818334Speter      putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH=");
453918334Speter      putenv_from_prefixes (&startfile_prefixes, "LIBRARY_PATH=");
454018334Speter
454118334Speter      /* Build COLLECT_GCC_OPTIONS to have all of the options specified to
454218334Speter	 the compiler.  */
454318334Speter      obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
454418334Speter		    sizeof ("COLLECT_GCC_OPTIONS=")-1);
454518334Speter
454618334Speter      first_time = TRUE;
454718334Speter      for (i = 0; i < n_switches; i++)
454818334Speter	{
454918334Speter	  char **args;
455018334Speter	  if (!first_time)
455118334Speter	    obstack_grow (&collect_obstack, " ", 1);
455218334Speter
455318334Speter	  first_time = FALSE;
455418334Speter	  obstack_grow (&collect_obstack, "-", 1);
455518334Speter	  obstack_grow (&collect_obstack, switches[i].part1,
455618334Speter			strlen (switches[i].part1));
455718334Speter
455818334Speter	  for (args = switches[i].args; args && *args; args++)
455918334Speter	    {
456018334Speter	      obstack_grow (&collect_obstack, " ", 1);
456118334Speter	      obstack_grow (&collect_obstack, *args, strlen (*args));
456218334Speter	    }
456318334Speter	}
456418334Speter      obstack_grow (&collect_obstack, "\0", 1);
456518334Speter      putenv (obstack_finish (&collect_obstack));
456618334Speter
456718334Speter      value = do_spec (link_command_spec);
456818334Speter      if (value < 0)
456918334Speter	error_count = 1;
457018334Speter      linker_was_run = (tmp != execution_count);
457118334Speter    }
457218334Speter
457318334Speter  /* Warn if a -B option was specified but the prefix was never used.  */
457418334Speter  unused_prefix_warnings (&exec_prefixes);
457518334Speter  unused_prefix_warnings (&startfile_prefixes);
457618334Speter
457718334Speter  /* If options said don't run linker,
457818334Speter     complain about input files to be given to the linker.  */
457918334Speter
458018334Speter  if (! linker_was_run && error_count == 0)
458118334Speter    for (i = 0; i < n_infiles; i++)
458218334Speter      if (explicit_link_files[i])
458318334Speter	error ("%s: linker input file unused since linking not done",
458418334Speter	       outfiles[i]);
458518334Speter
458618334Speter  /* Delete some or all of the temporary files we made.  */
458718334Speter
458818334Speter  if (error_count)
458918334Speter    delete_failure_queue ();
459018334Speter  delete_temp_files ();
459118334Speter
459218334Speter  exit (error_count > 0 ? (signal_count ? 2 : 1) : 0);
459318334Speter  /* NOTREACHED */
459418334Speter  return 0;
459518334Speter}
459618334Speter
459718334Speter/* Find the proper compilation spec for the file name NAME,
459818334Speter   whose length is LENGTH.  LANGUAGE is the specified language,
459918334Speter   or 0 if none specified.  */
460018334Speter
460118334Speterstatic struct compiler *
460218334Speterlookup_compiler (name, length, language)
460318334Speter     char *name;
460418334Speter     int length;
460518334Speter     char *language;
460618334Speter{
460718334Speter  struct compiler *cp;
460818334Speter
460918334Speter  /* Look for the language, if one is spec'd.  */
461018334Speter  if (language != 0)
461118334Speter    {
461218334Speter      for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
461318334Speter	{
461418334Speter	  if (language != 0)
461518334Speter	    {
461618334Speter	      if (cp->suffix[0] == '@'
461718334Speter		  && !strcmp (cp->suffix + 1, language))
461818334Speter		return cp;
461918334Speter	    }
462018334Speter	}
462118334Speter      error ("language %s not recognized", language);
462218334Speter    }
462318334Speter
462418334Speter  /* Look for a suffix.  */
462518334Speter  for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
462618334Speter    {
462718334Speter      if (/* The suffix `-' matches only the file name `-'.  */
462818334Speter	  (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
462918334Speter	  ||
463018334Speter	  (strlen (cp->suffix) < length
463118334Speter	   /* See if the suffix matches the end of NAME.  */
463218334Speter#ifdef OS2
463318334Speter	   && (!strcmp (cp->suffix,
463418334Speter			name + length - strlen (cp->suffix))
463518334Speter	    || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
463618334Speter	     && !strcasecmp (cp->suffix,
463718334Speter			  name + length - strlen (cp->suffix)))))
463818334Speter#else
463918334Speter	   && !strcmp (cp->suffix,
464018334Speter		       name + length - strlen (cp->suffix))))
464118334Speter#endif
464218334Speter	{
464318334Speter	  if (cp->spec[0][0] == '@')
464418334Speter	    {
464518334Speter	      struct compiler *new;
464618334Speter	      /* An alias entry maps a suffix to a language.
464718334Speter		 Search for the language; pass 0 for NAME and LENGTH
464818334Speter		 to avoid infinite recursion if language not found.
464918334Speter		 Construct the new compiler spec.  */
465018334Speter	      language = cp->spec[0] + 1;
465118334Speter	      new = (struct compiler *) xmalloc (sizeof (struct compiler));
465218334Speter	      new->suffix = cp->suffix;
465318334Speter	      bcopy ((char *) lookup_compiler (NULL_PTR, 0, language)->spec,
465418334Speter		     (char *) new->spec, sizeof new->spec);
465518334Speter	      return new;
465618334Speter	    }
465718334Speter	  /* A non-alias entry: return it.  */
465818334Speter	  return cp;
465918334Speter	}
466018334Speter    }
466118334Speter
466218334Speter  return 0;
466318334Speter}
466418334Speter
466518334Speterchar *
466618334Speterxmalloc (size)
466718334Speter     unsigned size;
466818334Speter{
466918334Speter  register char *value = (char *) malloc (size);
467018334Speter  if (value == 0)
467118334Speter    fatal ("virtual memory exhausted");
467218334Speter  return value;
467318334Speter}
467418334Speter
467518334Speterchar *
467618334Speterxrealloc (ptr, size)
467718334Speter     char *ptr;
467818334Speter     unsigned size;
467918334Speter{
468018334Speter  register char *value = (char *) realloc (ptr, size);
468118334Speter  if (value == 0)
468218334Speter    fatal ("virtual memory exhausted");
468318334Speter  return value;
468418334Speter}
468518334Speter
468618334Speter/* Return a newly-allocated string whose contents concatenate those of s1, s2 */
468718334Speter
468818334Speterstatic char *
468918334Speterconcat (s1, s2)
469018334Speter     char *s1, *s2;
469118334Speter{
469218334Speter  int len1 = strlen (s1);
469318334Speter  int len2 = strlen (s2);
469418334Speter  char *result = xmalloc (len1 + len2 + 1);
469518334Speter
469618334Speter  strcpy (result, s1);
469718334Speter  strcpy (result + len1, s2);
469818334Speter  *(result + len1 + len2) = 0;
469918334Speter
470018334Speter  return result;
470118334Speter}
470218334Speter
470318334Speterstatic char *
470418334Speterconcat3 (s1, s2, s3)
470518334Speter     char *s1, *s2, *s3;
470618334Speter{
470718334Speter  return concat (concat (s1, s2), s3);
470818334Speter}
470918334Speter
471018334Speterstatic char *
471118334Speterconcat4 (s1, s2, s3, s4)
471218334Speter     char *s1, *s2, *s3, *s4;
471318334Speter{
471418334Speter  return concat (concat (s1, s2), concat (s3, s4));
471518334Speter}
471618334Speter
471718334Speterstatic char *
471818334Speterconcat6 (s1, s2, s3, s4, s5, s6)
471918334Speter     char *s1, *s2, *s3, *s4, *s5, *s6;
472018334Speter{
472118334Speter  return concat3 (concat (s1, s2), concat (s3, s4), concat (s5, s6));
472218334Speter}
472318334Speter
472418334Speterstatic char *
472518334Spetersave_string (s, len)
472618334Speter     char *s;
472718334Speter     int len;
472818334Speter{
472918334Speter  register char *result = xmalloc (len + 1);
473018334Speter
473118334Speter  bcopy (s, result, len);
473218334Speter  result[len] = 0;
473318334Speter  return result;
473418334Speter}
473518334Speter
473618334Speterstatic void
473718334Speterpfatal_with_name (name)
473818334Speter     char *name;
473918334Speter{
474018334Speter  char *s;
474118334Speter
474218334Speter  if (errno < sys_nerr)
474318334Speter    s = concat ("%s: ", my_strerror( errno ));
474418334Speter  else
474518334Speter    s = "cannot open `%s'";
474618334Speter  fatal (s, name);
474718334Speter}
474818334Speter
474918334Speterstatic void
475018334Speterperror_with_name (name)
475118334Speter     char *name;
475218334Speter{
475318334Speter  char *s;
475418334Speter
475518334Speter  if (errno < sys_nerr)
475618334Speter    s = concat ("%s: ", my_strerror( errno ));
475718334Speter  else
475818334Speter    s = "cannot open `%s'";
475918334Speter  error (s, name);
476018334Speter}
476118334Speter
476218334Speterstatic void
476318334Speterperror_exec (name)
476418334Speter     char *name;
476518334Speter{
476618334Speter  char *s;
476718334Speter
476818334Speter  if (errno < sys_nerr)
476918334Speter    s = concat ("installation problem, cannot exec `%s': ",
477018334Speter		my_strerror (errno));
477118334Speter  else
477218334Speter    s = "installation problem, cannot exec `%s'";
477318334Speter  error (s, name);
477418334Speter}
477518334Speter
477618334Speter/* More 'friendly' abort that prints the line and file.
477718334Speter   config.h can #define abort fancy_abort if you like that sort of thing.  */
477818334Speter
477918334Spetervoid
478018334Speterfancy_abort ()
478118334Speter{
478218334Speter  fatal ("Internal gcc abort.");
478318334Speter}
478418334Speter
478518334Speter#ifdef HAVE_VPRINTF
478618334Speter
478718334Speter/* Output an error message and exit */
478818334Speter
478918334Speterstatic void
479018334Speterfatal VPROTO((char *format, ...))
479118334Speter{
479218334Speter#ifndef __STDC__
479318334Speter  char *format;
479418334Speter#endif
479518334Speter  va_list ap;
479618334Speter
479718334Speter  VA_START (ap, format);
479818334Speter
479918334Speter#ifndef __STDC__
480018334Speter  format = va_arg (ap, char*);
480118334Speter#endif
480218334Speter
480318334Speter  fprintf (stderr, "%s: ", programname);
480418334Speter  vfprintf (stderr, format, ap);
480518334Speter  va_end (ap);
480618334Speter  fprintf (stderr, "\n");
480718334Speter  delete_temp_files ();
480818334Speter  exit (1);
480918334Speter}
481018334Speter
481118334Speterstatic void
481218334Spetererror VPROTO((char *format, ...))
481318334Speter{
481418334Speter#ifndef __STDC__
481518334Speter  char *format;
481618334Speter#endif
481718334Speter  va_list ap;
481818334Speter
481918334Speter  VA_START (ap, format);
482018334Speter
482118334Speter#ifndef __STDC__
482218334Speter  format = va_arg (ap, char*);
482318334Speter#endif
482418334Speter
482518334Speter  fprintf (stderr, "%s: ", programname);
482618334Speter  vfprintf (stderr, format, ap);
482718334Speter  va_end (ap);
482818334Speter
482918334Speter  fprintf (stderr, "\n");
483018334Speter}
483118334Speter
483218334Speter#else /* not HAVE_VPRINTF */
483318334Speter
483418334Speterstatic void
483518334Speterfatal (msg, arg1, arg2)
483618334Speter     char *msg, *arg1, *arg2;
483718334Speter{
483818334Speter  error (msg, arg1, arg2);
483918334Speter  delete_temp_files ();
484018334Speter  exit (1);
484118334Speter}
484218334Speter
484318334Speterstatic void
484418334Spetererror (msg, arg1, arg2)
484518334Speter     char *msg, *arg1, *arg2;
484618334Speter{
484718334Speter  fprintf (stderr, "%s: ", programname);
484818334Speter  fprintf (stderr, msg, arg1, arg2);
484918334Speter  fprintf (stderr, "\n");
485018334Speter}
485118334Speter
485218334Speter#endif /* not HAVE_VPRINTF */
485318334Speter
485418334Speter
485518334Speterstatic void
485618334Spetervalidate_all_switches ()
485718334Speter{
485818334Speter  struct compiler *comp;
485918334Speter  register char *p;
486018334Speter  register char c;
486118334Speter  struct spec_list *spec;
486218334Speter
486318334Speter  for (comp = compilers; comp->spec[0]; comp++)
486418334Speter    {
486518334Speter      int i;
486618334Speter      for (i = 0; i < sizeof comp->spec / sizeof comp->spec[0] && comp->spec[i]; i++)
486718334Speter	{
486818334Speter	  p = comp->spec[i];
486918334Speter	  while (c = *p++)
487018334Speter	    if (c == '%' && *p == '{')
487118334Speter	      /* We have a switch spec.  */
487218334Speter	      validate_switches (p + 1);
487318334Speter	}
487418334Speter    }
487518334Speter
487618334Speter  /* look through the linked list of extra specs read from the specs file */
487718334Speter  for (spec = specs; spec ; spec = spec->next)
487818334Speter    {
487918334Speter      p = spec->spec;
488018334Speter      while (c = *p++)
488118334Speter	if (c == '%' && *p == '{')
488218334Speter	  /* We have a switch spec.  */
488318334Speter	  validate_switches (p + 1);
488418334Speter    }
488518334Speter
488618334Speter  p = link_command_spec;
488718334Speter  while (c = *p++)
488818334Speter    if (c == '%' && *p == '{')
488918334Speter      /* We have a switch spec.  */
489018334Speter      validate_switches (p + 1);
489118334Speter
489218334Speter  /* Now notice switches mentioned in the machine-specific specs.  */
489318334Speter
489418334Speter  p = asm_spec;
489518334Speter  while (c = *p++)
489618334Speter    if (c == '%' && *p == '{')
489718334Speter      /* We have a switch spec.  */
489818334Speter      validate_switches (p + 1);
489918334Speter
490018334Speter  p = asm_final_spec;
490118334Speter  while (c = *p++)
490218334Speter    if (c == '%' && *p == '{')
490318334Speter      /* We have a switch spec.  */
490418334Speter      validate_switches (p + 1);
490518334Speter
490618334Speter  p = cpp_spec;
490718334Speter  while (c = *p++)
490818334Speter    if (c == '%' && *p == '{')
490918334Speter      /* We have a switch spec.  */
491018334Speter      validate_switches (p + 1);
491118334Speter
491218334Speter  p = signed_char_spec;
491318334Speter  while (c = *p++)
491418334Speter    if (c == '%' && *p == '{')
491518334Speter      /* We have a switch spec.  */
491618334Speter      validate_switches (p + 1);
491718334Speter
491818334Speter  p = cc1_spec;
491918334Speter  while (c = *p++)
492018334Speter    if (c == '%' && *p == '{')
492118334Speter      /* We have a switch spec.  */
492218334Speter      validate_switches (p + 1);
492318334Speter
492418334Speter  p = cc1plus_spec;
492518334Speter  while (c = *p++)
492618334Speter    if (c == '%' && *p == '{')
492718334Speter      /* We have a switch spec.  */
492818334Speter      validate_switches (p + 1);
492918334Speter
493018334Speter  p = link_spec;
493118334Speter  while (c = *p++)
493218334Speter    if (c == '%' && *p == '{')
493318334Speter      /* We have a switch spec.  */
493418334Speter      validate_switches (p + 1);
493518334Speter
493618334Speter  p = lib_spec;
493718334Speter  while (c = *p++)
493818334Speter    if (c == '%' && *p == '{')
493918334Speter      /* We have a switch spec.  */
494018334Speter      validate_switches (p + 1);
494118334Speter
494218334Speter  p = libgcc_spec;
494318334Speter  while (c = *p++)
494418334Speter    if (c == '%' && *p == '{')
494518334Speter      /* We have a switch spec.  */
494618334Speter      validate_switches (p + 1);
494718334Speter
494818334Speter  p = startfile_spec;
494918334Speter  while (c = *p++)
495018334Speter    if (c == '%' && *p == '{')
495118334Speter      /* We have a switch spec.  */
495218334Speter      validate_switches (p + 1);
495318334Speter}
495418334Speter
495518334Speter/* Look at the switch-name that comes after START
495618334Speter   and mark as valid all supplied switches that match it.  */
495718334Speter
495818334Speterstatic void
495918334Spetervalidate_switches (start)
496018334Speter     char *start;
496118334Speter{
496218334Speter  register char *p = start;
496318334Speter  char *filter;
496418334Speter  register int i;
496518334Speter  int suffix = 0;
496618334Speter
496718334Speter  if (*p == '|')
496818334Speter    ++p;
496918334Speter
497018334Speter  if (*p == '!')
497118334Speter    ++p;
497218334Speter
497318334Speter  if (*p == '.')
497418334Speter    suffix = 1, ++p;
497518334Speter
497618334Speter  filter = p;
497718334Speter  while (*p != ':' && *p != '}') p++;
497818334Speter
497918334Speter  if (suffix)
498018334Speter    ;
498118334Speter  else if (p[-1] == '*')
498218334Speter    {
498318334Speter      /* Mark all matching switches as valid.  */
498418334Speter      --p;
498518334Speter      for (i = 0; i < n_switches; i++)
498618334Speter	if (!strncmp (switches[i].part1, filter, p - filter))
498718334Speter	  switches[i].valid = 1;
498818334Speter    }
498918334Speter  else
499018334Speter    {
499118334Speter      /* Mark an exact matching switch as valid.  */
499218334Speter      for (i = 0; i < n_switches; i++)
499318334Speter	{
499418334Speter	  if (!strncmp (switches[i].part1, filter, p - filter)
499518334Speter	      && switches[i].part1[p - filter] == 0)
499618334Speter	    switches[i].valid = 1;
499718334Speter	}
499818334Speter    }
499918334Speter}
500018334Speter
500118334Speter/* Check whether a particular argument was used.  */
500218334Speter
500318334Speterstatic int
500418334Speterused_arg (p, len)
500518334Speter     char *p;
500618334Speter     int len;
500718334Speter{
500818334Speter  int i;
500918334Speter
501018334Speter  for (i = 0; i < n_switches; i++)
501118334Speter    if (! strncmp (switches[i].part1, p, len)
501218334Speter	&& strlen (switches[i].part1) == len)
501318334Speter      return 1;
501418334Speter  return 0;
501518334Speter}
501618334Speter
501718334Speter/* Check whether a particular argument is a default argument.  */
501818334Speter
501918334Speter#ifndef MULTILIB_DEFAULTS
502018334Speter#define MULTILIB_DEFAULTS { NULL }
502118334Speter#endif
502218334Speter
502318334Speterstatic char *multilib_defaults[] = MULTILIB_DEFAULTS;
502418334Speter
502518334Speterstatic int
502618334Speterdefault_arg (p, len)
502718334Speter     char *p;
502818334Speter     int len;
502918334Speter{
503018334Speter  int count = sizeof multilib_defaults / sizeof multilib_defaults[0];
503118334Speter  int i;
503218334Speter
503318334Speter  for (i = 0; i < count; i++)
503418334Speter    if (multilib_defaults[i] != NULL
503518334Speter	&& strncmp (multilib_defaults[i], p, len) == 0
503618334Speter	&& multilib_defaults[i][len] == '\0')
503718334Speter      return 1;
503818334Speter
503918334Speter  return 0;
504018334Speter}
504118334Speter
504218334Speter/* Work out the subdirectory to use based on the
504318334Speter   options.  The format of multilib_select is a list of elements.
504418334Speter   Each element is a subdirectory name followed by a list of options
504518334Speter   followed by a semicolon.  gcc will consider each line in turn.  If
504618334Speter   none of the options beginning with an exclamation point are
504718334Speter   present, and all of the other options are present, that
504818334Speter   subdirectory will be used.  */
504918334Speter
505018334Speterstatic void
505118334Speterset_multilib_dir ()
505218334Speter{
505318334Speter  char *p = multilib_select;
505418334Speter  int this_path_len;
505518334Speter  char *this_path, *this_arg;
505618334Speter  int not_arg;
505718334Speter  int ok;
505818334Speter
505918334Speter  while (*p != '\0')
506018334Speter    {
506118334Speter      /* Ignore newlines.  */
506218334Speter      if (*p == '\n')
506318334Speter	{
506418334Speter	  ++p;
506518334Speter	  continue;
506618334Speter	}
506718334Speter
506818334Speter      /* Get the initial path.  */
506918334Speter      this_path = p;
507018334Speter      while (*p != ' ')
507118334Speter	{
507218334Speter	  if (*p == '\0')
507318334Speter	    abort ();
507418334Speter	  ++p;
507518334Speter	}
507618334Speter      this_path_len = p - this_path;
507718334Speter
507818334Speter      /* Check the arguments.  */
507918334Speter      ok = 1;
508018334Speter      ++p;
508118334Speter      while (*p != ';')
508218334Speter	{
508318334Speter	  if (*p == '\0')
508418334Speter	    abort ();
508518334Speter
508618334Speter	  if (! ok)
508718334Speter	    {
508818334Speter	      ++p;
508918334Speter	      continue;
509018334Speter	    }
509118334Speter
509218334Speter	  this_arg = p;
509318334Speter	  while (*p != ' ' && *p != ';')
509418334Speter	    {
509518334Speter	      if (*p == '\0')
509618334Speter		abort ();
509718334Speter	      ++p;
509818334Speter	    }
509918334Speter
510018334Speter	  if (*this_arg != '!')
510118334Speter	    not_arg = 0;
510218334Speter	  else
510318334Speter	    {
510418334Speter	      not_arg = 1;
510518334Speter	      ++this_arg;
510618334Speter	    }
510718334Speter
510818334Speter	  /* If this is a default argument, we can just ignore it.
510918334Speter	     This is true even if this_arg begins with '!'.  Beginning
511018334Speter	     with '!' does not mean that this argument is necessarily
511118334Speter	     inappropriate for this library: it merely means that
511218334Speter	     there is a more specific library which uses this
511318334Speter	     argument.  If this argument is a default, we need not
511418334Speter	     consider that more specific library.  */
511518334Speter	  if (! default_arg (this_arg, p - this_arg))
511618334Speter	    {
511718334Speter	      ok = used_arg (this_arg, p - this_arg);
511818334Speter	      if (not_arg)
511918334Speter		ok = ! ok;
512018334Speter	    }
512118334Speter
512218334Speter	  if (*p == ' ')
512318334Speter	    ++p;
512418334Speter	}
512518334Speter
512618334Speter      if (ok)
512718334Speter	{
512818334Speter	  if (this_path_len != 1
512918334Speter	      || this_path[0] != '.')
513018334Speter	    {
513118334Speter	      multilib_dir = xmalloc (this_path_len + 1);
513218334Speter	      strncpy (multilib_dir, this_path, this_path_len);
513318334Speter	      multilib_dir[this_path_len] = '\0';
513418334Speter	    }
513518334Speter	  break;
513618334Speter	}
513718334Speter
513818334Speter      ++p;
513918334Speter    }
514018334Speter}
514118334Speter
514218334Speter/* Print out the multiple library subdirectory selection
514318334Speter   information.  This prints out a series of lines.  Each line looks
514418334Speter   like SUBDIRECTORY;@OPTION@OPTION, with as many options as is
514518334Speter   required.  Only the desired options are printed out, the negative
514618334Speter   matches.  The options are print without a leading dash.  There are
514718334Speter   no spaces to make it easy to use the information in the shell.
514818334Speter   Each subdirectory is printed only once.  This assumes the ordering
514918334Speter   generated by the genmultilib script.  */
515018334Speter
515118334Speterstatic void
515218334Speterprint_multilib_info ()
515318334Speter{
515418334Speter  char *p = multilib_select;
515518334Speter  char *last_path = 0, *this_path;
515618334Speter  int skip;
515718334Speter  int last_path_len = 0;
515818334Speter
515918334Speter  while (*p != '\0')
516018334Speter    {
516118334Speter      /* Ignore newlines.  */
516218334Speter      if (*p == '\n')
516318334Speter	{
516418334Speter	  ++p;
516518334Speter	  continue;
516618334Speter	}
516718334Speter
516818334Speter      /* Get the initial path.  */
516918334Speter      this_path = p;
517018334Speter      while (*p != ' ')
517118334Speter	{
517218334Speter	  if (*p == '\0')
517318334Speter	    abort ();
517418334Speter	  ++p;
517518334Speter	}
517618334Speter
517718334Speter      /* If this is a duplicate, skip it.  */
517818334Speter      skip = (last_path != 0 && p - this_path == last_path_len
517918334Speter	      && ! strncmp (last_path, this_path, last_path_len));
518018334Speter
518118334Speter      last_path = this_path;
518218334Speter      last_path_len = p - this_path;
518318334Speter
518418334Speter      /* If this directory requires any default arguments, we can skip
518518334Speter	 it.  We will already have printed a directory identical to
518618334Speter	 this one which does not require that default argument.  */
518718334Speter      if (! skip)
518818334Speter	{
518918334Speter	  char *q;
519018334Speter
519118334Speter	  q = p + 1;
519218334Speter	  while (*q != ';')
519318334Speter	    {
519418334Speter	      char *arg;
519518334Speter
519618334Speter	      if (*q == '\0')
519718334Speter		abort ();
519818334Speter
519918334Speter	      if (*q == '!')
520018334Speter		arg = NULL;
520118334Speter	      else
520218334Speter		arg = q;
520318334Speter
520418334Speter	      while (*q != ' ' && *q != ';')
520518334Speter		{
520618334Speter		  if (*q == '\0')
520718334Speter		    abort ();
520818334Speter		  ++q;
520918334Speter		}
521018334Speter
521118334Speter	      if (arg != NULL
521218334Speter		  && default_arg (arg, q - arg))
521318334Speter		{
521418334Speter		  skip = 1;
521518334Speter		  break;
521618334Speter		}
521718334Speter
521818334Speter	      if (*q == ' ')
521918334Speter		++q;
522018334Speter	    }
522118334Speter	}
522218334Speter
522318334Speter      if (! skip)
522418334Speter	{
522518334Speter	  char *p1;
522618334Speter
522718334Speter	  for (p1 = last_path; p1 < p; p1++)
522818334Speter	    putchar (*p1);
522918334Speter	  putchar (';');
523018334Speter	}
523118334Speter
523218334Speter      ++p;
523318334Speter      while (*p != ';')
523418334Speter	{
523518334Speter	  int use_arg;
523618334Speter
523718334Speter	  if (*p == '\0')
523818334Speter	    abort ();
523918334Speter
524018334Speter	  if (skip)
524118334Speter	    {
524218334Speter	      ++p;
524318334Speter	      continue;
524418334Speter	    }
524518334Speter
524618334Speter	  use_arg = *p != '!';
524718334Speter
524818334Speter	  if (use_arg)
524918334Speter	    putchar ('@');
525018334Speter
525118334Speter	  while (*p != ' ' && *p != ';')
525218334Speter	    {
525318334Speter	      if (*p == '\0')
525418334Speter		abort ();
525518334Speter	      if (use_arg)
525618334Speter		putchar (*p);
525718334Speter	      ++p;
525818334Speter	    }
525918334Speter
526018334Speter	  if (*p == ' ')
526118334Speter	    ++p;
526218334Speter	}
526318334Speter
526418334Speter      if (! skip)
526518334Speter	putchar ('\n');
526618334Speter
526718334Speter      ++p;
526818334Speter    }
526918334Speter}
5270