158997Selan /* Compiler driver program that can handle many languages.
258997Selan Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
358997Selan
458997Selan This file is part of GNU CC.
558997Selan
658997Selan GNU CC is free software; you can redistribute it and/or modify
758997Selan it under the terms of the GNU General Public License as published by
858997Selan the Free Software Foundation; either version 2, or (at your option)
958997Selan any later version.
1058997Selan
1158997Selan GNU CC is distributed in the hope that it will be useful,
1258997Selan but WITHOUT ANY WARRANTY; without even the implied warranty of
1358997Selan MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1458997Selan GNU General Public License for more details.
1558997Selan
1658997Selan You should have received a copy of the GNU General Public License
1758997Selan along with GNU CC; see the file COPYING. If not, write to
1858997Selan the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
1958997Selan
2058997Selan This paragraph is here to try to keep Sun CC from dying.
2158997Selan The number of chars here seems crucial!!!! */
2258997Selan
2358997Selan /* This program is the user interface to the C compiler and possibly to
2458997Selan other compilers. It is used because compilation is a complicated procedure
2558997Selan which involves running several programs and passing temporary files between
2658997Selan them, forwarding the users switches to those programs selectively,
2758997Selan and deleting the temporary files at the end.
2858997Selan
2958997Selan CC recognizes how to compile each input file by suffixes in the file names.
3058997Selan Once it knows which kind of compilation to perform, the procedure for
3158997Selan compilation is specified by a string called a "spec". */
3258997Selan
3358997Selan #include <sys/types.h>
3458997Selan #include <ctype.h>
3558997Selan #include <signal.h>
3658997Selan #include <sys/stat.h>
3758997Selan #include <sys/file.h> /* May get R_OK, etc. on some systems. */
3858997Selan
3958997Selan #include "config.h"
4058997Selan #include "obstack.h"
4158997Selan #include "gvarargs.h"
4258997Selan #include <stdio.h>
4358997Selan
4458997Selan #ifndef R_OK
4558997Selan #define R_OK 4
4658997Selan #define W_OK 2
4758997Selan #define X_OK 1
4858997Selan #endif
4958997Selan
5058997Selan /* Define a generic NULL if one hasn't already been defined. */
5158997Selan
5258997Selan #ifndef NULL
5358997Selan #define NULL 0
5458997Selan #endif
5558997Selan
5658997Selan #ifndef GENERIC_PTR
5758997Selan #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
5858997Selan #define GENERIC_PTR void *
5958997Selan #else
6058997Selan #define GENERIC_PTR char *
6158997Selan #endif
6258997Selan #endif
6358997Selan
6458997Selan #ifndef NULL_PTR
6558997Selan #define NULL_PTR ((GENERIC_PTR)0)
6658997Selan #endif
6758997Selan
6858997Selan #ifdef USG
6958997Selan #define vfork fork
7058997Selan #endif /* USG */
7158997Selan
7258997Selan /* On MSDOS, write temp files in current dir
7358997Selan because there's no place else we can expect to use. */
7458997Selan #if __MSDOS__
7558997Selan #ifndef P_tmpdir
7658997Selan #define P_tmpdir "./"
7758997Selan #endif
7858997Selan #endif
7958997Selan
8058997Selan /* Test if something is a normal file. */
8158997Selan #ifndef S_ISREG
8258997Selan #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
8358997Selan #endif
8458997Selan
8558997Selan /* Test if something is a directory. */
8658997Selan #ifndef S_ISDIR
8758997Selan #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
8858997Selan #endif
8958997Selan
9058997Selan /* By default there is no special suffix for executables. */
9158997Selan #ifndef EXECUTABLE_SUFFIX
9258997Selan #define EXECUTABLE_SUFFIX ""
9358997Selan #endif
9458997Selan
9558997Selan /* By default, colon separates directories in a path. */
9658997Selan #ifndef PATH_SEPARATOR
9758997Selan #define PATH_SEPARATOR ':'
9858997Selan #endif
9958997Selan
10058997Selan #define obstack_chunk_alloc xmalloc
10158997Selan #define obstack_chunk_free free
10258997Selan
10358997Selan extern void free ();
10458997Selan extern char *getenv ();
10558997Selan
10658997Selan extern int errno, sys_nerr;
107*60377Selan extern const char *const sys_errlist[];
10858997Selan
10958997Selan extern int execv (), execvp ();
11058997Selan
11158997Selan /* If a stage of compilation returns an exit status >= 1,
11258997Selan compilation of that file ceases. */
11358997Selan
11458997Selan #define MIN_FATAL_STATUS 1
11558997Selan
11658997Selan /* Flag saying to print the full filename of libgcc.a
11758997Selan as found through our usual search mechanism. */
11858997Selan
11958997Selan static int print_libgcc_file_name;
12058997Selan
12158997Selan /* Flag indicating whether we should print the command and arguments */
12258997Selan
12358997Selan static int verbose_flag;
12458997Selan
12558997Selan /* Nonzero means write "temp" files in source directory
12658997Selan and use the source file's name in them, and don't delete them. */
12758997Selan
12858997Selan static int save_temps_flag;
12958997Selan
13058997Selan /* The compiler version specified with -V */
13158997Selan
13258997Selan static char *spec_version;
13358997Selan
13458997Selan /* The target machine specified with -b. */
13558997Selan
13658997Selan static char *spec_machine = DEFAULT_TARGET_MACHINE;
13758997Selan
13858997Selan /* Nonzero if cross-compiling.
13958997Selan When -b is used, the value comes from the `specs' file. */
14058997Selan
14158997Selan #ifdef CROSS_COMPILE
14258997Selan static int cross_compile = 1;
14358997Selan #else
14458997Selan static int cross_compile = 0;
14558997Selan #endif
14658997Selan
14758997Selan /* This is the obstack which we use to allocate many strings. */
14858997Selan
14958997Selan static struct obstack obstack;
15058997Selan
15158997Selan /* This is the obstack to build an environment variable to pass to
15258997Selan collect2 that describes all of the relevant switches of what to
15358997Selan pass the compiler in building the list of pointers to constructors
15458997Selan and destructors. */
15558997Selan
15658997Selan static struct obstack collect_obstack;
15758997Selan
15858997Selan extern char *version_string;
15958997Selan
16058997Selan static void set_spec ();
16158997Selan static struct compiler *lookup_compiler ();
16258997Selan static char *find_a_file ();
16358997Selan static void add_prefix ();
16458997Selan static char *skip_whitespace ();
16558997Selan static void record_temp_file ();
16658997Selan static char *handle_braces ();
16758997Selan static char *save_string ();
16858997Selan static char *concat ();
16958997Selan static int do_spec ();
17058997Selan static int do_spec_1 ();
17158997Selan static char *find_file ();
17258997Selan static int is_linker_dir ();
17358997Selan static void validate_switches ();
17458997Selan static void validate_all_switches ();
17558997Selan static void give_switch ();
17658997Selan static void pfatal_with_name ();
17758997Selan static void perror_with_name ();
17858997Selan static void perror_exec ();
17958997Selan static void fatal ();
18058997Selan static void error ();
18158997Selan void fancy_abort ();
18258997Selan char *xmalloc ();
18358997Selan char *xrealloc ();
18458997Selan
18558997Selan /* Specs are strings containing lines, each of which (if not blank)
18658997Selan is made up of a program name, and arguments separated by spaces.
18758997Selan The program name must be exact and start from root, since no path
18858997Selan is searched and it is unreliable to depend on the current working directory.
18958997Selan Redirection of input or output is not supported; the subprograms must
19058997Selan accept filenames saying what files to read and write.
19158997Selan
19258997Selan In addition, the specs can contain %-sequences to substitute variable text
19358997Selan or for conditional text. Here is a table of all defined %-sequences.
19458997Selan Note that spaces are not generated automatically around the results of
19558997Selan expanding these sequences; therefore, you can concatenate them together
19658997Selan or with constant text in a single argument.
19758997Selan
19858997Selan %% substitute one % into the program name or argument.
19958997Selan %i substitute the name of the input file being processed.
20058997Selan %b substitute the basename of the input file being processed.
20158997Selan This is the substring up to (and not including) the last period
20258997Selan and not including the directory.
20358997Selan %g substitute the temporary-file-name-base. This is a string chosen
20458997Selan once per compilation. Different temporary file names are made by
20558997Selan concatenation of constant strings on the end, as in `%g.s'.
20658997Selan %g also has the same effect of %d.
20758997Selan %u like %g, but make the temporary file name unique.
20858997Selan %U returns the last file name generated with %u.
20958997Selan %d marks the argument containing or following the %d as a
21058997Selan temporary file name, so that that file will be deleted if CC exits
21158997Selan successfully. Unlike %g, this contributes no text to the argument.
21258997Selan %w marks the argument containing or following the %w as the
21358997Selan "output file" of this compilation. This puts the argument
21458997Selan into the sequence of arguments that %o will substitute later.
21558997Selan %W{...}
21658997Selan like %{...} but mark last argument supplied within
21758997Selan as a file to be deleted on failure.
21858997Selan %o substitutes the names of all the output files, with spaces
21958997Selan automatically placed around them. You should write spaces
22058997Selan around the %o as well or the results are undefined.
22158997Selan %o is for use in the specs for running the linker.
22258997Selan Input files whose names have no recognized suffix are not compiled
22358997Selan at all, but they are included among the output files, so they will
22458997Selan be linked.
22558997Selan %p substitutes the standard macro predefinitions for the
22658997Selan current target machine. Use this when running cpp.
22758997Selan %P like %p, but puts `__' before and after the name of each macro.
22858997Selan (Except macros that already have __.)
22958997Selan This is for ANSI C.
23058997Selan %I Substitute a -iprefix option made from GCC_EXEC_PREFIX.
23158997Selan %s current argument is the name of a library or startup file of some sort.
23258997Selan Search for that file in a standard list of directories
23358997Selan and substitute the full name found.
23458997Selan %eSTR Print STR as an error message. STR is terminated by a newline.
23558997Selan Use this when inconsistent options are detected.
23658997Selan %x{OPTION} Accumulate an option for %X.
23758997Selan %X Output the accumulated linker options specified by compilations.
23858997Selan %Y Output the accumulated assembler options specified by compilations.
23958997Selan %a process ASM_SPEC as a spec.
24058997Selan This allows config.h to specify part of the spec for running as.
24158997Selan %A process ASM_FINAL_SPEC as a spec. A capital A is actually
24258997Selan used here. This can be used to run a post-processor after the
24358997Selan assembler has done it's job.
24458997Selan %D Dump out a -L option for each directory in library_prefix,
24558997Selan followed by a -L option for each directory in startfile_prefix.
24658997Selan %l process LINK_SPEC as a spec.
24758997Selan %L process LIB_SPEC as a spec.
24858997Selan %S process STARTFILE_SPEC as a spec. A capital S is actually used here.
24958997Selan %E process ENDFILE_SPEC as a spec. A capital E is actually used here.
25058997Selan %c process SIGNED_CHAR_SPEC as a spec.
25158997Selan %C process CPP_SPEC as a spec. A capital C is actually used here.
25258997Selan %1 process CC1_SPEC as a spec.
25358997Selan %2 process CC1PLUS_SPEC as a spec.
25458997Selan %* substitute the variable part of a matched option. (See below.)
25558997Selan Note that each comma in the substituted string is replaced by
25658997Selan a single space.
25758997Selan %{S} substitutes the -S switch, if that switch was given to CC.
25858997Selan If that switch was not specified, this substitutes nothing.
25958997Selan Here S is a metasyntactic variable.
26058997Selan %{S*} substitutes all the switches specified to CC whose names start
26158997Selan with -S. This is used for -o, -D, -I, etc; switches that take
26258997Selan arguments. CC considers `-o foo' as being one switch whose
26358997Selan name starts with `o'. %{o*} would substitute this text,
26458997Selan including the space; thus, two arguments would be generated.
26558997Selan %{S*:X} substitutes X if one or more switches whose names start with -S are
26658997Selan specified to CC. Note that the tail part of the -S option
26758997Selan (i.e. the part matched by the `*') will be substituted for each
26858997Selan occurrence of %* within X.
26958997Selan %{S:X} substitutes X, but only if the -S switch was given to CC.
27058997Selan %{!S:X} substitutes X, but only if the -S switch was NOT given to CC.
27158997Selan %{|S:X} like %{S:X}, but if no S switch, substitute `-'.
27258997Selan %{|!S:X} like %{!S:X}, but if there is an S switch, substitute `-'.
27358997Selan %{.S:X} substitutes X, but only if processing a file with suffix S.
27458997Selan %{!.S:X} substitutes X, but only if NOT processing a file with suffix S.
27558997Selan %(Spec) processes a specification defined in a specs file as *Spec:
27658997Selan %[Spec] as above, but put __ around -D arguments
27758997Selan
27858997Selan The conditional text X in a %{S:X} or %{!S:X} construct may contain
27958997Selan other nested % constructs or spaces, or even newlines. They are
28058997Selan processed as usual, as described above.
28158997Selan
28258997Selan The character | is used to indicate that a command should be piped to
28358997Selan the following command, but only if -pipe is specified.
28458997Selan
28558997Selan Note that it is built into CC which switches take arguments and which
28658997Selan do not. You might think it would be useful to generalize this to
28758997Selan allow each compiler's spec to say which switches take arguments. But
28858997Selan this cannot be done in a consistent fashion. CC cannot even decide
28958997Selan which input files have been specified without knowing which switches
29058997Selan take arguments, and it must know which input files to compile in order
29158997Selan to tell which compilers to run.
29258997Selan
29358997Selan CC also knows implicitly that arguments starting in `-l' are to be
29458997Selan treated as compiler output files, and passed to the linker in their
29558997Selan proper position among the other output files. */
29658997Selan
29758997Selan /* Define the macros used for specs %a, %l, %L, %S, %c, %C, %1. */
29858997Selan
29958997Selan /* config.h can define ASM_SPEC to provide extra args to the assembler
30058997Selan or extra switch-translations. */
30158997Selan #ifndef ASM_SPEC
30258997Selan #define ASM_SPEC ""
30358997Selan #endif
30458997Selan
30558997Selan /* config.h can define ASM_FINAL_SPEC to run a post processor after
30658997Selan the assembler has run. */
30758997Selan #ifndef ASM_FINAL_SPEC
30858997Selan #define ASM_FINAL_SPEC ""
30958997Selan #endif
31058997Selan
31158997Selan /* config.h can define CPP_SPEC to provide extra args to the C preprocessor
31258997Selan or extra switch-translations. */
31358997Selan #ifndef CPP_SPEC
31458997Selan #define CPP_SPEC ""
31558997Selan #endif
31658997Selan
31758997Selan /* config.h can define CC1_SPEC to provide extra args to cc1 and cc1plus
31858997Selan or extra switch-translations. */
31958997Selan #ifndef CC1_SPEC
32058997Selan #define CC1_SPEC ""
32158997Selan #endif
32258997Selan
32358997Selan /* config.h can define CC1PLUS_SPEC to provide extra args to cc1plus
32458997Selan or extra switch-translations. */
32558997Selan #ifndef CC1PLUS_SPEC
32658997Selan #define CC1PLUS_SPEC ""
32758997Selan #endif
32858997Selan
32958997Selan /* config.h can define LINK_SPEC to provide extra args to the linker
33058997Selan or extra switch-translations. */
33158997Selan #ifndef LINK_SPEC
33258997Selan #define LINK_SPEC ""
33358997Selan #endif
33458997Selan
33558997Selan /* config.h can define LIB_SPEC to override the default libraries. */
33658997Selan #ifndef LIB_SPEC
33758997Selan #define LIB_SPEC "%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}"
33858997Selan #endif
33958997Selan
34058997Selan /* config.h can define STARTFILE_SPEC to override the default crt0 files. */
34158997Selan #ifndef STARTFILE_SPEC
34258997Selan #define STARTFILE_SPEC \
34358997Selan "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}"
34458997Selan #endif
34558997Selan
34658997Selan /* config.h can define SWITCHES_NEED_SPACES to control passing -o and -L.
34758997Selan Make the string nonempty to require spaces there. */
34858997Selan #ifndef SWITCHES_NEED_SPACES
34958997Selan #define SWITCHES_NEED_SPACES ""
35058997Selan #endif
35158997Selan
35258997Selan /* config.h can define ENDFILE_SPEC to override the default crtn files. */
35358997Selan #ifndef ENDFILE_SPEC
35458997Selan #define ENDFILE_SPEC ""
35558997Selan #endif
35658997Selan
35758997Selan /* This spec is used for telling cpp whether char is signed or not. */
35858997Selan #ifndef SIGNED_CHAR_SPEC
35958997Selan /* Use #if rather than ?:
36058997Selan because MIPS C compiler rejects like ?: in initializers. */
36158997Selan #if DEFAULT_SIGNED_CHAR
36258997Selan #define SIGNED_CHAR_SPEC "%{funsigned-char:-D__CHAR_UNSIGNED__}"
36358997Selan #else
36458997Selan #define SIGNED_CHAR_SPEC "%{!fsigned-char:-D__CHAR_UNSIGNED__}"
36558997Selan #endif
36658997Selan #endif
36758997Selan
36858997Selan static char *cpp_spec = CPP_SPEC;
36958997Selan static char *cpp_predefines = CPP_PREDEFINES;
37058997Selan static char *cc1_spec = CC1_SPEC;
37158997Selan static char *cc1plus_spec = CC1PLUS_SPEC;
37258997Selan static char *signed_char_spec = SIGNED_CHAR_SPEC;
37358997Selan static char *asm_spec = ASM_SPEC;
37458997Selan static char *asm_final_spec = ASM_FINAL_SPEC;
37558997Selan static char *link_spec = LINK_SPEC;
37658997Selan static char *lib_spec = LIB_SPEC;
37758997Selan static char *endfile_spec = ENDFILE_SPEC;
37858997Selan static char *startfile_spec = STARTFILE_SPEC;
37958997Selan static char *switches_need_spaces = SWITCHES_NEED_SPACES;
38058997Selan
38158997Selan /* This defines which switch letters take arguments. */
38258997Selan
38358997Selan #ifndef SWITCH_TAKES_ARG
38458997Selan #define SWITCH_TAKES_ARG(CHAR) \
38558997Selan ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
38658997Selan || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
38758997Selan || (CHAR) == 'I' || (CHAR) == 'm' \
38858997Selan || (CHAR) == 'L' || (CHAR) == 'A')
38958997Selan #endif
39058997Selan
39158997Selan /* This defines which multi-letter switches take arguments. */
39258997Selan
39358997Selan #ifndef WORD_SWITCH_TAKES_ARG
39458997Selan #define WORD_SWITCH_TAKES_ARG(STR) \
39558997Selan (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \
39658997Selan || !strcmp (STR, "Tbss") || !strcmp (STR, "include") \
39758997Selan || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info"))
39858997Selan #endif
39958997Selan
40058997Selan /* Record the mapping from file suffixes for compilation specs. */
40158997Selan
40258997Selan struct compiler
40358997Selan {
40458997Selan char *suffix; /* Use this compiler for input files
40558997Selan whose names end in this suffix. */
40658997Selan
40758997Selan char *spec[4]; /* To use this compiler, concatenate these
40858997Selan specs and pass to do_spec. */
40958997Selan };
41058997Selan
41158997Selan /* Pointer to a vector of `struct compiler' that gives the spec for
41258997Selan compiling a file, based on its suffix.
41358997Selan A file that does not end in any of these suffixes will be passed
41458997Selan unchanged to the loader and nothing else will be done to it.
41558997Selan
41658997Selan An entry containing two 0s is used to terminate the vector.
41758997Selan
41858997Selan If multiple entries match a file, the last matching one is used. */
41958997Selan
42058997Selan static struct compiler *compilers;
42158997Selan
42258997Selan /* Number of entries in `compilers', not counting the null terminator. */
42358997Selan
42458997Selan static int n_compilers;
42558997Selan
42658997Selan /* The default list of file name suffixes and their compilation specs. */
42758997Selan
42858997Selan static struct compiler default_compilers[] =
42958997Selan {
43058997Selan {".c", "@c"},
43158997Selan {"@c",
43258997Selan "cpp -lang-c %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
43358997Selan %{C:%{!E:%eGNU C does not support -C without using -E}}\
43458997Selan %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d}\
43558997Selan -undef -D__GNUC__=2 %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
43658997Selan %{!undef:%{!ansi:%p} %P} %{trigraphs} \
43758997Selan %c %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
43858997Selan %{traditional-cpp:-traditional}\
43958997Selan %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*}\
44058997Selan %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
44158997Selan "%{!M:%{!MM:%{!E:cc1 %{!pipe:%g.i} %1 \
44258997Selan %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a}\
44358997Selan %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
44458997Selan %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
44558997Selan %{aux-info*}\
44658997Selan %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
44758997Selan %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
44858997Selan %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\
44958997Selan %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o}\
45058997Selan %{!pipe:%g.s} %A\n }}}}"},
45158997Selan {"-",
45258997Selan "%{E:cpp -lang-c %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
45358997Selan %{C:%{!E:%eGNU C does not support -C without using -E}}\
45458997Selan %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d}\
45558997Selan -undef -D__GNUC__=2 %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
45658997Selan %{!undef:%{!ansi:%p} %P} %{trigraphs}\
45758997Selan %c %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
45858997Selan %{traditional-cpp:-traditional}\
45958997Selan %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*}\
46058997Selan %i %W{o*}}\
46158997Selan %{!E:%e-E required when input is from standard input}"},
46258997Selan {".m", "@objective-c"},
46358997Selan {"@objective-c",
46458997Selan "cpp -lang-objc %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
46558997Selan %{C:%{!E:%eGNU C does not support -C without using -E}}\
46658997Selan %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d}\
46758997Selan -undef -D__OBJC__ -D__GNUC__=2 %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
46858997Selan %{!undef:%{!ansi:%p} %P} %{trigraphs}\
46958997Selan %c %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
47058997Selan %{traditional-cpp:-traditional}\
47158997Selan %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*}\
47258997Selan %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
47358997Selan "%{!M:%{!MM:%{!E:cc1obj %{!pipe:%g.i} %1 \
47458997Selan %{!Q:-quiet} -dumpbase %b.m %{d*} %{m*} %{a}\
47558997Selan %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
47658997Selan %{traditional} %{v:-version} %{pg:-p} %{p} %{f*} \
47758997Selan -lang-objc %{gen-decls} \
47858997Selan %{aux-info*}\
47958997Selan %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
48058997Selan %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
48158997Selan %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\
48258997Selan %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o}\
48358997Selan %{!pipe:%g.s} %A\n }}}}"},
48458997Selan {".h", "@c-header"},
48558997Selan {"@c-header",
48658997Selan "%{!E:%eCompilation of header file requested} \
48758997Selan cpp %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
48858997Selan %{C:%{!E:%eGNU C does not support -C without using -E}}\
48958997Selan %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} \
49058997Selan -undef -D__GNUC__=2 %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
49158997Selan %{!undef:%{!ansi:%p} %P} %{trigraphs}\
49258997Selan %c %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
49358997Selan %{traditional-cpp:-traditional}\
49458997Selan %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*}\
49558997Selan %i %W{o*}"},
49658997Selan {".cc", "@c++"},
49758997Selan {".cxx", "@c++"},
49858997Selan {".C", "@c++"},
49958997Selan {"@c++",
50058997Selan "cpp -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
50158997Selan %{C:%{!E:%eGNU C++ does not support -C without using -E}}\
50258997Selan %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} \
50358997Selan -undef -D__GNUC__=2 -D__GNUG__=2 -D__cplusplus \
50458997Selan %{ansi:-trigraphs -$ -D__STRICT_ANSI__} %{!undef:%{!ansi:%p} %P}\
50558997Selan %c %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
50658997Selan %{traditional-cpp:-traditional} %{trigraphs}\
50758997Selan %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*}\
50858997Selan %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
50958997Selan "%{!M:%{!MM:%{!E:cc1plus %{!pipe:%g.i} %1 %2\
51058997Selan %{!Q:-quiet} -dumpbase %b.cc %{d*} %{m*} %{a}\
51158997Selan %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} %{traditional}\
51258997Selan %{v:-version} %{pg:-p} %{p} %{f*} %{+e*}\
51358997Selan %{aux-info*}\
51458997Selan %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
51558997Selan %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
51658997Selan %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\
51758997Selan %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o}\
51858997Selan %{!pipe:%g.s} %A\n }}}}"},
51958997Selan {".i", "@cpp-output"},
52058997Selan {"@cpp-output",
52158997Selan "cc1 %i %1 %{!Q:-quiet} %{d*} %{m*} %{a}\
52258997Selan %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} %{traditional}\
52358997Selan %{v:-version} %{pg:-p} %{p} %{f*}\
52458997Selan %{aux-info*}\
52558997Selan %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
52658997Selan %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
52758997Selan %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\
52858997Selan %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o} %{!pipe:%g.s} %A\n }"},
52958997Selan {".ii", "@c++-cpp-output"},
53058997Selan {"@c++-cpp-output",
53158997Selan "cc1plus %i %1 %2 %{!Q:-quiet} %{d*} %{m*} %{a}\
53258997Selan %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} %{traditional}\
53358997Selan %{v:-version} %{pg:-p} %{p} %{f*} %{+e*}\
53458997Selan %{aux-info*}\
53558997Selan %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
53658997Selan %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
53758997Selan %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\
53858997Selan %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o}\
53958997Selan %{!pipe:%g.s} %A\n }"},
54058997Selan {".s", "@assembler"},
54158997Selan {"@assembler",
54258997Selan "%{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\
54358997Selan %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o} %i %A\n }"},
54458997Selan {".S", "@assembler-with-cpp"},
54558997Selan {"@assembler-with-cpp",
54658997Selan "cpp -lang-asm %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
54758997Selan %{C:%{!E:%eGNU C does not support -C without using -E}}\
54858997Selan %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{trigraphs} \
54958997Selan -undef -$ %{!undef:%p %P} -D__ASSEMBLER__ \
55058997Selan %c %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
55158997Selan %{traditional-cpp:-traditional}\
55258997Selan %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*}\
55358997Selan %i %{!M:%{!MM:%{!E:%{!pipe:%g.s}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
55458997Selan "%{!M:%{!MM:%{!E:%{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\
55558997Selan %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o}\
55658997Selan %{!pipe:%g.s} %A\n }}}}"},
55758997Selan /* Mark end of table */
55858997Selan {0, 0}
55958997Selan };
56058997Selan
56158997Selan /* Number of elements in default_compilers, not counting the terminator. */
56258997Selan
56358997Selan static int n_default_compilers
56458997Selan = (sizeof default_compilers / sizeof (struct compiler)) - 1;
56558997Selan
56658997Selan /* Here is the spec for running the linker, after compiling all files. */
56758997Selan
56858997Selan /* -u* was put back because both BSD and SysV seem to support it. */
56958997Selan /* %{static:} simply prevents an error message if the target machine
57058997Selan doesn't handle -static. */
57158997Selan #ifdef LINK_LIBGCC_SPECIAL_1
57258997Selan /* Have gcc do the search for libgcc.a, but generate -L options as usual. */
57358997Selan static char *link_command_spec = "\
57458997Selan %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
57558997Selan %{r} %{s} %{T*} %{t} %{u*} %{x} %{z}\
57658997Selan %{!A:%{!nostdlib:%S}} %{static:}\
577*60377Selan %{L*} %D %o %{!nostdlib:%L libgcc.a%s %L %{!A:%E}}\n }}}}}";
57858997Selan #else
57958997Selan #ifdef LINK_LIBGCC_SPECIAL
58058997Selan /* Have gcc do the search for libgcc.a, and don't generate -L options. */
58158997Selan static char *link_command_spec = "\
58258997Selan %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
58358997Selan %{r} %{s} %{T*} %{t} %{u*} %{x} %{z}\
58458997Selan %{!A:%{!nostdlib:%S}} %{static:}\
585*60377Selan %{L*} %o %{!nostdlib:%L libgcc.a%s %L %{!A:%E}}\n }}}}}";
58658997Selan #else
58758997Selan /* Use -L and have the linker do the search for -lgcc. */
58858997Selan static char *link_command_spec = "\
58958997Selan %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
59058997Selan %{r} %{s} %{T*} %{t} %{u*} %{x} %{z}\
59158997Selan %{!A:%{!nostdlib:%S}} %{static:}\
592*60377Selan %{L*} %D %o %{!nostdlib:%L -lgcc %L %{!A:%E}}\n }}}}}";
59358997Selan #endif
59458997Selan #endif
59558997Selan
59658997Selan /* A vector of options to give to the linker.
59758997Selan These options are accumulated by -Xlinker and -Wl,
59858997Selan and substituted into the linker command with %X. */
59958997Selan static int n_linker_options;
60058997Selan static char **linker_options;
60158997Selan
60258997Selan /* A vector of options to give to the assembler.
60358997Selan These options are accumulated by -Wa,
60458997Selan and substituted into the assembler command with %X. */
60558997Selan static int n_assembler_options;
60658997Selan static char **assembler_options;
60758997Selan
60858997Selan /* Read compilation specs from a file named FILENAME,
60958997Selan replacing the default ones.
61058997Selan
61158997Selan A suffix which starts with `*' is a definition for
61258997Selan one of the machine-specific sub-specs. The "suffix" should be
61358997Selan *asm, *cc1, *cpp, *link, *startfile, *signed_char, etc.
61458997Selan The corresponding spec is stored in asm_spec, etc.,
61558997Selan rather than in the `compilers' vector.
61658997Selan
61758997Selan Anything invalid in the file is a fatal error. */
61858997Selan
61958997Selan static void
read_specs(filename)62058997Selan read_specs (filename)
62158997Selan char *filename;
62258997Selan {
62358997Selan int desc;
62458997Selan struct stat statbuf;
62558997Selan char *buffer;
62658997Selan register char *p;
62758997Selan
62858997Selan if (verbose_flag)
62958997Selan fprintf (stderr, "Reading specs from %s\n", filename);
63058997Selan
63158997Selan /* Open and stat the file. */
63258997Selan desc = open (filename, 0, 0);
63358997Selan if (desc < 0)
63458997Selan pfatal_with_name (filename);
63558997Selan if (stat (filename, &statbuf) < 0)
63658997Selan pfatal_with_name (filename);
63758997Selan
63858997Selan /* Read contents of file into BUFFER. */
63958997Selan buffer = xmalloc ((unsigned) statbuf.st_size + 1);
64058997Selan read (desc, buffer, (unsigned) statbuf.st_size);
64158997Selan buffer[statbuf.st_size] = 0;
64258997Selan close (desc);
64358997Selan
64458997Selan /* Scan BUFFER for specs, putting them in the vector. */
64558997Selan p = buffer;
64658997Selan while (1)
64758997Selan {
64858997Selan char *suffix;
64958997Selan char *spec;
65058997Selan char *in, *out, *p1, *p2;
65158997Selan
65258997Selan /* Advance P in BUFFER to the next nonblank nocomment line. */
65358997Selan p = skip_whitespace (p);
65458997Selan if (*p == 0)
65558997Selan break;
65658997Selan
65758997Selan /* Find the colon that should end the suffix. */
65858997Selan p1 = p;
65958997Selan while (*p1 && *p1 != ':' && *p1 != '\n') p1++;
66058997Selan /* The colon shouldn't be missing. */
66158997Selan if (*p1 != ':')
66258997Selan fatal ("specs file malformed after %d characters", p1 - buffer);
66358997Selan /* Skip back over trailing whitespace. */
66458997Selan p2 = p1;
66558997Selan while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t')) p2--;
66658997Selan /* Copy the suffix to a string. */
66758997Selan suffix = save_string (p, p2 - p);
66858997Selan /* Find the next line. */
66958997Selan p = skip_whitespace (p1 + 1);
67058997Selan if (p[1] == 0)
67158997Selan fatal ("specs file malformed after %d characters", p - buffer);
67258997Selan p1 = p;
67358997Selan /* Find next blank line. */
67458997Selan while (*p1 && !(*p1 == '\n' && p1[1] == '\n')) p1++;
67558997Selan /* Specs end at the blank line and do not include the newline. */
67658997Selan spec = save_string (p, p1 - p);
67758997Selan p = p1;
67858997Selan
67958997Selan /* Delete backslash-newline sequences from the spec. */
68058997Selan in = spec;
68158997Selan out = spec;
68258997Selan while (*in != 0)
68358997Selan {
68458997Selan if (in[0] == '\\' && in[1] == '\n')
68558997Selan in += 2;
68658997Selan else if (in[0] == '#')
68758997Selan {
68858997Selan while (*in && *in != '\n') in++;
68958997Selan }
69058997Selan else
69158997Selan *out++ = *in++;
69258997Selan }
69358997Selan *out = 0;
69458997Selan
69558997Selan if (suffix[0] == '*')
69658997Selan {
69758997Selan if (! strcmp (suffix, "*link_command"))
69858997Selan link_command_spec = spec;
69958997Selan else
70058997Selan set_spec (suffix + 1, spec);
70158997Selan }
70258997Selan else
70358997Selan {
70458997Selan /* Add this pair to the vector. */
70558997Selan compilers
70658997Selan = ((struct compiler *)
70758997Selan xrealloc (compilers, (n_compilers + 2) * sizeof (struct compiler)));
70858997Selan compilers[n_compilers].suffix = suffix;
70958997Selan bzero (compilers[n_compilers].spec,
71058997Selan sizeof compilers[n_compilers].spec);
71158997Selan compilers[n_compilers].spec[0] = spec;
71258997Selan n_compilers++;
71358997Selan }
71458997Selan
71558997Selan if (*suffix == 0)
71658997Selan link_command_spec = spec;
71758997Selan }
71858997Selan
71958997Selan if (link_command_spec == 0)
72058997Selan fatal ("spec file has no spec for linking");
72158997Selan }
72258997Selan
72358997Selan static char *
skip_whitespace(p)72458997Selan skip_whitespace (p)
72558997Selan char *p;
72658997Selan {
72758997Selan while (1)
72858997Selan {
72958997Selan /* A fully-blank line is a delimiter in the SPEC file and shouldn't
73058997Selan be considered whitespace. */
73158997Selan if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n')
73258997Selan return p + 1;
73358997Selan else if (*p == '\n' || *p == ' ' || *p == '\t')
73458997Selan p++;
73558997Selan else if (*p == '#')
73658997Selan {
73758997Selan while (*p != '\n') p++;
73858997Selan p++;
73958997Selan }
74058997Selan else
74158997Selan break;
74258997Selan }
74358997Selan
74458997Selan return p;
74558997Selan }
74658997Selan
74758997Selan /* Structure to keep track of the specs that have been defined so far. These
74858997Selan are accessed using %(specname) or %[specname] in a compiler or link spec. */
74958997Selan
75058997Selan struct spec_list
75158997Selan {
75258997Selan char *name; /* Name of the spec. */
75358997Selan char *spec; /* The spec itself. */
75458997Selan struct spec_list *next; /* Next spec in linked list. */
75558997Selan };
75658997Selan
75758997Selan /* List of specs that have been defined so far. */
75858997Selan
75958997Selan static struct spec_list *specs = (struct spec_list *) 0;
76058997Selan
76158997Selan /* Change the value of spec NAME to SPEC. If SPEC is empty, then the spec is
76258997Selan removed; If the spec starts with a + then SPEC is added to the end of the
76358997Selan current spec. */
76458997Selan
76558997Selan static void
set_spec(name,spec)76658997Selan set_spec (name, spec)
76758997Selan char *name;
76858997Selan char *spec;
76958997Selan {
77058997Selan struct spec_list *sl;
77158997Selan char *old_spec;
77258997Selan
77358997Selan /* See if the spec already exists */
77458997Selan for (sl = specs; sl; sl = sl->next)
77558997Selan if (strcmp (sl->name, name) == 0)
77658997Selan break;
77758997Selan
77858997Selan if (!sl)
77958997Selan {
78058997Selan /* Not found - make it */
78158997Selan sl = (struct spec_list *) xmalloc (sizeof (struct spec_list));
78258997Selan sl->name = save_string (name, strlen (name));
78358997Selan sl->spec = save_string ("", 0);
78458997Selan sl->next = specs;
78558997Selan specs = sl;
78658997Selan }
78758997Selan
78858997Selan old_spec = sl->spec;
78958997Selan if (name && spec[0] == '+' && isspace (spec[1]))
79058997Selan sl->spec = concat (old_spec, spec + 1, "");
79158997Selan else
79258997Selan sl->spec = save_string (spec, strlen (spec));
79358997Selan
79458997Selan if (! strcmp (name, "asm"))
79558997Selan asm_spec = sl->spec;
79658997Selan else if (! strcmp (name, "asm_final"))
79758997Selan asm_final_spec = sl->spec;
79858997Selan else if (! strcmp (name, "cc1"))
79958997Selan cc1_spec = sl->spec;
80058997Selan else if (! strcmp (name, "cc1plus"))
80158997Selan cc1plus_spec = sl->spec;
80258997Selan else if (! strcmp (name, "cpp"))
80358997Selan cpp_spec = sl->spec;
80458997Selan else if (! strcmp (name, "endfile"))
80558997Selan endfile_spec = sl->spec;
80658997Selan else if (! strcmp (name, "lib"))
80758997Selan lib_spec = sl->spec;
80858997Selan else if (! strcmp (name, "link"))
80958997Selan link_spec = sl->spec;
81058997Selan else if (! strcmp (name, "predefines"))
81158997Selan cpp_predefines = sl->spec;
81258997Selan else if (! strcmp (name, "signed_char"))
81358997Selan signed_char_spec = sl->spec;
81458997Selan else if (! strcmp (name, "startfile"))
81558997Selan startfile_spec = sl->spec;
81658997Selan else if (! strcmp (name, "switches_need_spaces"))
81758997Selan switches_need_spaces = sl->spec;
81858997Selan else if (! strcmp (name, "cross_compile"))
81958997Selan cross_compile = atoi (sl->spec);
82058997Selan /* Free the old spec */
82158997Selan if (old_spec)
82258997Selan free (old_spec);
82358997Selan }
82458997Selan
82558997Selan /* Accumulate a command (program name and args), and run it. */
82658997Selan
82758997Selan /* Vector of pointers to arguments in the current line of specifications. */
82858997Selan
82958997Selan static char **argbuf;
83058997Selan
83158997Selan /* Number of elements allocated in argbuf. */
83258997Selan
83358997Selan static int argbuf_length;
83458997Selan
83558997Selan /* Number of elements in argbuf currently in use (containing args). */
83658997Selan
83758997Selan static int argbuf_index;
83858997Selan
83958997Selan /* This is the list of suffixes and codes (%g/%u/%U) and the associated
84058997Selan temp file. Used only if MKTEMP_EACH_FILE. */
84158997Selan
84258997Selan static struct temp_name {
84358997Selan char *suffix; /* suffix associated with the code. */
84458997Selan int length; /* strlen (suffix). */
84558997Selan int unique; /* Indicates whether %g or %u/%U was used. */
84658997Selan char *filename; /* associated filename. */
84758997Selan int filename_length; /* strlen (filename). */
84858997Selan struct temp_name *next;
84958997Selan } *temp_names;
85058997Selan
85158997Selan /* Number of commands executed so far. */
85258997Selan
85358997Selan static int execution_count;
85458997Selan
85558997Selan /* Number of commands that exited with a signal. */
85658997Selan
85758997Selan static int signal_count;
85858997Selan
85958997Selan /* Name with which this program was invoked. */
86058997Selan
86158997Selan static char *programname;
86258997Selan
86358997Selan /* Structures to keep track of prefixes to try when looking for files. */
86458997Selan
86558997Selan struct prefix_list
86658997Selan {
86758997Selan char *prefix; /* String to prepend to the path. */
86858997Selan struct prefix_list *next; /* Next in linked list. */
86958997Selan int require_machine_suffix; /* Don't use without machine_suffix. */
87058997Selan /* 2 means try both machine_suffix and just_machine_suffix. */
87158997Selan int *used_flag_ptr; /* 1 if a file was found with this prefix. */
87258997Selan };
87358997Selan
87458997Selan struct path_prefix
87558997Selan {
87658997Selan struct prefix_list *plist; /* List of prefixes to try */
87758997Selan int max_len; /* Max length of a prefix in PLIST */
87858997Selan char *name; /* Name of this list (used in config stuff) */
87958997Selan };
88058997Selan
88158997Selan /* List of prefixes to try when looking for executables. */
88258997Selan
88358997Selan static struct path_prefix exec_prefix = { 0, 0, "exec" };
88458997Selan
88558997Selan /* List of prefixes to try when looking for startup (crt0) files. */
88658997Selan
88758997Selan static struct path_prefix startfile_prefix = { 0, 0, "startfile" };
88858997Selan
88958997Selan /* List of prefixes to try when looking for libraries. */
89058997Selan
89158997Selan static struct path_prefix library_prefix = { 0, 0, "libraryfile" };
89258997Selan
89358997Selan /* Suffix to attach to directories searched for commands.
89458997Selan This looks like `MACHINE/VERSION/'. */
89558997Selan
89658997Selan static char *machine_suffix = 0;
89758997Selan
89858997Selan /* Suffix to attach to directories searched for commands.
89958997Selan This is just `MACHINE/'. */
90058997Selan
90158997Selan static char *just_machine_suffix = 0;
90258997Selan
90358997Selan /* Adjusted value of GCC_EXEC_PREFIX envvar. */
90458997Selan
90558997Selan static char *gcc_exec_prefix;
90658997Selan
90758997Selan /* Default prefixes to attach to command names. */
90858997Selan
90958997Selan #ifdef CROSS_COMPILE /* Don't use these prefixes for a cross compiler. */
91058997Selan #undef MD_EXEC_PREFIX
91158997Selan #undef MD_STARTFILE_PREFIX
91258997Selan #undef MD_STARTFILE_PREFIX_1
91358997Selan #endif
91458997Selan
91558997Selan #ifndef STANDARD_EXEC_PREFIX
916*60377Selan #define STANDARD_EXEC_PREFIX "/usr/libexec/gcc2/"
91758997Selan #endif /* !defined STANDARD_EXEC_PREFIX */
91858997Selan
91958997Selan static char *standard_exec_prefix = STANDARD_EXEC_PREFIX;
92058997Selan static char *standard_exec_prefix_1 = "/usr/lib/gcc/";
92158997Selan #ifdef MD_EXEC_PREFIX
92258997Selan static char *md_exec_prefix = MD_EXEC_PREFIX;
92358997Selan #endif
92458997Selan
92558997Selan #ifndef STANDARD_STARTFILE_PREFIX
92658997Selan #define STANDARD_STARTFILE_PREFIX "/usr/local/lib/"
92758997Selan #endif /* !defined STANDARD_STARTFILE_PREFIX */
92858997Selan
92958997Selan #ifdef MD_STARTFILE_PREFIX
93058997Selan static char *md_startfile_prefix = MD_STARTFILE_PREFIX;
93158997Selan #endif
93258997Selan #ifdef MD_STARTFILE_PREFIX_1
93358997Selan static char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
93458997Selan #endif
93558997Selan static char *standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
93658997Selan static char *standard_startfile_prefix_1 = "/lib/";
93758997Selan static char *standard_startfile_prefix_2 = "/usr/lib/";
93858997Selan
93958997Selan /* Clear out the vector of arguments (after a command is executed). */
94058997Selan
94158997Selan static void
clear_args()94258997Selan clear_args ()
94358997Selan {
94458997Selan argbuf_index = 0;
94558997Selan }
94658997Selan
94758997Selan /* Add one argument to the vector at the end.
94858997Selan This is done when a space is seen or at the end of the line.
94958997Selan If DELETE_ALWAYS is nonzero, the arg is a filename
95058997Selan and the file should be deleted eventually.
95158997Selan If DELETE_FAILURE is nonzero, the arg is a filename
95258997Selan and the file should be deleted if this compilation fails. */
95358997Selan
95458997Selan static void
store_arg(arg,delete_always,delete_failure)95558997Selan store_arg (arg, delete_always, delete_failure)
95658997Selan char *arg;
95758997Selan int delete_always, delete_failure;
95858997Selan {
95958997Selan if (argbuf_index + 1 == argbuf_length)
96058997Selan {
96158997Selan argbuf = (char **) xrealloc (argbuf, (argbuf_length *= 2) * sizeof (char *));
96258997Selan }
96358997Selan
96458997Selan argbuf[argbuf_index++] = arg;
96558997Selan argbuf[argbuf_index] = 0;
96658997Selan
96758997Selan if (delete_always || delete_failure)
96858997Selan record_temp_file (arg, delete_always, delete_failure);
96958997Selan }
97058997Selan
97158997Selan /* Record the names of temporary files we tell compilers to write,
97258997Selan and delete them at the end of the run. */
97358997Selan
97458997Selan /* This is the common prefix we use to make temp file names.
97558997Selan It is chosen once for each run of this program.
97658997Selan It is substituted into a spec by %g.
97758997Selan Thus, all temp file names contain this prefix.
97858997Selan In practice, all temp file names start with this prefix.
97958997Selan
98058997Selan This prefix comes from the envvar TMPDIR if it is defined;
98158997Selan otherwise, from the P_tmpdir macro if that is defined;
98258997Selan otherwise, in /usr/tmp or /tmp. */
98358997Selan
98458997Selan static char *temp_filename;
98558997Selan
98658997Selan /* Length of the prefix. */
98758997Selan
98858997Selan static int temp_filename_length;
98958997Selan
99058997Selan /* Define the list of temporary files to delete. */
99158997Selan
99258997Selan struct temp_file
99358997Selan {
99458997Selan char *name;
99558997Selan struct temp_file *next;
99658997Selan };
99758997Selan
99858997Selan /* Queue of files to delete on success or failure of compilation. */
99958997Selan static struct temp_file *always_delete_queue;
100058997Selan /* Queue of files to delete on failure of compilation. */
100158997Selan static struct temp_file *failure_delete_queue;
100258997Selan
100358997Selan /* Record FILENAME as a file to be deleted automatically.
100458997Selan ALWAYS_DELETE nonzero means delete it if all compilation succeeds;
100558997Selan otherwise delete it in any case.
100658997Selan FAIL_DELETE nonzero means delete it if a compilation step fails;
100758997Selan otherwise delete it in any case. */
100858997Selan
100958997Selan static void
record_temp_file(filename,always_delete,fail_delete)101058997Selan record_temp_file (filename, always_delete, fail_delete)
101158997Selan char *filename;
101258997Selan int always_delete;
101358997Selan int fail_delete;
101458997Selan {
101558997Selan register char *name;
101658997Selan name = xmalloc (strlen (filename) + 1);
101758997Selan strcpy (name, filename);
101858997Selan
101958997Selan if (always_delete)
102058997Selan {
102158997Selan register struct temp_file *temp;
102258997Selan for (temp = always_delete_queue; temp; temp = temp->next)
102358997Selan if (! strcmp (name, temp->name))
102458997Selan goto already1;
102558997Selan temp = (struct temp_file *) xmalloc (sizeof (struct temp_file));
102658997Selan temp->next = always_delete_queue;
102758997Selan temp->name = name;
102858997Selan always_delete_queue = temp;
102958997Selan already1:;
103058997Selan }
103158997Selan
103258997Selan if (fail_delete)
103358997Selan {
103458997Selan register struct temp_file *temp;
103558997Selan for (temp = failure_delete_queue; temp; temp = temp->next)
103658997Selan if (! strcmp (name, temp->name))
103758997Selan goto already2;
103858997Selan temp = (struct temp_file *) xmalloc (sizeof (struct temp_file));
103958997Selan temp->next = failure_delete_queue;
104058997Selan temp->name = name;
104158997Selan failure_delete_queue = temp;
104258997Selan already2:;
104358997Selan }
104458997Selan }
104558997Selan
104658997Selan /* Delete all the temporary files whose names we previously recorded. */
104758997Selan
104858997Selan static void
delete_temp_files()104958997Selan delete_temp_files ()
105058997Selan {
105158997Selan register struct temp_file *temp;
105258997Selan
105358997Selan for (temp = always_delete_queue; temp; temp = temp->next)
105458997Selan {
105558997Selan #ifdef DEBUG
105658997Selan int i;
105758997Selan printf ("Delete %s? (y or n) ", temp->name);
105858997Selan fflush (stdout);
105958997Selan i = getchar ();
106058997Selan if (i != '\n')
106158997Selan while (getchar () != '\n') ;
106258997Selan if (i == 'y' || i == 'Y')
106358997Selan #endif /* DEBUG */
106458997Selan {
106558997Selan struct stat st;
106658997Selan if (stat (temp->name, &st) >= 0)
106758997Selan {
106858997Selan /* Delete only ordinary files. */
106958997Selan if (S_ISREG (st.st_mode))
107058997Selan if (unlink (temp->name) < 0)
107158997Selan if (verbose_flag)
107258997Selan perror_with_name (temp->name);
107358997Selan }
107458997Selan }
107558997Selan }
107658997Selan
107758997Selan always_delete_queue = 0;
107858997Selan }
107958997Selan
108058997Selan /* Delete all the files to be deleted on error. */
108158997Selan
108258997Selan static void
delete_failure_queue()108358997Selan delete_failure_queue ()
108458997Selan {
108558997Selan register struct temp_file *temp;
108658997Selan
108758997Selan for (temp = failure_delete_queue; temp; temp = temp->next)
108858997Selan {
108958997Selan #ifdef DEBUG
109058997Selan int i;
109158997Selan printf ("Delete %s? (y or n) ", temp->name);
109258997Selan fflush (stdout);
109358997Selan i = getchar ();
109458997Selan if (i != '\n')
109558997Selan while (getchar () != '\n') ;
109658997Selan if (i == 'y' || i == 'Y')
109758997Selan #endif /* DEBUG */
109858997Selan {
109958997Selan if (unlink (temp->name) < 0)
110058997Selan if (verbose_flag)
110158997Selan perror_with_name (temp->name);
110258997Selan }
110358997Selan }
110458997Selan }
110558997Selan
110658997Selan static void
clear_failure_queue()110758997Selan clear_failure_queue ()
110858997Selan {
110958997Selan failure_delete_queue = 0;
111058997Selan }
111158997Selan
111258997Selan /* Compute a string to use as the base of all temporary file names.
111358997Selan It is substituted for %g. */
111458997Selan
111558997Selan static void
choose_temp_base()111658997Selan choose_temp_base ()
111758997Selan {
111858997Selan char *base = getenv ("TMPDIR");
111958997Selan int len;
112058997Selan
112158997Selan if (base == (char *)0)
112258997Selan {
112358997Selan #ifdef P_tmpdir
112458997Selan if (access (P_tmpdir, R_OK | W_OK) == 0)
112558997Selan base = P_tmpdir;
112658997Selan #endif
112758997Selan if (base == (char *)0)
112858997Selan {
112958997Selan if (access ("/usr/tmp", R_OK | W_OK) == 0)
113058997Selan base = "/usr/tmp/";
113158997Selan else
113258997Selan base = "/tmp/";
113358997Selan }
113458997Selan }
113558997Selan
113658997Selan len = strlen (base);
113758997Selan temp_filename = xmalloc (len + sizeof("/ccXXXXXX"));
113858997Selan strcpy (temp_filename, base);
113958997Selan if (len > 0 && temp_filename[len-1] != '/')
114058997Selan temp_filename[len++] = '/';
114158997Selan strcpy (temp_filename + len, "ccXXXXXX");
114258997Selan
114358997Selan mktemp (temp_filename);
114458997Selan temp_filename_length = strlen (temp_filename);
114558997Selan if (temp_filename_length == 0)
114658997Selan abort ();
114758997Selan }
114858997Selan
114958997Selan
115058997Selan /* Routine to add variables to the environment. We do this to pass
115158997Selan the pathname of the gcc driver, and the directories search to the
115258997Selan collect2 program, which is being run as ld. This way, we can be
115358997Selan sure of executing the right compiler when collect2 wants to build
115458997Selan constructors and destructors. Since the environment variables we
115558997Selan use come from an obstack, we don't have to worry about allocating
115658997Selan space for them. */
115758997Selan
115858997Selan #ifndef HAVE_PUTENV
115958997Selan
putenv(str)116058997Selan putenv (str)
116158997Selan char *str;
116258997Selan {
116358997Selan #ifndef VMS /* nor about VMS */
116458997Selan
116558997Selan extern char **environ;
116658997Selan char **old_environ = environ;
116758997Selan char **envp;
116858997Selan int num_envs = 0;
116958997Selan int name_len = 1;
117058997Selan int str_len = strlen (str);
117158997Selan char *p = str;
117258997Selan int ch;
117358997Selan
117458997Selan while ((ch = *p++) != '\0' && ch != '=')
117558997Selan name_len++;
117658997Selan
117758997Selan if (!ch)
117858997Selan abort ();
117958997Selan
118058997Selan /* Search for replacing an existing environment variable, and
118158997Selan count the number of total environment variables. */
118258997Selan for (envp = old_environ; *envp; envp++)
118358997Selan {
118458997Selan num_envs++;
118558997Selan if (!strncmp (str, *envp, name_len))
118658997Selan {
118758997Selan *envp = str;
118858997Selan return;
118958997Selan }
119058997Selan }
119158997Selan
119258997Selan /* Add a new environment variable */
119358997Selan environ = (char **) xmalloc (sizeof (char *) * (num_envs+2));
119458997Selan *environ = str;
119558997Selan bcopy (old_environ, environ+1, sizeof (char *) * (num_envs+1));
119658997Selan
119758997Selan #endif /* VMS */
119858997Selan }
119958997Selan
120058997Selan #endif /* HAVE_PUTENV */
120158997Selan
120258997Selan
120358997Selan /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables for collect. */
120458997Selan
120558997Selan static void
putenv_from_prefixes(paths,env_var)120658997Selan putenv_from_prefixes (paths, env_var)
120758997Selan struct path_prefix *paths;
120858997Selan char *env_var;
120958997Selan {
121058997Selan int suffix_len = (machine_suffix) ? strlen (machine_suffix) : 0;
121158997Selan int first_time = TRUE;
121258997Selan struct prefix_list *pprefix;
121358997Selan
121458997Selan obstack_grow (&collect_obstack, env_var, strlen (env_var));
121558997Selan
121658997Selan for (pprefix = paths->plist; pprefix != 0; pprefix = pprefix->next)
121758997Selan {
121858997Selan int len = strlen (pprefix->prefix);
121958997Selan
122058997Selan if (machine_suffix)
122158997Selan {
122258997Selan if (!first_time)
122358997Selan obstack_grow (&collect_obstack, ":", 1);
122458997Selan
122558997Selan first_time = FALSE;
122658997Selan obstack_grow (&collect_obstack, pprefix->prefix, len);
122758997Selan obstack_grow (&collect_obstack, machine_suffix, suffix_len);
122858997Selan }
122958997Selan
123058997Selan if (just_machine_suffix && pprefix->require_machine_suffix == 2)
123158997Selan {
123258997Selan if (!first_time)
123358997Selan obstack_grow (&collect_obstack, ":", 1);
123458997Selan
123558997Selan first_time = FALSE;
123658997Selan obstack_grow (&collect_obstack, pprefix->prefix, len);
123758997Selan obstack_grow (&collect_obstack, machine_suffix, suffix_len);
123858997Selan }
123958997Selan
124058997Selan if (!pprefix->require_machine_suffix)
124158997Selan {
124258997Selan if (!first_time)
124358997Selan obstack_grow (&collect_obstack, ":", 1);
124458997Selan
124558997Selan first_time = FALSE;
124658997Selan obstack_grow (&collect_obstack, pprefix->prefix, len);
124758997Selan }
124858997Selan }
124958997Selan obstack_grow (&collect_obstack, "\0", 1);
125058997Selan putenv (obstack_finish (&collect_obstack));
125158997Selan }
125258997Selan
125358997Selan
125458997Selan /* Search for NAME using the prefix list PREFIXES. MODE is passed to
125558997Selan access to check permissions.
125658997Selan Return 0 if not found, otherwise return its name, allocated with malloc. */
125758997Selan
125858997Selan static char *
find_a_file(pprefix,name,mode)125958997Selan find_a_file (pprefix, name, mode)
126058997Selan struct path_prefix *pprefix;
126158997Selan char *name;
126258997Selan int mode;
126358997Selan {
126458997Selan char *temp;
126558997Selan char *file_suffix = ((mode & X_OK) != 0 ? EXECUTABLE_SUFFIX : "");
126658997Selan struct prefix_list *pl;
126758997Selan int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1;
126858997Selan
126958997Selan if (machine_suffix)
127058997Selan len += strlen (machine_suffix);
127158997Selan
127258997Selan temp = xmalloc (len);
127358997Selan
127458997Selan /* Determine the filename to execute (special case for absolute paths). */
127558997Selan
127658997Selan if (*name == '/')
127758997Selan {
127858997Selan if (access (name, mode))
127958997Selan {
128058997Selan strcpy (temp, name);
128158997Selan return temp;
128258997Selan }
128358997Selan }
128458997Selan else
128558997Selan for (pl = pprefix->plist; pl; pl = pl->next)
128658997Selan {
128758997Selan if (machine_suffix)
128858997Selan {
128958997Selan strcpy (temp, pl->prefix);
129058997Selan strcat (temp, machine_suffix);
129158997Selan strcat (temp, name);
129258997Selan if (access (temp, mode) == 0)
129358997Selan {
129458997Selan if (pl->used_flag_ptr != 0)
129558997Selan *pl->used_flag_ptr = 1;
129658997Selan return temp;
129758997Selan }
129858997Selan /* Some systems have a suffix for executable files.
129958997Selan So try appending that. */
130058997Selan if (file_suffix[0] != 0)
130158997Selan {
130258997Selan strcat (temp, file_suffix);
130358997Selan if (access (temp, mode) == 0)
130458997Selan {
130558997Selan if (pl->used_flag_ptr != 0)
130658997Selan *pl->used_flag_ptr = 1;
130758997Selan return temp;
130858997Selan }
130958997Selan }
131058997Selan }
131158997Selan /* Certain prefixes are tried with just the machine type,
131258997Selan not the version. This is used for finding as, ld, etc. */
131358997Selan if (just_machine_suffix && pl->require_machine_suffix == 2)
131458997Selan {
131558997Selan strcpy (temp, pl->prefix);
131658997Selan strcat (temp, just_machine_suffix);
131758997Selan strcat (temp, name);
131858997Selan if (access (temp, mode) == 0)
131958997Selan {
132058997Selan if (pl->used_flag_ptr != 0)
132158997Selan *pl->used_flag_ptr = 1;
132258997Selan return temp;
132358997Selan }
132458997Selan /* Some systems have a suffix for executable files.
132558997Selan So try appending that. */
132658997Selan if (file_suffix[0] != 0)
132758997Selan {
132858997Selan strcat (temp, file_suffix);
132958997Selan if (access (temp, mode) == 0)
133058997Selan {
133158997Selan if (pl->used_flag_ptr != 0)
133258997Selan *pl->used_flag_ptr = 1;
133358997Selan return temp;
133458997Selan }
133558997Selan }
133658997Selan }
133758997Selan /* Certain prefixes can't be used without the machine suffix
133858997Selan when the machine or version is explicitly specified. */
133958997Selan if (!pl->require_machine_suffix)
134058997Selan {
134158997Selan strcpy (temp, pl->prefix);
134258997Selan strcat (temp, name);
134358997Selan if (access (temp, mode) == 0)
134458997Selan {
134558997Selan if (pl->used_flag_ptr != 0)
134658997Selan *pl->used_flag_ptr = 1;
134758997Selan return temp;
134858997Selan }
134958997Selan /* Some systems have a suffix for executable files.
135058997Selan So try appending that. */
135158997Selan if (file_suffix[0] != 0)
135258997Selan {
135358997Selan strcat (temp, file_suffix);
135458997Selan if (access (temp, mode) == 0)
135558997Selan {
135658997Selan if (pl->used_flag_ptr != 0)
135758997Selan *pl->used_flag_ptr = 1;
135858997Selan return temp;
135958997Selan }
136058997Selan }
136158997Selan }
136258997Selan }
136358997Selan
136458997Selan free (temp);
136558997Selan return 0;
136658997Selan }
136758997Selan
136858997Selan /* Add an entry for PREFIX in PLIST. If FIRST is set, it goes
136958997Selan at the start of the list, otherwise it goes at the end.
137058997Selan
137158997Selan If WARN is nonzero, we will warn if no file is found
137258997Selan through this prefix. WARN should point to an int
137358997Selan which will be set to 1 if this entry is used.
137458997Selan
137558997Selan REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without
137658997Selan the complete value of machine_suffix.
137758997Selan 2 means try both machine_suffix and just_machine_suffix. */
137858997Selan
137958997Selan static void
add_prefix(pprefix,prefix,first,require_machine_suffix,warn)138058997Selan add_prefix (pprefix, prefix, first, require_machine_suffix, warn)
138158997Selan struct path_prefix *pprefix;
138258997Selan char *prefix;
138358997Selan int first;
138458997Selan int require_machine_suffix;
138558997Selan int *warn;
138658997Selan {
138758997Selan struct prefix_list *pl, **prev;
138858997Selan int len;
138958997Selan
139058997Selan if (!first && pprefix->plist)
139158997Selan {
139258997Selan for (pl = pprefix->plist; pl->next; pl = pl->next)
139358997Selan ;
139458997Selan prev = &pl->next;
139558997Selan }
139658997Selan else
139758997Selan prev = &pprefix->plist;
139858997Selan
139958997Selan /* Keep track of the longest prefix */
140058997Selan
140158997Selan len = strlen (prefix);
140258997Selan if (len > pprefix->max_len)
140358997Selan pprefix->max_len = len;
140458997Selan
140558997Selan pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
140658997Selan pl->prefix = save_string (prefix, len);
140758997Selan pl->require_machine_suffix = require_machine_suffix;
140858997Selan pl->used_flag_ptr = warn;
140958997Selan if (warn)
141058997Selan *warn = 0;
141158997Selan
141258997Selan if (*prev)
141358997Selan pl->next = *prev;
141458997Selan else
141558997Selan pl->next = (struct prefix_list *) 0;
141658997Selan *prev = pl;
141758997Selan }
141858997Selan
141958997Selan /* Print warnings for any prefixes in the list PPREFIX that were not used. */
142058997Selan
142158997Selan static void
unused_prefix_warnings(pprefix)142258997Selan unused_prefix_warnings (pprefix)
142358997Selan struct path_prefix *pprefix;
142458997Selan {
142558997Selan struct prefix_list *pl = pprefix->plist;
142658997Selan
142758997Selan while (pl)
142858997Selan {
142958997Selan if (pl->used_flag_ptr != 0 && !*pl->used_flag_ptr)
143058997Selan {
143158997Selan error ("file path prefix `%s' never used",
143258997Selan pl->prefix);
143358997Selan /* Prevent duplicate warnings. */
143458997Selan *pl->used_flag_ptr = 1;
143558997Selan }
143658997Selan pl = pl->next;
143758997Selan }
143858997Selan }
143958997Selan
144058997Selan /* Get rid of all prefixes built up so far in *PLISTP. */
144158997Selan
144258997Selan static void
free_path_prefix(pprefix)144358997Selan free_path_prefix (pprefix)
144458997Selan struct path_prefix *pprefix;
144558997Selan {
144658997Selan struct prefix_list *pl = pprefix->plist;
144758997Selan struct prefix_list *temp;
144858997Selan
144958997Selan while (pl)
145058997Selan {
145158997Selan temp = pl;
145258997Selan pl = pl->next;
145358997Selan free (temp->prefix);
145458997Selan free ((char *) temp);
145558997Selan }
145658997Selan pprefix->plist = (struct prefix_list *) 0;
145758997Selan }
145858997Selan
145958997Selan /* stdin file number. */
146058997Selan #define STDIN_FILE_NO 0
146158997Selan
146258997Selan /* stdout file number. */
146358997Selan #define STDOUT_FILE_NO 1
146458997Selan
146558997Selan /* value of `pipe': port index for reading. */
146658997Selan #define READ_PORT 0
146758997Selan
146858997Selan /* value of `pipe': port index for writing. */
146958997Selan #define WRITE_PORT 1
147058997Selan
147158997Selan /* Pipe waiting from last process, to be used as input for the next one.
147258997Selan Value is STDIN_FILE_NO if no pipe is waiting
147358997Selan (i.e. the next command is the first of a group). */
147458997Selan
147558997Selan static int last_pipe_input;
147658997Selan
147758997Selan /* Fork one piped subcommand. FUNC is the system call to use
147858997Selan (either execv or execvp). ARGV is the arg vector to use.
147958997Selan NOT_LAST is nonzero if this is not the last subcommand
148058997Selan (i.e. its output should be piped to the next one.) */
148158997Selan
148258997Selan #ifndef OS2
148358997Selan #ifdef __MSDOS__
148458997Selan
148558997Selan /* Declare these to avoid compilation error. They won't be called. */
execv(const char * a,const char ** b)148658997Selan int execv(const char *a, const char **b){}
execvp(const char * a,const char ** b)148758997Selan int execvp(const char *a, const char **b){}
148858997Selan
148958997Selan static int
pexecute(search_flag,program,argv,not_last)149058997Selan pexecute (search_flag, program, argv, not_last)
149158997Selan int search_flag;
149258997Selan char *program;
149358997Selan char *argv[];
149458997Selan int not_last;
149558997Selan {
149658997Selan char *scmd;
149758997Selan FILE *argfile;
149858997Selan int i;
149958997Selan
150058997Selan scmd = (char *)malloc (strlen (program) + strlen (temp_filename) + 6);
150158997Selan sprintf (scmd, "%s @%s.gp", program, temp_filename);
150258997Selan argfile = fopen (scmd+strlen (program) + 2, "w");
150358997Selan if (argfile == 0)
150458997Selan pfatal_with_name (scmd + strlen (program) + 2);
150558997Selan
150658997Selan for (i=1; argv[i]; i++)
150758997Selan {
150858997Selan char *cp;
150958997Selan for (cp = argv[i]; *cp; cp++)
151058997Selan {
151158997Selan if (*cp == '"' || *cp == '\'' || *cp == '\\' || isspace (*cp))
151258997Selan fputc ('\\', argfile);
151358997Selan fputc (*cp, argfile);
151458997Selan }
151558997Selan fputc ('\n', argfile);
151658997Selan }
151758997Selan fclose (argfile);
151858997Selan
151958997Selan i = system (scmd);
152058997Selan
152158997Selan remove (scmd + strlen (program) + 2);
152258997Selan return i << 8;
152358997Selan }
152458997Selan
152558997Selan #else /* not __MSDOS__ */
152658997Selan
152758997Selan static int
pexecute(search_flag,program,argv,not_last)152858997Selan pexecute (search_flag, program, argv, not_last)
152958997Selan int search_flag;
153058997Selan char *program;
153158997Selan char *argv[];
153258997Selan int not_last;
153358997Selan {
153458997Selan int (*func)() = (search_flag ? execv : execvp);
153558997Selan int pid;
153658997Selan int pdes[2];
153758997Selan int input_desc = last_pipe_input;
153858997Selan int output_desc = STDOUT_FILE_NO;
153958997Selan int retries, sleep_interval;
154058997Selan
154158997Selan /* If this isn't the last process, make a pipe for its output,
154258997Selan and record it as waiting to be the input to the next process. */
154358997Selan
154458997Selan if (not_last)
154558997Selan {
154658997Selan if (pipe (pdes) < 0)
154758997Selan pfatal_with_name ("pipe");
154858997Selan output_desc = pdes[WRITE_PORT];
154958997Selan last_pipe_input = pdes[READ_PORT];
155058997Selan }
155158997Selan else
155258997Selan last_pipe_input = STDIN_FILE_NO;
155358997Selan
155458997Selan /* Fork a subprocess; wait and retry if it fails. */
155558997Selan sleep_interval = 1;
155658997Selan for (retries = 0; retries < 4; retries++)
155758997Selan {
155858997Selan pid = vfork ();
155958997Selan if (pid >= 0)
156058997Selan break;
156158997Selan sleep (sleep_interval);
156258997Selan sleep_interval *= 2;
156358997Selan }
156458997Selan
156558997Selan switch (pid)
156658997Selan {
156758997Selan case -1:
156858997Selan #ifdef vfork
156958997Selan pfatal_with_name ("fork");
157058997Selan #else
157158997Selan pfatal_with_name ("vfork");
157258997Selan #endif
157358997Selan /* NOTREACHED */
157458997Selan return 0;
157558997Selan
157658997Selan case 0: /* child */
157758997Selan /* Move the input and output pipes into place, if nec. */
157858997Selan if (input_desc != STDIN_FILE_NO)
157958997Selan {
158058997Selan close (STDIN_FILE_NO);
158158997Selan dup (input_desc);
158258997Selan close (input_desc);
158358997Selan }
158458997Selan if (output_desc != STDOUT_FILE_NO)
158558997Selan {
158658997Selan close (STDOUT_FILE_NO);
158758997Selan dup (output_desc);
158858997Selan close (output_desc);
158958997Selan }
159058997Selan
159158997Selan /* Close the parent's descs that aren't wanted here. */
159258997Selan if (last_pipe_input != STDIN_FILE_NO)
159358997Selan close (last_pipe_input);
159458997Selan
159558997Selan /* Exec the program. */
159658997Selan (*func) (program, argv);
159758997Selan perror_exec (program);
159858997Selan exit (-1);
159958997Selan /* NOTREACHED */
160058997Selan return 0;
160158997Selan
160258997Selan default:
160358997Selan /* In the parent, after forking.
160458997Selan Close the descriptors that we made for this child. */
160558997Selan if (input_desc != STDIN_FILE_NO)
160658997Selan close (input_desc);
160758997Selan if (output_desc != STDOUT_FILE_NO)
160858997Selan close (output_desc);
160958997Selan
161058997Selan /* Return child's process number. */
161158997Selan return pid;
161258997Selan }
161358997Selan }
161458997Selan
161558997Selan #endif /* not __MSDOS__ */
161658997Selan #else /* not OS2 */
161758997Selan
161858997Selan static int
pexecute(search_flag,program,argv,not_last)161958997Selan pexecute (search_flag, program, argv, not_last)
162058997Selan int search_flag;
162158997Selan char *program;
162258997Selan char *argv[];
162358997Selan int not_last;
162458997Selan {
162558997Selan return (search_flag ? spawnv : spawnvp) (1, program, argv);
162658997Selan }
162758997Selan #endif /* not OS2 */
162858997Selan
162958997Selan /* Execute the command specified by the arguments on the current line of spec.
163058997Selan When using pipes, this includes several piped-together commands
163158997Selan with `|' between them.
163258997Selan
163358997Selan Return 0 if successful, -1 if failed. */
163458997Selan
163558997Selan static int
execute()163658997Selan execute ()
163758997Selan {
163858997Selan int i;
163958997Selan int n_commands; /* # of command. */
164058997Selan char *string;
164158997Selan struct command
164258997Selan {
164358997Selan char *prog; /* program name. */
164458997Selan char **argv; /* vector of args. */
164558997Selan int pid; /* pid of process for this command. */
164658997Selan };
164758997Selan
164858997Selan struct command *commands; /* each command buffer with above info. */
164958997Selan
165058997Selan /* Count # of piped commands. */
165158997Selan for (n_commands = 1, i = 0; i < argbuf_index; i++)
165258997Selan if (strcmp (argbuf[i], "|") == 0)
165358997Selan n_commands++;
165458997Selan
165558997Selan /* Get storage for each command. */
165658997Selan commands
165758997Selan = (struct command *) alloca (n_commands * sizeof (struct command));
165858997Selan
165958997Selan /* Split argbuf into its separate piped processes,
166058997Selan and record info about each one.
166158997Selan Also search for the programs that are to be run. */
166258997Selan
166358997Selan commands[0].prog = argbuf[0]; /* first command. */
166458997Selan commands[0].argv = &argbuf[0];
166558997Selan string = find_a_file (&exec_prefix, commands[0].prog, X_OK);
166658997Selan if (string)
166758997Selan commands[0].argv[0] = string;
166858997Selan
166958997Selan for (n_commands = 1, i = 0; i < argbuf_index; i++)
167058997Selan if (strcmp (argbuf[i], "|") == 0)
167158997Selan { /* each command. */
167258997Selan #ifdef __MSDOS__
167358997Selan fatal ("-pipe not supported under MS-DOS");
167458997Selan #endif
167558997Selan argbuf[i] = 0; /* termination of command args. */
167658997Selan commands[n_commands].prog = argbuf[i + 1];
167758997Selan commands[n_commands].argv = &argbuf[i + 1];
167858997Selan string = find_a_file (&exec_prefix, commands[n_commands].prog, X_OK);
167958997Selan if (string)
168058997Selan commands[n_commands].argv[0] = string;
168158997Selan n_commands++;
168258997Selan }
168358997Selan
168458997Selan argbuf[argbuf_index] = 0;
168558997Selan
168658997Selan /* If -v, print what we are about to do, and maybe query. */
168758997Selan
168858997Selan if (verbose_flag)
168958997Selan {
169058997Selan /* Print each piped command as a separate line. */
169158997Selan for (i = 0; i < n_commands ; i++)
169258997Selan {
169358997Selan char **j;
169458997Selan
169558997Selan for (j = commands[i].argv; *j; j++)
169658997Selan fprintf (stderr, " %s", *j);
169758997Selan
169858997Selan /* Print a pipe symbol after all but the last command. */
169958997Selan if (i + 1 != n_commands)
170058997Selan fprintf (stderr, " |");
170158997Selan fprintf (stderr, "\n");
170258997Selan }
170358997Selan fflush (stderr);
170458997Selan #ifdef DEBUG
170558997Selan fprintf (stderr, "\nGo ahead? (y or n) ");
170658997Selan fflush (stderr);
170758997Selan i = getchar ();
170858997Selan if (i != '\n')
170958997Selan while (getchar () != '\n') ;
171058997Selan if (i != 'y' && i != 'Y')
171158997Selan return 0;
171258997Selan #endif /* DEBUG */
171358997Selan }
171458997Selan
171558997Selan /* Run each piped subprocess. */
171658997Selan
171758997Selan last_pipe_input = STDIN_FILE_NO;
171858997Selan for (i = 0; i < n_commands; i++)
171958997Selan {
172058997Selan char *string = commands[i].argv[0];
172158997Selan
172258997Selan commands[i].pid = pexecute (string != commands[i].prog,
172358997Selan string, commands[i].argv,
172458997Selan i + 1 < n_commands);
172558997Selan
172658997Selan if (string != commands[i].prog)
172758997Selan free (string);
172858997Selan }
172958997Selan
173058997Selan execution_count++;
173158997Selan
173258997Selan /* Wait for all the subprocesses to finish.
173358997Selan We don't care what order they finish in;
173458997Selan we know that N_COMMANDS waits will get them all. */
173558997Selan
173658997Selan {
173758997Selan int ret_code = 0;
173858997Selan
173958997Selan for (i = 0; i < n_commands; i++)
174058997Selan {
174158997Selan int status;
174258997Selan int pid;
174358997Selan char *prog;
174458997Selan
174558997Selan #ifdef __MSDOS__
174658997Selan status = pid = commands[i].pid;
174758997Selan #else
174858997Selan pid = wait (&status);
174958997Selan #endif
175058997Selan if (pid < 0)
175158997Selan abort ();
175258997Selan
175358997Selan if (status != 0)
175458997Selan {
175558997Selan int j;
175658997Selan for (j = 0; j < n_commands; j++)
175758997Selan if (commands[j].pid == pid)
175858997Selan prog = commands[j].prog;
175958997Selan
176058997Selan if ((status & 0x7F) != 0)
176158997Selan {
176258997Selan fatal ("Internal compiler error: program %s got fatal signal %d",
176358997Selan prog, (status & 0x7F));
176458997Selan signal_count++;
176558997Selan }
176658997Selan if (((status & 0xFF00) >> 8) >= MIN_FATAL_STATUS)
176758997Selan ret_code = -1;
176858997Selan }
176958997Selan }
177058997Selan return ret_code;
177158997Selan }
177258997Selan }
177358997Selan
177458997Selan /* Find all the switches given to us
177558997Selan and make a vector describing them.
177658997Selan The elements of the vector are strings, one per switch given.
177758997Selan If a switch uses following arguments, then the `part1' field
177858997Selan is the switch itself and the `args' field
177958997Selan is a null-terminated vector containing the following arguments.
178058997Selan The `valid' field is nonzero if any spec has looked at this switch;
178158997Selan if it remains zero at the end of the run, it must be meaningless. */
178258997Selan
178358997Selan struct switchstr
178458997Selan {
178558997Selan char *part1;
178658997Selan char **args;
178758997Selan int valid;
178858997Selan };
178958997Selan
179058997Selan static struct switchstr *switches;
179158997Selan
179258997Selan static int n_switches;
179358997Selan
179458997Selan struct infile
179558997Selan {
179658997Selan char *name;
179758997Selan char *language;
179858997Selan };
179958997Selan
180058997Selan /* Also a vector of input files specified. */
180158997Selan
180258997Selan static struct infile *infiles;
180358997Selan
180458997Selan static int n_infiles;
180558997Selan
180658997Selan /* And a vector of corresponding output files is made up later. */
180758997Selan
180858997Selan static char **outfiles;
180958997Selan
181058997Selan /* Create the vector `switches' and its contents.
181158997Selan Store its length in `n_switches'. */
181258997Selan
181358997Selan static void
process_command(argc,argv)181458997Selan process_command (argc, argv)
181558997Selan int argc;
181658997Selan char **argv;
181758997Selan {
181858997Selan register int i;
181958997Selan char *temp;
182058997Selan char *spec_lang = 0;
182158997Selan int last_language_n_infiles;
182258997Selan
182358997Selan gcc_exec_prefix = getenv ("GCC_EXEC_PREFIX");
182458997Selan
182558997Selan n_switches = 0;
182658997Selan n_infiles = 0;
182758997Selan
182858997Selan /* Default for -V is our version number, ending at first space. */
182958997Selan spec_version = save_string (version_string, strlen (version_string));
183058997Selan for (temp = spec_version; *temp && *temp != ' '; temp++);
183158997Selan if (*temp) *temp = '\0';
183258997Selan
183358997Selan /* Set up the default search paths. */
1834*60377Selan if (gcc_exec_prefix == 0)
1835*60377Selan gcc_exec_prefix = standard_exec_prefix;
183658997Selan
1837*60377Selan add_prefix (&exec_prefix, gcc_exec_prefix, 0, 0, NULL_PTR);
1838*60377Selan add_prefix (&startfile_prefix, gcc_exec_prefix, 0, 0, NULL_PTR);
183958997Selan
184058997Selan /* COMPILER_PATH and LIBRARY_PATH have values
184158997Selan that are lists of directory names with colons. */
184258997Selan
184358997Selan temp = getenv ("COMPILER_PATH");
184458997Selan if (temp)
184558997Selan {
184658997Selan char *startp, *endp;
184758997Selan char *nstore = (char *) alloca (strlen (temp) + 3);
184858997Selan
184958997Selan startp = endp = temp;
185058997Selan while (1)
185158997Selan {
185258997Selan if (*endp == PATH_SEPARATOR || *endp == 0)
185358997Selan {
185458997Selan strncpy (nstore, startp, endp-startp);
185558997Selan if (endp == startp)
185658997Selan {
185758997Selan strcpy (nstore, "./");
185858997Selan }
185958997Selan else if (endp[-1] != '/')
186058997Selan {
186158997Selan nstore[endp-startp] = '/';
186258997Selan nstore[endp-startp+1] = 0;
186358997Selan }
186458997Selan else
186558997Selan nstore[endp-startp] = 0;
186658997Selan add_prefix (&exec_prefix, nstore, 0, 0, NULL_PTR);
186758997Selan if (*endp == 0)
186858997Selan break;
186958997Selan endp = startp = endp + 1;
187058997Selan }
187158997Selan else
187258997Selan endp++;
187358997Selan }
187458997Selan }
187558997Selan
187658997Selan temp = getenv ("LIBRARY_PATH");
187758997Selan if (temp)
187858997Selan {
187958997Selan char *startp, *endp;
188058997Selan char *nstore = (char *) alloca (strlen (temp) + 3);
188158997Selan
188258997Selan startp = endp = temp;
188358997Selan while (1)
188458997Selan {
188558997Selan if (*endp == PATH_SEPARATOR || *endp == 0)
188658997Selan {
188758997Selan strncpy (nstore, startp, endp-startp);
188858997Selan if (endp == startp)
188958997Selan {
189058997Selan strcpy (nstore, "./");
189158997Selan }
189258997Selan else if (endp[-1] != '/')
189358997Selan {
189458997Selan nstore[endp-startp] = '/';
189558997Selan nstore[endp-startp+1] = 0;
189658997Selan }
189758997Selan else
189858997Selan nstore[endp-startp] = 0;
189958997Selan add_prefix (&startfile_prefix, nstore, 0, 0, NULL_PTR);
190058997Selan /* Make separate list of dirs that came from LIBRARY_PATH. */
190158997Selan add_prefix (&library_prefix, nstore, 0, 0, NULL_PTR);
190258997Selan if (*endp == 0)
190358997Selan break;
190458997Selan endp = startp = endp + 1;
190558997Selan }
190658997Selan else
190758997Selan endp++;
190858997Selan }
190958997Selan }
191058997Selan
191158997Selan /* Use LPATH like LIBRARY_PATH (for the CMU build program). */
191258997Selan temp = getenv ("LPATH");
191358997Selan if (temp)
191458997Selan {
191558997Selan char *startp, *endp;
191658997Selan char *nstore = (char *) alloca (strlen (temp) + 3);
191758997Selan
191858997Selan startp = endp = temp;
191958997Selan while (1)
192058997Selan {
192158997Selan if (*endp == PATH_SEPARATOR || *endp == 0)
192258997Selan {
192358997Selan strncpy (nstore, startp, endp-startp);
192458997Selan if (endp == startp)
192558997Selan {
192658997Selan strcpy (nstore, "./");
192758997Selan }
192858997Selan else if (endp[-1] != '/')
192958997Selan {
193058997Selan nstore[endp-startp] = '/';
193158997Selan nstore[endp-startp+1] = 0;
193258997Selan }
193358997Selan else
193458997Selan nstore[endp-startp] = 0;
193558997Selan add_prefix (&startfile_prefix, nstore, 0, 0, NULL_PTR);
193658997Selan /* Make separate list of dirs that came from LIBRARY_PATH. */
193758997Selan add_prefix (&library_prefix, nstore, 0, 0, NULL_PTR);
193858997Selan if (*endp == 0)
193958997Selan break;
194058997Selan endp = startp = endp + 1;
194158997Selan }
194258997Selan else
194358997Selan endp++;
194458997Selan }
194558997Selan }
194658997Selan
194758997Selan /* Scan argv twice. Here, the first time, just count how many switches
194858997Selan there will be in their vector, and how many input files in theirs.
194958997Selan Here we also parse the switches that cc itself uses (e.g. -v). */
195058997Selan
195158997Selan for (i = 1; i < argc; i++)
195258997Selan {
195358997Selan if (! strcmp (argv[i], "-dumpspecs"))
195458997Selan {
195558997Selan printf ("*asm:\n%s\n\n", asm_spec);
195658997Selan printf ("*asm_final:\n%s\n\n", asm_final_spec);
195758997Selan printf ("*cpp:\n%s\n\n", cpp_spec);
195858997Selan printf ("*cc1:\n%s\n\n", cc1_spec);
195958997Selan printf ("*cc1plus:\n%s\n\n", cc1plus_spec);
196058997Selan printf ("*endfile:\n%s\n\n", endfile_spec);
196158997Selan printf ("*link:\n%s\n\n", link_spec);
196258997Selan printf ("*lib:\n%s\n\n", lib_spec);
196358997Selan printf ("*startfile:\n%s\n\n", startfile_spec);
196458997Selan printf ("*switches_need_spaces:\n%s\n\n", switches_need_spaces);
196558997Selan printf ("*signed_char:\n%s\n\n", signed_char_spec);
196658997Selan printf ("*predefines:\n%s\n\n", cpp_predefines);
196758997Selan printf ("*cross_compile:\n%d\n\n", cross_compile);
196858997Selan
196958997Selan exit (0);
197058997Selan }
197158997Selan else if (! strcmp (argv[i], "-dumpversion"))
197258997Selan {
197358997Selan printf ("%s\n", version_string);
197458997Selan exit (0);
197558997Selan }
197658997Selan else if (! strcmp (argv[i], "-print-libgcc-file-name"))
197758997Selan {
197858997Selan print_libgcc_file_name = 1;
197958997Selan }
198058997Selan else if (! strcmp (argv[i], "-Xlinker"))
198158997Selan {
198258997Selan /* Pass the argument of this option to the linker when we link. */
198358997Selan
198458997Selan if (i + 1 == argc)
198558997Selan fatal ("argument to `-Xlinker' is missing");
198658997Selan
198758997Selan n_linker_options++;
198858997Selan if (!linker_options)
198958997Selan linker_options
199058997Selan = (char **) xmalloc (n_linker_options * sizeof (char **));
199158997Selan else
199258997Selan linker_options
199358997Selan = (char **) xrealloc (linker_options,
199458997Selan n_linker_options * sizeof (char **));
199558997Selan
199658997Selan linker_options[n_linker_options - 1] = argv[++i];
199758997Selan }
199858997Selan else if (! strncmp (argv[i], "-Wl,", 4))
199958997Selan {
200058997Selan int prev, j;
200158997Selan /* Pass the rest of this option to the linker when we link. */
200258997Selan
200358997Selan n_linker_options++;
200458997Selan if (!linker_options)
200558997Selan linker_options
200658997Selan = (char **) xmalloc (n_linker_options * sizeof (char **));
200758997Selan else
200858997Selan linker_options
200958997Selan = (char **) xrealloc (linker_options,
201058997Selan n_linker_options * sizeof (char **));
201158997Selan
201258997Selan /* Split the argument at commas. */
201358997Selan prev = 4;
201458997Selan for (j = 4; argv[i][j]; j++)
201558997Selan if (argv[i][j] == ',')
201658997Selan {
201758997Selan linker_options[n_linker_options - 1]
201858997Selan = save_string (argv[i] + prev, j - prev);
201958997Selan n_linker_options++;
202058997Selan linker_options
202158997Selan = (char **) xrealloc (linker_options,
202258997Selan n_linker_options * sizeof (char **));
202358997Selan prev = j + 1;
202458997Selan }
202558997Selan /* Record the part after the last comma. */
202658997Selan linker_options[n_linker_options - 1] = argv[i] + prev;
202758997Selan }
202858997Selan else if (! strncmp (argv[i], "-Wa,", 4))
202958997Selan {
203058997Selan int prev, j;
203158997Selan /* Pass the rest of this option to the assembler. */
203258997Selan
203358997Selan n_assembler_options++;
203458997Selan if (!assembler_options)
203558997Selan assembler_options
203658997Selan = (char **) xmalloc (n_assembler_options * sizeof (char **));
203758997Selan else
203858997Selan assembler_options
203958997Selan = (char **) xrealloc (assembler_options,
204058997Selan n_assembler_options * sizeof (char **));
204158997Selan
204258997Selan /* Split the argument at commas. */
204358997Selan prev = 4;
204458997Selan for (j = 4; argv[i][j]; j++)
204558997Selan if (argv[i][j] == ',')
204658997Selan {
204758997Selan assembler_options[n_assembler_options - 1]
204858997Selan = save_string (argv[i] + prev, j - prev);
204958997Selan n_assembler_options++;
205058997Selan assembler_options
205158997Selan = (char **) xrealloc (assembler_options,
205258997Selan n_assembler_options * sizeof (char **));
205358997Selan prev = j + 1;
205458997Selan }
205558997Selan /* Record the part after the last comma. */
205658997Selan assembler_options[n_assembler_options - 1] = argv[i] + prev;
205758997Selan }
205858997Selan else if (argv[i][0] == '+' && argv[i][1] == 'e')
205958997Selan /* Compensate for the +e options to the C++ front-end. */
206058997Selan n_switches++;
206158997Selan else if (argv[i][0] == '-' && argv[i][1] != 0 && argv[i][1] != 'l')
206258997Selan {
206358997Selan register char *p = &argv[i][1];
206458997Selan register int c = *p;
206558997Selan
206658997Selan switch (c)
206758997Selan {
206858997Selan case 'b':
206958997Selan if (p[1] == 0 && i + 1 == argc)
207058997Selan fatal ("argument to `-b' is missing");
207158997Selan if (p[1] == 0)
207258997Selan spec_machine = argv[++i];
207358997Selan else
207458997Selan spec_machine = p + 1;
207558997Selan break;
207658997Selan
207758997Selan case 'B':
207858997Selan {
207958997Selan int *temp = (int *) xmalloc (sizeof (int));
208058997Selan char *value;
208158997Selan if (p[1] == 0 && i + 1 == argc)
208258997Selan fatal ("argument to `-B' is missing");
208358997Selan if (p[1] == 0)
208458997Selan value = argv[++i];
208558997Selan else
208658997Selan value = p + 1;
208758997Selan add_prefix (&exec_prefix, value, 1, 0, temp);
208858997Selan add_prefix (&startfile_prefix, value, 1, 0, temp);
208958997Selan }
209058997Selan break;
209158997Selan
209258997Selan case 'v': /* Print our subcommands and print versions. */
209358997Selan n_switches++;
209458997Selan /* If they do anything other than exactly `-v', don't set
209558997Selan verbose_flag; rather, continue on to give the error. */
209658997Selan if (p[1] != 0)
209758997Selan break;
209858997Selan verbose_flag++;
209958997Selan break;
210058997Selan
210158997Selan case 'V':
210258997Selan if (p[1] == 0 && i + 1 == argc)
210358997Selan fatal ("argument to `-V' is missing");
210458997Selan if (p[1] == 0)
210558997Selan spec_version = argv[++i];
210658997Selan else
210758997Selan spec_version = p + 1;
210858997Selan break;
210958997Selan
211058997Selan case 's':
211158997Selan if (!strcmp (p, "save-temps"))
211258997Selan {
211358997Selan save_temps_flag = 1;
211458997Selan n_switches++;
211558997Selan break;
211658997Selan }
211758997Selan default:
211858997Selan n_switches++;
211958997Selan
212058997Selan if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
212158997Selan i += SWITCH_TAKES_ARG (c) - (p[1] != 0);
212258997Selan else if (WORD_SWITCH_TAKES_ARG (p))
212358997Selan i += WORD_SWITCH_TAKES_ARG (p);
212458997Selan }
212558997Selan }
212658997Selan else
212758997Selan n_infiles++;
212858997Selan }
212958997Selan
213058997Selan /* Set up the search paths before we go looking for config files. */
213158997Selan
213258997Selan /* These come before the md prefixes so that we will find gcc's subcommands
213358997Selan (such as cpp) rather than those of the host system. */
213458997Selan /* Use 2 as fourth arg meaning try just the machine as a suffix,
213558997Selan as well as trying the machine and the version. */
213658997Selan add_prefix (&exec_prefix, standard_exec_prefix, 0, 2, NULL_PTR);
213758997Selan add_prefix (&exec_prefix, standard_exec_prefix_1, 0, 2, NULL_PTR);
213858997Selan
213958997Selan add_prefix (&startfile_prefix, standard_exec_prefix, 0, 1, NULL_PTR);
214058997Selan add_prefix (&startfile_prefix, standard_exec_prefix_1, 0, 1, NULL_PTR);
214158997Selan
214258997Selan /* More prefixes are enabled in main, after we read the specs file
214358997Selan and determine whether this is cross-compilation or not. */
214458997Selan
214558997Selan
214658997Selan /* Then create the space for the vectors and scan again. */
214758997Selan
214858997Selan switches = ((struct switchstr *)
214958997Selan xmalloc ((n_switches + 1) * sizeof (struct switchstr)));
215058997Selan infiles = (struct infile *) xmalloc ((n_infiles + 1) * sizeof (struct infile));
215158997Selan n_switches = 0;
215258997Selan n_infiles = 0;
215358997Selan last_language_n_infiles = -1;
215458997Selan
215558997Selan /* This, time, copy the text of each switch and store a pointer
215658997Selan to the copy in the vector of switches.
215758997Selan Store all the infiles in their vector. */
215858997Selan
215958997Selan for (i = 1; i < argc; i++)
216058997Selan {
216158997Selan /* Just skip the switches that were handled by the preceding loop. */
216258997Selan if (!strcmp (argv[i], "-Xlinker"))
216358997Selan i++;
216458997Selan else if (! strncmp (argv[i], "-Wl,", 4))
216558997Selan ;
216658997Selan else if (! strncmp (argv[i], "-Wa,", 4))
216758997Selan ;
216858997Selan else if (! strcmp (argv[i], "-print-libgcc-file-name"))
216958997Selan ;
217058997Selan else if (argv[i][0] == '+' && argv[i][1] == 'e')
217158997Selan {
217258997Selan /* Compensate for the +e options to the C++ front-end;
217358997Selan they're there simply for cfront call-compatability. We do
217458997Selan some magic in default_compilers to pass them down properly.
217558997Selan Note we deliberately start at the `+' here, to avoid passing
217658997Selan -e0 or -e1 down into the linker. */
217758997Selan switches[n_switches].part1 = &argv[i][0];
217858997Selan switches[n_switches].args = 0;
217958997Selan switches[n_switches].valid = 0;
218058997Selan n_switches++;
218158997Selan }
218258997Selan else if (argv[i][0] == '-' && argv[i][1] != 0 && argv[i][1] != 'l')
218358997Selan {
218458997Selan register char *p = &argv[i][1];
218558997Selan register int c = *p;
218658997Selan
218758997Selan if (c == 'B' || c == 'b' || c == 'V')
218858997Selan {
218958997Selan /* Skip a separate arg, if any. */
219058997Selan if (p[1] == 0)
219158997Selan i++;
219258997Selan continue;
219358997Selan }
219458997Selan if (c == 'x')
219558997Selan {
219658997Selan if (p[1] == 0 && i + 1 == argc)
219758997Selan fatal ("argument to `-x' is missing");
219858997Selan if (p[1] == 0)
219958997Selan spec_lang = argv[++i];
220058997Selan else
220158997Selan spec_lang = p + 1;
220258997Selan if (! strcmp (spec_lang, "none"))
220358997Selan /* Suppress the warning if -xnone comes after the last input file,
220458997Selan because alternate command interfaces like g++ might find it
220558997Selan useful to place -xnone after each input file. */
220658997Selan spec_lang = 0;
220758997Selan else
220858997Selan last_language_n_infiles = n_infiles;
220958997Selan continue;
221058997Selan }
221158997Selan switches[n_switches].part1 = p;
221258997Selan /* Deal with option arguments in separate argv elements. */
221358997Selan if ((SWITCH_TAKES_ARG (c) > (p[1] != 0))
221458997Selan || WORD_SWITCH_TAKES_ARG (p)) {
221558997Selan int j = 0;
221658997Selan int n_args = WORD_SWITCH_TAKES_ARG (p);
221758997Selan
221858997Selan if (n_args == 0) {
221958997Selan /* Count only the option arguments in separate argv elements. */
222058997Selan n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0);
222158997Selan }
222258997Selan if (i + n_args >= argc)
222358997Selan fatal ("argument to `-%s' is missing", p);
222458997Selan switches[n_switches].args
222558997Selan = (char **) xmalloc ((n_args + 1) * sizeof (char *));
222658997Selan while (j < n_args)
222758997Selan switches[n_switches].args[j++] = argv[++i];
222858997Selan /* Null-terminate the vector. */
222958997Selan switches[n_switches].args[j] = 0;
223058997Selan } else if (*switches_need_spaces != 0 && (c == 'o' || c == 'L')) {
223158997Selan /* On some systems, ld cannot handle -o or -L without space.
223258997Selan So split the -o or -L from its argument. */
223358997Selan switches[n_switches].part1 = (c == 'o' ? "o" : "L");
223458997Selan switches[n_switches].args = (char **) xmalloc (2 * sizeof (char *));
223558997Selan switches[n_switches].args[0] = xmalloc (strlen (p));
223658997Selan strcpy (switches[n_switches].args[0], &p[1]);
223758997Selan switches[n_switches].args[1] = 0;
223858997Selan } else
223958997Selan switches[n_switches].args = 0;
224058997Selan switches[n_switches].valid = 0;
224158997Selan /* This is always valid, since gcc.c itself understands it. */
224258997Selan if (!strcmp (p, "save-temps"))
224358997Selan switches[n_switches].valid = 1;
224458997Selan n_switches++;
224558997Selan }
224658997Selan else
224758997Selan {
224858997Selan infiles[n_infiles].language = spec_lang;
224958997Selan infiles[n_infiles++].name = argv[i];
225058997Selan }
225158997Selan }
225258997Selan
225358997Selan if (n_infiles == last_language_n_infiles)
225458997Selan error ("Warning: `-x %s' after last input file has no effect", spec_lang);
225558997Selan
225658997Selan switches[n_switches].part1 = 0;
225758997Selan infiles[n_infiles].name = 0;
225858997Selan
225958997Selan /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake. */
226058997Selan if (gcc_exec_prefix)
226158997Selan {
226258997Selan temp = (char *) xmalloc (strlen (gcc_exec_prefix) + strlen (spec_version)
226358997Selan + strlen (spec_machine) + 3);
226458997Selan strcpy (temp, gcc_exec_prefix);
226558997Selan strcat (temp, spec_machine);
226658997Selan strcat (temp, "/");
226758997Selan strcat (temp, spec_version);
226858997Selan strcat (temp, "/");
226958997Selan gcc_exec_prefix = temp;
227058997Selan }
227158997Selan }
227258997Selan
227358997Selan /* Process a spec string, accumulating and running commands. */
227458997Selan
227558997Selan /* These variables describe the input file name.
227658997Selan input_file_number is the index on outfiles of this file,
227758997Selan so that the output file name can be stored for later use by %o.
227858997Selan input_basename is the start of the part of the input file
227958997Selan sans all directory names, and basename_length is the number
228058997Selan of characters starting there excluding the suffix .c or whatever. */
228158997Selan
228258997Selan static char *input_filename;
228358997Selan static int input_file_number;
228458997Selan static int input_filename_length;
228558997Selan static int basename_length;
228658997Selan static char *input_basename;
228758997Selan static char *input_suffix;
228858997Selan
228958997Selan /* These are variables used within do_spec and do_spec_1. */
229058997Selan
229158997Selan /* Nonzero if an arg has been started and not yet terminated
229258997Selan (with space, tab or newline). */
229358997Selan static int arg_going;
229458997Selan
229558997Selan /* Nonzero means %d or %g has been seen; the next arg to be terminated
229658997Selan is a temporary file name. */
229758997Selan static int delete_this_arg;
229858997Selan
229958997Selan /* Nonzero means %w has been seen; the next arg to be terminated
230058997Selan is the output file name of this compilation. */
230158997Selan static int this_is_output_file;
230258997Selan
230358997Selan /* Nonzero means %s has been seen; the next arg to be terminated
230458997Selan is the name of a library file and we should try the standard
230558997Selan search dirs for it. */
230658997Selan static int this_is_library_file;
230758997Selan
230858997Selan /* Process the spec SPEC and run the commands specified therein.
230958997Selan Returns 0 if the spec is successfully processed; -1 if failed. */
231058997Selan
231158997Selan static int
do_spec(spec)231258997Selan do_spec (spec)
231358997Selan char *spec;
231458997Selan {
231558997Selan int value;
231658997Selan
231758997Selan clear_args ();
231858997Selan arg_going = 0;
231958997Selan delete_this_arg = 0;
232058997Selan this_is_output_file = 0;
232158997Selan this_is_library_file = 0;
232258997Selan
232358997Selan value = do_spec_1 (spec, 0, NULL_PTR);
232458997Selan
232558997Selan /* Force out any unfinished command.
232658997Selan If -pipe, this forces out the last command if it ended in `|'. */
232758997Selan if (value == 0)
232858997Selan {
232958997Selan if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
233058997Selan argbuf_index--;
233158997Selan
233258997Selan if (argbuf_index > 0)
233358997Selan value = execute ();
233458997Selan }
233558997Selan
233658997Selan return value;
233758997Selan }
233858997Selan
233958997Selan /* Process the sub-spec SPEC as a portion of a larger spec.
234058997Selan This is like processing a whole spec except that we do
234158997Selan not initialize at the beginning and we do not supply a
234258997Selan newline by default at the end.
234358997Selan INSWITCH nonzero means don't process %-sequences in SPEC;
234458997Selan in this case, % is treated as an ordinary character.
234558997Selan This is used while substituting switches.
234658997Selan INSWITCH nonzero also causes SPC not to terminate an argument.
234758997Selan
234858997Selan Value is zero unless a line was finished
234958997Selan and the command on that line reported an error. */
235058997Selan
235158997Selan static int
do_spec_1(spec,inswitch,soft_matched_part)235258997Selan do_spec_1 (spec, inswitch, soft_matched_part)
235358997Selan char *spec;
235458997Selan int inswitch;
235558997Selan char *soft_matched_part;
235658997Selan {
235758997Selan register char *p = spec;
235858997Selan register int c;
235958997Selan int i;
236058997Selan char *string;
236158997Selan
236258997Selan while (c = *p++)
236358997Selan /* If substituting a switch, treat all chars like letters.
236458997Selan Otherwise, NL, SPC, TAB and % are special. */
236558997Selan switch (inswitch ? 'a' : c)
236658997Selan {
236758997Selan case '\n':
236858997Selan /* End of line: finish any pending argument,
236958997Selan then run the pending command if one has been started. */
237058997Selan if (arg_going)
237158997Selan {
237258997Selan obstack_1grow (&obstack, 0);
237358997Selan string = obstack_finish (&obstack);
237458997Selan if (this_is_library_file)
237558997Selan string = find_file (string);
237658997Selan store_arg (string, delete_this_arg, this_is_output_file);
237758997Selan if (this_is_output_file)
237858997Selan outfiles[input_file_number] = string;
237958997Selan }
238058997Selan arg_going = 0;
238158997Selan
238258997Selan if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
238358997Selan {
238458997Selan int i;
238558997Selan for (i = 0; i < n_switches; i++)
238658997Selan if (!strcmp (switches[i].part1, "pipe"))
238758997Selan break;
238858997Selan
238958997Selan /* A `|' before the newline means use a pipe here,
239058997Selan but only if -pipe was specified.
239158997Selan Otherwise, execute now and don't pass the `|' as an arg. */
239258997Selan if (i < n_switches)
239358997Selan {
239458997Selan switches[i].valid = 1;
239558997Selan break;
239658997Selan }
239758997Selan else
239858997Selan argbuf_index--;
239958997Selan }
240058997Selan
240158997Selan if (argbuf_index > 0)
240258997Selan {
240358997Selan int value = execute ();
240458997Selan if (value)
240558997Selan return value;
240658997Selan }
240758997Selan /* Reinitialize for a new command, and for a new argument. */
240858997Selan clear_args ();
240958997Selan arg_going = 0;
241058997Selan delete_this_arg = 0;
241158997Selan this_is_output_file = 0;
241258997Selan this_is_library_file = 0;
241358997Selan break;
241458997Selan
241558997Selan case '|':
241658997Selan /* End any pending argument. */
241758997Selan if (arg_going)
241858997Selan {
241958997Selan obstack_1grow (&obstack, 0);
242058997Selan string = obstack_finish (&obstack);
242158997Selan if (this_is_library_file)
242258997Selan string = find_file (string);
242358997Selan store_arg (string, delete_this_arg, this_is_output_file);
242458997Selan if (this_is_output_file)
242558997Selan outfiles[input_file_number] = string;
242658997Selan }
242758997Selan
242858997Selan /* Use pipe */
242958997Selan obstack_1grow (&obstack, c);
243058997Selan arg_going = 1;
243158997Selan break;
243258997Selan
243358997Selan case '\t':
243458997Selan case ' ':
243558997Selan /* Space or tab ends an argument if one is pending. */
243658997Selan if (arg_going)
243758997Selan {
243858997Selan obstack_1grow (&obstack, 0);
243958997Selan string = obstack_finish (&obstack);
244058997Selan if (this_is_library_file)
244158997Selan string = find_file (string);
244258997Selan store_arg (string, delete_this_arg, this_is_output_file);
244358997Selan if (this_is_output_file)
244458997Selan outfiles[input_file_number] = string;
244558997Selan }
244658997Selan /* Reinitialize for a new argument. */
244758997Selan arg_going = 0;
244858997Selan delete_this_arg = 0;
244958997Selan this_is_output_file = 0;
245058997Selan this_is_library_file = 0;
245158997Selan break;
245258997Selan
245358997Selan case '%':
245458997Selan switch (c = *p++)
245558997Selan {
245658997Selan case 0:
245758997Selan fatal ("Invalid specification! Bug in cc.");
245858997Selan
245958997Selan case 'b':
246058997Selan obstack_grow (&obstack, input_basename, basename_length);
246158997Selan arg_going = 1;
246258997Selan break;
246358997Selan
246458997Selan case 'd':
246558997Selan delete_this_arg = 2;
246658997Selan break;
246758997Selan
246858997Selan /* Dump out the directories specified with LIBRARY_PATH,
246958997Selan followed by the absolute directories
247058997Selan that we search for startfiles. */
247158997Selan case 'D':
247258997Selan for (i = 0; i < 2; i++)
247358997Selan {
247458997Selan struct prefix_list *pl
247558997Selan = (i == 0 ? library_prefix.plist : startfile_prefix.plist);
247658997Selan int bufsize = 100;
247758997Selan char *buffer = (char *) xmalloc (bufsize);
247858997Selan int idx;
247958997Selan
248058997Selan for (; pl; pl = pl->next)
248158997Selan {
248258997Selan #ifdef RELATIVE_PREFIX_NOT_LINKDIR
248358997Selan /* Used on systems which record the specified -L dirs
248458997Selan and use them to search for dynamic linking. */
248558997Selan /* Relative directories always come from -B,
248658997Selan and it is better not to use them for searching
248758997Selan at run time. In particular, stage1 loses */
248858997Selan if (pl->prefix[0] != '/')
248958997Selan continue;
249058997Selan #endif
249158997Selan if (machine_suffix)
249258997Selan {
249358997Selan if (is_linker_dir (pl->prefix, machine_suffix))
249458997Selan {
249558997Selan do_spec_1 ("-L", 0, NULL_PTR);
249658997Selan #ifdef SPACE_AFTER_L_OPTION
249758997Selan do_spec_1 (" ", 0, NULL_PTR);
249858997Selan #endif
249958997Selan do_spec_1 (pl->prefix, 1, NULL_PTR);
250058997Selan /* Remove slash from machine_suffix. */
250158997Selan if (strlen (machine_suffix) >= bufsize)
250258997Selan bufsize = strlen (machine_suffix) * 2 + 1;
250358997Selan buffer = (char *) xrealloc (buffer, bufsize);
250458997Selan strcpy (buffer, machine_suffix);
250558997Selan idx = strlen (buffer);
250658997Selan if (buffer[idx - 1] == '/')
250758997Selan buffer[idx - 1] = 0;
250858997Selan do_spec_1 (buffer, 1, NULL_PTR);
250958997Selan /* Make this a separate argument. */
251058997Selan do_spec_1 (" ", 0, NULL_PTR);
251158997Selan }
251258997Selan }
251358997Selan if (!pl->require_machine_suffix)
251458997Selan {
251558997Selan if (is_linker_dir (pl->prefix, ""))
251658997Selan {
251758997Selan do_spec_1 ("-L", 0, NULL_PTR);
251858997Selan #ifdef SPACE_AFTER_L_OPTION
251958997Selan do_spec_1 (" ", 0, NULL_PTR);
252058997Selan #endif
252158997Selan /* Remove slash from pl->prefix. */
252258997Selan if (strlen (pl->prefix) >= bufsize)
252358997Selan bufsize = strlen (pl->prefix) * 2 + 1;
252458997Selan buffer = (char *) xrealloc (buffer, bufsize);
252558997Selan strcpy (buffer, pl->prefix);
252658997Selan idx = strlen (buffer);
252758997Selan if (buffer[idx - 1] == '/')
252858997Selan buffer[idx - 1] = 0;
252958997Selan do_spec_1 (buffer, 1, NULL_PTR);
253058997Selan /* Make this a separate argument. */
253158997Selan do_spec_1 (" ", 0, NULL_PTR);
253258997Selan }
253358997Selan }
253458997Selan }
253558997Selan free (buffer);
253658997Selan }
253758997Selan break;
253858997Selan
253958997Selan case 'e':
254058997Selan /* {...:%efoo} means report an error with `foo' as error message
254158997Selan and don't execute any more commands for this file. */
254258997Selan {
254358997Selan char *q = p;
254458997Selan char *buf;
254558997Selan while (*p != 0 && *p != '\n') p++;
254658997Selan buf = (char *) alloca (p - q + 1);
254758997Selan strncpy (buf, q, p - q);
254858997Selan buf[p - q] = 0;
254958997Selan error ("%s", buf);
255058997Selan return -1;
255158997Selan }
255258997Selan break;
255358997Selan
255458997Selan case 'g':
255558997Selan case 'u':
255658997Selan case 'U':
255758997Selan if (save_temps_flag)
255858997Selan obstack_grow (&obstack, input_basename, basename_length);
255958997Selan else
256058997Selan {
256158997Selan #ifdef MKTEMP_EACH_FILE
256258997Selan /* ??? This has a problem: the total number of
256358997Selan values mktemp can return is limited.
256458997Selan That matters for the names of object files.
256558997Selan In 2.4, do something about that. */
256658997Selan struct temp_name *t;
256758997Selan char *suffix = p;
256858997Selan while (*p == '.' || isalpha (*p))
256958997Selan p++;
257058997Selan
257158997Selan /* See if we already have an association of %g/%u/%U and
257258997Selan suffix. */
257358997Selan for (t = temp_names; t; t = t->next)
257458997Selan if (t->length == p - suffix
257558997Selan && strncmp (t->suffix, suffix, p - suffix) == 0
257658997Selan && t->unique == (c != 'g'))
257758997Selan break;
257858997Selan
257958997Selan /* Make a new association if needed. %u requires one. */
258058997Selan if (t == 0 || c == 'u')
258158997Selan {
258258997Selan if (t == 0)
258358997Selan {
258458997Selan t = (struct temp_name *) xmalloc (sizeof (struct temp_name));
258558997Selan t->next = temp_names;
258658997Selan temp_names = t;
258758997Selan }
258858997Selan t->length = p - suffix;
258958997Selan t->suffix = save_string (suffix, p - suffix);
259058997Selan t->unique = (c != 'g');
259158997Selan choose_temp_base ();
259258997Selan t->filename = temp_filename;
259358997Selan t->filename_length = temp_filename_length;
259458997Selan }
259558997Selan
259658997Selan obstack_grow (&obstack, t->filename, t->filename_length);
259758997Selan delete_this_arg = 1;
259858997Selan #else
259958997Selan obstack_grow (&obstack, temp_filename, temp_filename_length);
260058997Selan if (c == 'u' || c == 'U')
260158997Selan {
260258997Selan static int unique;
260358997Selan char buff[9];
260458997Selan if (c == 'u')
260558997Selan unique++;
260658997Selan sprintf (buff, "%d", unique);
260758997Selan obstack_grow (&obstack, buff, strlen (buff));
260858997Selan }
260958997Selan #endif
261058997Selan delete_this_arg = 1;
261158997Selan }
261258997Selan arg_going = 1;
261358997Selan break;
261458997Selan
261558997Selan case 'i':
261658997Selan obstack_grow (&obstack, input_filename, input_filename_length);
261758997Selan arg_going = 1;
261858997Selan break;
261958997Selan
262058997Selan case 'I':
262158997Selan if (gcc_exec_prefix)
262258997Selan {
262358997Selan do_spec_1 ("-iprefix", 1, NULL_PTR);
262458997Selan /* Make this a separate argument. */
262558997Selan do_spec_1 (" ", 0, NULL_PTR);
262658997Selan do_spec_1 (gcc_exec_prefix, 1, NULL_PTR);
262758997Selan do_spec_1 (" ", 0, NULL_PTR);
262858997Selan }
262958997Selan break;
263058997Selan
263158997Selan case 'o':
263258997Selan {
263358997Selan register int f;
263458997Selan for (f = 0; f < n_infiles; f++)
263558997Selan store_arg (outfiles[f], 0, 0);
263658997Selan }
263758997Selan break;
263858997Selan
263958997Selan case 's':
264058997Selan this_is_library_file = 1;
264158997Selan break;
264258997Selan
264358997Selan case 'w':
264458997Selan this_is_output_file = 1;
264558997Selan break;
264658997Selan
264758997Selan case 'W':
264858997Selan {
264958997Selan int index = argbuf_index;
265058997Selan /* Handle the {...} following the %W. */
265158997Selan if (*p != '{')
265258997Selan abort ();
265358997Selan p = handle_braces (p + 1);
265458997Selan if (p == 0)
265558997Selan return -1;
265658997Selan /* If any args were output, mark the last one for deletion
265758997Selan on failure. */
265858997Selan if (argbuf_index != index)
265958997Selan record_temp_file (argbuf[argbuf_index - 1], 0, 1);
266058997Selan break;
266158997Selan }
266258997Selan
266358997Selan /* %x{OPTION} records OPTION for %X to output. */
266458997Selan case 'x':
266558997Selan {
266658997Selan char *p1 = p;
266758997Selan char *string;
266858997Selan
266958997Selan /* Skip past the option value and make a copy. */
267058997Selan if (*p != '{')
267158997Selan abort ();
267258997Selan while (*p++ != '}')
267358997Selan ;
267458997Selan string = save_string (p1 + 1, p - p1 - 2);
267558997Selan
267658997Selan /* See if we already recorded this option. */
267758997Selan for (i = 0; i < n_linker_options; i++)
267858997Selan if (! strcmp (string, linker_options[i]))
267958997Selan {
268058997Selan free (string);
268158997Selan return 0;
268258997Selan }
268358997Selan
268458997Selan /* This option is new; add it. */
268558997Selan n_linker_options++;
268658997Selan if (!linker_options)
268758997Selan linker_options
268858997Selan = (char **) xmalloc (n_linker_options * sizeof (char **));
268958997Selan else
269058997Selan linker_options
269158997Selan = (char **) xrealloc (linker_options,
269258997Selan n_linker_options * sizeof (char **));
269358997Selan
269458997Selan linker_options[n_linker_options - 1] = string;
269558997Selan }
269658997Selan break;
269758997Selan
269858997Selan /* Dump out the options accumulated previously using %x,
269958997Selan -Xlinker and -Wl,. */
270058997Selan case 'X':
270158997Selan for (i = 0; i < n_linker_options; i++)
270258997Selan {
270358997Selan do_spec_1 (linker_options[i], 1, NULL_PTR);
270458997Selan /* Make each accumulated option a separate argument. */
270558997Selan do_spec_1 (" ", 0, NULL_PTR);
270658997Selan }
270758997Selan break;
270858997Selan
270958997Selan /* Dump out the options accumulated previously using -Wa,. */
271058997Selan case 'Y':
271158997Selan for (i = 0; i < n_assembler_options; i++)
271258997Selan {
271358997Selan do_spec_1 (assembler_options[i], 1, NULL_PTR);
271458997Selan /* Make each accumulated option a separate argument. */
271558997Selan do_spec_1 (" ", 0, NULL_PTR);
271658997Selan }
271758997Selan break;
271858997Selan
271958997Selan /* Here are digits and numbers that just process
272058997Selan a certain constant string as a spec.
272158997Selan /* Here are digits and numbers that just process
272258997Selan a certain constant string as a spec. */
272358997Selan
272458997Selan case '1':
272558997Selan do_spec_1 (cc1_spec, 0, NULL_PTR);
272658997Selan break;
272758997Selan
272858997Selan case '2':
272958997Selan do_spec_1 (cc1plus_spec, 0, NULL_PTR);
273058997Selan break;
273158997Selan
273258997Selan case 'a':
273358997Selan do_spec_1 (asm_spec, 0, NULL_PTR);
273458997Selan break;
273558997Selan
273658997Selan case 'A':
273758997Selan do_spec_1 (asm_final_spec, 0, NULL_PTR);
273858997Selan break;
273958997Selan
274058997Selan case 'c':
274158997Selan do_spec_1 (signed_char_spec, 0, NULL_PTR);
274258997Selan break;
274358997Selan
274458997Selan case 'C':
274558997Selan do_spec_1 (cpp_spec, 0, NULL_PTR);
274658997Selan break;
274758997Selan
274858997Selan case 'E':
274958997Selan do_spec_1 (endfile_spec, 0, NULL_PTR);
275058997Selan break;
275158997Selan
275258997Selan case 'l':
275358997Selan do_spec_1 (link_spec, 0, NULL_PTR);
275458997Selan break;
275558997Selan
275658997Selan case 'L':
275758997Selan do_spec_1 (lib_spec, 0, NULL_PTR);
275858997Selan break;
275958997Selan
276058997Selan case 'p':
276158997Selan {
276258997Selan char *x = (char *) alloca (strlen (cpp_predefines) + 1);
276358997Selan char *buf = x;
276458997Selan char *y;
276558997Selan
276658997Selan /* Copy all of the -D options in CPP_PREDEFINES into BUF. */
276758997Selan y = cpp_predefines;
276858997Selan while (*y != 0)
276958997Selan {
277058997Selan if (! strncmp (y, "-D", 2))
277158997Selan /* Copy the whole option. */
277258997Selan while (*y && *y != ' ' && *y != '\t')
277358997Selan *x++ = *y++;
277458997Selan else if (*y == ' ' || *y == '\t')
277558997Selan /* Copy whitespace to the result. */
277658997Selan *x++ = *y++;
277758997Selan /* Don't copy other options. */
277858997Selan else
277958997Selan y++;
278058997Selan }
278158997Selan
278258997Selan *x = 0;
278358997Selan
278458997Selan do_spec_1 (buf, 0, NULL_PTR);
278558997Selan }
278658997Selan break;
278758997Selan
278858997Selan case 'P':
278958997Selan {
279058997Selan char *x = (char *) alloca (strlen (cpp_predefines) * 4 + 1);
279158997Selan char *buf = x;
279258997Selan char *y;
279358997Selan
279458997Selan /* Copy all of CPP_PREDEFINES into BUF,
279558997Selan but put __ after every -D and at the end of each arg. */
279658997Selan y = cpp_predefines;
279758997Selan while (*y != 0)
279858997Selan {
279958997Selan if (! strncmp (y, "-D", 2))
280058997Selan {
280158997Selan int flag = 0;
280258997Selan
280358997Selan *x++ = *y++;
280458997Selan *x++ = *y++;
280558997Selan
280658997Selan if (strncmp (y, "__", 2))
280758997Selan {
280858997Selan /* Stick __ at front of macro name. */
280958997Selan *x++ = '_';
281058997Selan *x++ = '_';
281158997Selan /* Arrange to stick __ at the end as well. */
281258997Selan flag = 1;
281358997Selan }
281458997Selan
281558997Selan /* Copy the macro name. */
281658997Selan while (*y && *y != '=' && *y != ' ' && *y != '\t')
281758997Selan *x++ = *y++;
281858997Selan
281958997Selan if (flag)
282058997Selan {
282158997Selan *x++ = '_';
282258997Selan *x++ = '_';
282358997Selan }
282458997Selan
282558997Selan /* Copy the value given, if any. */
282658997Selan while (*y && *y != ' ' && *y != '\t')
282758997Selan *x++ = *y++;
282858997Selan }
282958997Selan else if (*y == ' ' || *y == '\t')
283058997Selan /* Copy whitespace to the result. */
283158997Selan *x++ = *y++;
283258997Selan /* Don't copy -A options */
283358997Selan else
283458997Selan y++;
283558997Selan }
283658997Selan *x++ = ' ';
283758997Selan
283858997Selan /* Copy all of CPP_PREDEFINES into BUF,
283958997Selan but put __ after every -D. */
284058997Selan y = cpp_predefines;
284158997Selan while (*y != 0)
284258997Selan {
284358997Selan if (! strncmp (y, "-D", 2))
284458997Selan {
284558997Selan *x++ = *y++;
284658997Selan *x++ = *y++;
284758997Selan
284858997Selan if (strncmp (y, "__", 2))
284958997Selan {
285058997Selan /* Stick __ at front of macro name. */
285158997Selan *x++ = '_';
285258997Selan *x++ = '_';
285358997Selan }
285458997Selan
285558997Selan /* Copy the macro name. */
285658997Selan while (*y && *y != '=' && *y != ' ' && *y != '\t')
285758997Selan *x++ = *y++;
285858997Selan
285958997Selan /* Copy the value given, if any. */
286058997Selan while (*y && *y != ' ' && *y != '\t')
286158997Selan *x++ = *y++;
286258997Selan }
286358997Selan else if (*y == ' ' || *y == '\t')
286458997Selan /* Copy whitespace to the result. */
286558997Selan *x++ = *y++;
286658997Selan /* Don't copy -A options */
286758997Selan else
286858997Selan y++;
286958997Selan }
287058997Selan *x++ = ' ';
287158997Selan
287258997Selan /* Copy all of the -A options in CPP_PREDEFINES into BUF. */
287358997Selan y = cpp_predefines;
287458997Selan while (*y != 0)
287558997Selan {
287658997Selan if (! strncmp (y, "-A", 2))
287758997Selan /* Copy the whole option. */
287858997Selan while (*y && *y != ' ' && *y != '\t')
287958997Selan *x++ = *y++;
288058997Selan else if (*y == ' ' || *y == '\t')
288158997Selan /* Copy whitespace to the result. */
288258997Selan *x++ = *y++;
288358997Selan /* Don't copy other options. */
288458997Selan else
288558997Selan y++;
288658997Selan }
288758997Selan
288858997Selan *x = 0;
288958997Selan
289058997Selan do_spec_1 (buf, 0, NULL_PTR);
289158997Selan }
289258997Selan break;
289358997Selan
289458997Selan case 'S':
289558997Selan do_spec_1 (startfile_spec, 0, NULL_PTR);
289658997Selan break;
289758997Selan
289858997Selan /* Here we define characters other than letters and digits. */
289958997Selan
290058997Selan case '{':
290158997Selan p = handle_braces (p);
290258997Selan if (p == 0)
290358997Selan return -1;
290458997Selan break;
290558997Selan
290658997Selan case '%':
290758997Selan obstack_1grow (&obstack, '%');
290858997Selan break;
290958997Selan
291058997Selan case '*':
291158997Selan do_spec_1 (soft_matched_part, 1, NULL_PTR);
291258997Selan do_spec_1 (" ", 0, NULL_PTR);
291358997Selan break;
291458997Selan
291558997Selan /* Process a string found as the value of a spec given by name.
291658997Selan This feature allows individual machine descriptions
291758997Selan to add and use their own specs.
291858997Selan %[...] modifies -D options the way %P does;
291958997Selan %(...) uses the spec unmodified. */
292058997Selan case '(':
292158997Selan case '[':
292258997Selan {
292358997Selan char *name = p;
292458997Selan struct spec_list *sl;
292558997Selan int len;
292658997Selan
292758997Selan /* The string after the S/P is the name of a spec that is to be
292858997Selan processed. */
292958997Selan while (*p && *p != ')' && *p != ']')
293058997Selan p++;
293158997Selan
293258997Selan /* See if it's in the list */
293358997Selan for (len = p - name, sl = specs; sl; sl = sl->next)
293458997Selan if (strncmp (sl->name, name, len) == 0 && !sl->name[len])
293558997Selan {
293658997Selan name = sl->spec;
293758997Selan break;
293858997Selan }
293958997Selan
294058997Selan if (sl)
294158997Selan {
294258997Selan if (c == '(')
294358997Selan do_spec_1 (name, 0, NULL_PTR);
294458997Selan else
294558997Selan {
294658997Selan char *x = (char *) alloca (strlen (name) * 2 + 1);
294758997Selan char *buf = x;
294858997Selan char *y = name;
294958997Selan
295058997Selan /* Copy all of NAME into BUF, but put __ after
295158997Selan every -D and at the end of each arg, */
295258997Selan while (1)
295358997Selan {
295458997Selan if (! strncmp (y, "-D", 2))
295558997Selan {
295658997Selan *x++ = '-';
295758997Selan *x++ = 'D';
295858997Selan *x++ = '_';
295958997Selan *x++ = '_';
296058997Selan y += 2;
296158997Selan }
296258997Selan else if (*y == ' ' || *y == 0)
296358997Selan {
296458997Selan *x++ = '_';
296558997Selan *x++ = '_';
296658997Selan if (*y == 0)
296758997Selan break;
296858997Selan else
296958997Selan *x++ = *y++;
297058997Selan }
297158997Selan else
297258997Selan *x++ = *y++;
297358997Selan }
297458997Selan *x = 0;
297558997Selan
297658997Selan do_spec_1 (buf, 0, NULL_PTR);
297758997Selan }
297858997Selan }
297958997Selan
298058997Selan /* Discard the closing paren or bracket. */
298158997Selan if (*p)
298258997Selan p++;
298358997Selan }
298458997Selan break;
298558997Selan
298658997Selan default:
298758997Selan abort ();
298858997Selan }
298958997Selan break;
299058997Selan
299158997Selan case '\\':
299258997Selan /* Backslash: treat next character as ordinary. */
299358997Selan c = *p++;
299458997Selan
299558997Selan /* fall through */
299658997Selan default:
299758997Selan /* Ordinary character: put it into the current argument. */
299858997Selan obstack_1grow (&obstack, c);
299958997Selan arg_going = 1;
300058997Selan }
300158997Selan
300258997Selan return 0; /* End of string */
300358997Selan }
300458997Selan
300558997Selan /* Return 0 if we call do_spec_1 and that returns -1. */
300658997Selan
300758997Selan static char *
handle_braces(p)300858997Selan handle_braces (p)
300958997Selan register char *p;
301058997Selan {
301158997Selan register char *q;
301258997Selan char *filter;
301358997Selan int pipe = 0;
301458997Selan int negate = 0;
301558997Selan int suffix = 0;
301658997Selan
301758997Selan if (*p == '|')
301858997Selan /* A `|' after the open-brace means,
301958997Selan if the test fails, output a single minus sign rather than nothing.
302058997Selan This is used in %{|!pipe:...}. */
302158997Selan pipe = 1, ++p;
302258997Selan
302358997Selan if (*p == '!')
302458997Selan /* A `!' after the open-brace negates the condition:
302558997Selan succeed if the specified switch is not present. */
302658997Selan negate = 1, ++p;
302758997Selan
302858997Selan if (*p == '.')
302958997Selan /* A `.' after the open-brace means test against the current suffix. */
303058997Selan {
303158997Selan if (pipe)
303258997Selan abort ();
303358997Selan
303458997Selan suffix = 1;
303558997Selan ++p;
303658997Selan }
303758997Selan
303858997Selan filter = p;
303958997Selan while (*p != ':' && *p != '}') p++;
304058997Selan if (*p != '}')
304158997Selan {
304258997Selan register int count = 1;
304358997Selan q = p + 1;
304458997Selan while (count > 0)
304558997Selan {
304658997Selan if (*q == '{')
304758997Selan count++;
304858997Selan else if (*q == '}')
304958997Selan count--;
305058997Selan else if (*q == 0)
305158997Selan abort ();
305258997Selan q++;
305358997Selan }
305458997Selan }
305558997Selan else
305658997Selan q = p + 1;
305758997Selan
305858997Selan if (suffix)
305958997Selan {
306058997Selan int found = (input_suffix != 0
306158997Selan && strlen (input_suffix) == p - filter
306258997Selan && strncmp (input_suffix, filter, p - filter) == 0);
306358997Selan
306458997Selan if (p[0] == '}')
306558997Selan abort ();
306658997Selan
306758997Selan if (negate != found
306858997Selan && do_spec_1 (save_string (p + 1, q - p - 2), 0, NULL_PTR) < 0)
306958997Selan return 0;
307058997Selan
307158997Selan return q;
307258997Selan }
307358997Selan else if (p[-1] == '*' && p[0] == '}')
307458997Selan {
307558997Selan /* Substitute all matching switches as separate args. */
307658997Selan register int i;
307758997Selan --p;
307858997Selan for (i = 0; i < n_switches; i++)
307958997Selan if (!strncmp (switches[i].part1, filter, p - filter))
308058997Selan give_switch (i, 0);
308158997Selan }
308258997Selan else
308358997Selan {
308458997Selan /* Test for presence of the specified switch. */
308558997Selan register int i;
308658997Selan int present = 0;
308758997Selan
308858997Selan /* If name specified ends in *, as in {x*:...},
308958997Selan check for %* and handle that case. */
309058997Selan if (p[-1] == '*' && !negate)
309158997Selan {
309258997Selan int substitution;
309358997Selan char *r = p;
309458997Selan
309558997Selan /* First see whether we have %*. */
309658997Selan substitution = 0;
309758997Selan while (r < q)
309858997Selan {
309958997Selan if (*r == '%' && r[1] == '*')
310058997Selan substitution = 1;
310158997Selan r++;
310258997Selan }
310358997Selan /* If we do, handle that case. */
310458997Selan if (substitution)
310558997Selan {
310658997Selan /* Substitute all matching switches as separate args.
310758997Selan But do this by substituting for %*
310858997Selan in the text that follows the colon. */
310958997Selan
311058997Selan unsigned hard_match_len = p - filter - 1;
311158997Selan char *string = save_string (p + 1, q - p - 2);
311258997Selan
311358997Selan for (i = 0; i < n_switches; i++)
311458997Selan if (!strncmp (switches[i].part1, filter, hard_match_len))
311558997Selan {
311658997Selan do_spec_1 (string, 0, &switches[i].part1[hard_match_len]);
311758997Selan /* Pass any arguments this switch has. */
311858997Selan give_switch (i, 1);
311958997Selan }
312058997Selan
312158997Selan return q;
312258997Selan }
312358997Selan }
312458997Selan
312558997Selan /* If name specified ends in *, as in {x*:...},
312658997Selan check for presence of any switch name starting with x. */
312758997Selan if (p[-1] == '*')
312858997Selan {
312958997Selan for (i = 0; i < n_switches; i++)
313058997Selan {
313158997Selan unsigned hard_match_len = p - filter - 1;
313258997Selan
313358997Selan if (!strncmp (switches[i].part1, filter, hard_match_len))
313458997Selan {
313558997Selan switches[i].valid = 1;
313658997Selan present = 1;
313758997Selan }
313858997Selan }
313958997Selan }
314058997Selan /* Otherwise, check for presence of exact name specified. */
314158997Selan else
314258997Selan {
314358997Selan for (i = 0; i < n_switches; i++)
314458997Selan {
314558997Selan if (!strncmp (switches[i].part1, filter, p - filter)
314658997Selan && switches[i].part1[p - filter] == 0)
314758997Selan {
314858997Selan switches[i].valid = 1;
314958997Selan present = 1;
315058997Selan break;
315158997Selan }
315258997Selan }
315358997Selan }
315458997Selan
315558997Selan /* If it is as desired (present for %{s...}, absent for %{-s...})
315658997Selan then substitute either the switch or the specified
315758997Selan conditional text. */
315858997Selan if (present != negate)
315958997Selan {
316058997Selan if (*p == '}')
316158997Selan {
316258997Selan give_switch (i, 0);
316358997Selan }
316458997Selan else
316558997Selan {
316658997Selan if (do_spec_1 (save_string (p + 1, q - p - 2), 0, NULL_PTR) < 0)
316758997Selan return 0;
316858997Selan }
316958997Selan }
317058997Selan else if (pipe)
317158997Selan {
317258997Selan /* Here if a %{|...} conditional fails: output a minus sign,
317358997Selan which means "standard output" or "standard input". */
317458997Selan do_spec_1 ("-", 0, NULL_PTR);
317558997Selan }
317658997Selan }
317758997Selan
317858997Selan return q;
317958997Selan }
318058997Selan
318158997Selan /* Pass a switch to the current accumulating command
318258997Selan in the same form that we received it.
318358997Selan SWITCHNUM identifies the switch; it is an index into
318458997Selan the vector of switches gcc received, which is `switches'.
318558997Selan This cannot fail since it never finishes a command line.
318658997Selan
318758997Selan If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument. */
318858997Selan
318958997Selan static void
give_switch(switchnum,omit_first_word)319058997Selan give_switch (switchnum, omit_first_word)
319158997Selan int switchnum;
319258997Selan int omit_first_word;
319358997Selan {
319458997Selan if (!omit_first_word)
319558997Selan {
319658997Selan do_spec_1 ("-", 0, NULL_PTR);
319758997Selan do_spec_1 (switches[switchnum].part1, 1, NULL_PTR);
319858997Selan }
319958997Selan do_spec_1 (" ", 0, NULL_PTR);
320058997Selan if (switches[switchnum].args != 0)
320158997Selan {
320258997Selan char **p;
320358997Selan for (p = switches[switchnum].args; *p; p++)
320458997Selan {
320558997Selan do_spec_1 (*p, 1, NULL_PTR);
320658997Selan do_spec_1 (" ", 0, NULL_PTR);
320758997Selan }
320858997Selan }
320958997Selan switches[switchnum].valid = 1;
321058997Selan }
321158997Selan
321258997Selan /* Search for a file named NAME trying various prefixes including the
321358997Selan user's -B prefix and some standard ones.
321458997Selan Return the absolute file name found. If nothing is found, return NAME. */
321558997Selan
321658997Selan static char *
find_file(name)321758997Selan find_file (name)
321858997Selan char *name;
321958997Selan {
322058997Selan char *newname;
322158997Selan
322258997Selan newname = find_a_file (&startfile_prefix, name, R_OK);
322358997Selan return newname ? newname : name;
322458997Selan }
322558997Selan
322658997Selan /* Determine whether a -L option is relevant. Not required for certain
322758997Selan fixed names and for directories that don't exist. */
322858997Selan
322958997Selan static int
is_linker_dir(path1,path2)323058997Selan is_linker_dir (path1, path2)
323158997Selan char *path1;
323258997Selan char *path2;
323358997Selan {
323458997Selan int len1 = strlen (path1);
323558997Selan int len2 = strlen (path2);
323658997Selan char *path = (char *) alloca (3 + len1 + len2);
323758997Selan char *cp;
323858997Selan struct stat st;
323958997Selan
324058997Selan /* Construct the path from the two parts. Ensure the string ends with "/.".
324158997Selan The resulting path will be a directory even if the given path is a
324258997Selan symbolic link. */
324358997Selan bcopy (path1, path, len1);
324458997Selan bcopy (path2, path + len1, len2);
324558997Selan cp = path + len1 + len2;
324658997Selan if (cp[-1] != '/')
324758997Selan *cp++ = '/';
324858997Selan *cp++ = '.';
324958997Selan *cp = '\0';
325058997Selan
325158997Selan /* Exclude directories that the linker is known to search. */
325258997Selan if ((cp - path == 6 && strcmp (path, "/lib/.") == 0)
325358997Selan || (cp - path == 10 && strcmp (path, "/usr/lib/.") == 0))
325458997Selan return 0;
325558997Selan
325658997Selan return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
325758997Selan }
325858997Selan
325958997Selan /* On fatal signals, delete all the temporary files. */
326058997Selan
326158997Selan static void
fatal_error(signum)326258997Selan fatal_error (signum)
326358997Selan int signum;
326458997Selan {
326558997Selan signal (signum, SIG_DFL);
326658997Selan delete_failure_queue ();
326758997Selan delete_temp_files ();
326858997Selan /* Get the same signal again, this time not handled,
326958997Selan so its normal effect occurs. */
327058997Selan kill (getpid (), signum);
327158997Selan }
327258997Selan
327358997Selan int
main(argc,argv)327458997Selan main (argc, argv)
327558997Selan int argc;
327658997Selan char **argv;
327758997Selan {
327858997Selan register int i;
327958997Selan int j;
328058997Selan int value;
328158997Selan int error_count = 0;
328258997Selan int linker_was_run = 0;
328358997Selan char *explicit_link_files;
328458997Selan char *specs_file;
328558997Selan
328658997Selan programname = argv[0];
328758997Selan
328858997Selan if (signal (SIGINT, SIG_IGN) != SIG_IGN)
328958997Selan signal (SIGINT, fatal_error);
329058997Selan if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
329158997Selan signal (SIGHUP, fatal_error);
329258997Selan if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
329358997Selan signal (SIGTERM, fatal_error);
329458997Selan #ifdef SIGPIPE
329558997Selan if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
329658997Selan signal (SIGPIPE, fatal_error);
329758997Selan #endif
329858997Selan
329958997Selan argbuf_length = 10;
330058997Selan argbuf = (char **) xmalloc (argbuf_length * sizeof (char *));
330158997Selan
330258997Selan obstack_init (&obstack);
330358997Selan
330458997Selan /* Set up to remember the pathname of gcc and any options
330558997Selan needed for collect. */
330658997Selan obstack_init (&collect_obstack);
330758997Selan obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=")-1);
330858997Selan obstack_grow (&collect_obstack, programname, strlen (programname)+1);
330958997Selan putenv (obstack_finish (&collect_obstack));
331058997Selan
331158997Selan /* Choose directory for temp files. */
331258997Selan
331358997Selan choose_temp_base ();
331458997Selan
331558997Selan /* Make a table of what switches there are (switches, n_switches).
331658997Selan Make a table of specified input files (infiles, n_infiles).
331758997Selan Decode switches that are handled locally. */
331858997Selan
331958997Selan process_command (argc, argv);
332058997Selan
332158997Selan /* Initialize the vector of specs to just the default.
332258997Selan This means one element containing 0s, as a terminator. */
332358997Selan
332458997Selan compilers = (struct compiler *) xmalloc (sizeof default_compilers);
332558997Selan bcopy (default_compilers, compilers, sizeof default_compilers);
332658997Selan n_compilers = n_default_compilers;
332758997Selan
332858997Selan /* Read specs from a file if there is one. */
332958997Selan
333058997Selan machine_suffix = concat (spec_machine, "/", concat (spec_version, "/", ""));
333158997Selan just_machine_suffix = concat (spec_machine, "/", "");
333258997Selan
333358997Selan specs_file = find_a_file (&startfile_prefix, "specs", R_OK);
333458997Selan /* Read the specs file unless it is a default one. */
333558997Selan if (specs_file != 0 && strcmp (specs_file, "specs"))
333658997Selan read_specs (specs_file);
333758997Selan
333858997Selan /* If not cross-compiling, look for startfiles in the standard places. */
333958997Selan /* The fact that these are done here, after reading the specs file,
334058997Selan means that it cannot be found in these directories.
334158997Selan But that's okay. It should never be there anyway. */
334258997Selan if (!cross_compile)
334358997Selan {
334458997Selan #ifdef MD_EXEC_PREFIX
334558997Selan add_prefix (&exec_prefix, md_exec_prefix, 0, 0, NULL_PTR);
334658997Selan add_prefix (&startfile_prefix, md_exec_prefix, 0, 0, NULL_PTR);
334758997Selan #endif
334858997Selan
334958997Selan #ifdef MD_STARTFILE_PREFIX
335058997Selan add_prefix (&startfile_prefix, md_startfile_prefix, 0, 0, NULL_PTR);
335158997Selan #endif
335258997Selan
335358997Selan #ifdef MD_STARTFILE_PREFIX_1
335458997Selan add_prefix (&startfile_prefix, md_startfile_prefix_1, 0, 0, NULL_PTR);
335558997Selan #endif
335658997Selan
335758997Selan add_prefix (&startfile_prefix, standard_startfile_prefix, 0, 0,
335858997Selan NULL_PTR);
335958997Selan add_prefix (&startfile_prefix, standard_startfile_prefix_1, 0, 0,
336058997Selan NULL_PTR);
336158997Selan add_prefix (&startfile_prefix, standard_startfile_prefix_2, 0, 0,
336258997Selan NULL_PTR);
336358997Selan #if 0 /* Can cause surprises, and one can use -B./ instead. */
336458997Selan add_prefix (&startfile_prefix, "./", 0, 1, NULL_PTR);
336558997Selan #endif
336658997Selan }
336758997Selan
336858997Selan /* Now we have the specs.
336958997Selan Set the `valid' bits for switches that match anything in any spec. */
337058997Selan
337158997Selan validate_all_switches ();
337258997Selan
337358997Selan /* Warn about any switches that no pass was interested in. */
337458997Selan
337558997Selan for (i = 0; i < n_switches; i++)
337658997Selan if (! switches[i].valid)
337758997Selan error ("unrecognized option `-%s'", switches[i].part1);
337858997Selan
337958997Selan if (print_libgcc_file_name)
338058997Selan {
338158997Selan printf ("%s\n", find_file ("libgcc.a"));
338258997Selan exit (0);
338358997Selan }
338458997Selan
338558997Selan /* Obey some of the options. */
338658997Selan
338758997Selan if (verbose_flag)
338858997Selan {
338958997Selan fprintf (stderr, "gcc version %s\n", version_string);
339058997Selan if (n_infiles == 0)
339158997Selan exit (0);
339258997Selan }
339358997Selan
339458997Selan if (n_infiles == 0)
339558997Selan fatal ("No input files specified.");
339658997Selan
339758997Selan /* Make a place to record the compiler output file names
339858997Selan that correspond to the input files. */
339958997Selan
340058997Selan outfiles = (char **) xmalloc (n_infiles * sizeof (char *));
340158997Selan bzero (outfiles, n_infiles * sizeof (char *));
340258997Selan
340358997Selan /* Record which files were specified explicitly as link input. */
340458997Selan
340558997Selan explicit_link_files = xmalloc (n_infiles);
340658997Selan bzero (explicit_link_files, n_infiles);
340758997Selan
340858997Selan for (i = 0; i < n_infiles; i++)
340958997Selan {
341058997Selan register struct compiler *cp = 0;
341158997Selan int this_file_error = 0;
341258997Selan
341358997Selan /* Tell do_spec what to substitute for %i. */
341458997Selan
341558997Selan input_filename = infiles[i].name;
341658997Selan input_filename_length = strlen (input_filename);
341758997Selan input_file_number = i;
341858997Selan
341958997Selan /* Use the same thing in %o, unless cp->spec says otherwise. */
342058997Selan
342158997Selan outfiles[i] = input_filename;
342258997Selan
342358997Selan /* Figure out which compiler from the file's suffix. */
342458997Selan
342558997Selan cp = lookup_compiler (infiles[i].name, input_filename_length,
342658997Selan infiles[i].language);
342758997Selan
342858997Selan if (cp)
342958997Selan {
343058997Selan /* Ok, we found an applicable compiler. Run its spec. */
343158997Selan /* First say how much of input_filename to substitute for %b */
343258997Selan register char *p;
343358997Selan int len;
343458997Selan
343558997Selan input_basename = input_filename;
343658997Selan for (p = input_filename; *p; p++)
343758997Selan if (*p == '/')
343858997Selan input_basename = p + 1;
343958997Selan
344058997Selan /* Find a suffix starting with the last period,
344158997Selan and set basename_length to exclude that suffix. */
344258997Selan basename_length = strlen (input_basename);
344358997Selan p = input_basename + basename_length;
344458997Selan while (p != input_basename && *p != '.') --p;
344558997Selan if (*p == '.' && p != input_basename)
344658997Selan {
344758997Selan basename_length = p - input_basename;
344858997Selan input_suffix = p + 1;
344958997Selan }
345058997Selan else
345158997Selan input_suffix = "";
345258997Selan
345358997Selan len = 0;
345458997Selan for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++)
345558997Selan if (cp->spec[j])
345658997Selan len += strlen (cp->spec[j]);
345758997Selan
345858997Selan p = (char *) xmalloc (len + 1);
345958997Selan
346058997Selan len = 0;
346158997Selan for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++)
346258997Selan if (cp->spec[j])
346358997Selan {
346458997Selan strcpy (p + len, cp->spec[j]);
346558997Selan len += strlen (cp->spec[j]);
346658997Selan }
346758997Selan
346858997Selan value = do_spec (p);
346958997Selan free (p);
347058997Selan if (value < 0)
347158997Selan this_file_error = 1;
347258997Selan }
347358997Selan
347458997Selan /* If this file's name does not contain a recognized suffix,
347558997Selan record it as explicit linker input. */
347658997Selan
347758997Selan else
347858997Selan explicit_link_files[i] = 1;
347958997Selan
348058997Selan /* Clear the delete-on-failure queue, deleting the files in it
348158997Selan if this compilation failed. */
348258997Selan
348358997Selan if (this_file_error)
348458997Selan {
348558997Selan delete_failure_queue ();
348658997Selan error_count++;
348758997Selan }
348858997Selan /* If this compilation succeeded, don't delete those files later. */
348958997Selan clear_failure_queue ();
349058997Selan }
349158997Selan
349258997Selan /* Run ld to link all the compiler output files. */
349358997Selan
349458997Selan if (error_count == 0)
349558997Selan {
349658997Selan int tmp = execution_count;
349758997Selan int i;
349858997Selan int first_time;
349958997Selan
350058997Selan /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
350158997Selan for collect. */
350258997Selan putenv_from_prefixes (&exec_prefix, "COMPILER_PATH=");
350358997Selan putenv_from_prefixes (&startfile_prefix, "LIBRARY_PATH=");
350458997Selan
350558997Selan /* Build COLLECT_GCC_OPTIONS to have all of the options specified to
350658997Selan the compiler. */
350758997Selan obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
350858997Selan sizeof ("COLLECT_GCC_OPTIONS=")-1);
350958997Selan
351058997Selan first_time = TRUE;
351158997Selan for (i = 0; i < n_switches; i++)
351258997Selan {
351358997Selan char **args;
351458997Selan if (!first_time)
351558997Selan obstack_grow (&collect_obstack, " ", 1);
351658997Selan
351758997Selan first_time = FALSE;
351858997Selan obstack_grow (&collect_obstack, "-", 1);
351958997Selan obstack_grow (&collect_obstack, switches[i].part1,
352058997Selan strlen (switches[i].part1));
352158997Selan
352258997Selan for (args = switches[i].args; args && *args; args++)
352358997Selan {
352458997Selan obstack_grow (&collect_obstack, " ", 1);
352558997Selan obstack_grow (&collect_obstack, *args, strlen (*args));
352658997Selan }
352758997Selan }
352858997Selan obstack_grow (&collect_obstack, "\0", 1);
352958997Selan putenv (obstack_finish (&collect_obstack));
353058997Selan
353158997Selan value = do_spec (link_command_spec);
353258997Selan if (value < 0)
353358997Selan error_count = 1;
353458997Selan linker_was_run = (tmp != execution_count);
353558997Selan }
353658997Selan
353758997Selan /* Warn if a -B option was specified but the prefix was never used. */
353858997Selan unused_prefix_warnings (&exec_prefix);
353958997Selan unused_prefix_warnings (&startfile_prefix);
354058997Selan
354158997Selan /* If options said don't run linker,
354258997Selan complain about input files to be given to the linker. */
354358997Selan
354458997Selan if (! linker_was_run && error_count == 0)
354558997Selan for (i = 0; i < n_infiles; i++)
354658997Selan if (explicit_link_files[i])
354758997Selan error ("%s: linker input file unused since linking not done",
354858997Selan outfiles[i]);
354958997Selan
355058997Selan /* Delete some or all of the temporary files we made. */
355158997Selan
355258997Selan if (error_count)
355358997Selan delete_failure_queue ();
355458997Selan delete_temp_files ();
355558997Selan
355658997Selan exit (error_count > 0 ? (signal_count ? 2 : 1) : 0);
355758997Selan /* NOTREACHED */
355858997Selan return 0;
355958997Selan }
356058997Selan
356158997Selan /* Find the proper compilation spec for the file name NAME,
356258997Selan whose length is LENGTH. LANGUAGE is the specified language,
356358997Selan or 0 if none specified. */
356458997Selan
356558997Selan static struct compiler *
lookup_compiler(name,length,language)356658997Selan lookup_compiler (name, length, language)
356758997Selan char *name;
356858997Selan int length;
356958997Selan char *language;
357058997Selan {
357158997Selan struct compiler *cp;
357258997Selan
357358997Selan /* Look for the language, if one is spec'd. */
357458997Selan if (language != 0)
357558997Selan {
357658997Selan for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
357758997Selan {
357858997Selan if (language != 0)
357958997Selan {
358058997Selan if (cp->suffix[0] == '@'
358158997Selan && !strcmp (cp->suffix + 1, language))
358258997Selan return cp;
358358997Selan }
358458997Selan }
358558997Selan error ("language %s not recognized", language);
358658997Selan }
358758997Selan
358858997Selan /* Look for a suffix. */
358958997Selan for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
359058997Selan {
359158997Selan if (strlen (cp->suffix) < length
359258997Selan /* See if the suffix matches the end of NAME. */
359358997Selan && !strcmp (cp->suffix,
359458997Selan name + length - strlen (cp->suffix))
359558997Selan /* The suffix `-' matches only the file name `-'. */
359658997Selan && !(!strcmp (cp->suffix, "-") && length != 1))
359758997Selan {
359858997Selan if (cp->spec[0][0] == '@')
359958997Selan {
360058997Selan struct compiler *new;
360158997Selan /* An alias entry maps a suffix to a language.
360258997Selan Search for the language; pass 0 for NAME and LENGTH
360358997Selan to avoid infinite recursion if language not found.
360458997Selan Construct the new compiler spec. */
360558997Selan language = cp->spec[0] + 1;
360658997Selan new = (struct compiler *) xmalloc (sizeof (struct compiler));
360758997Selan new->suffix = cp->suffix;
360858997Selan bcopy (lookup_compiler (NULL_PTR, 0, language)->spec,
360958997Selan new->spec, sizeof new->spec);
361058997Selan return new;
361158997Selan }
361258997Selan /* A non-alias entry: return it. */
361358997Selan return cp;
361458997Selan }
361558997Selan }
361658997Selan
361758997Selan return 0;
361858997Selan }
361958997Selan
362058997Selan char *
xmalloc(size)362158997Selan xmalloc (size)
362258997Selan unsigned size;
362358997Selan {
362458997Selan register char *value = (char *) malloc (size);
362558997Selan if (value == 0)
362658997Selan fatal ("virtual memory exhausted");
362758997Selan return value;
362858997Selan }
362958997Selan
363058997Selan char *
xrealloc(ptr,size)363158997Selan xrealloc (ptr, size)
363258997Selan char *ptr;
363358997Selan unsigned size;
363458997Selan {
363558997Selan register char *value = (char *) realloc (ptr, size);
363658997Selan if (value == 0)
363758997Selan fatal ("virtual memory exhausted");
363858997Selan return value;
363958997Selan }
364058997Selan
364158997Selan /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
364258997Selan
364358997Selan static char *
concat(s1,s2,s3)364458997Selan concat (s1, s2, s3)
364558997Selan char *s1, *s2, *s3;
364658997Selan {
364758997Selan int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
364858997Selan char *result = xmalloc (len1 + len2 + len3 + 1);
364958997Selan
365058997Selan strcpy (result, s1);
365158997Selan strcpy (result + len1, s2);
365258997Selan strcpy (result + len1 + len2, s3);
365358997Selan *(result + len1 + len2 + len3) = 0;
365458997Selan
365558997Selan return result;
365658997Selan }
365758997Selan
365858997Selan static char *
save_string(s,len)365958997Selan save_string (s, len)
366058997Selan char *s;
366158997Selan int len;
366258997Selan {
366358997Selan register char *result = xmalloc (len + 1);
366458997Selan
366558997Selan bcopy (s, result, len);
366658997Selan result[len] = 0;
366758997Selan return result;
366858997Selan }
366958997Selan
367058997Selan static void
pfatal_with_name(name)367158997Selan pfatal_with_name (name)
367258997Selan char *name;
367358997Selan {
367458997Selan char *s;
367558997Selan
367658997Selan if (errno < sys_nerr)
367758997Selan s = concat ("%s: ", sys_errlist[errno], "");
367858997Selan else
367958997Selan s = "cannot open %s";
368058997Selan fatal (s, name);
368158997Selan }
368258997Selan
368358997Selan static void
perror_with_name(name)368458997Selan perror_with_name (name)
368558997Selan char *name;
368658997Selan {
368758997Selan char *s;
368858997Selan
368958997Selan if (errno < sys_nerr)
369058997Selan s = concat ("%s: ", sys_errlist[errno], "");
369158997Selan else
369258997Selan s = "cannot open %s";
369358997Selan error (s, name);
369458997Selan }
369558997Selan
369658997Selan static void
perror_exec(name)369758997Selan perror_exec (name)
369858997Selan char *name;
369958997Selan {
370058997Selan char *s;
370158997Selan
370258997Selan if (errno < sys_nerr)
370358997Selan s = concat ("installation problem, cannot exec %s: ",
370458997Selan sys_errlist[errno], "");
370558997Selan else
370658997Selan s = "installation problem, cannot exec %s";
370758997Selan error (s, name);
370858997Selan }
370958997Selan
371058997Selan /* More 'friendly' abort that prints the line and file.
371158997Selan config.h can #define abort fancy_abort if you like that sort of thing. */
371258997Selan
371358997Selan void
fancy_abort()371458997Selan fancy_abort ()
371558997Selan {
371658997Selan fatal ("Internal gcc abort.");
371758997Selan }
371858997Selan
371958997Selan #ifdef HAVE_VPRINTF
372058997Selan
372158997Selan /* Output an error message and exit */
372258997Selan
372358997Selan static void
fatal(va_alist)372458997Selan fatal (va_alist)
372558997Selan va_dcl
372658997Selan {
372758997Selan va_list ap;
372858997Selan char *format;
372958997Selan
373058997Selan va_start (ap);
373158997Selan format = va_arg (ap, char *);
373258997Selan fprintf (stderr, "%s: ", programname);
373358997Selan vfprintf (stderr, format, ap);
373458997Selan va_end (ap);
373558997Selan fprintf (stderr, "\n");
373658997Selan delete_temp_files ();
373758997Selan exit (1);
373858997Selan }
373958997Selan
374058997Selan static void
error(va_alist)374158997Selan error (va_alist)
374258997Selan va_dcl
374358997Selan {
374458997Selan va_list ap;
374558997Selan char *format;
374658997Selan
374758997Selan va_start (ap);
374858997Selan format = va_arg (ap, char *);
374958997Selan fprintf (stderr, "%s: ", programname);
375058997Selan vfprintf (stderr, format, ap);
375158997Selan va_end (ap);
375258997Selan
375358997Selan fprintf (stderr, "\n");
375458997Selan }
375558997Selan
375658997Selan #else /* not HAVE_VPRINTF */
375758997Selan
375858997Selan static void
fatal(msg,arg1,arg2)375958997Selan fatal (msg, arg1, arg2)
376058997Selan char *msg, *arg1, *arg2;
376158997Selan {
376258997Selan error (msg, arg1, arg2);
376358997Selan delete_temp_files ();
376458997Selan exit (1);
376558997Selan }
376658997Selan
376758997Selan static void
error(msg,arg1,arg2)376858997Selan error (msg, arg1, arg2)
376958997Selan char *msg, *arg1, *arg2;
377058997Selan {
377158997Selan fprintf (stderr, "%s: ", programname);
377258997Selan fprintf (stderr, msg, arg1, arg2);
377358997Selan fprintf (stderr, "\n");
377458997Selan }
377558997Selan
377658997Selan #endif /* not HAVE_VPRINTF */
377758997Selan
377858997Selan
377958997Selan static void
validate_all_switches()378058997Selan validate_all_switches ()
378158997Selan {
378258997Selan struct compiler *comp;
378358997Selan register char *p;
378458997Selan register char c;
378558997Selan struct spec_list *spec;
378658997Selan
378758997Selan for (comp = compilers; comp->spec[0]; comp++)
378858997Selan {
378958997Selan int i;
379058997Selan for (i = 0; i < sizeof comp->spec / sizeof comp->spec[0] && comp->spec[i]; i++)
379158997Selan {
379258997Selan p = comp->spec[i];
379358997Selan while (c = *p++)
379458997Selan if (c == '%' && *p == '{')
379558997Selan /* We have a switch spec. */
379658997Selan validate_switches (p + 1);
379758997Selan }
379858997Selan }
379958997Selan
380058997Selan /* look through the linked list of extra specs read from the specs file */
380158997Selan for (spec = specs; spec ; spec = spec->next)
380258997Selan {
380358997Selan p = spec->spec;
380458997Selan while (c = *p++)
380558997Selan if (c == '%' && *p == '{')
380658997Selan /* We have a switch spec. */
380758997Selan validate_switches (p + 1);
380858997Selan }
380958997Selan
381058997Selan p = link_command_spec;
381158997Selan while (c = *p++)
381258997Selan if (c == '%' && *p == '{')
381358997Selan /* We have a switch spec. */
381458997Selan validate_switches (p + 1);
381558997Selan
381658997Selan /* Now notice switches mentioned in the machine-specific specs. */
381758997Selan
381858997Selan p = asm_spec;
381958997Selan while (c = *p++)
382058997Selan if (c == '%' && *p == '{')
382158997Selan /* We have a switch spec. */
382258997Selan validate_switches (p + 1);
382358997Selan
382458997Selan p = asm_final_spec;
382558997Selan while (c = *p++)
382658997Selan if (c == '%' && *p == '{')
382758997Selan /* We have a switch spec. */
382858997Selan validate_switches (p + 1);
382958997Selan
383058997Selan p = cpp_spec;
383158997Selan while (c = *p++)
383258997Selan if (c == '%' && *p == '{')
383358997Selan /* We have a switch spec. */
383458997Selan validate_switches (p + 1);
383558997Selan
383658997Selan p = signed_char_spec;
383758997Selan while (c = *p++)
383858997Selan if (c == '%' && *p == '{')
383958997Selan /* We have a switch spec. */
384058997Selan validate_switches (p + 1);
384158997Selan
384258997Selan p = cc1_spec;
384358997Selan while (c = *p++)
384458997Selan if (c == '%' && *p == '{')
384558997Selan /* We have a switch spec. */
384658997Selan validate_switches (p + 1);
384758997Selan
384858997Selan p = cc1plus_spec;
384958997Selan while (c = *p++)
385058997Selan if (c == '%' && *p == '{')
385158997Selan /* We have a switch spec. */
385258997Selan validate_switches (p + 1);
385358997Selan
385458997Selan p = link_spec;
385558997Selan while (c = *p++)
385658997Selan if (c == '%' && *p == '{')
385758997Selan /* We have a switch spec. */
385858997Selan validate_switches (p + 1);
385958997Selan
386058997Selan p = lib_spec;
386158997Selan while (c = *p++)
386258997Selan if (c == '%' && *p == '{')
386358997Selan /* We have a switch spec. */
386458997Selan validate_switches (p + 1);
386558997Selan
386658997Selan p = startfile_spec;
386758997Selan while (c = *p++)
386858997Selan if (c == '%' && *p == '{')
386958997Selan /* We have a switch spec. */
387058997Selan validate_switches (p + 1);
387158997Selan }
387258997Selan
387358997Selan /* Look at the switch-name that comes after START
387458997Selan and mark as valid all supplied switches that match it. */
387558997Selan
387658997Selan static void
validate_switches(start)387758997Selan validate_switches (start)
387858997Selan char *start;
387958997Selan {
388058997Selan register char *p = start;
388158997Selan char *filter;
388258997Selan register int i;
388358997Selan int suffix = 0;
388458997Selan
388558997Selan if (*p == '|')
388658997Selan ++p;
388758997Selan
388858997Selan if (*p == '!')
388958997Selan ++p;
389058997Selan
389158997Selan if (*p == '.')
389258997Selan suffix = 1, ++p;
389358997Selan
389458997Selan filter = p;
389558997Selan while (*p != ':' && *p != '}') p++;
389658997Selan
389758997Selan if (suffix)
389858997Selan ;
389958997Selan else if (p[-1] == '*')
390058997Selan {
390158997Selan /* Mark all matching switches as valid. */
390258997Selan --p;
390358997Selan for (i = 0; i < n_switches; i++)
390458997Selan if (!strncmp (switches[i].part1, filter, p - filter))
390558997Selan switches[i].valid = 1;
390658997Selan }
390758997Selan else
390858997Selan {
390958997Selan /* Mark an exact matching switch as valid. */
391058997Selan for (i = 0; i < n_switches; i++)
391158997Selan {
391258997Selan if (!strncmp (switches[i].part1, filter, p - filter)
391358997Selan && switches[i].part1[p - filter] == 0)
391458997Selan switches[i].valid = 1;
391558997Selan }
391658997Selan }
391758997Selan }
3918