xref: /csrg-svn/contrib/gcc-2.3.3/gcc.c (revision 58997)
1*58997Selan /* Compiler driver program that can handle many languages.
2*58997Selan    Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
3*58997Selan 
4*58997Selan This file is part of GNU CC.
5*58997Selan 
6*58997Selan GNU CC is free software; you can redistribute it and/or modify
7*58997Selan it under the terms of the GNU General Public License as published by
8*58997Selan the Free Software Foundation; either version 2, or (at your option)
9*58997Selan any later version.
10*58997Selan 
11*58997Selan GNU CC is distributed in the hope that it will be useful,
12*58997Selan but WITHOUT ANY WARRANTY; without even the implied warranty of
13*58997Selan MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*58997Selan GNU General Public License for more details.
15*58997Selan 
16*58997Selan You should have received a copy of the GNU General Public License
17*58997Selan along with GNU CC; see the file COPYING.  If not, write to
18*58997Selan the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19*58997Selan 
20*58997Selan This paragraph is here to try to keep Sun CC from dying.
21*58997Selan The number of chars here seems crucial!!!!  */
22*58997Selan 
23*58997Selan /* This program is the user interface to the C compiler and possibly to
24*58997Selan other compilers.  It is used because compilation is a complicated procedure
25*58997Selan which involves running several programs and passing temporary files between
26*58997Selan them, forwarding the users switches to those programs selectively,
27*58997Selan and deleting the temporary files at the end.
28*58997Selan 
29*58997Selan CC recognizes how to compile each input file by suffixes in the file names.
30*58997Selan Once it knows which kind of compilation to perform, the procedure for
31*58997Selan compilation is specified by a string called a "spec".  */
32*58997Selan 
33*58997Selan #include <sys/types.h>
34*58997Selan #include <ctype.h>
35*58997Selan #include <signal.h>
36*58997Selan #include <sys/stat.h>
37*58997Selan #include <sys/file.h>   /* May get R_OK, etc. on some systems.  */
38*58997Selan 
39*58997Selan #include "config.h"
40*58997Selan #include "obstack.h"
41*58997Selan #include "gvarargs.h"
42*58997Selan #include <stdio.h>
43*58997Selan 
44*58997Selan #ifndef R_OK
45*58997Selan #define R_OK 4
46*58997Selan #define W_OK 2
47*58997Selan #define X_OK 1
48*58997Selan #endif
49*58997Selan 
50*58997Selan /* Define a generic NULL if one hasn't already been defined.  */
51*58997Selan 
52*58997Selan #ifndef NULL
53*58997Selan #define NULL 0
54*58997Selan #endif
55*58997Selan 
56*58997Selan #ifndef GENERIC_PTR
57*58997Selan #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
58*58997Selan #define GENERIC_PTR void *
59*58997Selan #else
60*58997Selan #define GENERIC_PTR char *
61*58997Selan #endif
62*58997Selan #endif
63*58997Selan 
64*58997Selan #ifndef NULL_PTR
65*58997Selan #define NULL_PTR ((GENERIC_PTR)0)
66*58997Selan #endif
67*58997Selan 
68*58997Selan #ifdef USG
69*58997Selan #define vfork fork
70*58997Selan #endif /* USG */
71*58997Selan 
72*58997Selan /* On MSDOS, write temp files in current dir
73*58997Selan    because there's no place else we can expect to use.  */
74*58997Selan #if __MSDOS__
75*58997Selan #ifndef P_tmpdir
76*58997Selan #define P_tmpdir "./"
77*58997Selan #endif
78*58997Selan #endif
79*58997Selan 
80*58997Selan /* Test if something is a normal file.  */
81*58997Selan #ifndef S_ISREG
82*58997Selan #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
83*58997Selan #endif
84*58997Selan 
85*58997Selan /* Test if something is a directory.  */
86*58997Selan #ifndef S_ISDIR
87*58997Selan #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
88*58997Selan #endif
89*58997Selan 
90*58997Selan /* By default there is no special suffix for executables.  */
91*58997Selan #ifndef EXECUTABLE_SUFFIX
92*58997Selan #define EXECUTABLE_SUFFIX ""
93*58997Selan #endif
94*58997Selan 
95*58997Selan /* By default, colon separates directories in a path.  */
96*58997Selan #ifndef PATH_SEPARATOR
97*58997Selan #define PATH_SEPARATOR ':'
98*58997Selan #endif
99*58997Selan 
100*58997Selan #define obstack_chunk_alloc xmalloc
101*58997Selan #define obstack_chunk_free free
102*58997Selan 
103*58997Selan extern void free ();
104*58997Selan extern char *getenv ();
105*58997Selan 
106*58997Selan extern int errno, sys_nerr;
107*58997Selan extern char *sys_errlist[];
108*58997Selan 
109*58997Selan extern int execv (), execvp ();
110*58997Selan 
111*58997Selan /* If a stage of compilation returns an exit status >= 1,
112*58997Selan    compilation of that file ceases.  */
113*58997Selan 
114*58997Selan #define MIN_FATAL_STATUS 1
115*58997Selan 
116*58997Selan /* Flag saying to print the full filename of libgcc.a
117*58997Selan    as found through our usual search mechanism.  */
118*58997Selan 
119*58997Selan static int print_libgcc_file_name;
120*58997Selan 
121*58997Selan /* Flag indicating whether we should print the command and arguments */
122*58997Selan 
123*58997Selan static int verbose_flag;
124*58997Selan 
125*58997Selan /* Nonzero means write "temp" files in source directory
126*58997Selan    and use the source file's name in them, and don't delete them.  */
127*58997Selan 
128*58997Selan static int save_temps_flag;
129*58997Selan 
130*58997Selan /* The compiler version specified with -V */
131*58997Selan 
132*58997Selan static char *spec_version;
133*58997Selan 
134*58997Selan /* The target machine specified with -b.  */
135*58997Selan 
136*58997Selan static char *spec_machine = DEFAULT_TARGET_MACHINE;
137*58997Selan 
138*58997Selan /* Nonzero if cross-compiling.
139*58997Selan    When -b is used, the value comes from the `specs' file.  */
140*58997Selan 
141*58997Selan #ifdef CROSS_COMPILE
142*58997Selan static int cross_compile = 1;
143*58997Selan #else
144*58997Selan static int cross_compile = 0;
145*58997Selan #endif
146*58997Selan 
147*58997Selan /* This is the obstack which we use to allocate many strings.  */
148*58997Selan 
149*58997Selan static struct obstack obstack;
150*58997Selan 
151*58997Selan /* This is the obstack to build an environment variable to pass to
152*58997Selan    collect2 that describes all of the relevant switches of what to
153*58997Selan    pass the compiler in building the list of pointers to constructors
154*58997Selan    and destructors.  */
155*58997Selan 
156*58997Selan static struct obstack collect_obstack;
157*58997Selan 
158*58997Selan extern char *version_string;
159*58997Selan 
160*58997Selan static void set_spec ();
161*58997Selan static struct compiler *lookup_compiler ();
162*58997Selan static char *find_a_file ();
163*58997Selan static void add_prefix ();
164*58997Selan static char *skip_whitespace ();
165*58997Selan static void record_temp_file ();
166*58997Selan static char *handle_braces ();
167*58997Selan static char *save_string ();
168*58997Selan static char *concat ();
169*58997Selan static int do_spec ();
170*58997Selan static int do_spec_1 ();
171*58997Selan static char *find_file ();
172*58997Selan static int is_linker_dir ();
173*58997Selan static void validate_switches ();
174*58997Selan static void validate_all_switches ();
175*58997Selan static void give_switch ();
176*58997Selan static void pfatal_with_name ();
177*58997Selan static void perror_with_name ();
178*58997Selan static void perror_exec ();
179*58997Selan static void fatal ();
180*58997Selan static void error ();
181*58997Selan void fancy_abort ();
182*58997Selan char *xmalloc ();
183*58997Selan char *xrealloc ();
184*58997Selan 
185*58997Selan /* Specs are strings containing lines, each of which (if not blank)
186*58997Selan is made up of a program name, and arguments separated by spaces.
187*58997Selan The program name must be exact and start from root, since no path
188*58997Selan is searched and it is unreliable to depend on the current working directory.
189*58997Selan Redirection of input or output is not supported; the subprograms must
190*58997Selan accept filenames saying what files to read and write.
191*58997Selan 
192*58997Selan In addition, the specs can contain %-sequences to substitute variable text
193*58997Selan or for conditional text.  Here is a table of all defined %-sequences.
194*58997Selan Note that spaces are not generated automatically around the results of
195*58997Selan expanding these sequences; therefore, you can concatenate them together
196*58997Selan or with constant text in a single argument.
197*58997Selan 
198*58997Selan  %%	substitute one % into the program name or argument.
199*58997Selan  %i     substitute the name of the input file being processed.
200*58997Selan  %b     substitute the basename of the input file being processed.
201*58997Selan 	This is the substring up to (and not including) the last period
202*58997Selan 	and not including the directory.
203*58997Selan  %g     substitute the temporary-file-name-base.  This is a string chosen
204*58997Selan 	once per compilation.  Different temporary file names are made by
205*58997Selan 	concatenation of constant strings on the end, as in `%g.s'.
206*58997Selan 	%g also has the same effect of %d.
207*58997Selan  %u	like %g, but make the temporary file name unique.
208*58997Selan  %U	returns the last file name generated with %u.
209*58997Selan  %d	marks the argument containing or following the %d as a
210*58997Selan 	temporary file name, so that that file will be deleted if CC exits
211*58997Selan 	successfully.  Unlike %g, this contributes no text to the argument.
212*58997Selan  %w	marks the argument containing or following the %w as the
213*58997Selan 	"output file" of this compilation.  This puts the argument
214*58997Selan 	into the sequence of arguments that %o will substitute later.
215*58997Selan  %W{...}
216*58997Selan 	like %{...} but mark last argument supplied within
217*58997Selan 	as a file to be deleted on failure.
218*58997Selan  %o	substitutes the names of all the output files, with spaces
219*58997Selan 	automatically placed around them.  You should write spaces
220*58997Selan 	around the %o as well or the results are undefined.
221*58997Selan 	%o is for use in the specs for running the linker.
222*58997Selan 	Input files whose names have no recognized suffix are not compiled
223*58997Selan 	at all, but they are included among the output files, so they will
224*58997Selan 	be linked.
225*58997Selan  %p	substitutes the standard macro predefinitions for the
226*58997Selan 	current target machine.  Use this when running cpp.
227*58997Selan  %P	like %p, but puts `__' before and after the name of each macro.
228*58997Selan 	(Except macros that already have __.)
229*58997Selan 	This is for ANSI C.
230*58997Selan  %I	Substitute a -iprefix option made from GCC_EXEC_PREFIX.
231*58997Selan  %s     current argument is the name of a library or startup file of some sort.
232*58997Selan         Search for that file in a standard list of directories
233*58997Selan 	and substitute the full name found.
234*58997Selan  %eSTR  Print STR as an error message.  STR is terminated by a newline.
235*58997Selan         Use this when inconsistent options are detected.
236*58997Selan  %x{OPTION}	Accumulate an option for %X.
237*58997Selan  %X	Output the accumulated linker options specified by compilations.
238*58997Selan  %Y	Output the accumulated assembler options specified by compilations.
239*58997Selan  %a     process ASM_SPEC as a spec.
240*58997Selan         This allows config.h to specify part of the spec for running as.
241*58997Selan  %A	process ASM_FINAL_SPEC as a spec.  A capital A is actually
242*58997Selan 	used here.  This can be used to run a post-processor after the
243*58997Selan 	assembler has done it's job.
244*58997Selan  %D	Dump out a -L option for each directory in library_prefix,
245*58997Selan 	followed by a -L option for each directory in startfile_prefix.
246*58997Selan  %l     process LINK_SPEC as a spec.
247*58997Selan  %L     process LIB_SPEC as a spec.
248*58997Selan  %S     process STARTFILE_SPEC as a spec.  A capital S is actually used here.
249*58997Selan  %E     process ENDFILE_SPEC as a spec.  A capital E is actually used here.
250*58997Selan  %c	process SIGNED_CHAR_SPEC as a spec.
251*58997Selan  %C     process CPP_SPEC as a spec.  A capital C is actually used here.
252*58997Selan  %1	process CC1_SPEC as a spec.
253*58997Selan  %2	process CC1PLUS_SPEC as a spec.
254*58997Selan  %*	substitute the variable part of a matched option.  (See below.)
255*58997Selan 	Note that each comma in the substituted string is replaced by
256*58997Selan 	a single space.
257*58997Selan  %{S}   substitutes the -S switch, if that switch was given to CC.
258*58997Selan 	If that switch was not specified, this substitutes nothing.
259*58997Selan 	Here S is a metasyntactic variable.
260*58997Selan  %{S*}  substitutes all the switches specified to CC whose names start
261*58997Selan 	with -S.  This is used for -o, -D, -I, etc; switches that take
262*58997Selan 	arguments.  CC considers `-o foo' as being one switch whose
263*58997Selan 	name starts with `o'.  %{o*} would substitute this text,
264*58997Selan 	including the space; thus, two arguments would be generated.
265*58997Selan  %{S*:X} substitutes X if one or more switches whose names start with -S are
266*58997Selan 	specified to CC.  Note that the tail part of the -S option
267*58997Selan 	(i.e. the part matched by the `*') will be substituted for each
268*58997Selan 	occurrence of %* within X.
269*58997Selan  %{S:X} substitutes X, but only if the -S switch was given to CC.
270*58997Selan  %{!S:X} substitutes X, but only if the -S switch was NOT given to CC.
271*58997Selan  %{|S:X} like %{S:X}, but if no S switch, substitute `-'.
272*58997Selan  %{|!S:X} like %{!S:X}, but if there is an S switch, substitute `-'.
273*58997Selan  %{.S:X} substitutes X, but only if processing a file with suffix S.
274*58997Selan  %{!.S:X} substitutes X, but only if NOT processing a file with suffix S.
275*58997Selan  %(Spec) processes a specification defined in a specs file as *Spec:
276*58997Selan  %[Spec] as above, but put __ around -D arguments
277*58997Selan 
278*58997Selan The conditional text X in a %{S:X} or %{!S:X} construct may contain
279*58997Selan other nested % constructs or spaces, or even newlines.  They are
280*58997Selan processed as usual, as described above.
281*58997Selan 
282*58997Selan The character | is used to indicate that a command should be piped to
283*58997Selan the following command, but only if -pipe is specified.
284*58997Selan 
285*58997Selan Note that it is built into CC which switches take arguments and which
286*58997Selan do not.  You might think it would be useful to generalize this to
287*58997Selan allow each compiler's spec to say which switches take arguments.  But
288*58997Selan this cannot be done in a consistent fashion.  CC cannot even decide
289*58997Selan which input files have been specified without knowing which switches
290*58997Selan take arguments, and it must know which input files to compile in order
291*58997Selan to tell which compilers to run.
292*58997Selan 
293*58997Selan CC also knows implicitly that arguments starting in `-l' are to be
294*58997Selan treated as compiler output files, and passed to the linker in their
295*58997Selan proper position among the other output files.  */
296*58997Selan 
297*58997Selan /* Define the macros used for specs %a, %l, %L, %S, %c, %C, %1.  */
298*58997Selan 
299*58997Selan /* config.h can define ASM_SPEC to provide extra args to the assembler
300*58997Selan    or extra switch-translations.  */
301*58997Selan #ifndef ASM_SPEC
302*58997Selan #define ASM_SPEC ""
303*58997Selan #endif
304*58997Selan 
305*58997Selan /* config.h can define ASM_FINAL_SPEC to run a post processor after
306*58997Selan    the assembler has run.  */
307*58997Selan #ifndef ASM_FINAL_SPEC
308*58997Selan #define ASM_FINAL_SPEC ""
309*58997Selan #endif
310*58997Selan 
311*58997Selan /* config.h can define CPP_SPEC to provide extra args to the C preprocessor
312*58997Selan    or extra switch-translations.  */
313*58997Selan #ifndef CPP_SPEC
314*58997Selan #define CPP_SPEC ""
315*58997Selan #endif
316*58997Selan 
317*58997Selan /* config.h can define CC1_SPEC to provide extra args to cc1 and cc1plus
318*58997Selan    or extra switch-translations.  */
319*58997Selan #ifndef CC1_SPEC
320*58997Selan #define CC1_SPEC ""
321*58997Selan #endif
322*58997Selan 
323*58997Selan /* config.h can define CC1PLUS_SPEC to provide extra args to cc1plus
324*58997Selan    or extra switch-translations.  */
325*58997Selan #ifndef CC1PLUS_SPEC
326*58997Selan #define CC1PLUS_SPEC ""
327*58997Selan #endif
328*58997Selan 
329*58997Selan /* config.h can define LINK_SPEC to provide extra args to the linker
330*58997Selan    or extra switch-translations.  */
331*58997Selan #ifndef LINK_SPEC
332*58997Selan #define LINK_SPEC ""
333*58997Selan #endif
334*58997Selan 
335*58997Selan /* config.h can define LIB_SPEC to override the default libraries.  */
336*58997Selan #ifndef LIB_SPEC
337*58997Selan #define LIB_SPEC "%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}"
338*58997Selan #endif
339*58997Selan 
340*58997Selan /* config.h can define STARTFILE_SPEC to override the default crt0 files.  */
341*58997Selan #ifndef STARTFILE_SPEC
342*58997Selan #define STARTFILE_SPEC  \
343*58997Selan   "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}"
344*58997Selan #endif
345*58997Selan 
346*58997Selan /* config.h can define SWITCHES_NEED_SPACES to control passing -o and -L.
347*58997Selan    Make the string nonempty to require spaces there.  */
348*58997Selan #ifndef SWITCHES_NEED_SPACES
349*58997Selan #define SWITCHES_NEED_SPACES ""
350*58997Selan #endif
351*58997Selan 
352*58997Selan /* config.h can define ENDFILE_SPEC to override the default crtn files.  */
353*58997Selan #ifndef ENDFILE_SPEC
354*58997Selan #define ENDFILE_SPEC ""
355*58997Selan #endif
356*58997Selan 
357*58997Selan /* This spec is used for telling cpp whether char is signed or not.  */
358*58997Selan #ifndef SIGNED_CHAR_SPEC
359*58997Selan /* Use #if rather than ?:
360*58997Selan    because MIPS C compiler rejects like ?: in initializers.  */
361*58997Selan #if DEFAULT_SIGNED_CHAR
362*58997Selan #define SIGNED_CHAR_SPEC "%{funsigned-char:-D__CHAR_UNSIGNED__}"
363*58997Selan #else
364*58997Selan #define SIGNED_CHAR_SPEC "%{!fsigned-char:-D__CHAR_UNSIGNED__}"
365*58997Selan #endif
366*58997Selan #endif
367*58997Selan 
368*58997Selan static char *cpp_spec = CPP_SPEC;
369*58997Selan static char *cpp_predefines = CPP_PREDEFINES;
370*58997Selan static char *cc1_spec = CC1_SPEC;
371*58997Selan static char *cc1plus_spec = CC1PLUS_SPEC;
372*58997Selan static char *signed_char_spec = SIGNED_CHAR_SPEC;
373*58997Selan static char *asm_spec = ASM_SPEC;
374*58997Selan static char *asm_final_spec = ASM_FINAL_SPEC;
375*58997Selan static char *link_spec = LINK_SPEC;
376*58997Selan static char *lib_spec = LIB_SPEC;
377*58997Selan static char *endfile_spec = ENDFILE_SPEC;
378*58997Selan static char *startfile_spec = STARTFILE_SPEC;
379*58997Selan static char *switches_need_spaces = SWITCHES_NEED_SPACES;
380*58997Selan 
381*58997Selan /* This defines which switch letters take arguments.  */
382*58997Selan 
383*58997Selan #ifndef SWITCH_TAKES_ARG
384*58997Selan #define SWITCH_TAKES_ARG(CHAR)      \
385*58997Selan   ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
386*58997Selan    || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
387*58997Selan    || (CHAR) == 'I' || (CHAR) == 'm' \
388*58997Selan    || (CHAR) == 'L' || (CHAR) == 'A')
389*58997Selan #endif
390*58997Selan 
391*58997Selan /* This defines which multi-letter switches take arguments.  */
392*58997Selan 
393*58997Selan #ifndef WORD_SWITCH_TAKES_ARG
394*58997Selan #define WORD_SWITCH_TAKES_ARG(STR)			\
395*58997Selan  (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext")	\
396*58997Selan   || !strcmp (STR, "Tbss") || !strcmp (STR, "include")	\
397*58997Selan   || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info"))
398*58997Selan #endif
399*58997Selan 
400*58997Selan /* Record the mapping from file suffixes for compilation specs.  */
401*58997Selan 
402*58997Selan struct compiler
403*58997Selan {
404*58997Selan   char *suffix;			/* Use this compiler for input files
405*58997Selan 				   whose names end in this suffix.  */
406*58997Selan 
407*58997Selan   char *spec[4];		/* To use this compiler, concatenate these
408*58997Selan 				   specs and pass to do_spec.  */
409*58997Selan };
410*58997Selan 
411*58997Selan /* Pointer to a vector of `struct compiler' that gives the spec for
412*58997Selan    compiling a file, based on its suffix.
413*58997Selan    A file that does not end in any of these suffixes will be passed
414*58997Selan    unchanged to the loader and nothing else will be done to it.
415*58997Selan 
416*58997Selan    An entry containing two 0s is used to terminate the vector.
417*58997Selan 
418*58997Selan    If multiple entries match a file, the last matching one is used.  */
419*58997Selan 
420*58997Selan static struct compiler *compilers;
421*58997Selan 
422*58997Selan /* Number of entries in `compilers', not counting the null terminator.  */
423*58997Selan 
424*58997Selan static int n_compilers;
425*58997Selan 
426*58997Selan /* The default list of file name suffixes and their compilation specs.  */
427*58997Selan 
428*58997Selan static struct compiler default_compilers[] =
429*58997Selan {
430*58997Selan   {".c", "@c"},
431*58997Selan   {"@c",
432*58997Selan    "cpp -lang-c %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
433*58997Selan 	%{C:%{!E:%eGNU C does not support -C without using -E}}\
434*58997Selan 	%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d}\
435*58997Selan         -undef -D__GNUC__=2 %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
436*58997Selan 	%{!undef:%{!ansi:%p} %P} %{trigraphs} \
437*58997Selan         %c %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
438*58997Selan         %{traditional-cpp:-traditional}\
439*58997Selan 	%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*}\
440*58997Selan         %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
441*58997Selan    "%{!M:%{!MM:%{!E:cc1 %{!pipe:%g.i} %1 \
442*58997Selan 		   %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a}\
443*58997Selan 		   %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
444*58997Selan 		   %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
445*58997Selan 		   %{aux-info*}\
446*58997Selan 		   %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
447*58997Selan 		   %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
448*58997Selan               %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\
449*58997Selan 		      %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o}\
450*58997Selan                       %{!pipe:%g.s} %A\n }}}}"},
451*58997Selan   {"-",
452*58997Selan    "%{E:cpp -lang-c %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
453*58997Selan 	%{C:%{!E:%eGNU C does not support -C without using -E}}\
454*58997Selan 	%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d}\
455*58997Selan         -undef -D__GNUC__=2 %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
456*58997Selan 	%{!undef:%{!ansi:%p} %P} %{trigraphs}\
457*58997Selan         %c %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
458*58997Selan         %{traditional-cpp:-traditional}\
459*58997Selan 	%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*}\
460*58997Selan         %i %W{o*}}\
461*58997Selan     %{!E:%e-E required when input is from standard input}"},
462*58997Selan   {".m", "@objective-c"},
463*58997Selan   {"@objective-c",
464*58997Selan    "cpp -lang-objc %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
465*58997Selan 	%{C:%{!E:%eGNU C does not support -C without using -E}}\
466*58997Selan 	%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d}\
467*58997Selan         -undef -D__OBJC__ -D__GNUC__=2 %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
468*58997Selan 	%{!undef:%{!ansi:%p} %P} %{trigraphs}\
469*58997Selan         %c %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
470*58997Selan         %{traditional-cpp:-traditional}\
471*58997Selan 	%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*}\
472*58997Selan         %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
473*58997Selan    "%{!M:%{!MM:%{!E:cc1obj %{!pipe:%g.i} %1 \
474*58997Selan 		   %{!Q:-quiet} -dumpbase %b.m %{d*} %{m*} %{a}\
475*58997Selan 		   %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
476*58997Selan 		   %{traditional} %{v:-version} %{pg:-p} %{p} %{f*} \
477*58997Selan     		   -lang-objc %{gen-decls} \
478*58997Selan 		   %{aux-info*}\
479*58997Selan 		   %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
480*58997Selan 		   %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
481*58997Selan               %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\
482*58997Selan 		      %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o}\
483*58997Selan                       %{!pipe:%g.s} %A\n }}}}"},
484*58997Selan   {".h", "@c-header"},
485*58997Selan   {"@c-header",
486*58997Selan    "%{!E:%eCompilation of header file requested} \
487*58997Selan     cpp %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
488*58997Selan 	%{C:%{!E:%eGNU C does not support -C without using -E}}\
489*58997Selan 	 %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} \
490*58997Selan         -undef -D__GNUC__=2 %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
491*58997Selan 	%{!undef:%{!ansi:%p} %P} %{trigraphs}\
492*58997Selan         %c %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
493*58997Selan         %{traditional-cpp:-traditional}\
494*58997Selan 	%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*}\
495*58997Selan         %i %W{o*}"},
496*58997Selan   {".cc", "@c++"},
497*58997Selan   {".cxx", "@c++"},
498*58997Selan   {".C", "@c++"},
499*58997Selan   {"@c++",
500*58997Selan    "cpp -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
501*58997Selan 	%{C:%{!E:%eGNU C++ does not support -C without using -E}}\
502*58997Selan 	%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} \
503*58997Selan 	-undef -D__GNUC__=2 -D__GNUG__=2 -D__cplusplus \
504*58997Selan 	%{ansi:-trigraphs -$ -D__STRICT_ANSI__} %{!undef:%{!ansi:%p} %P}\
505*58997Selan         %c %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
506*58997Selan         %{traditional-cpp:-traditional} %{trigraphs}\
507*58997Selan 	%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*}\
508*58997Selan         %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
509*58997Selan    "%{!M:%{!MM:%{!E:cc1plus %{!pipe:%g.i} %1 %2\
510*58997Selan 		   %{!Q:-quiet} -dumpbase %b.cc %{d*} %{m*} %{a}\
511*58997Selan 		   %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} %{traditional}\
512*58997Selan 		   %{v:-version} %{pg:-p} %{p} %{f*} %{+e*}\
513*58997Selan 		   %{aux-info*}\
514*58997Selan 		   %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
515*58997Selan 		   %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
516*58997Selan               %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\
517*58997Selan 		      %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o}\
518*58997Selan                       %{!pipe:%g.s} %A\n }}}}"},
519*58997Selan   {".i", "@cpp-output"},
520*58997Selan   {"@cpp-output",
521*58997Selan    "cc1 %i %1 %{!Q:-quiet} %{d*} %{m*} %{a}\
522*58997Selan 	%{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} %{traditional}\
523*58997Selan 	%{v:-version} %{pg:-p} %{p} %{f*}\
524*58997Selan 	%{aux-info*}\
525*58997Selan 	%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
526*58997Selan 	%{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
527*58997Selan     %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\
528*58997Selan             %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o} %{!pipe:%g.s} %A\n }"},
529*58997Selan   {".ii", "@c++-cpp-output"},
530*58997Selan   {"@c++-cpp-output",
531*58997Selan    "cc1plus %i %1 %2 %{!Q:-quiet} %{d*} %{m*} %{a}\
532*58997Selan 	    %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} %{traditional}\
533*58997Selan 	    %{v:-version} %{pg:-p} %{p} %{f*} %{+e*}\
534*58997Selan 	    %{aux-info*}\
535*58997Selan 	    %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
536*58997Selan 	    %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
537*58997Selan        %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\
538*58997Selan 	       %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o}\
539*58997Selan 	       %{!pipe:%g.s} %A\n }"},
540*58997Selan   {".s", "@assembler"},
541*58997Selan   {"@assembler",
542*58997Selan    "%{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\
543*58997Selan             %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o} %i %A\n }"},
544*58997Selan   {".S", "@assembler-with-cpp"},
545*58997Selan   {"@assembler-with-cpp",
546*58997Selan    "cpp -lang-asm %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
547*58997Selan 	%{C:%{!E:%eGNU C does not support -C without using -E}}\
548*58997Selan 	%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{trigraphs} \
549*58997Selan         -undef -$ %{!undef:%p %P} -D__ASSEMBLER__ \
550*58997Selan         %c %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
551*58997Selan         %{traditional-cpp:-traditional}\
552*58997Selan 	%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*}\
553*58997Selan         %i %{!M:%{!MM:%{!E:%{!pipe:%g.s}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
554*58997Selan    "%{!M:%{!MM:%{!E:%{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\
555*58997Selan                     %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o}\
556*58997Selan 		    %{!pipe:%g.s} %A\n }}}}"},
557*58997Selan   /* Mark end of table */
558*58997Selan   {0, 0}
559*58997Selan };
560*58997Selan 
561*58997Selan /* Number of elements in default_compilers, not counting the terminator.  */
562*58997Selan 
563*58997Selan static int n_default_compilers
564*58997Selan   = (sizeof default_compilers / sizeof (struct compiler)) - 1;
565*58997Selan 
566*58997Selan /* Here is the spec for running the linker, after compiling all files.  */
567*58997Selan 
568*58997Selan /* -u* was put back because both BSD and SysV seem to support it.  */
569*58997Selan /* %{static:} simply prevents an error message if the target machine
570*58997Selan    doesn't handle -static.  */
571*58997Selan #ifdef LINK_LIBGCC_SPECIAL_1
572*58997Selan /* Have gcc do the search for libgcc.a, but generate -L options as usual.  */
573*58997Selan static char *link_command_spec = "\
574*58997Selan %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
575*58997Selan 			%{r} %{s} %{T*} %{t} %{u*} %{x} %{z}\
576*58997Selan 			%{!A:%{!nostdlib:%S}} %{static:}\
577*58997Selan 			%{L*} %D %o %{!nostdlib:libgcc.a%s %L libgcc.a%s %{!A:%E}}\n }}}}}";
578*58997Selan #else
579*58997Selan #ifdef LINK_LIBGCC_SPECIAL
580*58997Selan /* Have gcc do the search for libgcc.a, and don't generate -L options.  */
581*58997Selan static char *link_command_spec = "\
582*58997Selan %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
583*58997Selan 			%{r} %{s} %{T*} %{t} %{u*} %{x} %{z}\
584*58997Selan 			%{!A:%{!nostdlib:%S}} %{static:}\
585*58997Selan 			%{L*} %o %{!nostdlib:libgcc.a%s %L libgcc.a%s %{!A:%E}}\n }}}}}";
586*58997Selan #else
587*58997Selan /* Use -L and have the linker do the search for -lgcc.  */
588*58997Selan static char *link_command_spec = "\
589*58997Selan %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
590*58997Selan 			%{r} %{s} %{T*} %{t} %{u*} %{x} %{z}\
591*58997Selan 			%{!A:%{!nostdlib:%S}} %{static:}\
592*58997Selan 			%{L*} %D %o %{!nostdlib:-lgcc %L -lgcc %{!A:%E}}\n }}}}}";
593*58997Selan #endif
594*58997Selan #endif
595*58997Selan 
596*58997Selan /* A vector of options to give to the linker.
597*58997Selan    These options are accumulated by -Xlinker and -Wl,
598*58997Selan    and substituted into the linker command with %X.  */
599*58997Selan static int n_linker_options;
600*58997Selan static char **linker_options;
601*58997Selan 
602*58997Selan /* A vector of options to give to the assembler.
603*58997Selan    These options are accumulated by -Wa,
604*58997Selan    and substituted into the assembler command with %X.  */
605*58997Selan static int n_assembler_options;
606*58997Selan static char **assembler_options;
607*58997Selan 
608*58997Selan /* Read compilation specs from a file named FILENAME,
609*58997Selan    replacing the default ones.
610*58997Selan 
611*58997Selan    A suffix which starts with `*' is a definition for
612*58997Selan    one of the machine-specific sub-specs.  The "suffix" should be
613*58997Selan    *asm, *cc1, *cpp, *link, *startfile, *signed_char, etc.
614*58997Selan    The corresponding spec is stored in asm_spec, etc.,
615*58997Selan    rather than in the `compilers' vector.
616*58997Selan 
617*58997Selan    Anything invalid in the file is a fatal error.  */
618*58997Selan 
619*58997Selan static void
620*58997Selan read_specs (filename)
621*58997Selan      char *filename;
622*58997Selan {
623*58997Selan   int desc;
624*58997Selan   struct stat statbuf;
625*58997Selan   char *buffer;
626*58997Selan   register char *p;
627*58997Selan 
628*58997Selan   if (verbose_flag)
629*58997Selan     fprintf (stderr, "Reading specs from %s\n", filename);
630*58997Selan 
631*58997Selan   /* Open and stat the file.  */
632*58997Selan   desc = open (filename, 0, 0);
633*58997Selan   if (desc < 0)
634*58997Selan     pfatal_with_name (filename);
635*58997Selan   if (stat (filename, &statbuf) < 0)
636*58997Selan     pfatal_with_name (filename);
637*58997Selan 
638*58997Selan   /* Read contents of file into BUFFER.  */
639*58997Selan   buffer = xmalloc ((unsigned) statbuf.st_size + 1);
640*58997Selan   read (desc, buffer, (unsigned) statbuf.st_size);
641*58997Selan   buffer[statbuf.st_size] = 0;
642*58997Selan   close (desc);
643*58997Selan 
644*58997Selan   /* Scan BUFFER for specs, putting them in the vector.  */
645*58997Selan   p = buffer;
646*58997Selan   while (1)
647*58997Selan     {
648*58997Selan       char *suffix;
649*58997Selan       char *spec;
650*58997Selan       char *in, *out, *p1, *p2;
651*58997Selan 
652*58997Selan       /* Advance P in BUFFER to the next nonblank nocomment line.  */
653*58997Selan       p = skip_whitespace (p);
654*58997Selan       if (*p == 0)
655*58997Selan 	break;
656*58997Selan 
657*58997Selan       /* Find the colon that should end the suffix.  */
658*58997Selan       p1 = p;
659*58997Selan       while (*p1 && *p1 != ':' && *p1 != '\n') p1++;
660*58997Selan       /* The colon shouldn't be missing.  */
661*58997Selan       if (*p1 != ':')
662*58997Selan 	fatal ("specs file malformed after %d characters", p1 - buffer);
663*58997Selan       /* Skip back over trailing whitespace.  */
664*58997Selan       p2 = p1;
665*58997Selan       while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t')) p2--;
666*58997Selan       /* Copy the suffix to a string.  */
667*58997Selan       suffix = save_string (p, p2 - p);
668*58997Selan       /* Find the next line.  */
669*58997Selan       p = skip_whitespace (p1 + 1);
670*58997Selan       if (p[1] == 0)
671*58997Selan 	fatal ("specs file malformed after %d characters", p - buffer);
672*58997Selan       p1 = p;
673*58997Selan       /* Find next blank line.  */
674*58997Selan       while (*p1 && !(*p1 == '\n' && p1[1] == '\n')) p1++;
675*58997Selan       /* Specs end at the blank line and do not include the newline.  */
676*58997Selan       spec = save_string (p, p1 - p);
677*58997Selan       p = p1;
678*58997Selan 
679*58997Selan       /* Delete backslash-newline sequences from the spec.  */
680*58997Selan       in = spec;
681*58997Selan       out = spec;
682*58997Selan       while (*in != 0)
683*58997Selan 	{
684*58997Selan 	  if (in[0] == '\\' && in[1] == '\n')
685*58997Selan 	    in += 2;
686*58997Selan 	  else if (in[0] == '#')
687*58997Selan 	    {
688*58997Selan 	      while (*in && *in != '\n') in++;
689*58997Selan 	    }
690*58997Selan 	  else
691*58997Selan 	    *out++ = *in++;
692*58997Selan 	}
693*58997Selan       *out = 0;
694*58997Selan 
695*58997Selan       if (suffix[0] == '*')
696*58997Selan 	{
697*58997Selan 	  if (! strcmp (suffix, "*link_command"))
698*58997Selan 	    link_command_spec = spec;
699*58997Selan 	  else
700*58997Selan 	    set_spec (suffix + 1, spec);
701*58997Selan 	}
702*58997Selan       else
703*58997Selan 	{
704*58997Selan 	  /* Add this pair to the vector.  */
705*58997Selan 	  compilers
706*58997Selan 	    = ((struct compiler *)
707*58997Selan 	       xrealloc (compilers, (n_compilers + 2) * sizeof (struct compiler)));
708*58997Selan 	  compilers[n_compilers].suffix = suffix;
709*58997Selan 	  bzero (compilers[n_compilers].spec,
710*58997Selan 		 sizeof compilers[n_compilers].spec);
711*58997Selan 	  compilers[n_compilers].spec[0] = spec;
712*58997Selan 	  n_compilers++;
713*58997Selan 	}
714*58997Selan 
715*58997Selan       if (*suffix == 0)
716*58997Selan 	link_command_spec = spec;
717*58997Selan     }
718*58997Selan 
719*58997Selan   if (link_command_spec == 0)
720*58997Selan     fatal ("spec file has no spec for linking");
721*58997Selan }
722*58997Selan 
723*58997Selan static char *
724*58997Selan skip_whitespace (p)
725*58997Selan      char *p;
726*58997Selan {
727*58997Selan   while (1)
728*58997Selan     {
729*58997Selan       /* A fully-blank line is a delimiter in the SPEC file and shouldn't
730*58997Selan 	 be considered whitespace.  */
731*58997Selan       if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n')
732*58997Selan 	return p + 1;
733*58997Selan       else if (*p == '\n' || *p == ' ' || *p == '\t')
734*58997Selan 	p++;
735*58997Selan       else if (*p == '#')
736*58997Selan 	{
737*58997Selan 	  while (*p != '\n') p++;
738*58997Selan 	  p++;
739*58997Selan 	}
740*58997Selan       else
741*58997Selan 	break;
742*58997Selan     }
743*58997Selan 
744*58997Selan   return p;
745*58997Selan }
746*58997Selan 
747*58997Selan /* Structure to keep track of the specs that have been defined so far.  These
748*58997Selan    are accessed using %(specname) or %[specname] in a compiler or link spec. */
749*58997Selan 
750*58997Selan struct spec_list
751*58997Selan {
752*58997Selan   char *name;                 /* Name of the spec. */
753*58997Selan   char *spec;                 /* The spec itself. */
754*58997Selan   struct spec_list *next;     /* Next spec in linked list. */
755*58997Selan };
756*58997Selan 
757*58997Selan /* List of specs that have been defined so far. */
758*58997Selan 
759*58997Selan static struct spec_list *specs = (struct spec_list *) 0;
760*58997Selan 
761*58997Selan /* Change the value of spec NAME to SPEC.  If SPEC is empty, then the spec is
762*58997Selan    removed; If the spec starts with a + then SPEC is added to the end of the
763*58997Selan    current spec. */
764*58997Selan 
765*58997Selan static void
766*58997Selan set_spec (name, spec)
767*58997Selan      char *name;
768*58997Selan      char *spec;
769*58997Selan {
770*58997Selan   struct spec_list *sl;
771*58997Selan   char *old_spec;
772*58997Selan 
773*58997Selan   /* See if the spec already exists */
774*58997Selan   for (sl = specs; sl; sl = sl->next)
775*58997Selan     if (strcmp (sl->name, name) == 0)
776*58997Selan       break;
777*58997Selan 
778*58997Selan   if (!sl)
779*58997Selan     {
780*58997Selan       /* Not found - make it */
781*58997Selan       sl = (struct spec_list *) xmalloc (sizeof (struct spec_list));
782*58997Selan       sl->name = save_string (name, strlen (name));
783*58997Selan       sl->spec = save_string ("", 0);
784*58997Selan       sl->next = specs;
785*58997Selan       specs = sl;
786*58997Selan     }
787*58997Selan 
788*58997Selan   old_spec = sl->spec;
789*58997Selan   if (name && spec[0] == '+' && isspace (spec[1]))
790*58997Selan     sl->spec = concat (old_spec, spec + 1, "");
791*58997Selan   else
792*58997Selan     sl->spec = save_string (spec, strlen (spec));
793*58997Selan 
794*58997Selan   if (! strcmp (name, "asm"))
795*58997Selan     asm_spec = sl->spec;
796*58997Selan   else if (! strcmp (name, "asm_final"))
797*58997Selan     asm_final_spec = sl->spec;
798*58997Selan   else if (! strcmp (name, "cc1"))
799*58997Selan     cc1_spec = sl->spec;
800*58997Selan   else if (! strcmp (name, "cc1plus"))
801*58997Selan     cc1plus_spec = sl->spec;
802*58997Selan   else if (! strcmp (name, "cpp"))
803*58997Selan     cpp_spec = sl->spec;
804*58997Selan   else if (! strcmp (name, "endfile"))
805*58997Selan     endfile_spec = sl->spec;
806*58997Selan   else if (! strcmp (name, "lib"))
807*58997Selan     lib_spec = sl->spec;
808*58997Selan   else if (! strcmp (name, "link"))
809*58997Selan     link_spec = sl->spec;
810*58997Selan   else if (! strcmp (name, "predefines"))
811*58997Selan     cpp_predefines = sl->spec;
812*58997Selan   else if (! strcmp (name, "signed_char"))
813*58997Selan     signed_char_spec = sl->spec;
814*58997Selan   else if (! strcmp (name, "startfile"))
815*58997Selan     startfile_spec = sl->spec;
816*58997Selan   else if (! strcmp (name, "switches_need_spaces"))
817*58997Selan     switches_need_spaces = sl->spec;
818*58997Selan   else if (! strcmp (name, "cross_compile"))
819*58997Selan     cross_compile = atoi (sl->spec);
820*58997Selan   /* Free the old spec */
821*58997Selan   if (old_spec)
822*58997Selan     free (old_spec);
823*58997Selan }
824*58997Selan 
825*58997Selan /* Accumulate a command (program name and args), and run it.  */
826*58997Selan 
827*58997Selan /* Vector of pointers to arguments in the current line of specifications.  */
828*58997Selan 
829*58997Selan static char **argbuf;
830*58997Selan 
831*58997Selan /* Number of elements allocated in argbuf.  */
832*58997Selan 
833*58997Selan static int argbuf_length;
834*58997Selan 
835*58997Selan /* Number of elements in argbuf currently in use (containing args).  */
836*58997Selan 
837*58997Selan static int argbuf_index;
838*58997Selan 
839*58997Selan /* This is the list of suffixes and codes (%g/%u/%U) and the associated
840*58997Selan    temp file.  Used only if MKTEMP_EACH_FILE.  */
841*58997Selan 
842*58997Selan static struct temp_name {
843*58997Selan   char *suffix;		/* suffix associated with the code.  */
844*58997Selan   int length;		/* strlen (suffix).  */
845*58997Selan   int unique;		/* Indicates whether %g or %u/%U was used.  */
846*58997Selan   char *filename;	/* associated filename.  */
847*58997Selan   int filename_length;	/* strlen (filename).  */
848*58997Selan   struct temp_name *next;
849*58997Selan } *temp_names;
850*58997Selan 
851*58997Selan /* Number of commands executed so far.  */
852*58997Selan 
853*58997Selan static int execution_count;
854*58997Selan 
855*58997Selan /* Number of commands that exited with a signal.  */
856*58997Selan 
857*58997Selan static int signal_count;
858*58997Selan 
859*58997Selan /* Name with which this program was invoked.  */
860*58997Selan 
861*58997Selan static char *programname;
862*58997Selan 
863*58997Selan /* Structures to keep track of prefixes to try when looking for files. */
864*58997Selan 
865*58997Selan struct prefix_list
866*58997Selan {
867*58997Selan   char *prefix;               /* String to prepend to the path. */
868*58997Selan   struct prefix_list *next;   /* Next in linked list. */
869*58997Selan   int require_machine_suffix; /* Don't use without machine_suffix.  */
870*58997Selan   /* 2 means try both machine_suffix and just_machine_suffix.  */
871*58997Selan   int *used_flag_ptr;	      /* 1 if a file was found with this prefix.  */
872*58997Selan };
873*58997Selan 
874*58997Selan struct path_prefix
875*58997Selan {
876*58997Selan   struct prefix_list *plist;  /* List of prefixes to try */
877*58997Selan   int max_len;                /* Max length of a prefix in PLIST */
878*58997Selan   char *name;                 /* Name of this list (used in config stuff) */
879*58997Selan };
880*58997Selan 
881*58997Selan /* List of prefixes to try when looking for executables. */
882*58997Selan 
883*58997Selan static struct path_prefix exec_prefix = { 0, 0, "exec" };
884*58997Selan 
885*58997Selan /* List of prefixes to try when looking for startup (crt0) files. */
886*58997Selan 
887*58997Selan static struct path_prefix startfile_prefix = { 0, 0, "startfile" };
888*58997Selan 
889*58997Selan /* List of prefixes to try when looking for libraries. */
890*58997Selan 
891*58997Selan static struct path_prefix library_prefix = { 0, 0, "libraryfile" };
892*58997Selan 
893*58997Selan /* Suffix to attach to directories searched for commands.
894*58997Selan    This looks like `MACHINE/VERSION/'.  */
895*58997Selan 
896*58997Selan static char *machine_suffix = 0;
897*58997Selan 
898*58997Selan /* Suffix to attach to directories searched for commands.
899*58997Selan    This is just `MACHINE/'.  */
900*58997Selan 
901*58997Selan static char *just_machine_suffix = 0;
902*58997Selan 
903*58997Selan /* Adjusted value of GCC_EXEC_PREFIX envvar.  */
904*58997Selan 
905*58997Selan static char *gcc_exec_prefix;
906*58997Selan 
907*58997Selan /* Default prefixes to attach to command names.  */
908*58997Selan 
909*58997Selan #ifdef CROSS_COMPILE  /* Don't use these prefixes for a cross compiler.  */
910*58997Selan #undef MD_EXEC_PREFIX
911*58997Selan #undef MD_STARTFILE_PREFIX
912*58997Selan #undef MD_STARTFILE_PREFIX_1
913*58997Selan #endif
914*58997Selan 
915*58997Selan #ifndef STANDARD_EXEC_PREFIX
916*58997Selan #define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/"
917*58997Selan #endif /* !defined STANDARD_EXEC_PREFIX */
918*58997Selan 
919*58997Selan static char *standard_exec_prefix = STANDARD_EXEC_PREFIX;
920*58997Selan static char *standard_exec_prefix_1 = "/usr/lib/gcc/";
921*58997Selan #ifdef MD_EXEC_PREFIX
922*58997Selan static char *md_exec_prefix = MD_EXEC_PREFIX;
923*58997Selan #endif
924*58997Selan 
925*58997Selan #ifndef STANDARD_STARTFILE_PREFIX
926*58997Selan #define STANDARD_STARTFILE_PREFIX "/usr/local/lib/"
927*58997Selan #endif /* !defined STANDARD_STARTFILE_PREFIX */
928*58997Selan 
929*58997Selan #ifdef MD_STARTFILE_PREFIX
930*58997Selan static char *md_startfile_prefix = MD_STARTFILE_PREFIX;
931*58997Selan #endif
932*58997Selan #ifdef MD_STARTFILE_PREFIX_1
933*58997Selan static char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
934*58997Selan #endif
935*58997Selan static char *standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
936*58997Selan static char *standard_startfile_prefix_1 = "/lib/";
937*58997Selan static char *standard_startfile_prefix_2 = "/usr/lib/";
938*58997Selan 
939*58997Selan /* Clear out the vector of arguments (after a command is executed).  */
940*58997Selan 
941*58997Selan static void
942*58997Selan clear_args ()
943*58997Selan {
944*58997Selan   argbuf_index = 0;
945*58997Selan }
946*58997Selan 
947*58997Selan /* Add one argument to the vector at the end.
948*58997Selan    This is done when a space is seen or at the end of the line.
949*58997Selan    If DELETE_ALWAYS is nonzero, the arg is a filename
950*58997Selan     and the file should be deleted eventually.
951*58997Selan    If DELETE_FAILURE is nonzero, the arg is a filename
952*58997Selan     and the file should be deleted if this compilation fails.  */
953*58997Selan 
954*58997Selan static void
955*58997Selan store_arg (arg, delete_always, delete_failure)
956*58997Selan      char *arg;
957*58997Selan      int delete_always, delete_failure;
958*58997Selan {
959*58997Selan   if (argbuf_index + 1 == argbuf_length)
960*58997Selan     {
961*58997Selan       argbuf = (char **) xrealloc (argbuf, (argbuf_length *= 2) * sizeof (char *));
962*58997Selan     }
963*58997Selan 
964*58997Selan   argbuf[argbuf_index++] = arg;
965*58997Selan   argbuf[argbuf_index] = 0;
966*58997Selan 
967*58997Selan   if (delete_always || delete_failure)
968*58997Selan     record_temp_file (arg, delete_always, delete_failure);
969*58997Selan }
970*58997Selan 
971*58997Selan /* Record the names of temporary files we tell compilers to write,
972*58997Selan    and delete them at the end of the run.  */
973*58997Selan 
974*58997Selan /* This is the common prefix we use to make temp file names.
975*58997Selan    It is chosen once for each run of this program.
976*58997Selan    It is substituted into a spec by %g.
977*58997Selan    Thus, all temp file names contain this prefix.
978*58997Selan    In practice, all temp file names start with this prefix.
979*58997Selan 
980*58997Selan    This prefix comes from the envvar TMPDIR if it is defined;
981*58997Selan    otherwise, from the P_tmpdir macro if that is defined;
982*58997Selan    otherwise, in /usr/tmp or /tmp.  */
983*58997Selan 
984*58997Selan static char *temp_filename;
985*58997Selan 
986*58997Selan /* Length of the prefix.  */
987*58997Selan 
988*58997Selan static int temp_filename_length;
989*58997Selan 
990*58997Selan /* Define the list of temporary files to delete.  */
991*58997Selan 
992*58997Selan struct temp_file
993*58997Selan {
994*58997Selan   char *name;
995*58997Selan   struct temp_file *next;
996*58997Selan };
997*58997Selan 
998*58997Selan /* Queue of files to delete on success or failure of compilation.  */
999*58997Selan static struct temp_file *always_delete_queue;
1000*58997Selan /* Queue of files to delete on failure of compilation.  */
1001*58997Selan static struct temp_file *failure_delete_queue;
1002*58997Selan 
1003*58997Selan /* Record FILENAME as a file to be deleted automatically.
1004*58997Selan    ALWAYS_DELETE nonzero means delete it if all compilation succeeds;
1005*58997Selan    otherwise delete it in any case.
1006*58997Selan    FAIL_DELETE nonzero means delete it if a compilation step fails;
1007*58997Selan    otherwise delete it in any case.  */
1008*58997Selan 
1009*58997Selan static void
1010*58997Selan record_temp_file (filename, always_delete, fail_delete)
1011*58997Selan      char *filename;
1012*58997Selan      int always_delete;
1013*58997Selan      int fail_delete;
1014*58997Selan {
1015*58997Selan   register char *name;
1016*58997Selan   name = xmalloc (strlen (filename) + 1);
1017*58997Selan   strcpy (name, filename);
1018*58997Selan 
1019*58997Selan   if (always_delete)
1020*58997Selan     {
1021*58997Selan       register struct temp_file *temp;
1022*58997Selan       for (temp = always_delete_queue; temp; temp = temp->next)
1023*58997Selan 	if (! strcmp (name, temp->name))
1024*58997Selan 	  goto already1;
1025*58997Selan       temp = (struct temp_file *) xmalloc (sizeof (struct temp_file));
1026*58997Selan       temp->next = always_delete_queue;
1027*58997Selan       temp->name = name;
1028*58997Selan       always_delete_queue = temp;
1029*58997Selan     already1:;
1030*58997Selan     }
1031*58997Selan 
1032*58997Selan   if (fail_delete)
1033*58997Selan     {
1034*58997Selan       register struct temp_file *temp;
1035*58997Selan       for (temp = failure_delete_queue; temp; temp = temp->next)
1036*58997Selan 	if (! strcmp (name, temp->name))
1037*58997Selan 	  goto already2;
1038*58997Selan       temp = (struct temp_file *) xmalloc (sizeof (struct temp_file));
1039*58997Selan       temp->next = failure_delete_queue;
1040*58997Selan       temp->name = name;
1041*58997Selan       failure_delete_queue = temp;
1042*58997Selan     already2:;
1043*58997Selan     }
1044*58997Selan }
1045*58997Selan 
1046*58997Selan /* Delete all the temporary files whose names we previously recorded.  */
1047*58997Selan 
1048*58997Selan static void
1049*58997Selan delete_temp_files ()
1050*58997Selan {
1051*58997Selan   register struct temp_file *temp;
1052*58997Selan 
1053*58997Selan   for (temp = always_delete_queue; temp; temp = temp->next)
1054*58997Selan     {
1055*58997Selan #ifdef DEBUG
1056*58997Selan       int i;
1057*58997Selan       printf ("Delete %s? (y or n) ", temp->name);
1058*58997Selan       fflush (stdout);
1059*58997Selan       i = getchar ();
1060*58997Selan       if (i != '\n')
1061*58997Selan 	while (getchar () != '\n') ;
1062*58997Selan       if (i == 'y' || i == 'Y')
1063*58997Selan #endif /* DEBUG */
1064*58997Selan 	{
1065*58997Selan 	  struct stat st;
1066*58997Selan 	  if (stat (temp->name, &st) >= 0)
1067*58997Selan 	    {
1068*58997Selan 	      /* Delete only ordinary files.  */
1069*58997Selan 	      if (S_ISREG (st.st_mode))
1070*58997Selan 		if (unlink (temp->name) < 0)
1071*58997Selan 		  if (verbose_flag)
1072*58997Selan 		    perror_with_name (temp->name);
1073*58997Selan 	    }
1074*58997Selan 	}
1075*58997Selan     }
1076*58997Selan 
1077*58997Selan   always_delete_queue = 0;
1078*58997Selan }
1079*58997Selan 
1080*58997Selan /* Delete all the files to be deleted on error.  */
1081*58997Selan 
1082*58997Selan static void
1083*58997Selan delete_failure_queue ()
1084*58997Selan {
1085*58997Selan   register struct temp_file *temp;
1086*58997Selan 
1087*58997Selan   for (temp = failure_delete_queue; temp; temp = temp->next)
1088*58997Selan     {
1089*58997Selan #ifdef DEBUG
1090*58997Selan       int i;
1091*58997Selan       printf ("Delete %s? (y or n) ", temp->name);
1092*58997Selan       fflush (stdout);
1093*58997Selan       i = getchar ();
1094*58997Selan       if (i != '\n')
1095*58997Selan 	while (getchar () != '\n') ;
1096*58997Selan       if (i == 'y' || i == 'Y')
1097*58997Selan #endif /* DEBUG */
1098*58997Selan 	{
1099*58997Selan 	  if (unlink (temp->name) < 0)
1100*58997Selan 	    if (verbose_flag)
1101*58997Selan 	      perror_with_name (temp->name);
1102*58997Selan 	}
1103*58997Selan     }
1104*58997Selan }
1105*58997Selan 
1106*58997Selan static void
1107*58997Selan clear_failure_queue ()
1108*58997Selan {
1109*58997Selan   failure_delete_queue = 0;
1110*58997Selan }
1111*58997Selan 
1112*58997Selan /* Compute a string to use as the base of all temporary file names.
1113*58997Selan    It is substituted for %g.  */
1114*58997Selan 
1115*58997Selan static void
1116*58997Selan choose_temp_base ()
1117*58997Selan {
1118*58997Selan   char *base = getenv ("TMPDIR");
1119*58997Selan   int len;
1120*58997Selan 
1121*58997Selan   if (base == (char *)0)
1122*58997Selan     {
1123*58997Selan #ifdef P_tmpdir
1124*58997Selan       if (access (P_tmpdir, R_OK | W_OK) == 0)
1125*58997Selan 	base = P_tmpdir;
1126*58997Selan #endif
1127*58997Selan       if (base == (char *)0)
1128*58997Selan 	{
1129*58997Selan 	  if (access ("/usr/tmp", R_OK | W_OK) == 0)
1130*58997Selan 	    base = "/usr/tmp/";
1131*58997Selan 	  else
1132*58997Selan 	    base = "/tmp/";
1133*58997Selan 	}
1134*58997Selan     }
1135*58997Selan 
1136*58997Selan   len = strlen (base);
1137*58997Selan   temp_filename = xmalloc (len + sizeof("/ccXXXXXX"));
1138*58997Selan   strcpy (temp_filename, base);
1139*58997Selan   if (len > 0 && temp_filename[len-1] != '/')
1140*58997Selan     temp_filename[len++] = '/';
1141*58997Selan   strcpy (temp_filename + len, "ccXXXXXX");
1142*58997Selan 
1143*58997Selan   mktemp (temp_filename);
1144*58997Selan   temp_filename_length = strlen (temp_filename);
1145*58997Selan   if (temp_filename_length == 0)
1146*58997Selan     abort ();
1147*58997Selan }
1148*58997Selan 
1149*58997Selan 
1150*58997Selan /* Routine to add variables to the environment.  We do this to pass
1151*58997Selan    the pathname of the gcc driver, and the directories search to the
1152*58997Selan    collect2 program, which is being run as ld.  This way, we can be
1153*58997Selan    sure of executing the right compiler when collect2 wants to build
1154*58997Selan    constructors and destructors.  Since the environment variables we
1155*58997Selan    use come from an obstack, we don't have to worry about allocating
1156*58997Selan    space for them.  */
1157*58997Selan 
1158*58997Selan #ifndef HAVE_PUTENV
1159*58997Selan 
1160*58997Selan putenv (str)
1161*58997Selan      char *str;
1162*58997Selan {
1163*58997Selan #ifndef VMS			/* nor about VMS */
1164*58997Selan 
1165*58997Selan   extern char **environ;
1166*58997Selan   char **old_environ = environ;
1167*58997Selan   char **envp;
1168*58997Selan   int num_envs = 0;
1169*58997Selan   int name_len = 1;
1170*58997Selan   int str_len = strlen (str);
1171*58997Selan   char *p = str;
1172*58997Selan   int ch;
1173*58997Selan 
1174*58997Selan   while ((ch = *p++) != '\0' && ch != '=')
1175*58997Selan     name_len++;
1176*58997Selan 
1177*58997Selan   if (!ch)
1178*58997Selan     abort ();
1179*58997Selan 
1180*58997Selan   /* Search for replacing an existing environment variable, and
1181*58997Selan      count the number of total environment variables.  */
1182*58997Selan   for (envp = old_environ; *envp; envp++)
1183*58997Selan     {
1184*58997Selan       num_envs++;
1185*58997Selan       if (!strncmp (str, *envp, name_len))
1186*58997Selan 	{
1187*58997Selan 	  *envp = str;
1188*58997Selan 	  return;
1189*58997Selan 	}
1190*58997Selan     }
1191*58997Selan 
1192*58997Selan   /* Add a new environment variable */
1193*58997Selan   environ = (char **) xmalloc (sizeof (char *) * (num_envs+2));
1194*58997Selan   *environ = str;
1195*58997Selan   bcopy (old_environ, environ+1, sizeof (char *) * (num_envs+1));
1196*58997Selan 
1197*58997Selan #endif	/* VMS */
1198*58997Selan }
1199*58997Selan 
1200*58997Selan #endif	/* HAVE_PUTENV */
1201*58997Selan 
1202*58997Selan 
1203*58997Selan /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables for collect.  */
1204*58997Selan 
1205*58997Selan static void
1206*58997Selan putenv_from_prefixes (paths, env_var)
1207*58997Selan      struct path_prefix *paths;
1208*58997Selan      char *env_var;
1209*58997Selan {
1210*58997Selan   int suffix_len = (machine_suffix) ? strlen (machine_suffix) : 0;
1211*58997Selan   int first_time = TRUE;
1212*58997Selan   struct prefix_list *pprefix;
1213*58997Selan 
1214*58997Selan   obstack_grow (&collect_obstack, env_var, strlen (env_var));
1215*58997Selan 
1216*58997Selan   for (pprefix = paths->plist; pprefix != 0; pprefix = pprefix->next)
1217*58997Selan     {
1218*58997Selan       int len = strlen (pprefix->prefix);
1219*58997Selan 
1220*58997Selan       if (machine_suffix)
1221*58997Selan 	{
1222*58997Selan 	  if (!first_time)
1223*58997Selan 	    obstack_grow (&collect_obstack, ":", 1);
1224*58997Selan 
1225*58997Selan 	  first_time = FALSE;
1226*58997Selan 	  obstack_grow (&collect_obstack, pprefix->prefix, len);
1227*58997Selan 	  obstack_grow (&collect_obstack, machine_suffix, suffix_len);
1228*58997Selan 	}
1229*58997Selan 
1230*58997Selan       if (just_machine_suffix && pprefix->require_machine_suffix == 2)
1231*58997Selan 	{
1232*58997Selan 	  if (!first_time)
1233*58997Selan 	    obstack_grow (&collect_obstack, ":", 1);
1234*58997Selan 
1235*58997Selan 	  first_time = FALSE;
1236*58997Selan 	  obstack_grow (&collect_obstack, pprefix->prefix, len);
1237*58997Selan 	  obstack_grow (&collect_obstack, machine_suffix, suffix_len);
1238*58997Selan 	}
1239*58997Selan 
1240*58997Selan       if (!pprefix->require_machine_suffix)
1241*58997Selan 	{
1242*58997Selan 	  if (!first_time)
1243*58997Selan 	    obstack_grow (&collect_obstack, ":", 1);
1244*58997Selan 
1245*58997Selan 	  first_time = FALSE;
1246*58997Selan 	  obstack_grow (&collect_obstack, pprefix->prefix, len);
1247*58997Selan 	}
1248*58997Selan     }
1249*58997Selan   obstack_grow (&collect_obstack, "\0", 1);
1250*58997Selan   putenv (obstack_finish (&collect_obstack));
1251*58997Selan }
1252*58997Selan 
1253*58997Selan 
1254*58997Selan /* Search for NAME using the prefix list PREFIXES.  MODE is passed to
1255*58997Selan    access to check permissions.
1256*58997Selan    Return 0 if not found, otherwise return its name, allocated with malloc. */
1257*58997Selan 
1258*58997Selan static char *
1259*58997Selan find_a_file (pprefix, name, mode)
1260*58997Selan      struct path_prefix *pprefix;
1261*58997Selan      char *name;
1262*58997Selan      int mode;
1263*58997Selan {
1264*58997Selan   char *temp;
1265*58997Selan   char *file_suffix = ((mode & X_OK) != 0 ? EXECUTABLE_SUFFIX : "");
1266*58997Selan   struct prefix_list *pl;
1267*58997Selan   int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1;
1268*58997Selan 
1269*58997Selan   if (machine_suffix)
1270*58997Selan     len += strlen (machine_suffix);
1271*58997Selan 
1272*58997Selan   temp = xmalloc (len);
1273*58997Selan 
1274*58997Selan   /* Determine the filename to execute (special case for absolute paths).  */
1275*58997Selan 
1276*58997Selan   if (*name == '/')
1277*58997Selan     {
1278*58997Selan       if (access (name, mode))
1279*58997Selan 	{
1280*58997Selan 	  strcpy (temp, name);
1281*58997Selan 	  return temp;
1282*58997Selan 	}
1283*58997Selan     }
1284*58997Selan   else
1285*58997Selan     for (pl = pprefix->plist; pl; pl = pl->next)
1286*58997Selan       {
1287*58997Selan 	if (machine_suffix)
1288*58997Selan 	  {
1289*58997Selan 	    strcpy (temp, pl->prefix);
1290*58997Selan 	    strcat (temp, machine_suffix);
1291*58997Selan 	    strcat (temp, name);
1292*58997Selan 	    if (access (temp, mode) == 0)
1293*58997Selan 	      {
1294*58997Selan 		if (pl->used_flag_ptr != 0)
1295*58997Selan 		  *pl->used_flag_ptr = 1;
1296*58997Selan 		return temp;
1297*58997Selan 	      }
1298*58997Selan 	    /* Some systems have a suffix for executable files.
1299*58997Selan 	       So try appending that.  */
1300*58997Selan 	    if (file_suffix[0] != 0)
1301*58997Selan 	      {
1302*58997Selan 		strcat (temp, file_suffix);
1303*58997Selan 		if (access (temp, mode) == 0)
1304*58997Selan 		  {
1305*58997Selan 		    if (pl->used_flag_ptr != 0)
1306*58997Selan 		      *pl->used_flag_ptr = 1;
1307*58997Selan 		    return temp;
1308*58997Selan 		  }
1309*58997Selan 	      }
1310*58997Selan 	  }
1311*58997Selan 	/* Certain prefixes are tried with just the machine type,
1312*58997Selan 	   not the version.  This is used for finding as, ld, etc.  */
1313*58997Selan 	if (just_machine_suffix && pl->require_machine_suffix == 2)
1314*58997Selan 	  {
1315*58997Selan 	    strcpy (temp, pl->prefix);
1316*58997Selan 	    strcat (temp, just_machine_suffix);
1317*58997Selan 	    strcat (temp, name);
1318*58997Selan 	    if (access (temp, mode) == 0)
1319*58997Selan 	      {
1320*58997Selan 		if (pl->used_flag_ptr != 0)
1321*58997Selan 		  *pl->used_flag_ptr = 1;
1322*58997Selan 		return temp;
1323*58997Selan 	      }
1324*58997Selan 	    /* Some systems have a suffix for executable files.
1325*58997Selan 	       So try appending that.  */
1326*58997Selan 	    if (file_suffix[0] != 0)
1327*58997Selan 	      {
1328*58997Selan 		strcat (temp, file_suffix);
1329*58997Selan 		if (access (temp, mode) == 0)
1330*58997Selan 		  {
1331*58997Selan 		    if (pl->used_flag_ptr != 0)
1332*58997Selan 		      *pl->used_flag_ptr = 1;
1333*58997Selan 		    return temp;
1334*58997Selan 		  }
1335*58997Selan 	      }
1336*58997Selan 	  }
1337*58997Selan 	/* Certain prefixes can't be used without the machine suffix
1338*58997Selan 	   when the machine or version is explicitly specified.  */
1339*58997Selan 	if (!pl->require_machine_suffix)
1340*58997Selan 	  {
1341*58997Selan 	    strcpy (temp, pl->prefix);
1342*58997Selan 	    strcat (temp, name);
1343*58997Selan 	    if (access (temp, mode) == 0)
1344*58997Selan 	      {
1345*58997Selan 		if (pl->used_flag_ptr != 0)
1346*58997Selan 		  *pl->used_flag_ptr = 1;
1347*58997Selan 		return temp;
1348*58997Selan 	      }
1349*58997Selan 	    /* Some systems have a suffix for executable files.
1350*58997Selan 	       So try appending that.  */
1351*58997Selan 	    if (file_suffix[0] != 0)
1352*58997Selan 	      {
1353*58997Selan 		strcat (temp, file_suffix);
1354*58997Selan 		if (access (temp, mode) == 0)
1355*58997Selan 		  {
1356*58997Selan 		    if (pl->used_flag_ptr != 0)
1357*58997Selan 		      *pl->used_flag_ptr = 1;
1358*58997Selan 		    return temp;
1359*58997Selan 		  }
1360*58997Selan 	      }
1361*58997Selan 	  }
1362*58997Selan       }
1363*58997Selan 
1364*58997Selan   free (temp);
1365*58997Selan   return 0;
1366*58997Selan }
1367*58997Selan 
1368*58997Selan /* Add an entry for PREFIX in PLIST.  If FIRST is set, it goes
1369*58997Selan    at the start of the list, otherwise it goes at the end.
1370*58997Selan 
1371*58997Selan    If WARN is nonzero, we will warn if no file is found
1372*58997Selan    through this prefix.  WARN should point to an int
1373*58997Selan    which will be set to 1 if this entry is used.
1374*58997Selan 
1375*58997Selan    REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without
1376*58997Selan    the complete value of machine_suffix.
1377*58997Selan    2 means try both machine_suffix and just_machine_suffix.  */
1378*58997Selan 
1379*58997Selan static void
1380*58997Selan add_prefix (pprefix, prefix, first, require_machine_suffix, warn)
1381*58997Selan      struct path_prefix *pprefix;
1382*58997Selan      char *prefix;
1383*58997Selan      int first;
1384*58997Selan      int require_machine_suffix;
1385*58997Selan      int *warn;
1386*58997Selan {
1387*58997Selan   struct prefix_list *pl, **prev;
1388*58997Selan   int len;
1389*58997Selan 
1390*58997Selan   if (!first && pprefix->plist)
1391*58997Selan     {
1392*58997Selan       for (pl = pprefix->plist; pl->next; pl = pl->next)
1393*58997Selan 	;
1394*58997Selan       prev = &pl->next;
1395*58997Selan     }
1396*58997Selan   else
1397*58997Selan     prev = &pprefix->plist;
1398*58997Selan 
1399*58997Selan   /* Keep track of the longest prefix */
1400*58997Selan 
1401*58997Selan   len = strlen (prefix);
1402*58997Selan   if (len > pprefix->max_len)
1403*58997Selan     pprefix->max_len = len;
1404*58997Selan 
1405*58997Selan   pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
1406*58997Selan   pl->prefix = save_string (prefix, len);
1407*58997Selan   pl->require_machine_suffix = require_machine_suffix;
1408*58997Selan   pl->used_flag_ptr = warn;
1409*58997Selan   if (warn)
1410*58997Selan     *warn = 0;
1411*58997Selan 
1412*58997Selan   if (*prev)
1413*58997Selan     pl->next = *prev;
1414*58997Selan   else
1415*58997Selan     pl->next = (struct prefix_list *) 0;
1416*58997Selan   *prev = pl;
1417*58997Selan }
1418*58997Selan 
1419*58997Selan /* Print warnings for any prefixes in the list PPREFIX that were not used.  */
1420*58997Selan 
1421*58997Selan static void
1422*58997Selan unused_prefix_warnings (pprefix)
1423*58997Selan      struct path_prefix *pprefix;
1424*58997Selan {
1425*58997Selan   struct prefix_list *pl = pprefix->plist;
1426*58997Selan 
1427*58997Selan   while (pl)
1428*58997Selan     {
1429*58997Selan       if (pl->used_flag_ptr != 0 && !*pl->used_flag_ptr)
1430*58997Selan 	{
1431*58997Selan 	  error ("file path prefix `%s' never used",
1432*58997Selan 		 pl->prefix);
1433*58997Selan 	  /* Prevent duplicate warnings.  */
1434*58997Selan 	  *pl->used_flag_ptr = 1;
1435*58997Selan 	}
1436*58997Selan       pl = pl->next;
1437*58997Selan     }
1438*58997Selan }
1439*58997Selan 
1440*58997Selan /* Get rid of all prefixes built up so far in *PLISTP. */
1441*58997Selan 
1442*58997Selan static void
1443*58997Selan free_path_prefix (pprefix)
1444*58997Selan      struct path_prefix *pprefix;
1445*58997Selan {
1446*58997Selan   struct prefix_list *pl = pprefix->plist;
1447*58997Selan   struct prefix_list *temp;
1448*58997Selan 
1449*58997Selan   while (pl)
1450*58997Selan     {
1451*58997Selan       temp = pl;
1452*58997Selan       pl = pl->next;
1453*58997Selan       free (temp->prefix);
1454*58997Selan       free ((char *) temp);
1455*58997Selan     }
1456*58997Selan   pprefix->plist = (struct prefix_list *) 0;
1457*58997Selan }
1458*58997Selan 
1459*58997Selan /* stdin file number.  */
1460*58997Selan #define STDIN_FILE_NO 0
1461*58997Selan 
1462*58997Selan /* stdout file number.  */
1463*58997Selan #define STDOUT_FILE_NO 1
1464*58997Selan 
1465*58997Selan /* value of `pipe': port index for reading.  */
1466*58997Selan #define READ_PORT 0
1467*58997Selan 
1468*58997Selan /* value of `pipe': port index for writing.  */
1469*58997Selan #define WRITE_PORT 1
1470*58997Selan 
1471*58997Selan /* Pipe waiting from last process, to be used as input for the next one.
1472*58997Selan    Value is STDIN_FILE_NO if no pipe is waiting
1473*58997Selan    (i.e. the next command is the first of a group).  */
1474*58997Selan 
1475*58997Selan static int last_pipe_input;
1476*58997Selan 
1477*58997Selan /* Fork one piped subcommand.  FUNC is the system call to use
1478*58997Selan    (either execv or execvp).  ARGV is the arg vector to use.
1479*58997Selan    NOT_LAST is nonzero if this is not the last subcommand
1480*58997Selan    (i.e. its output should be piped to the next one.)  */
1481*58997Selan 
1482*58997Selan #ifndef OS2
1483*58997Selan #ifdef __MSDOS__
1484*58997Selan 
1485*58997Selan /* Declare these to avoid compilation error.  They won't be called.  */
1486*58997Selan int execv(const char *a, const char **b){}
1487*58997Selan int execvp(const char *a, const char **b){}
1488*58997Selan 
1489*58997Selan static int
1490*58997Selan pexecute (search_flag, program, argv, not_last)
1491*58997Selan      int search_flag;
1492*58997Selan      char *program;
1493*58997Selan      char *argv[];
1494*58997Selan      int not_last;
1495*58997Selan {
1496*58997Selan   char *scmd;
1497*58997Selan   FILE *argfile;
1498*58997Selan   int i;
1499*58997Selan 
1500*58997Selan   scmd = (char *)malloc (strlen (program) + strlen (temp_filename) + 6);
1501*58997Selan   sprintf (scmd, "%s @%s.gp", program, temp_filename);
1502*58997Selan   argfile = fopen (scmd+strlen (program) + 2, "w");
1503*58997Selan   if (argfile == 0)
1504*58997Selan     pfatal_with_name (scmd + strlen (program) + 2);
1505*58997Selan 
1506*58997Selan   for (i=1; argv[i]; i++)
1507*58997Selan   {
1508*58997Selan     char *cp;
1509*58997Selan     for (cp = argv[i]; *cp; cp++)
1510*58997Selan       {
1511*58997Selan 	if (*cp == '"' || *cp == '\'' || *cp == '\\' || isspace (*cp))
1512*58997Selan 	  fputc ('\\', argfile);
1513*58997Selan 	fputc (*cp, argfile);
1514*58997Selan       }
1515*58997Selan     fputc ('\n', argfile);
1516*58997Selan   }
1517*58997Selan   fclose (argfile);
1518*58997Selan 
1519*58997Selan   i = system (scmd);
1520*58997Selan 
1521*58997Selan   remove (scmd + strlen (program) + 2);
1522*58997Selan   return i << 8;
1523*58997Selan }
1524*58997Selan 
1525*58997Selan #else /* not __MSDOS__ */
1526*58997Selan 
1527*58997Selan static int
1528*58997Selan pexecute (search_flag, program, argv, not_last)
1529*58997Selan      int search_flag;
1530*58997Selan      char *program;
1531*58997Selan      char *argv[];
1532*58997Selan      int not_last;
1533*58997Selan {
1534*58997Selan   int (*func)() = (search_flag ? execv : execvp);
1535*58997Selan   int pid;
1536*58997Selan   int pdes[2];
1537*58997Selan   int input_desc = last_pipe_input;
1538*58997Selan   int output_desc = STDOUT_FILE_NO;
1539*58997Selan   int retries, sleep_interval;
1540*58997Selan 
1541*58997Selan   /* If this isn't the last process, make a pipe for its output,
1542*58997Selan      and record it as waiting to be the input to the next process.  */
1543*58997Selan 
1544*58997Selan   if (not_last)
1545*58997Selan     {
1546*58997Selan       if (pipe (pdes) < 0)
1547*58997Selan 	pfatal_with_name ("pipe");
1548*58997Selan       output_desc = pdes[WRITE_PORT];
1549*58997Selan       last_pipe_input = pdes[READ_PORT];
1550*58997Selan     }
1551*58997Selan   else
1552*58997Selan     last_pipe_input = STDIN_FILE_NO;
1553*58997Selan 
1554*58997Selan   /* Fork a subprocess; wait and retry if it fails.  */
1555*58997Selan   sleep_interval = 1;
1556*58997Selan   for (retries = 0; retries < 4; retries++)
1557*58997Selan     {
1558*58997Selan       pid = vfork ();
1559*58997Selan       if (pid >= 0)
1560*58997Selan 	break;
1561*58997Selan       sleep (sleep_interval);
1562*58997Selan       sleep_interval *= 2;
1563*58997Selan     }
1564*58997Selan 
1565*58997Selan   switch (pid)
1566*58997Selan     {
1567*58997Selan     case -1:
1568*58997Selan #ifdef vfork
1569*58997Selan       pfatal_with_name ("fork");
1570*58997Selan #else
1571*58997Selan       pfatal_with_name ("vfork");
1572*58997Selan #endif
1573*58997Selan       /* NOTREACHED */
1574*58997Selan       return 0;
1575*58997Selan 
1576*58997Selan     case 0: /* child */
1577*58997Selan       /* Move the input and output pipes into place, if nec.  */
1578*58997Selan       if (input_desc != STDIN_FILE_NO)
1579*58997Selan 	{
1580*58997Selan 	  close (STDIN_FILE_NO);
1581*58997Selan 	  dup (input_desc);
1582*58997Selan 	  close (input_desc);
1583*58997Selan 	}
1584*58997Selan       if (output_desc != STDOUT_FILE_NO)
1585*58997Selan 	{
1586*58997Selan 	  close (STDOUT_FILE_NO);
1587*58997Selan 	  dup (output_desc);
1588*58997Selan 	  close (output_desc);
1589*58997Selan 	}
1590*58997Selan 
1591*58997Selan       /* Close the parent's descs that aren't wanted here.  */
1592*58997Selan       if (last_pipe_input != STDIN_FILE_NO)
1593*58997Selan 	close (last_pipe_input);
1594*58997Selan 
1595*58997Selan       /* Exec the program.  */
1596*58997Selan       (*func) (program, argv);
1597*58997Selan       perror_exec (program);
1598*58997Selan       exit (-1);
1599*58997Selan       /* NOTREACHED */
1600*58997Selan       return 0;
1601*58997Selan 
1602*58997Selan     default:
1603*58997Selan       /* In the parent, after forking.
1604*58997Selan 	 Close the descriptors that we made for this child.  */
1605*58997Selan       if (input_desc != STDIN_FILE_NO)
1606*58997Selan 	close (input_desc);
1607*58997Selan       if (output_desc != STDOUT_FILE_NO)
1608*58997Selan 	close (output_desc);
1609*58997Selan 
1610*58997Selan       /* Return child's process number.  */
1611*58997Selan       return pid;
1612*58997Selan     }
1613*58997Selan }
1614*58997Selan 
1615*58997Selan #endif /* not __MSDOS__ */
1616*58997Selan #else /* not OS2 */
1617*58997Selan 
1618*58997Selan static int
1619*58997Selan pexecute (search_flag, program, argv, not_last)
1620*58997Selan      int search_flag;
1621*58997Selan      char *program;
1622*58997Selan      char *argv[];
1623*58997Selan      int not_last;
1624*58997Selan {
1625*58997Selan   return (search_flag ? spawnv : spawnvp) (1, program, argv);
1626*58997Selan }
1627*58997Selan #endif /* not OS2 */
1628*58997Selan 
1629*58997Selan /* Execute the command specified by the arguments on the current line of spec.
1630*58997Selan    When using pipes, this includes several piped-together commands
1631*58997Selan    with `|' between them.
1632*58997Selan 
1633*58997Selan    Return 0 if successful, -1 if failed.  */
1634*58997Selan 
1635*58997Selan static int
1636*58997Selan execute ()
1637*58997Selan {
1638*58997Selan   int i;
1639*58997Selan   int n_commands;		/* # of command.  */
1640*58997Selan   char *string;
1641*58997Selan   struct command
1642*58997Selan     {
1643*58997Selan       char *prog;		/* program name.  */
1644*58997Selan       char **argv;		/* vector of args.  */
1645*58997Selan       int pid;			/* pid of process for this command.  */
1646*58997Selan     };
1647*58997Selan 
1648*58997Selan   struct command *commands;	/* each command buffer with above info.  */
1649*58997Selan 
1650*58997Selan   /* Count # of piped commands.  */
1651*58997Selan   for (n_commands = 1, i = 0; i < argbuf_index; i++)
1652*58997Selan     if (strcmp (argbuf[i], "|") == 0)
1653*58997Selan       n_commands++;
1654*58997Selan 
1655*58997Selan   /* Get storage for each command.  */
1656*58997Selan   commands
1657*58997Selan     = (struct command *) alloca (n_commands * sizeof (struct command));
1658*58997Selan 
1659*58997Selan   /* Split argbuf into its separate piped processes,
1660*58997Selan      and record info about each one.
1661*58997Selan      Also search for the programs that are to be run.  */
1662*58997Selan 
1663*58997Selan   commands[0].prog = argbuf[0]; /* first command.  */
1664*58997Selan   commands[0].argv = &argbuf[0];
1665*58997Selan   string = find_a_file (&exec_prefix, commands[0].prog, X_OK);
1666*58997Selan   if (string)
1667*58997Selan     commands[0].argv[0] = string;
1668*58997Selan 
1669*58997Selan   for (n_commands = 1, i = 0; i < argbuf_index; i++)
1670*58997Selan     if (strcmp (argbuf[i], "|") == 0)
1671*58997Selan       {				/* each command.  */
1672*58997Selan #ifdef __MSDOS__
1673*58997Selan         fatal ("-pipe not supported under MS-DOS");
1674*58997Selan #endif
1675*58997Selan 	argbuf[i] = 0;	/* termination of command args.  */
1676*58997Selan 	commands[n_commands].prog = argbuf[i + 1];
1677*58997Selan 	commands[n_commands].argv = &argbuf[i + 1];
1678*58997Selan 	string = find_a_file (&exec_prefix, commands[n_commands].prog, X_OK);
1679*58997Selan 	if (string)
1680*58997Selan 	  commands[n_commands].argv[0] = string;
1681*58997Selan 	n_commands++;
1682*58997Selan       }
1683*58997Selan 
1684*58997Selan   argbuf[argbuf_index] = 0;
1685*58997Selan 
1686*58997Selan   /* If -v, print what we are about to do, and maybe query.  */
1687*58997Selan 
1688*58997Selan   if (verbose_flag)
1689*58997Selan     {
1690*58997Selan       /* Print each piped command as a separate line.  */
1691*58997Selan       for (i = 0; i < n_commands ; i++)
1692*58997Selan 	{
1693*58997Selan 	  char **j;
1694*58997Selan 
1695*58997Selan 	  for (j = commands[i].argv; *j; j++)
1696*58997Selan 	    fprintf (stderr, " %s", *j);
1697*58997Selan 
1698*58997Selan 	  /* Print a pipe symbol after all but the last command.  */
1699*58997Selan 	  if (i + 1 != n_commands)
1700*58997Selan 	    fprintf (stderr, " |");
1701*58997Selan 	  fprintf (stderr, "\n");
1702*58997Selan 	}
1703*58997Selan       fflush (stderr);
1704*58997Selan #ifdef DEBUG
1705*58997Selan       fprintf (stderr, "\nGo ahead? (y or n) ");
1706*58997Selan       fflush (stderr);
1707*58997Selan       i = getchar ();
1708*58997Selan       if (i != '\n')
1709*58997Selan 	while (getchar () != '\n') ;
1710*58997Selan       if (i != 'y' && i != 'Y')
1711*58997Selan 	return 0;
1712*58997Selan #endif /* DEBUG */
1713*58997Selan     }
1714*58997Selan 
1715*58997Selan   /* Run each piped subprocess.  */
1716*58997Selan 
1717*58997Selan   last_pipe_input = STDIN_FILE_NO;
1718*58997Selan   for (i = 0; i < n_commands; i++)
1719*58997Selan     {
1720*58997Selan       char *string = commands[i].argv[0];
1721*58997Selan 
1722*58997Selan       commands[i].pid = pexecute (string != commands[i].prog,
1723*58997Selan 				  string, commands[i].argv,
1724*58997Selan 				  i + 1 < n_commands);
1725*58997Selan 
1726*58997Selan       if (string != commands[i].prog)
1727*58997Selan 	free (string);
1728*58997Selan     }
1729*58997Selan 
1730*58997Selan   execution_count++;
1731*58997Selan 
1732*58997Selan   /* Wait for all the subprocesses to finish.
1733*58997Selan      We don't care what order they finish in;
1734*58997Selan      we know that N_COMMANDS waits will get them all.  */
1735*58997Selan 
1736*58997Selan   {
1737*58997Selan     int ret_code = 0;
1738*58997Selan 
1739*58997Selan     for (i = 0; i < n_commands; i++)
1740*58997Selan       {
1741*58997Selan 	int status;
1742*58997Selan 	int pid;
1743*58997Selan 	char *prog;
1744*58997Selan 
1745*58997Selan #ifdef __MSDOS__
1746*58997Selan         status = pid = commands[i].pid;
1747*58997Selan #else
1748*58997Selan 	pid = wait (&status);
1749*58997Selan #endif
1750*58997Selan 	if (pid < 0)
1751*58997Selan 	  abort ();
1752*58997Selan 
1753*58997Selan 	if (status != 0)
1754*58997Selan 	  {
1755*58997Selan 	    int j;
1756*58997Selan 	    for (j = 0; j < n_commands; j++)
1757*58997Selan 	      if (commands[j].pid == pid)
1758*58997Selan 		prog = commands[j].prog;
1759*58997Selan 
1760*58997Selan 	    if ((status & 0x7F) != 0)
1761*58997Selan 	      {
1762*58997Selan 		fatal ("Internal compiler error: program %s got fatal signal %d",
1763*58997Selan 		       prog, (status & 0x7F));
1764*58997Selan 		signal_count++;
1765*58997Selan 	      }
1766*58997Selan 	    if (((status & 0xFF00) >> 8) >= MIN_FATAL_STATUS)
1767*58997Selan 	      ret_code = -1;
1768*58997Selan 	  }
1769*58997Selan       }
1770*58997Selan     return ret_code;
1771*58997Selan   }
1772*58997Selan }
1773*58997Selan 
1774*58997Selan /* Find all the switches given to us
1775*58997Selan    and make a vector describing them.
1776*58997Selan    The elements of the vector are strings, one per switch given.
1777*58997Selan    If a switch uses following arguments, then the `part1' field
1778*58997Selan    is the switch itself and the `args' field
1779*58997Selan    is a null-terminated vector containing the following arguments.
1780*58997Selan    The `valid' field is nonzero if any spec has looked at this switch;
1781*58997Selan    if it remains zero at the end of the run, it must be meaningless.  */
1782*58997Selan 
1783*58997Selan struct switchstr
1784*58997Selan {
1785*58997Selan   char *part1;
1786*58997Selan   char **args;
1787*58997Selan   int valid;
1788*58997Selan };
1789*58997Selan 
1790*58997Selan static struct switchstr *switches;
1791*58997Selan 
1792*58997Selan static int n_switches;
1793*58997Selan 
1794*58997Selan struct infile
1795*58997Selan {
1796*58997Selan   char *name;
1797*58997Selan   char *language;
1798*58997Selan };
1799*58997Selan 
1800*58997Selan /* Also a vector of input files specified.  */
1801*58997Selan 
1802*58997Selan static struct infile *infiles;
1803*58997Selan 
1804*58997Selan static int n_infiles;
1805*58997Selan 
1806*58997Selan /* And a vector of corresponding output files is made up later.  */
1807*58997Selan 
1808*58997Selan static char **outfiles;
1809*58997Selan 
1810*58997Selan /* Create the vector `switches' and its contents.
1811*58997Selan    Store its length in `n_switches'.  */
1812*58997Selan 
1813*58997Selan static void
1814*58997Selan process_command (argc, argv)
1815*58997Selan      int argc;
1816*58997Selan      char **argv;
1817*58997Selan {
1818*58997Selan   register int i;
1819*58997Selan   char *temp;
1820*58997Selan   char *spec_lang = 0;
1821*58997Selan   int last_language_n_infiles;
1822*58997Selan 
1823*58997Selan   gcc_exec_prefix = getenv ("GCC_EXEC_PREFIX");
1824*58997Selan 
1825*58997Selan   n_switches = 0;
1826*58997Selan   n_infiles = 0;
1827*58997Selan 
1828*58997Selan   /* Default for -V is our version number, ending at first space.  */
1829*58997Selan   spec_version = save_string (version_string, strlen (version_string));
1830*58997Selan   for (temp = spec_version; *temp && *temp != ' '; temp++);
1831*58997Selan   if (*temp) *temp = '\0';
1832*58997Selan 
1833*58997Selan   /* Set up the default search paths.  */
1834*58997Selan 
1835*58997Selan   if (gcc_exec_prefix)
1836*58997Selan     {
1837*58997Selan       add_prefix (&exec_prefix, gcc_exec_prefix, 0, 0, NULL_PTR);
1838*58997Selan       add_prefix (&startfile_prefix, gcc_exec_prefix, 0, 0, NULL_PTR);
1839*58997Selan     }
1840*58997Selan 
1841*58997Selan   /* COMPILER_PATH and LIBRARY_PATH have values
1842*58997Selan      that are lists of directory names with colons.  */
1843*58997Selan 
1844*58997Selan   temp = getenv ("COMPILER_PATH");
1845*58997Selan   if (temp)
1846*58997Selan     {
1847*58997Selan       char *startp, *endp;
1848*58997Selan       char *nstore = (char *) alloca (strlen (temp) + 3);
1849*58997Selan 
1850*58997Selan       startp = endp = temp;
1851*58997Selan       while (1)
1852*58997Selan 	{
1853*58997Selan 	  if (*endp == PATH_SEPARATOR || *endp == 0)
1854*58997Selan 	    {
1855*58997Selan 	      strncpy (nstore, startp, endp-startp);
1856*58997Selan 	      if (endp == startp)
1857*58997Selan 		{
1858*58997Selan 		  strcpy (nstore, "./");
1859*58997Selan 		}
1860*58997Selan 	      else if (endp[-1] != '/')
1861*58997Selan 		{
1862*58997Selan 		  nstore[endp-startp] = '/';
1863*58997Selan 		  nstore[endp-startp+1] = 0;
1864*58997Selan 		}
1865*58997Selan 	      else
1866*58997Selan 		nstore[endp-startp] = 0;
1867*58997Selan 	      add_prefix (&exec_prefix, nstore, 0, 0, NULL_PTR);
1868*58997Selan 	      if (*endp == 0)
1869*58997Selan 		break;
1870*58997Selan 	      endp = startp = endp + 1;
1871*58997Selan 	    }
1872*58997Selan 	  else
1873*58997Selan 	    endp++;
1874*58997Selan 	}
1875*58997Selan     }
1876*58997Selan 
1877*58997Selan   temp = getenv ("LIBRARY_PATH");
1878*58997Selan   if (temp)
1879*58997Selan     {
1880*58997Selan       char *startp, *endp;
1881*58997Selan       char *nstore = (char *) alloca (strlen (temp) + 3);
1882*58997Selan 
1883*58997Selan       startp = endp = temp;
1884*58997Selan       while (1)
1885*58997Selan 	{
1886*58997Selan 	  if (*endp == PATH_SEPARATOR || *endp == 0)
1887*58997Selan 	    {
1888*58997Selan 	      strncpy (nstore, startp, endp-startp);
1889*58997Selan 	      if (endp == startp)
1890*58997Selan 		{
1891*58997Selan 		  strcpy (nstore, "./");
1892*58997Selan 		}
1893*58997Selan 	      else if (endp[-1] != '/')
1894*58997Selan 		{
1895*58997Selan 		  nstore[endp-startp] = '/';
1896*58997Selan 		  nstore[endp-startp+1] = 0;
1897*58997Selan 		}
1898*58997Selan 	      else
1899*58997Selan 		nstore[endp-startp] = 0;
1900*58997Selan 	      add_prefix (&startfile_prefix, nstore, 0, 0, NULL_PTR);
1901*58997Selan 	      /* Make separate list of dirs that came from LIBRARY_PATH.  */
1902*58997Selan 	      add_prefix (&library_prefix, nstore, 0, 0, NULL_PTR);
1903*58997Selan 	      if (*endp == 0)
1904*58997Selan 		break;
1905*58997Selan 	      endp = startp = endp + 1;
1906*58997Selan 	    }
1907*58997Selan 	  else
1908*58997Selan 	    endp++;
1909*58997Selan 	}
1910*58997Selan     }
1911*58997Selan 
1912*58997Selan   /* Use LPATH like LIBRARY_PATH (for the CMU build program).  */
1913*58997Selan   temp = getenv ("LPATH");
1914*58997Selan   if (temp)
1915*58997Selan     {
1916*58997Selan       char *startp, *endp;
1917*58997Selan       char *nstore = (char *) alloca (strlen (temp) + 3);
1918*58997Selan 
1919*58997Selan       startp = endp = temp;
1920*58997Selan       while (1)
1921*58997Selan 	{
1922*58997Selan 	  if (*endp == PATH_SEPARATOR || *endp == 0)
1923*58997Selan 	    {
1924*58997Selan 	      strncpy (nstore, startp, endp-startp);
1925*58997Selan 	      if (endp == startp)
1926*58997Selan 		{
1927*58997Selan 		  strcpy (nstore, "./");
1928*58997Selan 		}
1929*58997Selan 	      else if (endp[-1] != '/')
1930*58997Selan 		{
1931*58997Selan 		  nstore[endp-startp] = '/';
1932*58997Selan 		  nstore[endp-startp+1] = 0;
1933*58997Selan 		}
1934*58997Selan 	      else
1935*58997Selan 		nstore[endp-startp] = 0;
1936*58997Selan 	      add_prefix (&startfile_prefix, nstore, 0, 0, NULL_PTR);
1937*58997Selan 	      /* Make separate list of dirs that came from LIBRARY_PATH.  */
1938*58997Selan 	      add_prefix (&library_prefix, nstore, 0, 0, NULL_PTR);
1939*58997Selan 	      if (*endp == 0)
1940*58997Selan 		break;
1941*58997Selan 	      endp = startp = endp + 1;
1942*58997Selan 	    }
1943*58997Selan 	  else
1944*58997Selan 	    endp++;
1945*58997Selan 	}
1946*58997Selan     }
1947*58997Selan 
1948*58997Selan   /* Scan argv twice.  Here, the first time, just count how many switches
1949*58997Selan      there will be in their vector, and how many input files in theirs.
1950*58997Selan      Here we also parse the switches that cc itself uses (e.g. -v).  */
1951*58997Selan 
1952*58997Selan   for (i = 1; i < argc; i++)
1953*58997Selan     {
1954*58997Selan       if (! strcmp (argv[i], "-dumpspecs"))
1955*58997Selan 	{
1956*58997Selan 	  printf ("*asm:\n%s\n\n", asm_spec);
1957*58997Selan 	  printf ("*asm_final:\n%s\n\n", asm_final_spec);
1958*58997Selan 	  printf ("*cpp:\n%s\n\n", cpp_spec);
1959*58997Selan 	  printf ("*cc1:\n%s\n\n", cc1_spec);
1960*58997Selan 	  printf ("*cc1plus:\n%s\n\n", cc1plus_spec);
1961*58997Selan 	  printf ("*endfile:\n%s\n\n", endfile_spec);
1962*58997Selan 	  printf ("*link:\n%s\n\n", link_spec);
1963*58997Selan 	  printf ("*lib:\n%s\n\n", lib_spec);
1964*58997Selan 	  printf ("*startfile:\n%s\n\n", startfile_spec);
1965*58997Selan 	  printf ("*switches_need_spaces:\n%s\n\n", switches_need_spaces);
1966*58997Selan 	  printf ("*signed_char:\n%s\n\n", signed_char_spec);
1967*58997Selan 	  printf ("*predefines:\n%s\n\n", cpp_predefines);
1968*58997Selan 	  printf ("*cross_compile:\n%d\n\n", cross_compile);
1969*58997Selan 
1970*58997Selan 	  exit (0);
1971*58997Selan 	}
1972*58997Selan       else if (! strcmp (argv[i], "-dumpversion"))
1973*58997Selan 	{
1974*58997Selan 	  printf ("%s\n", version_string);
1975*58997Selan 	  exit (0);
1976*58997Selan 	}
1977*58997Selan       else if (! strcmp (argv[i], "-print-libgcc-file-name"))
1978*58997Selan 	{
1979*58997Selan 	  print_libgcc_file_name = 1;
1980*58997Selan 	}
1981*58997Selan       else if (! strcmp (argv[i], "-Xlinker"))
1982*58997Selan 	{
1983*58997Selan 	  /* Pass the argument of this option to the linker when we link.  */
1984*58997Selan 
1985*58997Selan 	  if (i + 1 == argc)
1986*58997Selan 	    fatal ("argument to `-Xlinker' is missing");
1987*58997Selan 
1988*58997Selan 	  n_linker_options++;
1989*58997Selan 	  if (!linker_options)
1990*58997Selan 	    linker_options
1991*58997Selan 	      = (char **) xmalloc (n_linker_options * sizeof (char **));
1992*58997Selan 	  else
1993*58997Selan 	    linker_options
1994*58997Selan 	      = (char **) xrealloc (linker_options,
1995*58997Selan 				    n_linker_options * sizeof (char **));
1996*58997Selan 
1997*58997Selan 	  linker_options[n_linker_options - 1] = argv[++i];
1998*58997Selan 	}
1999*58997Selan       else if (! strncmp (argv[i], "-Wl,", 4))
2000*58997Selan 	{
2001*58997Selan 	  int prev, j;
2002*58997Selan 	  /* Pass the rest of this option to the linker when we link.  */
2003*58997Selan 
2004*58997Selan 	  n_linker_options++;
2005*58997Selan 	  if (!linker_options)
2006*58997Selan 	    linker_options
2007*58997Selan 	      = (char **) xmalloc (n_linker_options * sizeof (char **));
2008*58997Selan 	  else
2009*58997Selan 	    linker_options
2010*58997Selan 	      = (char **) xrealloc (linker_options,
2011*58997Selan 				    n_linker_options * sizeof (char **));
2012*58997Selan 
2013*58997Selan 	  /* Split the argument at commas.  */
2014*58997Selan 	  prev = 4;
2015*58997Selan 	  for (j = 4; argv[i][j]; j++)
2016*58997Selan 	    if (argv[i][j] == ',')
2017*58997Selan 	      {
2018*58997Selan 		linker_options[n_linker_options - 1]
2019*58997Selan 		  = save_string (argv[i] + prev, j - prev);
2020*58997Selan 		n_linker_options++;
2021*58997Selan 		linker_options
2022*58997Selan 		  = (char **) xrealloc (linker_options,
2023*58997Selan 					n_linker_options * sizeof (char **));
2024*58997Selan 		prev = j + 1;
2025*58997Selan 	      }
2026*58997Selan 	  /* Record the part after the last comma.  */
2027*58997Selan 	  linker_options[n_linker_options - 1] = argv[i] + prev;
2028*58997Selan 	}
2029*58997Selan       else if (! strncmp (argv[i], "-Wa,", 4))
2030*58997Selan 	{
2031*58997Selan 	  int prev, j;
2032*58997Selan 	  /* Pass the rest of this option to the assembler.  */
2033*58997Selan 
2034*58997Selan 	  n_assembler_options++;
2035*58997Selan 	  if (!assembler_options)
2036*58997Selan 	    assembler_options
2037*58997Selan 	      = (char **) xmalloc (n_assembler_options * sizeof (char **));
2038*58997Selan 	  else
2039*58997Selan 	    assembler_options
2040*58997Selan 	      = (char **) xrealloc (assembler_options,
2041*58997Selan 				    n_assembler_options * sizeof (char **));
2042*58997Selan 
2043*58997Selan 	  /* Split the argument at commas.  */
2044*58997Selan 	  prev = 4;
2045*58997Selan 	  for (j = 4; argv[i][j]; j++)
2046*58997Selan 	    if (argv[i][j] == ',')
2047*58997Selan 	      {
2048*58997Selan 		assembler_options[n_assembler_options - 1]
2049*58997Selan 		  = save_string (argv[i] + prev, j - prev);
2050*58997Selan 		n_assembler_options++;
2051*58997Selan 		assembler_options
2052*58997Selan 		  = (char **) xrealloc (assembler_options,
2053*58997Selan 					n_assembler_options * sizeof (char **));
2054*58997Selan 		prev = j + 1;
2055*58997Selan 	      }
2056*58997Selan 	  /* Record the part after the last comma.  */
2057*58997Selan 	  assembler_options[n_assembler_options - 1] = argv[i] + prev;
2058*58997Selan 	}
2059*58997Selan       else if (argv[i][0] == '+' && argv[i][1] == 'e')
2060*58997Selan 	/* Compensate for the +e options to the C++ front-end.  */
2061*58997Selan 	n_switches++;
2062*58997Selan       else if (argv[i][0] == '-' && argv[i][1] != 0 && argv[i][1] != 'l')
2063*58997Selan 	{
2064*58997Selan 	  register char *p = &argv[i][1];
2065*58997Selan 	  register int c = *p;
2066*58997Selan 
2067*58997Selan 	  switch (c)
2068*58997Selan 	    {
2069*58997Selan 	    case 'b':
2070*58997Selan 	      if (p[1] == 0 && i + 1 == argc)
2071*58997Selan 		fatal ("argument to `-b' is missing");
2072*58997Selan 	      if (p[1] == 0)
2073*58997Selan 		spec_machine = argv[++i];
2074*58997Selan 	      else
2075*58997Selan 		spec_machine = p + 1;
2076*58997Selan 	      break;
2077*58997Selan 
2078*58997Selan 	    case 'B':
2079*58997Selan 	      {
2080*58997Selan 		int *temp = (int *) xmalloc (sizeof (int));
2081*58997Selan 		char *value;
2082*58997Selan 		if (p[1] == 0 && i + 1 == argc)
2083*58997Selan 		  fatal ("argument to `-B' is missing");
2084*58997Selan 		if (p[1] == 0)
2085*58997Selan 		  value = argv[++i];
2086*58997Selan 		else
2087*58997Selan 		  value = p + 1;
2088*58997Selan 		add_prefix (&exec_prefix, value, 1, 0, temp);
2089*58997Selan 		add_prefix (&startfile_prefix, value, 1, 0, temp);
2090*58997Selan 	      }
2091*58997Selan 	      break;
2092*58997Selan 
2093*58997Selan 	    case 'v':	/* Print our subcommands and print versions.  */
2094*58997Selan 	      n_switches++;
2095*58997Selan 	      /* If they do anything other than exactly `-v', don't set
2096*58997Selan 		 verbose_flag; rather, continue on to give the error.  */
2097*58997Selan 	      if (p[1] != 0)
2098*58997Selan 		break;
2099*58997Selan 	      verbose_flag++;
2100*58997Selan 	      break;
2101*58997Selan 
2102*58997Selan 	    case 'V':
2103*58997Selan 	      if (p[1] == 0 && i + 1 == argc)
2104*58997Selan 		fatal ("argument to `-V' is missing");
2105*58997Selan 	      if (p[1] == 0)
2106*58997Selan 		spec_version = argv[++i];
2107*58997Selan 	      else
2108*58997Selan 		spec_version = p + 1;
2109*58997Selan 	      break;
2110*58997Selan 
2111*58997Selan 	    case 's':
2112*58997Selan 	      if (!strcmp (p, "save-temps"))
2113*58997Selan 		{
2114*58997Selan 		  save_temps_flag = 1;
2115*58997Selan 		  n_switches++;
2116*58997Selan 		  break;
2117*58997Selan 		}
2118*58997Selan 	    default:
2119*58997Selan 	      n_switches++;
2120*58997Selan 
2121*58997Selan 	      if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
2122*58997Selan 		i += SWITCH_TAKES_ARG (c) - (p[1] != 0);
2123*58997Selan 	      else if (WORD_SWITCH_TAKES_ARG (p))
2124*58997Selan 		i += WORD_SWITCH_TAKES_ARG (p);
2125*58997Selan 	    }
2126*58997Selan 	}
2127*58997Selan       else
2128*58997Selan 	n_infiles++;
2129*58997Selan     }
2130*58997Selan 
2131*58997Selan   /* Set up the search paths before we go looking for config files.  */
2132*58997Selan 
2133*58997Selan   /* These come before the md prefixes so that we will find gcc's subcommands
2134*58997Selan      (such as cpp) rather than those of the host system.  */
2135*58997Selan   /* Use 2 as fourth arg meaning try just the machine as a suffix,
2136*58997Selan      as well as trying the machine and the version.  */
2137*58997Selan   add_prefix (&exec_prefix, standard_exec_prefix, 0, 2, NULL_PTR);
2138*58997Selan   add_prefix (&exec_prefix, standard_exec_prefix_1, 0, 2, NULL_PTR);
2139*58997Selan 
2140*58997Selan   add_prefix (&startfile_prefix, standard_exec_prefix, 0, 1, NULL_PTR);
2141*58997Selan   add_prefix (&startfile_prefix, standard_exec_prefix_1, 0, 1, NULL_PTR);
2142*58997Selan 
2143*58997Selan   /* More prefixes are enabled in main, after we read the specs file
2144*58997Selan      and determine whether this is cross-compilation or not.  */
2145*58997Selan 
2146*58997Selan 
2147*58997Selan   /* Then create the space for the vectors and scan again.  */
2148*58997Selan 
2149*58997Selan   switches = ((struct switchstr *)
2150*58997Selan 	      xmalloc ((n_switches + 1) * sizeof (struct switchstr)));
2151*58997Selan   infiles = (struct infile *) xmalloc ((n_infiles + 1) * sizeof (struct infile));
2152*58997Selan   n_switches = 0;
2153*58997Selan   n_infiles = 0;
2154*58997Selan   last_language_n_infiles = -1;
2155*58997Selan 
2156*58997Selan   /* This, time, copy the text of each switch and store a pointer
2157*58997Selan      to the copy in the vector of switches.
2158*58997Selan      Store all the infiles in their vector.  */
2159*58997Selan 
2160*58997Selan   for (i = 1; i < argc; i++)
2161*58997Selan     {
2162*58997Selan       /* Just skip the switches that were handled by the preceding loop.  */
2163*58997Selan       if (!strcmp (argv[i], "-Xlinker"))
2164*58997Selan 	i++;
2165*58997Selan       else if (! strncmp (argv[i], "-Wl,", 4))
2166*58997Selan 	;
2167*58997Selan       else if (! strncmp (argv[i], "-Wa,", 4))
2168*58997Selan 	;
2169*58997Selan       else if (! strcmp (argv[i], "-print-libgcc-file-name"))
2170*58997Selan 	;
2171*58997Selan       else if (argv[i][0] == '+' && argv[i][1] == 'e')
2172*58997Selan 	{
2173*58997Selan 	  /* Compensate for the +e options to the C++ front-end;
2174*58997Selan 	     they're there simply for cfront call-compatability.  We do
2175*58997Selan 	     some magic in default_compilers to pass them down properly.
2176*58997Selan 	     Note we deliberately start at the `+' here, to avoid passing
2177*58997Selan 	     -e0 or -e1 down into the linker.  */
2178*58997Selan 	  switches[n_switches].part1 = &argv[i][0];
2179*58997Selan 	  switches[n_switches].args = 0;
2180*58997Selan 	  switches[n_switches].valid = 0;
2181*58997Selan 	  n_switches++;
2182*58997Selan 	}
2183*58997Selan       else if (argv[i][0] == '-' && argv[i][1] != 0 && argv[i][1] != 'l')
2184*58997Selan 	{
2185*58997Selan 	  register char *p = &argv[i][1];
2186*58997Selan 	  register int c = *p;
2187*58997Selan 
2188*58997Selan 	  if (c == 'B' || c == 'b' || c == 'V')
2189*58997Selan 	    {
2190*58997Selan 	      /* Skip a separate arg, if any.  */
2191*58997Selan 	      if (p[1] == 0)
2192*58997Selan 		i++;
2193*58997Selan 	      continue;
2194*58997Selan 	    }
2195*58997Selan 	  if (c == 'x')
2196*58997Selan 	    {
2197*58997Selan 	      if (p[1] == 0 && i + 1 == argc)
2198*58997Selan 		fatal ("argument to `-x' is missing");
2199*58997Selan 	      if (p[1] == 0)
2200*58997Selan 		spec_lang = argv[++i];
2201*58997Selan 	      else
2202*58997Selan 		spec_lang = p + 1;
2203*58997Selan 	      if (! strcmp (spec_lang, "none"))
2204*58997Selan 		/* Suppress the warning if -xnone comes after the last input file,
2205*58997Selan 		   because alternate command interfaces like g++ might find it
2206*58997Selan 		   useful to place -xnone after each input file.  */
2207*58997Selan 		spec_lang = 0;
2208*58997Selan 	      else
2209*58997Selan 		last_language_n_infiles = n_infiles;
2210*58997Selan 	      continue;
2211*58997Selan 	    }
2212*58997Selan 	  switches[n_switches].part1 = p;
2213*58997Selan 	  /* Deal with option arguments in separate argv elements.  */
2214*58997Selan 	  if ((SWITCH_TAKES_ARG (c) > (p[1] != 0))
2215*58997Selan 	      || WORD_SWITCH_TAKES_ARG (p)) {
2216*58997Selan 	    int j = 0;
2217*58997Selan 	    int n_args = WORD_SWITCH_TAKES_ARG (p);
2218*58997Selan 
2219*58997Selan 	    if (n_args == 0) {
2220*58997Selan 	      /* Count only the option arguments in separate argv elements.  */
2221*58997Selan 	      n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0);
2222*58997Selan 	    }
2223*58997Selan 	    if (i + n_args >= argc)
2224*58997Selan 	      fatal ("argument to `-%s' is missing", p);
2225*58997Selan 	    switches[n_switches].args
2226*58997Selan 	      = (char **) xmalloc ((n_args + 1) * sizeof (char *));
2227*58997Selan 	    while (j < n_args)
2228*58997Selan 	      switches[n_switches].args[j++] = argv[++i];
2229*58997Selan 	    /* Null-terminate the vector.  */
2230*58997Selan 	    switches[n_switches].args[j] = 0;
2231*58997Selan 	  } else if (*switches_need_spaces != 0 && (c == 'o' || c == 'L')) {
2232*58997Selan 	    /* On some systems, ld cannot handle -o or -L without space.
2233*58997Selan 	       So split the -o or -L from its argument.  */
2234*58997Selan 	    switches[n_switches].part1 = (c == 'o' ? "o" : "L");
2235*58997Selan 	    switches[n_switches].args = (char **) xmalloc (2 * sizeof (char *));
2236*58997Selan 	    switches[n_switches].args[0] = xmalloc (strlen (p));
2237*58997Selan 	    strcpy (switches[n_switches].args[0], &p[1]);
2238*58997Selan 	    switches[n_switches].args[1] = 0;
2239*58997Selan 	  } else
2240*58997Selan 	    switches[n_switches].args = 0;
2241*58997Selan 	  switches[n_switches].valid = 0;
2242*58997Selan 	  /* This is always valid, since gcc.c itself understands it.  */
2243*58997Selan 	  if (!strcmp (p, "save-temps"))
2244*58997Selan 	    switches[n_switches].valid = 1;
2245*58997Selan 	  n_switches++;
2246*58997Selan 	}
2247*58997Selan       else
2248*58997Selan 	{
2249*58997Selan 	  infiles[n_infiles].language = spec_lang;
2250*58997Selan 	  infiles[n_infiles++].name = argv[i];
2251*58997Selan 	}
2252*58997Selan     }
2253*58997Selan 
2254*58997Selan   if (n_infiles == last_language_n_infiles)
2255*58997Selan     error ("Warning: `-x %s' after last input file has no effect", spec_lang);
2256*58997Selan 
2257*58997Selan   switches[n_switches].part1 = 0;
2258*58997Selan   infiles[n_infiles].name = 0;
2259*58997Selan 
2260*58997Selan   /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake.  */
2261*58997Selan   if (gcc_exec_prefix)
2262*58997Selan     {
2263*58997Selan       temp = (char *) xmalloc (strlen (gcc_exec_prefix) + strlen (spec_version)
2264*58997Selan 			       + strlen (spec_machine) + 3);
2265*58997Selan       strcpy (temp, gcc_exec_prefix);
2266*58997Selan       strcat (temp, spec_machine);
2267*58997Selan       strcat (temp, "/");
2268*58997Selan       strcat (temp, spec_version);
2269*58997Selan       strcat (temp, "/");
2270*58997Selan       gcc_exec_prefix = temp;
2271*58997Selan     }
2272*58997Selan }
2273*58997Selan 
2274*58997Selan /* Process a spec string, accumulating and running commands.  */
2275*58997Selan 
2276*58997Selan /* These variables describe the input file name.
2277*58997Selan    input_file_number is the index on outfiles of this file,
2278*58997Selan    so that the output file name can be stored for later use by %o.
2279*58997Selan    input_basename is the start of the part of the input file
2280*58997Selan    sans all directory names, and basename_length is the number
2281*58997Selan    of characters starting there excluding the suffix .c or whatever.  */
2282*58997Selan 
2283*58997Selan static char *input_filename;
2284*58997Selan static int input_file_number;
2285*58997Selan static int input_filename_length;
2286*58997Selan static int basename_length;
2287*58997Selan static char *input_basename;
2288*58997Selan static char *input_suffix;
2289*58997Selan 
2290*58997Selan /* These are variables used within do_spec and do_spec_1.  */
2291*58997Selan 
2292*58997Selan /* Nonzero if an arg has been started and not yet terminated
2293*58997Selan    (with space, tab or newline).  */
2294*58997Selan static int arg_going;
2295*58997Selan 
2296*58997Selan /* Nonzero means %d or %g has been seen; the next arg to be terminated
2297*58997Selan    is a temporary file name.  */
2298*58997Selan static int delete_this_arg;
2299*58997Selan 
2300*58997Selan /* Nonzero means %w has been seen; the next arg to be terminated
2301*58997Selan    is the output file name of this compilation.  */
2302*58997Selan static int this_is_output_file;
2303*58997Selan 
2304*58997Selan /* Nonzero means %s has been seen; the next arg to be terminated
2305*58997Selan    is the name of a library file and we should try the standard
2306*58997Selan    search dirs for it.  */
2307*58997Selan static int this_is_library_file;
2308*58997Selan 
2309*58997Selan /* Process the spec SPEC and run the commands specified therein.
2310*58997Selan    Returns 0 if the spec is successfully processed; -1 if failed.  */
2311*58997Selan 
2312*58997Selan static int
2313*58997Selan do_spec (spec)
2314*58997Selan      char *spec;
2315*58997Selan {
2316*58997Selan   int value;
2317*58997Selan 
2318*58997Selan   clear_args ();
2319*58997Selan   arg_going = 0;
2320*58997Selan   delete_this_arg = 0;
2321*58997Selan   this_is_output_file = 0;
2322*58997Selan   this_is_library_file = 0;
2323*58997Selan 
2324*58997Selan   value = do_spec_1 (spec, 0, NULL_PTR);
2325*58997Selan 
2326*58997Selan   /* Force out any unfinished command.
2327*58997Selan      If -pipe, this forces out the last command if it ended in `|'.  */
2328*58997Selan   if (value == 0)
2329*58997Selan     {
2330*58997Selan       if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
2331*58997Selan 	argbuf_index--;
2332*58997Selan 
2333*58997Selan       if (argbuf_index > 0)
2334*58997Selan 	value = execute ();
2335*58997Selan     }
2336*58997Selan 
2337*58997Selan   return value;
2338*58997Selan }
2339*58997Selan 
2340*58997Selan /* Process the sub-spec SPEC as a portion of a larger spec.
2341*58997Selan    This is like processing a whole spec except that we do
2342*58997Selan    not initialize at the beginning and we do not supply a
2343*58997Selan    newline by default at the end.
2344*58997Selan    INSWITCH nonzero means don't process %-sequences in SPEC;
2345*58997Selan    in this case, % is treated as an ordinary character.
2346*58997Selan    This is used while substituting switches.
2347*58997Selan    INSWITCH nonzero also causes SPC not to terminate an argument.
2348*58997Selan 
2349*58997Selan    Value is zero unless a line was finished
2350*58997Selan    and the command on that line reported an error.  */
2351*58997Selan 
2352*58997Selan static int
2353*58997Selan do_spec_1 (spec, inswitch, soft_matched_part)
2354*58997Selan      char *spec;
2355*58997Selan      int inswitch;
2356*58997Selan      char *soft_matched_part;
2357*58997Selan {
2358*58997Selan   register char *p = spec;
2359*58997Selan   register int c;
2360*58997Selan   int i;
2361*58997Selan   char *string;
2362*58997Selan 
2363*58997Selan   while (c = *p++)
2364*58997Selan     /* If substituting a switch, treat all chars like letters.
2365*58997Selan        Otherwise, NL, SPC, TAB and % are special.  */
2366*58997Selan     switch (inswitch ? 'a' : c)
2367*58997Selan       {
2368*58997Selan       case '\n':
2369*58997Selan 	/* End of line: finish any pending argument,
2370*58997Selan 	   then run the pending command if one has been started.  */
2371*58997Selan 	if (arg_going)
2372*58997Selan 	  {
2373*58997Selan 	    obstack_1grow (&obstack, 0);
2374*58997Selan 	    string = obstack_finish (&obstack);
2375*58997Selan 	    if (this_is_library_file)
2376*58997Selan 	      string = find_file (string);
2377*58997Selan 	    store_arg (string, delete_this_arg, this_is_output_file);
2378*58997Selan 	    if (this_is_output_file)
2379*58997Selan 	      outfiles[input_file_number] = string;
2380*58997Selan 	  }
2381*58997Selan 	arg_going = 0;
2382*58997Selan 
2383*58997Selan 	if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
2384*58997Selan 	  {
2385*58997Selan 	    int i;
2386*58997Selan 	    for (i = 0; i < n_switches; i++)
2387*58997Selan 	      if (!strcmp (switches[i].part1, "pipe"))
2388*58997Selan 		break;
2389*58997Selan 
2390*58997Selan 	    /* A `|' before the newline means use a pipe here,
2391*58997Selan 	       but only if -pipe was specified.
2392*58997Selan 	       Otherwise, execute now and don't pass the `|' as an arg.  */
2393*58997Selan 	    if (i < n_switches)
2394*58997Selan 	      {
2395*58997Selan 		switches[i].valid = 1;
2396*58997Selan 		break;
2397*58997Selan 	      }
2398*58997Selan 	    else
2399*58997Selan 	      argbuf_index--;
2400*58997Selan 	  }
2401*58997Selan 
2402*58997Selan 	if (argbuf_index > 0)
2403*58997Selan 	  {
2404*58997Selan 	    int value = execute ();
2405*58997Selan 	    if (value)
2406*58997Selan 	      return value;
2407*58997Selan 	  }
2408*58997Selan 	/* Reinitialize for a new command, and for a new argument.  */
2409*58997Selan 	clear_args ();
2410*58997Selan 	arg_going = 0;
2411*58997Selan 	delete_this_arg = 0;
2412*58997Selan 	this_is_output_file = 0;
2413*58997Selan 	this_is_library_file = 0;
2414*58997Selan 	break;
2415*58997Selan 
2416*58997Selan       case '|':
2417*58997Selan 	/* End any pending argument.  */
2418*58997Selan 	if (arg_going)
2419*58997Selan 	  {
2420*58997Selan 	    obstack_1grow (&obstack, 0);
2421*58997Selan 	    string = obstack_finish (&obstack);
2422*58997Selan 	    if (this_is_library_file)
2423*58997Selan 	      string = find_file (string);
2424*58997Selan 	    store_arg (string, delete_this_arg, this_is_output_file);
2425*58997Selan 	    if (this_is_output_file)
2426*58997Selan 	      outfiles[input_file_number] = string;
2427*58997Selan 	  }
2428*58997Selan 
2429*58997Selan 	/* Use pipe */
2430*58997Selan 	obstack_1grow (&obstack, c);
2431*58997Selan 	arg_going = 1;
2432*58997Selan 	break;
2433*58997Selan 
2434*58997Selan       case '\t':
2435*58997Selan       case ' ':
2436*58997Selan 	/* Space or tab ends an argument if one is pending.  */
2437*58997Selan 	if (arg_going)
2438*58997Selan 	  {
2439*58997Selan 	    obstack_1grow (&obstack, 0);
2440*58997Selan 	    string = obstack_finish (&obstack);
2441*58997Selan 	    if (this_is_library_file)
2442*58997Selan 	      string = find_file (string);
2443*58997Selan 	    store_arg (string, delete_this_arg, this_is_output_file);
2444*58997Selan 	    if (this_is_output_file)
2445*58997Selan 	      outfiles[input_file_number] = string;
2446*58997Selan 	  }
2447*58997Selan 	/* Reinitialize for a new argument.  */
2448*58997Selan 	arg_going = 0;
2449*58997Selan 	delete_this_arg = 0;
2450*58997Selan 	this_is_output_file = 0;
2451*58997Selan 	this_is_library_file = 0;
2452*58997Selan 	break;
2453*58997Selan 
2454*58997Selan       case '%':
2455*58997Selan 	switch (c = *p++)
2456*58997Selan 	  {
2457*58997Selan 	  case 0:
2458*58997Selan 	    fatal ("Invalid specification!  Bug in cc.");
2459*58997Selan 
2460*58997Selan 	  case 'b':
2461*58997Selan 	    obstack_grow (&obstack, input_basename, basename_length);
2462*58997Selan 	    arg_going = 1;
2463*58997Selan 	    break;
2464*58997Selan 
2465*58997Selan 	  case 'd':
2466*58997Selan 	    delete_this_arg = 2;
2467*58997Selan 	    break;
2468*58997Selan 
2469*58997Selan 	  /* Dump out the directories specified with LIBRARY_PATH,
2470*58997Selan 	     followed by the absolute directories
2471*58997Selan 	     that we search for startfiles.  */
2472*58997Selan 	  case 'D':
2473*58997Selan 	    for (i = 0; i < 2; i++)
2474*58997Selan 	      {
2475*58997Selan 		struct prefix_list *pl
2476*58997Selan 		  = (i == 0 ? library_prefix.plist : startfile_prefix.plist);
2477*58997Selan 		int bufsize = 100;
2478*58997Selan 		char *buffer = (char *) xmalloc (bufsize);
2479*58997Selan 		int idx;
2480*58997Selan 
2481*58997Selan 		for (; pl; pl = pl->next)
2482*58997Selan 		  {
2483*58997Selan #ifdef RELATIVE_PREFIX_NOT_LINKDIR
2484*58997Selan 		    /* Used on systems which record the specified -L dirs
2485*58997Selan 		       and use them to search for dynamic linking.  */
2486*58997Selan 		    /* Relative directories always come from -B,
2487*58997Selan 		       and it is better not to use them for searching
2488*58997Selan 		       at run time.  In particular, stage1 loses  */
2489*58997Selan 		    if (pl->prefix[0] != '/')
2490*58997Selan 		      continue;
2491*58997Selan #endif
2492*58997Selan 		    if (machine_suffix)
2493*58997Selan 		      {
2494*58997Selan 			if (is_linker_dir (pl->prefix, machine_suffix))
2495*58997Selan 			  {
2496*58997Selan 			    do_spec_1 ("-L", 0, NULL_PTR);
2497*58997Selan #ifdef SPACE_AFTER_L_OPTION
2498*58997Selan 			    do_spec_1 (" ", 0, NULL_PTR);
2499*58997Selan #endif
2500*58997Selan 			    do_spec_1 (pl->prefix, 1, NULL_PTR);
2501*58997Selan 			    /* Remove slash from machine_suffix.  */
2502*58997Selan 			    if (strlen (machine_suffix) >= bufsize)
2503*58997Selan 			      bufsize = strlen (machine_suffix) * 2 + 1;
2504*58997Selan 			    buffer = (char *) xrealloc (buffer, bufsize);
2505*58997Selan 			    strcpy (buffer, machine_suffix);
2506*58997Selan 			    idx = strlen (buffer);
2507*58997Selan 			    if (buffer[idx - 1] == '/')
2508*58997Selan 			      buffer[idx - 1] = 0;
2509*58997Selan 			    do_spec_1 (buffer, 1, NULL_PTR);
2510*58997Selan 			    /* Make this a separate argument.  */
2511*58997Selan 			    do_spec_1 (" ", 0, NULL_PTR);
2512*58997Selan 			  }
2513*58997Selan 		      }
2514*58997Selan 		    if (!pl->require_machine_suffix)
2515*58997Selan 		      {
2516*58997Selan 			if (is_linker_dir (pl->prefix, ""))
2517*58997Selan 			  {
2518*58997Selan 			    do_spec_1 ("-L", 0, NULL_PTR);
2519*58997Selan #ifdef SPACE_AFTER_L_OPTION
2520*58997Selan 			    do_spec_1 (" ", 0, NULL_PTR);
2521*58997Selan #endif
2522*58997Selan 			    /* Remove slash from pl->prefix.  */
2523*58997Selan 			    if (strlen (pl->prefix) >= bufsize)
2524*58997Selan 			      bufsize = strlen (pl->prefix) * 2 + 1;
2525*58997Selan 			    buffer = (char *) xrealloc (buffer, bufsize);
2526*58997Selan 			    strcpy (buffer, pl->prefix);
2527*58997Selan 			    idx = strlen (buffer);
2528*58997Selan 			    if (buffer[idx - 1] == '/')
2529*58997Selan 			      buffer[idx - 1] = 0;
2530*58997Selan 			    do_spec_1 (buffer, 1, NULL_PTR);
2531*58997Selan 			    /* Make this a separate argument.  */
2532*58997Selan 			    do_spec_1 (" ", 0, NULL_PTR);
2533*58997Selan 			  }
2534*58997Selan 		      }
2535*58997Selan 		  }
2536*58997Selan 		free (buffer);
2537*58997Selan 	      }
2538*58997Selan 	    break;
2539*58997Selan 
2540*58997Selan 	  case 'e':
2541*58997Selan 	    /* {...:%efoo} means report an error with `foo' as error message
2542*58997Selan 	       and don't execute any more commands for this file.  */
2543*58997Selan 	    {
2544*58997Selan 	      char *q = p;
2545*58997Selan 	      char *buf;
2546*58997Selan 	      while (*p != 0 && *p != '\n') p++;
2547*58997Selan 	      buf = (char *) alloca (p - q + 1);
2548*58997Selan 	      strncpy (buf, q, p - q);
2549*58997Selan 	      buf[p - q] = 0;
2550*58997Selan 	      error ("%s", buf);
2551*58997Selan 	      return -1;
2552*58997Selan 	    }
2553*58997Selan 	    break;
2554*58997Selan 
2555*58997Selan 	  case 'g':
2556*58997Selan 	  case 'u':
2557*58997Selan 	  case 'U':
2558*58997Selan 	    if (save_temps_flag)
2559*58997Selan 	      obstack_grow (&obstack, input_basename, basename_length);
2560*58997Selan 	    else
2561*58997Selan 	      {
2562*58997Selan #ifdef MKTEMP_EACH_FILE
2563*58997Selan 		/* ??? This has a problem: the total number of
2564*58997Selan 		   values mktemp can return is limited.
2565*58997Selan 		   That matters for the names of object files.
2566*58997Selan 		   In 2.4, do something about that.  */
2567*58997Selan 		struct temp_name *t;
2568*58997Selan 		char *suffix = p;
2569*58997Selan 		while (*p == '.' || isalpha (*p))
2570*58997Selan 		  p++;
2571*58997Selan 
2572*58997Selan 		/* See if we already have an association of %g/%u/%U and
2573*58997Selan 		   suffix.  */
2574*58997Selan 		for (t = temp_names; t; t = t->next)
2575*58997Selan 		  if (t->length == p - suffix
2576*58997Selan 		      && strncmp (t->suffix, suffix, p - suffix) == 0
2577*58997Selan 		      && t->unique == (c != 'g'))
2578*58997Selan 		    break;
2579*58997Selan 
2580*58997Selan 		/* Make a new association if needed.  %u requires one.  */
2581*58997Selan 		if (t == 0 || c == 'u')
2582*58997Selan 		  {
2583*58997Selan 		    if (t == 0)
2584*58997Selan 		      {
2585*58997Selan 			t = (struct temp_name *) xmalloc (sizeof (struct temp_name));
2586*58997Selan 			t->next = temp_names;
2587*58997Selan 			temp_names = t;
2588*58997Selan 		      }
2589*58997Selan 		    t->length = p - suffix;
2590*58997Selan 		    t->suffix = save_string (suffix, p - suffix);
2591*58997Selan 		    t->unique = (c != 'g');
2592*58997Selan 		    choose_temp_base ();
2593*58997Selan 		    t->filename = temp_filename;
2594*58997Selan 		    t->filename_length = temp_filename_length;
2595*58997Selan 		  }
2596*58997Selan 
2597*58997Selan 		obstack_grow (&obstack, t->filename, t->filename_length);
2598*58997Selan 		delete_this_arg = 1;
2599*58997Selan #else
2600*58997Selan 		obstack_grow (&obstack, temp_filename, temp_filename_length);
2601*58997Selan 		if (c == 'u' || c == 'U')
2602*58997Selan 		  {
2603*58997Selan 		    static int unique;
2604*58997Selan 		    char buff[9];
2605*58997Selan 		    if (c == 'u')
2606*58997Selan 		      unique++;
2607*58997Selan 		    sprintf (buff, "%d", unique);
2608*58997Selan 		    obstack_grow (&obstack, buff, strlen (buff));
2609*58997Selan 		  }
2610*58997Selan #endif
2611*58997Selan 		delete_this_arg = 1;
2612*58997Selan 	      }
2613*58997Selan 	    arg_going = 1;
2614*58997Selan 	    break;
2615*58997Selan 
2616*58997Selan 	  case 'i':
2617*58997Selan 	    obstack_grow (&obstack, input_filename, input_filename_length);
2618*58997Selan 	    arg_going = 1;
2619*58997Selan 	    break;
2620*58997Selan 
2621*58997Selan 	  case 'I':
2622*58997Selan 	    if (gcc_exec_prefix)
2623*58997Selan 	      {
2624*58997Selan 		do_spec_1 ("-iprefix", 1, NULL_PTR);
2625*58997Selan 		/* Make this a separate argument.  */
2626*58997Selan 		do_spec_1 (" ", 0, NULL_PTR);
2627*58997Selan 		do_spec_1 (gcc_exec_prefix, 1, NULL_PTR);
2628*58997Selan 		do_spec_1 (" ", 0, NULL_PTR);
2629*58997Selan 	      }
2630*58997Selan 	    break;
2631*58997Selan 
2632*58997Selan 	  case 'o':
2633*58997Selan 	    {
2634*58997Selan 	      register int f;
2635*58997Selan 	      for (f = 0; f < n_infiles; f++)
2636*58997Selan 		store_arg (outfiles[f], 0, 0);
2637*58997Selan 	    }
2638*58997Selan 	    break;
2639*58997Selan 
2640*58997Selan 	  case 's':
2641*58997Selan 	    this_is_library_file = 1;
2642*58997Selan 	    break;
2643*58997Selan 
2644*58997Selan 	  case 'w':
2645*58997Selan 	    this_is_output_file = 1;
2646*58997Selan 	    break;
2647*58997Selan 
2648*58997Selan 	  case 'W':
2649*58997Selan 	    {
2650*58997Selan 	      int index = argbuf_index;
2651*58997Selan 	      /* Handle the {...} following the %W.  */
2652*58997Selan 	      if (*p != '{')
2653*58997Selan 		abort ();
2654*58997Selan 	      p = handle_braces (p + 1);
2655*58997Selan 	      if (p == 0)
2656*58997Selan 		return -1;
2657*58997Selan 	      /* If any args were output, mark the last one for deletion
2658*58997Selan 		 on failure.  */
2659*58997Selan 	      if (argbuf_index != index)
2660*58997Selan 		record_temp_file (argbuf[argbuf_index - 1], 0, 1);
2661*58997Selan 	      break;
2662*58997Selan 	    }
2663*58997Selan 
2664*58997Selan 	  /* %x{OPTION} records OPTION for %X to output.  */
2665*58997Selan 	  case 'x':
2666*58997Selan 	    {
2667*58997Selan 	      char *p1 = p;
2668*58997Selan 	      char *string;
2669*58997Selan 
2670*58997Selan 	      /* Skip past the option value and make a copy.  */
2671*58997Selan 	      if (*p != '{')
2672*58997Selan 		abort ();
2673*58997Selan 	      while (*p++ != '}')
2674*58997Selan 		;
2675*58997Selan 	      string = save_string (p1 + 1, p - p1 - 2);
2676*58997Selan 
2677*58997Selan 	      /* See if we already recorded this option.  */
2678*58997Selan 	      for (i = 0; i < n_linker_options; i++)
2679*58997Selan 		if (! strcmp (string, linker_options[i]))
2680*58997Selan 		  {
2681*58997Selan 		    free (string);
2682*58997Selan 		    return 0;
2683*58997Selan 		  }
2684*58997Selan 
2685*58997Selan 	      /* This option is new; add it.  */
2686*58997Selan 	      n_linker_options++;
2687*58997Selan 	      if (!linker_options)
2688*58997Selan 		linker_options
2689*58997Selan 		  = (char **) xmalloc (n_linker_options * sizeof (char **));
2690*58997Selan 	      else
2691*58997Selan 		linker_options
2692*58997Selan 		  = (char **) xrealloc (linker_options,
2693*58997Selan 					n_linker_options * sizeof (char **));
2694*58997Selan 
2695*58997Selan 	      linker_options[n_linker_options - 1] = string;
2696*58997Selan 	    }
2697*58997Selan 	    break;
2698*58997Selan 
2699*58997Selan 	  /* Dump out the options accumulated previously using %x,
2700*58997Selan 	     -Xlinker and -Wl,.  */
2701*58997Selan 	  case 'X':
2702*58997Selan 	    for (i = 0; i < n_linker_options; i++)
2703*58997Selan 	      {
2704*58997Selan 		do_spec_1 (linker_options[i], 1, NULL_PTR);
2705*58997Selan 		/* Make each accumulated option a separate argument.  */
2706*58997Selan 		do_spec_1 (" ", 0, NULL_PTR);
2707*58997Selan 	      }
2708*58997Selan 	    break;
2709*58997Selan 
2710*58997Selan 	  /* Dump out the options accumulated previously using -Wa,.  */
2711*58997Selan 	  case 'Y':
2712*58997Selan 	    for (i = 0; i < n_assembler_options; i++)
2713*58997Selan 	      {
2714*58997Selan 		do_spec_1 (assembler_options[i], 1, NULL_PTR);
2715*58997Selan 		/* Make each accumulated option a separate argument.  */
2716*58997Selan 		do_spec_1 (" ", 0, NULL_PTR);
2717*58997Selan 	      }
2718*58997Selan 	    break;
2719*58997Selan 
2720*58997Selan 	    /* Here are digits and numbers that just process
2721*58997Selan 	       a certain constant string as a spec.
2722*58997Selan 	    /* Here are digits and numbers that just process
2723*58997Selan 	       a certain constant string as a spec.  */
2724*58997Selan 
2725*58997Selan 	  case '1':
2726*58997Selan 	    do_spec_1 (cc1_spec, 0, NULL_PTR);
2727*58997Selan 	    break;
2728*58997Selan 
2729*58997Selan 	  case '2':
2730*58997Selan 	    do_spec_1 (cc1plus_spec, 0, NULL_PTR);
2731*58997Selan 	    break;
2732*58997Selan 
2733*58997Selan 	  case 'a':
2734*58997Selan 	    do_spec_1 (asm_spec, 0, NULL_PTR);
2735*58997Selan 	    break;
2736*58997Selan 
2737*58997Selan 	  case 'A':
2738*58997Selan 	    do_spec_1 (asm_final_spec, 0, NULL_PTR);
2739*58997Selan 	    break;
2740*58997Selan 
2741*58997Selan 	  case 'c':
2742*58997Selan 	    do_spec_1 (signed_char_spec, 0, NULL_PTR);
2743*58997Selan 	    break;
2744*58997Selan 
2745*58997Selan 	  case 'C':
2746*58997Selan 	    do_spec_1 (cpp_spec, 0, NULL_PTR);
2747*58997Selan 	    break;
2748*58997Selan 
2749*58997Selan 	  case 'E':
2750*58997Selan 	    do_spec_1 (endfile_spec, 0, NULL_PTR);
2751*58997Selan 	    break;
2752*58997Selan 
2753*58997Selan 	  case 'l':
2754*58997Selan 	    do_spec_1 (link_spec, 0, NULL_PTR);
2755*58997Selan 	    break;
2756*58997Selan 
2757*58997Selan 	  case 'L':
2758*58997Selan 	    do_spec_1 (lib_spec, 0, NULL_PTR);
2759*58997Selan 	    break;
2760*58997Selan 
2761*58997Selan 	  case 'p':
2762*58997Selan 	    {
2763*58997Selan 	      char *x = (char *) alloca (strlen (cpp_predefines) + 1);
2764*58997Selan 	      char *buf = x;
2765*58997Selan 	      char *y;
2766*58997Selan 
2767*58997Selan 	      /* Copy all of the -D options in CPP_PREDEFINES into BUF.  */
2768*58997Selan 	      y = cpp_predefines;
2769*58997Selan 	      while (*y != 0)
2770*58997Selan 		{
2771*58997Selan 		  if (! strncmp (y, "-D", 2))
2772*58997Selan 		    /* Copy the whole option.  */
2773*58997Selan 		    while (*y && *y != ' ' && *y != '\t')
2774*58997Selan 		      *x++ = *y++;
2775*58997Selan 		  else if (*y == ' ' || *y == '\t')
2776*58997Selan 		    /* Copy whitespace to the result.  */
2777*58997Selan 		    *x++ = *y++;
2778*58997Selan 		  /* Don't copy other options.  */
2779*58997Selan 		  else
2780*58997Selan 		    y++;
2781*58997Selan 		}
2782*58997Selan 
2783*58997Selan 	      *x = 0;
2784*58997Selan 
2785*58997Selan 	      do_spec_1 (buf, 0, NULL_PTR);
2786*58997Selan 	    }
2787*58997Selan 	    break;
2788*58997Selan 
2789*58997Selan 	  case 'P':
2790*58997Selan 	    {
2791*58997Selan 	      char *x = (char *) alloca (strlen (cpp_predefines) * 4 + 1);
2792*58997Selan 	      char *buf = x;
2793*58997Selan 	      char *y;
2794*58997Selan 
2795*58997Selan 	      /* Copy all of CPP_PREDEFINES into BUF,
2796*58997Selan 		 but put __ after every -D and at the end of each arg.  */
2797*58997Selan 	      y = cpp_predefines;
2798*58997Selan 	      while (*y != 0)
2799*58997Selan 		{
2800*58997Selan 		  if (! strncmp (y, "-D", 2))
2801*58997Selan 		    {
2802*58997Selan 		      int flag = 0;
2803*58997Selan 
2804*58997Selan 		      *x++ = *y++;
2805*58997Selan 		      *x++ = *y++;
2806*58997Selan 
2807*58997Selan 		      if (strncmp (y, "__", 2))
2808*58997Selan 		        {
2809*58997Selan 			  /* Stick __ at front of macro name.  */
2810*58997Selan 			  *x++ = '_';
2811*58997Selan 			  *x++ = '_';
2812*58997Selan 			  /* Arrange to stick __ at the end as well.  */
2813*58997Selan 			  flag = 1;
2814*58997Selan 			}
2815*58997Selan 
2816*58997Selan 		      /* Copy the macro name.  */
2817*58997Selan 		      while (*y && *y != '=' && *y != ' ' && *y != '\t')
2818*58997Selan 			*x++ = *y++;
2819*58997Selan 
2820*58997Selan 		      if (flag)
2821*58997Selan 		        {
2822*58997Selan 			  *x++ = '_';
2823*58997Selan 			  *x++ = '_';
2824*58997Selan 			}
2825*58997Selan 
2826*58997Selan 		      /* Copy the value given, if any.  */
2827*58997Selan 		      while (*y && *y != ' ' && *y != '\t')
2828*58997Selan 			*x++ = *y++;
2829*58997Selan 		    }
2830*58997Selan 		  else if (*y == ' ' || *y == '\t')
2831*58997Selan 		    /* Copy whitespace to the result.  */
2832*58997Selan 		    *x++ = *y++;
2833*58997Selan 		  /* Don't copy -A options  */
2834*58997Selan 		  else
2835*58997Selan 		    y++;
2836*58997Selan 		}
2837*58997Selan 	      *x++ = ' ';
2838*58997Selan 
2839*58997Selan 	      /* Copy all of CPP_PREDEFINES into BUF,
2840*58997Selan 		 but put __ after every -D.  */
2841*58997Selan 	      y = cpp_predefines;
2842*58997Selan 	      while (*y != 0)
2843*58997Selan 		{
2844*58997Selan 		  if (! strncmp (y, "-D", 2))
2845*58997Selan 		    {
2846*58997Selan 		      *x++ = *y++;
2847*58997Selan 		      *x++ = *y++;
2848*58997Selan 
2849*58997Selan 		      if (strncmp (y, "__", 2))
2850*58997Selan 		        {
2851*58997Selan 			  /* Stick __ at front of macro name.  */
2852*58997Selan 			  *x++ = '_';
2853*58997Selan 			  *x++ = '_';
2854*58997Selan 			}
2855*58997Selan 
2856*58997Selan 		      /* Copy the macro name.  */
2857*58997Selan 		      while (*y && *y != '=' && *y != ' ' && *y != '\t')
2858*58997Selan 			*x++ = *y++;
2859*58997Selan 
2860*58997Selan 		      /* Copy the value given, if any.  */
2861*58997Selan 		      while (*y && *y != ' ' && *y != '\t')
2862*58997Selan 			*x++ = *y++;
2863*58997Selan 		    }
2864*58997Selan 		  else if (*y == ' ' || *y == '\t')
2865*58997Selan 		    /* Copy whitespace to the result.  */
2866*58997Selan 		    *x++ = *y++;
2867*58997Selan 		  /* Don't copy -A options  */
2868*58997Selan 		  else
2869*58997Selan 		    y++;
2870*58997Selan 		}
2871*58997Selan 	      *x++ = ' ';
2872*58997Selan 
2873*58997Selan 	      /* Copy all of the -A options in CPP_PREDEFINES into BUF.  */
2874*58997Selan 	      y = cpp_predefines;
2875*58997Selan 	      while (*y != 0)
2876*58997Selan 		{
2877*58997Selan 		  if (! strncmp (y, "-A", 2))
2878*58997Selan 		    /* Copy the whole option.  */
2879*58997Selan 		    while (*y && *y != ' ' && *y != '\t')
2880*58997Selan 		      *x++ = *y++;
2881*58997Selan 		  else if (*y == ' ' || *y == '\t')
2882*58997Selan 		    /* Copy whitespace to the result.  */
2883*58997Selan 		    *x++ = *y++;
2884*58997Selan 		  /* Don't copy other options.  */
2885*58997Selan 		  else
2886*58997Selan 		    y++;
2887*58997Selan 		}
2888*58997Selan 
2889*58997Selan 	      *x = 0;
2890*58997Selan 
2891*58997Selan 	      do_spec_1 (buf, 0, NULL_PTR);
2892*58997Selan 	    }
2893*58997Selan 	    break;
2894*58997Selan 
2895*58997Selan 	  case 'S':
2896*58997Selan 	    do_spec_1 (startfile_spec, 0, NULL_PTR);
2897*58997Selan 	    break;
2898*58997Selan 
2899*58997Selan 	    /* Here we define characters other than letters and digits.  */
2900*58997Selan 
2901*58997Selan 	  case '{':
2902*58997Selan 	    p = handle_braces (p);
2903*58997Selan 	    if (p == 0)
2904*58997Selan 	      return -1;
2905*58997Selan 	    break;
2906*58997Selan 
2907*58997Selan 	  case '%':
2908*58997Selan 	    obstack_1grow (&obstack, '%');
2909*58997Selan 	    break;
2910*58997Selan 
2911*58997Selan 	  case '*':
2912*58997Selan 	    do_spec_1 (soft_matched_part, 1, NULL_PTR);
2913*58997Selan 	    do_spec_1 (" ", 0, NULL_PTR);
2914*58997Selan 	    break;
2915*58997Selan 
2916*58997Selan 	    /* Process a string found as the value of a spec given by name.
2917*58997Selan 	       This feature allows individual machine descriptions
2918*58997Selan 	       to add and use their own specs.
2919*58997Selan 	       %[...] modifies -D options the way %P does;
2920*58997Selan 	       %(...) uses the spec unmodified.  */
2921*58997Selan 	  case '(':
2922*58997Selan 	  case '[':
2923*58997Selan 	    {
2924*58997Selan 	      char *name = p;
2925*58997Selan 	      struct spec_list *sl;
2926*58997Selan 	      int len;
2927*58997Selan 
2928*58997Selan 	      /* The string after the S/P is the name of a spec that is to be
2929*58997Selan 		 processed. */
2930*58997Selan 	      while (*p && *p != ')' && *p != ']')
2931*58997Selan 		p++;
2932*58997Selan 
2933*58997Selan 	      /* See if it's in the list */
2934*58997Selan 	      for (len = p - name, sl = specs; sl; sl = sl->next)
2935*58997Selan 		if (strncmp (sl->name, name, len) == 0 && !sl->name[len])
2936*58997Selan 		  {
2937*58997Selan 		    name = sl->spec;
2938*58997Selan 		    break;
2939*58997Selan 		  }
2940*58997Selan 
2941*58997Selan 	      if (sl)
2942*58997Selan 		{
2943*58997Selan 		  if (c == '(')
2944*58997Selan 		    do_spec_1 (name, 0, NULL_PTR);
2945*58997Selan 		  else
2946*58997Selan 		    {
2947*58997Selan 		      char *x = (char *) alloca (strlen (name) * 2 + 1);
2948*58997Selan 		      char *buf = x;
2949*58997Selan 		      char *y = name;
2950*58997Selan 
2951*58997Selan 		      /* Copy all of NAME into BUF, but put __ after
2952*58997Selan 			 every -D and at the end of each arg,  */
2953*58997Selan 		      while (1)
2954*58997Selan 			{
2955*58997Selan 			  if (! strncmp (y, "-D", 2))
2956*58997Selan 			    {
2957*58997Selan 			      *x++ = '-';
2958*58997Selan 			      *x++ = 'D';
2959*58997Selan 			      *x++ = '_';
2960*58997Selan 			      *x++ = '_';
2961*58997Selan 			      y += 2;
2962*58997Selan 			    }
2963*58997Selan 			  else if (*y == ' ' || *y == 0)
2964*58997Selan 			    {
2965*58997Selan 			      *x++ = '_';
2966*58997Selan 			      *x++ = '_';
2967*58997Selan 			      if (*y == 0)
2968*58997Selan 				break;
2969*58997Selan 			      else
2970*58997Selan 				*x++ = *y++;
2971*58997Selan 			    }
2972*58997Selan 			  else
2973*58997Selan 			    *x++ = *y++;
2974*58997Selan 			}
2975*58997Selan 		      *x = 0;
2976*58997Selan 
2977*58997Selan 		      do_spec_1 (buf, 0, NULL_PTR);
2978*58997Selan 		    }
2979*58997Selan 		}
2980*58997Selan 
2981*58997Selan 	      /* Discard the closing paren or bracket.  */
2982*58997Selan 	      if (*p)
2983*58997Selan 		p++;
2984*58997Selan 	    }
2985*58997Selan 	    break;
2986*58997Selan 
2987*58997Selan 	  default:
2988*58997Selan 	    abort ();
2989*58997Selan 	  }
2990*58997Selan 	break;
2991*58997Selan 
2992*58997Selan       case '\\':
2993*58997Selan 	/* Backslash: treat next character as ordinary.  */
2994*58997Selan 	c = *p++;
2995*58997Selan 
2996*58997Selan 	/* fall through */
2997*58997Selan       default:
2998*58997Selan 	/* Ordinary character: put it into the current argument.  */
2999*58997Selan 	obstack_1grow (&obstack, c);
3000*58997Selan 	arg_going = 1;
3001*58997Selan       }
3002*58997Selan 
3003*58997Selan   return 0;		/* End of string */
3004*58997Selan }
3005*58997Selan 
3006*58997Selan /* Return 0 if we call do_spec_1 and that returns -1.  */
3007*58997Selan 
3008*58997Selan static char *
3009*58997Selan handle_braces (p)
3010*58997Selan      register char *p;
3011*58997Selan {
3012*58997Selan   register char *q;
3013*58997Selan   char *filter;
3014*58997Selan   int pipe = 0;
3015*58997Selan   int negate = 0;
3016*58997Selan   int suffix = 0;
3017*58997Selan 
3018*58997Selan   if (*p == '|')
3019*58997Selan     /* A `|' after the open-brace means,
3020*58997Selan        if the test fails, output a single minus sign rather than nothing.
3021*58997Selan        This is used in %{|!pipe:...}.  */
3022*58997Selan     pipe = 1, ++p;
3023*58997Selan 
3024*58997Selan   if (*p == '!')
3025*58997Selan     /* A `!' after the open-brace negates the condition:
3026*58997Selan        succeed if the specified switch is not present.  */
3027*58997Selan     negate = 1, ++p;
3028*58997Selan 
3029*58997Selan   if (*p == '.')
3030*58997Selan     /* A `.' after the open-brace means test against the current suffix.  */
3031*58997Selan     {
3032*58997Selan       if (pipe)
3033*58997Selan 	abort ();
3034*58997Selan 
3035*58997Selan       suffix = 1;
3036*58997Selan       ++p;
3037*58997Selan     }
3038*58997Selan 
3039*58997Selan   filter = p;
3040*58997Selan   while (*p != ':' && *p != '}') p++;
3041*58997Selan   if (*p != '}')
3042*58997Selan     {
3043*58997Selan       register int count = 1;
3044*58997Selan       q = p + 1;
3045*58997Selan       while (count > 0)
3046*58997Selan 	{
3047*58997Selan 	  if (*q == '{')
3048*58997Selan 	    count++;
3049*58997Selan 	  else if (*q == '}')
3050*58997Selan 	    count--;
3051*58997Selan 	  else if (*q == 0)
3052*58997Selan 	    abort ();
3053*58997Selan 	  q++;
3054*58997Selan 	}
3055*58997Selan     }
3056*58997Selan   else
3057*58997Selan     q = p + 1;
3058*58997Selan 
3059*58997Selan   if (suffix)
3060*58997Selan     {
3061*58997Selan       int found = (input_suffix != 0
3062*58997Selan 		   && strlen (input_suffix) == p - filter
3063*58997Selan 		   && strncmp (input_suffix, filter, p - filter) == 0);
3064*58997Selan 
3065*58997Selan       if (p[0] == '}')
3066*58997Selan 	abort ();
3067*58997Selan 
3068*58997Selan       if (negate != found
3069*58997Selan 	  && do_spec_1 (save_string (p + 1, q - p - 2), 0, NULL_PTR) < 0)
3070*58997Selan 	return 0;
3071*58997Selan 
3072*58997Selan       return q;
3073*58997Selan     }
3074*58997Selan   else if (p[-1] == '*' && p[0] == '}')
3075*58997Selan     {
3076*58997Selan       /* Substitute all matching switches as separate args.  */
3077*58997Selan       register int i;
3078*58997Selan       --p;
3079*58997Selan       for (i = 0; i < n_switches; i++)
3080*58997Selan 	if (!strncmp (switches[i].part1, filter, p - filter))
3081*58997Selan 	  give_switch (i, 0);
3082*58997Selan     }
3083*58997Selan   else
3084*58997Selan     {
3085*58997Selan       /* Test for presence of the specified switch.  */
3086*58997Selan       register int i;
3087*58997Selan       int present = 0;
3088*58997Selan 
3089*58997Selan       /* If name specified ends in *, as in {x*:...},
3090*58997Selan 	 check for %* and handle that case.  */
3091*58997Selan       if (p[-1] == '*' && !negate)
3092*58997Selan 	{
3093*58997Selan 	  int substitution;
3094*58997Selan 	  char *r = p;
3095*58997Selan 
3096*58997Selan 	  /* First see whether we have %*.  */
3097*58997Selan 	  substitution = 0;
3098*58997Selan 	  while (r < q)
3099*58997Selan 	    {
3100*58997Selan 	      if (*r == '%' && r[1] == '*')
3101*58997Selan 		substitution = 1;
3102*58997Selan 	      r++;
3103*58997Selan 	    }
3104*58997Selan 	  /* If we do, handle that case.  */
3105*58997Selan 	  if (substitution)
3106*58997Selan 	    {
3107*58997Selan 	      /* Substitute all matching switches as separate args.
3108*58997Selan 		 But do this by substituting for %*
3109*58997Selan 		 in the text that follows the colon.  */
3110*58997Selan 
3111*58997Selan 	      unsigned hard_match_len = p - filter - 1;
3112*58997Selan 	      char *string = save_string (p + 1, q - p - 2);
3113*58997Selan 
3114*58997Selan 	      for (i = 0; i < n_switches; i++)
3115*58997Selan 		if (!strncmp (switches[i].part1, filter, hard_match_len))
3116*58997Selan 		  {
3117*58997Selan 		    do_spec_1 (string, 0, &switches[i].part1[hard_match_len]);
3118*58997Selan 		    /* Pass any arguments this switch has.  */
3119*58997Selan 		    give_switch (i, 1);
3120*58997Selan 		  }
3121*58997Selan 
3122*58997Selan 	      return q;
3123*58997Selan 	    }
3124*58997Selan 	}
3125*58997Selan 
3126*58997Selan       /* If name specified ends in *, as in {x*:...},
3127*58997Selan 	 check for presence of any switch name starting with x.  */
3128*58997Selan       if (p[-1] == '*')
3129*58997Selan 	{
3130*58997Selan 	  for (i = 0; i < n_switches; i++)
3131*58997Selan 	    {
3132*58997Selan 	      unsigned hard_match_len = p - filter - 1;
3133*58997Selan 
3134*58997Selan 	      if (!strncmp (switches[i].part1, filter, hard_match_len))
3135*58997Selan 		{
3136*58997Selan 		  switches[i].valid = 1;
3137*58997Selan 		  present = 1;
3138*58997Selan 		}
3139*58997Selan 	    }
3140*58997Selan 	}
3141*58997Selan       /* Otherwise, check for presence of exact name specified.  */
3142*58997Selan       else
3143*58997Selan 	{
3144*58997Selan 	  for (i = 0; i < n_switches; i++)
3145*58997Selan 	    {
3146*58997Selan 	      if (!strncmp (switches[i].part1, filter, p - filter)
3147*58997Selan 		  && switches[i].part1[p - filter] == 0)
3148*58997Selan 		{
3149*58997Selan 		  switches[i].valid = 1;
3150*58997Selan 		  present = 1;
3151*58997Selan 		  break;
3152*58997Selan 		}
3153*58997Selan 	    }
3154*58997Selan 	}
3155*58997Selan 
3156*58997Selan       /* If it is as desired (present for %{s...}, absent for %{-s...})
3157*58997Selan 	 then substitute either the switch or the specified
3158*58997Selan 	 conditional text.  */
3159*58997Selan       if (present != negate)
3160*58997Selan 	{
3161*58997Selan 	  if (*p == '}')
3162*58997Selan 	    {
3163*58997Selan 	      give_switch (i, 0);
3164*58997Selan 	    }
3165*58997Selan 	  else
3166*58997Selan 	    {
3167*58997Selan 	      if (do_spec_1 (save_string (p + 1, q - p - 2), 0, NULL_PTR) < 0)
3168*58997Selan 		return 0;
3169*58997Selan 	    }
3170*58997Selan 	}
3171*58997Selan       else if (pipe)
3172*58997Selan 	{
3173*58997Selan 	  /* Here if a %{|...} conditional fails: output a minus sign,
3174*58997Selan 	     which means "standard output" or "standard input".  */
3175*58997Selan 	  do_spec_1 ("-", 0, NULL_PTR);
3176*58997Selan 	}
3177*58997Selan     }
3178*58997Selan 
3179*58997Selan   return q;
3180*58997Selan }
3181*58997Selan 
3182*58997Selan /* Pass a switch to the current accumulating command
3183*58997Selan    in the same form that we received it.
3184*58997Selan    SWITCHNUM identifies the switch; it is an index into
3185*58997Selan    the vector of switches gcc received, which is `switches'.
3186*58997Selan    This cannot fail since it never finishes a command line.
3187*58997Selan 
3188*58997Selan    If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument.  */
3189*58997Selan 
3190*58997Selan static void
3191*58997Selan give_switch (switchnum, omit_first_word)
3192*58997Selan      int switchnum;
3193*58997Selan      int omit_first_word;
3194*58997Selan {
3195*58997Selan   if (!omit_first_word)
3196*58997Selan     {
3197*58997Selan       do_spec_1 ("-", 0, NULL_PTR);
3198*58997Selan       do_spec_1 (switches[switchnum].part1, 1, NULL_PTR);
3199*58997Selan     }
3200*58997Selan   do_spec_1 (" ", 0, NULL_PTR);
3201*58997Selan   if (switches[switchnum].args != 0)
3202*58997Selan     {
3203*58997Selan       char **p;
3204*58997Selan       for (p = switches[switchnum].args; *p; p++)
3205*58997Selan 	{
3206*58997Selan 	  do_spec_1 (*p, 1, NULL_PTR);
3207*58997Selan 	  do_spec_1 (" ", 0, NULL_PTR);
3208*58997Selan 	}
3209*58997Selan     }
3210*58997Selan   switches[switchnum].valid = 1;
3211*58997Selan }
3212*58997Selan 
3213*58997Selan /* Search for a file named NAME trying various prefixes including the
3214*58997Selan    user's -B prefix and some standard ones.
3215*58997Selan    Return the absolute file name found.  If nothing is found, return NAME.  */
3216*58997Selan 
3217*58997Selan static char *
3218*58997Selan find_file (name)
3219*58997Selan      char *name;
3220*58997Selan {
3221*58997Selan   char *newname;
3222*58997Selan 
3223*58997Selan   newname = find_a_file (&startfile_prefix, name, R_OK);
3224*58997Selan   return newname ? newname : name;
3225*58997Selan }
3226*58997Selan 
3227*58997Selan /* Determine whether a -L option is relevant.  Not required for certain
3228*58997Selan    fixed names and for directories that don't exist.  */
3229*58997Selan 
3230*58997Selan static int
3231*58997Selan is_linker_dir (path1, path2)
3232*58997Selan      char *path1;
3233*58997Selan      char *path2;
3234*58997Selan {
3235*58997Selan   int len1 = strlen (path1);
3236*58997Selan   int len2 = strlen (path2);
3237*58997Selan   char *path = (char *) alloca (3 + len1 + len2);
3238*58997Selan   char *cp;
3239*58997Selan   struct stat st;
3240*58997Selan 
3241*58997Selan   /* Construct the path from the two parts.  Ensure the string ends with "/.".
3242*58997Selan      The resulting path will be a directory even if the given path is a
3243*58997Selan      symbolic link.  */
3244*58997Selan   bcopy (path1, path, len1);
3245*58997Selan   bcopy (path2, path + len1, len2);
3246*58997Selan   cp = path + len1 + len2;
3247*58997Selan   if (cp[-1] != '/')
3248*58997Selan     *cp++ = '/';
3249*58997Selan   *cp++ = '.';
3250*58997Selan   *cp = '\0';
3251*58997Selan 
3252*58997Selan   /* Exclude directories that the linker is known to search.  */
3253*58997Selan   if ((cp - path == 6 && strcmp (path, "/lib/.") == 0)
3254*58997Selan       || (cp - path == 10 && strcmp (path, "/usr/lib/.") == 0))
3255*58997Selan     return 0;
3256*58997Selan 
3257*58997Selan   return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
3258*58997Selan }
3259*58997Selan 
3260*58997Selan /* On fatal signals, delete all the temporary files.  */
3261*58997Selan 
3262*58997Selan static void
3263*58997Selan fatal_error (signum)
3264*58997Selan      int signum;
3265*58997Selan {
3266*58997Selan   signal (signum, SIG_DFL);
3267*58997Selan   delete_failure_queue ();
3268*58997Selan   delete_temp_files ();
3269*58997Selan   /* Get the same signal again, this time not handled,
3270*58997Selan      so its normal effect occurs.  */
3271*58997Selan   kill (getpid (), signum);
3272*58997Selan }
3273*58997Selan 
3274*58997Selan int
3275*58997Selan main (argc, argv)
3276*58997Selan      int argc;
3277*58997Selan      char **argv;
3278*58997Selan {
3279*58997Selan   register int i;
3280*58997Selan   int j;
3281*58997Selan   int value;
3282*58997Selan   int error_count = 0;
3283*58997Selan   int linker_was_run = 0;
3284*58997Selan   char *explicit_link_files;
3285*58997Selan   char *specs_file;
3286*58997Selan 
3287*58997Selan   programname = argv[0];
3288*58997Selan 
3289*58997Selan   if (signal (SIGINT, SIG_IGN) != SIG_IGN)
3290*58997Selan     signal (SIGINT, fatal_error);
3291*58997Selan   if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
3292*58997Selan     signal (SIGHUP, fatal_error);
3293*58997Selan   if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
3294*58997Selan     signal (SIGTERM, fatal_error);
3295*58997Selan #ifdef SIGPIPE
3296*58997Selan   if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
3297*58997Selan     signal (SIGPIPE, fatal_error);
3298*58997Selan #endif
3299*58997Selan 
3300*58997Selan   argbuf_length = 10;
3301*58997Selan   argbuf = (char **) xmalloc (argbuf_length * sizeof (char *));
3302*58997Selan 
3303*58997Selan   obstack_init (&obstack);
3304*58997Selan 
3305*58997Selan   /* Set up to remember the pathname of gcc and any options
3306*58997Selan      needed for collect.  */
3307*58997Selan   obstack_init (&collect_obstack);
3308*58997Selan   obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=")-1);
3309*58997Selan   obstack_grow (&collect_obstack, programname, strlen (programname)+1);
3310*58997Selan   putenv (obstack_finish (&collect_obstack));
3311*58997Selan 
3312*58997Selan   /* Choose directory for temp files.  */
3313*58997Selan 
3314*58997Selan   choose_temp_base ();
3315*58997Selan 
3316*58997Selan   /* Make a table of what switches there are (switches, n_switches).
3317*58997Selan      Make a table of specified input files (infiles, n_infiles).
3318*58997Selan      Decode switches that are handled locally.  */
3319*58997Selan 
3320*58997Selan   process_command (argc, argv);
3321*58997Selan 
3322*58997Selan   /* Initialize the vector of specs to just the default.
3323*58997Selan      This means one element containing 0s, as a terminator.  */
3324*58997Selan 
3325*58997Selan   compilers = (struct compiler *) xmalloc (sizeof default_compilers);
3326*58997Selan   bcopy (default_compilers, compilers, sizeof default_compilers);
3327*58997Selan   n_compilers = n_default_compilers;
3328*58997Selan 
3329*58997Selan   /* Read specs from a file if there is one.  */
3330*58997Selan 
3331*58997Selan   machine_suffix = concat (spec_machine, "/", concat (spec_version, "/", ""));
3332*58997Selan   just_machine_suffix = concat (spec_machine, "/", "");
3333*58997Selan 
3334*58997Selan   specs_file = find_a_file (&startfile_prefix, "specs", R_OK);
3335*58997Selan   /* Read the specs file unless it is a default one.  */
3336*58997Selan   if (specs_file != 0 && strcmp (specs_file, "specs"))
3337*58997Selan     read_specs (specs_file);
3338*58997Selan 
3339*58997Selan   /* If not cross-compiling, look for startfiles in the standard places.  */
3340*58997Selan   /* The fact that these are done here, after reading the specs file,
3341*58997Selan      means that it cannot be found in these directories.
3342*58997Selan      But that's okay.  It should never be there anyway.  */
3343*58997Selan   if (!cross_compile)
3344*58997Selan     {
3345*58997Selan #ifdef MD_EXEC_PREFIX
3346*58997Selan       add_prefix (&exec_prefix, md_exec_prefix, 0, 0, NULL_PTR);
3347*58997Selan       add_prefix (&startfile_prefix, md_exec_prefix, 0, 0, NULL_PTR);
3348*58997Selan #endif
3349*58997Selan 
3350*58997Selan #ifdef MD_STARTFILE_PREFIX
3351*58997Selan       add_prefix (&startfile_prefix, md_startfile_prefix, 0, 0, NULL_PTR);
3352*58997Selan #endif
3353*58997Selan 
3354*58997Selan #ifdef MD_STARTFILE_PREFIX_1
3355*58997Selan       add_prefix (&startfile_prefix, md_startfile_prefix_1, 0, 0, NULL_PTR);
3356*58997Selan #endif
3357*58997Selan 
3358*58997Selan       add_prefix (&startfile_prefix, standard_startfile_prefix, 0, 0,
3359*58997Selan 		  NULL_PTR);
3360*58997Selan       add_prefix (&startfile_prefix, standard_startfile_prefix_1, 0, 0,
3361*58997Selan 		  NULL_PTR);
3362*58997Selan       add_prefix (&startfile_prefix, standard_startfile_prefix_2, 0, 0,
3363*58997Selan 		  NULL_PTR);
3364*58997Selan #if 0 /* Can cause surprises, and one can use -B./ instead.  */
3365*58997Selan       add_prefix (&startfile_prefix, "./", 0, 1, NULL_PTR);
3366*58997Selan #endif
3367*58997Selan     }
3368*58997Selan 
3369*58997Selan   /* Now we have the specs.
3370*58997Selan      Set the `valid' bits for switches that match anything in any spec.  */
3371*58997Selan 
3372*58997Selan   validate_all_switches ();
3373*58997Selan 
3374*58997Selan   /* Warn about any switches that no pass was interested in.  */
3375*58997Selan 
3376*58997Selan   for (i = 0; i < n_switches; i++)
3377*58997Selan     if (! switches[i].valid)
3378*58997Selan       error ("unrecognized option `-%s'", switches[i].part1);
3379*58997Selan 
3380*58997Selan   if (print_libgcc_file_name)
3381*58997Selan     {
3382*58997Selan       printf ("%s\n", find_file ("libgcc.a"));
3383*58997Selan       exit (0);
3384*58997Selan     }
3385*58997Selan 
3386*58997Selan   /* Obey some of the options.  */
3387*58997Selan 
3388*58997Selan   if (verbose_flag)
3389*58997Selan     {
3390*58997Selan       fprintf (stderr, "gcc version %s\n", version_string);
3391*58997Selan       if (n_infiles == 0)
3392*58997Selan 	exit (0);
3393*58997Selan     }
3394*58997Selan 
3395*58997Selan   if (n_infiles == 0)
3396*58997Selan     fatal ("No input files specified.");
3397*58997Selan 
3398*58997Selan   /* Make a place to record the compiler output file names
3399*58997Selan      that correspond to the input files.  */
3400*58997Selan 
3401*58997Selan   outfiles = (char **) xmalloc (n_infiles * sizeof (char *));
3402*58997Selan   bzero (outfiles, n_infiles * sizeof (char *));
3403*58997Selan 
3404*58997Selan   /* Record which files were specified explicitly as link input.  */
3405*58997Selan 
3406*58997Selan   explicit_link_files = xmalloc (n_infiles);
3407*58997Selan   bzero (explicit_link_files, n_infiles);
3408*58997Selan 
3409*58997Selan   for (i = 0; i < n_infiles; i++)
3410*58997Selan     {
3411*58997Selan       register struct compiler *cp = 0;
3412*58997Selan       int this_file_error = 0;
3413*58997Selan 
3414*58997Selan       /* Tell do_spec what to substitute for %i.  */
3415*58997Selan 
3416*58997Selan       input_filename = infiles[i].name;
3417*58997Selan       input_filename_length = strlen (input_filename);
3418*58997Selan       input_file_number = i;
3419*58997Selan 
3420*58997Selan       /* Use the same thing in %o, unless cp->spec says otherwise.  */
3421*58997Selan 
3422*58997Selan       outfiles[i] = input_filename;
3423*58997Selan 
3424*58997Selan       /* Figure out which compiler from the file's suffix.  */
3425*58997Selan 
3426*58997Selan       cp = lookup_compiler (infiles[i].name, input_filename_length,
3427*58997Selan 			    infiles[i].language);
3428*58997Selan 
3429*58997Selan       if (cp)
3430*58997Selan 	{
3431*58997Selan 	  /* Ok, we found an applicable compiler.  Run its spec.  */
3432*58997Selan 	  /* First say how much of input_filename to substitute for %b  */
3433*58997Selan 	  register char *p;
3434*58997Selan 	  int len;
3435*58997Selan 
3436*58997Selan 	  input_basename = input_filename;
3437*58997Selan 	  for (p = input_filename; *p; p++)
3438*58997Selan 	    if (*p == '/')
3439*58997Selan 	      input_basename = p + 1;
3440*58997Selan 
3441*58997Selan 	  /* Find a suffix starting with the last period,
3442*58997Selan 	     and set basename_length to exclude that suffix.  */
3443*58997Selan 	  basename_length = strlen (input_basename);
3444*58997Selan 	  p = input_basename + basename_length;
3445*58997Selan 	  while (p != input_basename && *p != '.') --p;
3446*58997Selan 	  if (*p == '.' && p != input_basename)
3447*58997Selan 	    {
3448*58997Selan 	      basename_length = p - input_basename;
3449*58997Selan 	      input_suffix = p + 1;
3450*58997Selan 	    }
3451*58997Selan 	  else
3452*58997Selan 	    input_suffix = "";
3453*58997Selan 
3454*58997Selan 	  len = 0;
3455*58997Selan 	  for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++)
3456*58997Selan 	    if (cp->spec[j])
3457*58997Selan 	      len += strlen (cp->spec[j]);
3458*58997Selan 
3459*58997Selan 	  p = (char *) xmalloc (len + 1);
3460*58997Selan 
3461*58997Selan 	  len = 0;
3462*58997Selan 	  for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++)
3463*58997Selan 	    if (cp->spec[j])
3464*58997Selan 	      {
3465*58997Selan 		strcpy (p + len, cp->spec[j]);
3466*58997Selan 		len += strlen (cp->spec[j]);
3467*58997Selan 	      }
3468*58997Selan 
3469*58997Selan 	  value = do_spec (p);
3470*58997Selan 	  free (p);
3471*58997Selan 	  if (value < 0)
3472*58997Selan 	    this_file_error = 1;
3473*58997Selan 	}
3474*58997Selan 
3475*58997Selan       /* If this file's name does not contain a recognized suffix,
3476*58997Selan 	 record it as explicit linker input.  */
3477*58997Selan 
3478*58997Selan       else
3479*58997Selan 	explicit_link_files[i] = 1;
3480*58997Selan 
3481*58997Selan       /* Clear the delete-on-failure queue, deleting the files in it
3482*58997Selan 	 if this compilation failed.  */
3483*58997Selan 
3484*58997Selan       if (this_file_error)
3485*58997Selan 	{
3486*58997Selan 	  delete_failure_queue ();
3487*58997Selan 	  error_count++;
3488*58997Selan 	}
3489*58997Selan       /* If this compilation succeeded, don't delete those files later.  */
3490*58997Selan       clear_failure_queue ();
3491*58997Selan     }
3492*58997Selan 
3493*58997Selan   /* Run ld to link all the compiler output files.  */
3494*58997Selan 
3495*58997Selan   if (error_count == 0)
3496*58997Selan     {
3497*58997Selan       int tmp = execution_count;
3498*58997Selan       int i;
3499*58997Selan       int first_time;
3500*58997Selan 
3501*58997Selan       /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
3502*58997Selan 	 for collect.  */
3503*58997Selan       putenv_from_prefixes (&exec_prefix, "COMPILER_PATH=");
3504*58997Selan       putenv_from_prefixes (&startfile_prefix, "LIBRARY_PATH=");
3505*58997Selan 
3506*58997Selan       /* Build COLLECT_GCC_OPTIONS to have all of the options specified to
3507*58997Selan 	 the compiler.  */
3508*58997Selan       obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
3509*58997Selan 		    sizeof ("COLLECT_GCC_OPTIONS=")-1);
3510*58997Selan 
3511*58997Selan       first_time = TRUE;
3512*58997Selan       for (i = 0; i < n_switches; i++)
3513*58997Selan 	{
3514*58997Selan 	  char **args;
3515*58997Selan 	  if (!first_time)
3516*58997Selan 	    obstack_grow (&collect_obstack, " ", 1);
3517*58997Selan 
3518*58997Selan 	  first_time = FALSE;
3519*58997Selan 	  obstack_grow (&collect_obstack, "-", 1);
3520*58997Selan 	  obstack_grow (&collect_obstack, switches[i].part1,
3521*58997Selan 			strlen (switches[i].part1));
3522*58997Selan 
3523*58997Selan 	  for (args = switches[i].args; args && *args; args++)
3524*58997Selan 	    {
3525*58997Selan 	      obstack_grow (&collect_obstack, " ", 1);
3526*58997Selan 	      obstack_grow (&collect_obstack, *args, strlen (*args));
3527*58997Selan 	    }
3528*58997Selan 	}
3529*58997Selan       obstack_grow (&collect_obstack, "\0", 1);
3530*58997Selan       putenv (obstack_finish (&collect_obstack));
3531*58997Selan 
3532*58997Selan       value = do_spec (link_command_spec);
3533*58997Selan       if (value < 0)
3534*58997Selan 	error_count = 1;
3535*58997Selan       linker_was_run = (tmp != execution_count);
3536*58997Selan     }
3537*58997Selan 
3538*58997Selan   /* Warn if a -B option was specified but the prefix was never used.  */
3539*58997Selan   unused_prefix_warnings (&exec_prefix);
3540*58997Selan   unused_prefix_warnings (&startfile_prefix);
3541*58997Selan 
3542*58997Selan   /* If options said don't run linker,
3543*58997Selan      complain about input files to be given to the linker.  */
3544*58997Selan 
3545*58997Selan   if (! linker_was_run && error_count == 0)
3546*58997Selan     for (i = 0; i < n_infiles; i++)
3547*58997Selan       if (explicit_link_files[i])
3548*58997Selan 	error ("%s: linker input file unused since linking not done",
3549*58997Selan 	       outfiles[i]);
3550*58997Selan 
3551*58997Selan   /* Delete some or all of the temporary files we made.  */
3552*58997Selan 
3553*58997Selan   if (error_count)
3554*58997Selan     delete_failure_queue ();
3555*58997Selan   delete_temp_files ();
3556*58997Selan 
3557*58997Selan   exit (error_count > 0 ? (signal_count ? 2 : 1) : 0);
3558*58997Selan   /* NOTREACHED */
3559*58997Selan   return 0;
3560*58997Selan }
3561*58997Selan 
3562*58997Selan /* Find the proper compilation spec for the file name NAME,
3563*58997Selan    whose length is LENGTH.  LANGUAGE is the specified language,
3564*58997Selan    or 0 if none specified.  */
3565*58997Selan 
3566*58997Selan static struct compiler *
3567*58997Selan lookup_compiler (name, length, language)
3568*58997Selan      char *name;
3569*58997Selan      int length;
3570*58997Selan      char *language;
3571*58997Selan {
3572*58997Selan   struct compiler *cp;
3573*58997Selan 
3574*58997Selan   /* Look for the language, if one is spec'd.  */
3575*58997Selan   if (language != 0)
3576*58997Selan     {
3577*58997Selan       for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
3578*58997Selan 	{
3579*58997Selan 	  if (language != 0)
3580*58997Selan 	    {
3581*58997Selan 	      if (cp->suffix[0] == '@'
3582*58997Selan 		  && !strcmp (cp->suffix + 1, language))
3583*58997Selan 		return cp;
3584*58997Selan 	    }
3585*58997Selan 	}
3586*58997Selan       error ("language %s not recognized", language);
3587*58997Selan     }
3588*58997Selan 
3589*58997Selan   /* Look for a suffix.  */
3590*58997Selan   for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
3591*58997Selan     {
3592*58997Selan       if (strlen (cp->suffix) < length
3593*58997Selan 	       /* See if the suffix matches the end of NAME.  */
3594*58997Selan 	       && !strcmp (cp->suffix,
3595*58997Selan 			   name + length - strlen (cp->suffix))
3596*58997Selan 	       /* The suffix `-' matches only the file name `-'.  */
3597*58997Selan 	       && !(!strcmp (cp->suffix, "-") && length != 1))
3598*58997Selan 	{
3599*58997Selan 	  if (cp->spec[0][0] == '@')
3600*58997Selan 	    {
3601*58997Selan 	      struct compiler *new;
3602*58997Selan 	      /* An alias entry maps a suffix to a language.
3603*58997Selan 		 Search for the language; pass 0 for NAME and LENGTH
3604*58997Selan 		 to avoid infinite recursion if language not found.
3605*58997Selan 		 Construct the new compiler spec.  */
3606*58997Selan 	      language = cp->spec[0] + 1;
3607*58997Selan 	      new = (struct compiler *) xmalloc (sizeof (struct compiler));
3608*58997Selan 	      new->suffix = cp->suffix;
3609*58997Selan 	      bcopy (lookup_compiler (NULL_PTR, 0, language)->spec,
3610*58997Selan 		     new->spec, sizeof new->spec);
3611*58997Selan 	      return new;
3612*58997Selan 	    }
3613*58997Selan 	  /* A non-alias entry: return it.  */
3614*58997Selan 	  return cp;
3615*58997Selan 	}
3616*58997Selan     }
3617*58997Selan 
3618*58997Selan   return 0;
3619*58997Selan }
3620*58997Selan 
3621*58997Selan char *
3622*58997Selan xmalloc (size)
3623*58997Selan      unsigned size;
3624*58997Selan {
3625*58997Selan   register char *value = (char *) malloc (size);
3626*58997Selan   if (value == 0)
3627*58997Selan     fatal ("virtual memory exhausted");
3628*58997Selan   return value;
3629*58997Selan }
3630*58997Selan 
3631*58997Selan char *
3632*58997Selan xrealloc (ptr, size)
3633*58997Selan      char *ptr;
3634*58997Selan      unsigned size;
3635*58997Selan {
3636*58997Selan   register char *value = (char *) realloc (ptr, size);
3637*58997Selan   if (value == 0)
3638*58997Selan     fatal ("virtual memory exhausted");
3639*58997Selan   return value;
3640*58997Selan }
3641*58997Selan 
3642*58997Selan /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3.  */
3643*58997Selan 
3644*58997Selan static char *
3645*58997Selan concat (s1, s2, s3)
3646*58997Selan      char *s1, *s2, *s3;
3647*58997Selan {
3648*58997Selan   int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
3649*58997Selan   char *result = xmalloc (len1 + len2 + len3 + 1);
3650*58997Selan 
3651*58997Selan   strcpy (result, s1);
3652*58997Selan   strcpy (result + len1, s2);
3653*58997Selan   strcpy (result + len1 + len2, s3);
3654*58997Selan   *(result + len1 + len2 + len3) = 0;
3655*58997Selan 
3656*58997Selan   return result;
3657*58997Selan }
3658*58997Selan 
3659*58997Selan static char *
3660*58997Selan save_string (s, len)
3661*58997Selan      char *s;
3662*58997Selan      int len;
3663*58997Selan {
3664*58997Selan   register char *result = xmalloc (len + 1);
3665*58997Selan 
3666*58997Selan   bcopy (s, result, len);
3667*58997Selan   result[len] = 0;
3668*58997Selan   return result;
3669*58997Selan }
3670*58997Selan 
3671*58997Selan static void
3672*58997Selan pfatal_with_name (name)
3673*58997Selan      char *name;
3674*58997Selan {
3675*58997Selan   char *s;
3676*58997Selan 
3677*58997Selan   if (errno < sys_nerr)
3678*58997Selan     s = concat ("%s: ", sys_errlist[errno], "");
3679*58997Selan   else
3680*58997Selan     s = "cannot open %s";
3681*58997Selan   fatal (s, name);
3682*58997Selan }
3683*58997Selan 
3684*58997Selan static void
3685*58997Selan perror_with_name (name)
3686*58997Selan      char *name;
3687*58997Selan {
3688*58997Selan   char *s;
3689*58997Selan 
3690*58997Selan   if (errno < sys_nerr)
3691*58997Selan     s = concat ("%s: ", sys_errlist[errno], "");
3692*58997Selan   else
3693*58997Selan     s = "cannot open %s";
3694*58997Selan   error (s, name);
3695*58997Selan }
3696*58997Selan 
3697*58997Selan static void
3698*58997Selan perror_exec (name)
3699*58997Selan      char *name;
3700*58997Selan {
3701*58997Selan   char *s;
3702*58997Selan 
3703*58997Selan   if (errno < sys_nerr)
3704*58997Selan     s = concat ("installation problem, cannot exec %s: ",
3705*58997Selan 		sys_errlist[errno], "");
3706*58997Selan   else
3707*58997Selan     s = "installation problem, cannot exec %s";
3708*58997Selan   error (s, name);
3709*58997Selan }
3710*58997Selan 
3711*58997Selan /* More 'friendly' abort that prints the line and file.
3712*58997Selan    config.h can #define abort fancy_abort if you like that sort of thing.  */
3713*58997Selan 
3714*58997Selan void
3715*58997Selan fancy_abort ()
3716*58997Selan {
3717*58997Selan   fatal ("Internal gcc abort.");
3718*58997Selan }
3719*58997Selan 
3720*58997Selan #ifdef HAVE_VPRINTF
3721*58997Selan 
3722*58997Selan /* Output an error message and exit */
3723*58997Selan 
3724*58997Selan static void
3725*58997Selan fatal (va_alist)
3726*58997Selan      va_dcl
3727*58997Selan {
3728*58997Selan   va_list ap;
3729*58997Selan   char *format;
3730*58997Selan 
3731*58997Selan   va_start (ap);
3732*58997Selan   format = va_arg (ap, char *);
3733*58997Selan   fprintf (stderr, "%s: ", programname);
3734*58997Selan   vfprintf (stderr, format, ap);
3735*58997Selan   va_end (ap);
3736*58997Selan   fprintf (stderr, "\n");
3737*58997Selan   delete_temp_files ();
3738*58997Selan   exit (1);
3739*58997Selan }
3740*58997Selan 
3741*58997Selan static void
3742*58997Selan error (va_alist)
3743*58997Selan      va_dcl
3744*58997Selan {
3745*58997Selan   va_list ap;
3746*58997Selan   char *format;
3747*58997Selan 
3748*58997Selan   va_start (ap);
3749*58997Selan   format = va_arg (ap, char *);
3750*58997Selan   fprintf (stderr, "%s: ", programname);
3751*58997Selan   vfprintf (stderr, format, ap);
3752*58997Selan   va_end (ap);
3753*58997Selan 
3754*58997Selan   fprintf (stderr, "\n");
3755*58997Selan }
3756*58997Selan 
3757*58997Selan #else /* not HAVE_VPRINTF */
3758*58997Selan 
3759*58997Selan static void
3760*58997Selan fatal (msg, arg1, arg2)
3761*58997Selan      char *msg, *arg1, *arg2;
3762*58997Selan {
3763*58997Selan   error (msg, arg1, arg2);
3764*58997Selan   delete_temp_files ();
3765*58997Selan   exit (1);
3766*58997Selan }
3767*58997Selan 
3768*58997Selan static void
3769*58997Selan error (msg, arg1, arg2)
3770*58997Selan      char *msg, *arg1, *arg2;
3771*58997Selan {
3772*58997Selan   fprintf (stderr, "%s: ", programname);
3773*58997Selan   fprintf (stderr, msg, arg1, arg2);
3774*58997Selan   fprintf (stderr, "\n");
3775*58997Selan }
3776*58997Selan 
3777*58997Selan #endif /* not HAVE_VPRINTF */
3778*58997Selan 
3779*58997Selan 
3780*58997Selan static void
3781*58997Selan validate_all_switches ()
3782*58997Selan {
3783*58997Selan   struct compiler *comp;
3784*58997Selan   register char *p;
3785*58997Selan   register char c;
3786*58997Selan   struct spec_list *spec;
3787*58997Selan 
3788*58997Selan   for (comp = compilers; comp->spec[0]; comp++)
3789*58997Selan     {
3790*58997Selan       int i;
3791*58997Selan       for (i = 0; i < sizeof comp->spec / sizeof comp->spec[0] && comp->spec[i]; i++)
3792*58997Selan 	{
3793*58997Selan 	  p = comp->spec[i];
3794*58997Selan 	  while (c = *p++)
3795*58997Selan 	    if (c == '%' && *p == '{')
3796*58997Selan 	      /* We have a switch spec.  */
3797*58997Selan 	      validate_switches (p + 1);
3798*58997Selan 	}
3799*58997Selan     }
3800*58997Selan 
3801*58997Selan   /* look through the linked list of extra specs read from the specs file */
3802*58997Selan   for (spec = specs; spec ; spec = spec->next)
3803*58997Selan     {
3804*58997Selan       p = spec->spec;
3805*58997Selan       while (c = *p++)
3806*58997Selan 	if (c == '%' && *p == '{')
3807*58997Selan 	  /* We have a switch spec.  */
3808*58997Selan 	  validate_switches (p + 1);
3809*58997Selan     }
3810*58997Selan 
3811*58997Selan   p = link_command_spec;
3812*58997Selan   while (c = *p++)
3813*58997Selan     if (c == '%' && *p == '{')
3814*58997Selan       /* We have a switch spec.  */
3815*58997Selan       validate_switches (p + 1);
3816*58997Selan 
3817*58997Selan   /* Now notice switches mentioned in the machine-specific specs.  */
3818*58997Selan 
3819*58997Selan   p = asm_spec;
3820*58997Selan   while (c = *p++)
3821*58997Selan     if (c == '%' && *p == '{')
3822*58997Selan       /* We have a switch spec.  */
3823*58997Selan       validate_switches (p + 1);
3824*58997Selan 
3825*58997Selan   p = asm_final_spec;
3826*58997Selan   while (c = *p++)
3827*58997Selan     if (c == '%' && *p == '{')
3828*58997Selan       /* We have a switch spec.  */
3829*58997Selan       validate_switches (p + 1);
3830*58997Selan 
3831*58997Selan   p = cpp_spec;
3832*58997Selan   while (c = *p++)
3833*58997Selan     if (c == '%' && *p == '{')
3834*58997Selan       /* We have a switch spec.  */
3835*58997Selan       validate_switches (p + 1);
3836*58997Selan 
3837*58997Selan   p = signed_char_spec;
3838*58997Selan   while (c = *p++)
3839*58997Selan     if (c == '%' && *p == '{')
3840*58997Selan       /* We have a switch spec.  */
3841*58997Selan       validate_switches (p + 1);
3842*58997Selan 
3843*58997Selan   p = cc1_spec;
3844*58997Selan   while (c = *p++)
3845*58997Selan     if (c == '%' && *p == '{')
3846*58997Selan       /* We have a switch spec.  */
3847*58997Selan       validate_switches (p + 1);
3848*58997Selan 
3849*58997Selan   p = cc1plus_spec;
3850*58997Selan   while (c = *p++)
3851*58997Selan     if (c == '%' && *p == '{')
3852*58997Selan       /* We have a switch spec.  */
3853*58997Selan       validate_switches (p + 1);
3854*58997Selan 
3855*58997Selan   p = link_spec;
3856*58997Selan   while (c = *p++)
3857*58997Selan     if (c == '%' && *p == '{')
3858*58997Selan       /* We have a switch spec.  */
3859*58997Selan       validate_switches (p + 1);
3860*58997Selan 
3861*58997Selan   p = lib_spec;
3862*58997Selan   while (c = *p++)
3863*58997Selan     if (c == '%' && *p == '{')
3864*58997Selan       /* We have a switch spec.  */
3865*58997Selan       validate_switches (p + 1);
3866*58997Selan 
3867*58997Selan   p = startfile_spec;
3868*58997Selan   while (c = *p++)
3869*58997Selan     if (c == '%' && *p == '{')
3870*58997Selan       /* We have a switch spec.  */
3871*58997Selan       validate_switches (p + 1);
3872*58997Selan }
3873*58997Selan 
3874*58997Selan /* Look at the switch-name that comes after START
3875*58997Selan    and mark as valid all supplied switches that match it.  */
3876*58997Selan 
3877*58997Selan static void
3878*58997Selan validate_switches (start)
3879*58997Selan      char *start;
3880*58997Selan {
3881*58997Selan   register char *p = start;
3882*58997Selan   char *filter;
3883*58997Selan   register int i;
3884*58997Selan   int suffix = 0;
3885*58997Selan 
3886*58997Selan   if (*p == '|')
3887*58997Selan     ++p;
3888*58997Selan 
3889*58997Selan   if (*p == '!')
3890*58997Selan     ++p;
3891*58997Selan 
3892*58997Selan   if (*p == '.')
3893*58997Selan     suffix = 1, ++p;
3894*58997Selan 
3895*58997Selan   filter = p;
3896*58997Selan   while (*p != ':' && *p != '}') p++;
3897*58997Selan 
3898*58997Selan   if (suffix)
3899*58997Selan     ;
3900*58997Selan   else if (p[-1] == '*')
3901*58997Selan     {
3902*58997Selan       /* Mark all matching switches as valid.  */
3903*58997Selan       --p;
3904*58997Selan       for (i = 0; i < n_switches; i++)
3905*58997Selan 	if (!strncmp (switches[i].part1, filter, p - filter))
3906*58997Selan 	  switches[i].valid = 1;
3907*58997Selan     }
3908*58997Selan   else
3909*58997Selan     {
3910*58997Selan       /* Mark an exact matching switch as valid.  */
3911*58997Selan       for (i = 0; i < n_switches; i++)
3912*58997Selan 	{
3913*58997Selan 	  if (!strncmp (switches[i].part1, filter, p - filter)
3914*58997Selan 	      && switches[i].part1[p - filter] == 0)
3915*58997Selan 	    switches[i].valid = 1;
3916*58997Selan 	}
3917*58997Selan     }
3918*58997Selan }
3919