xref: /dragonfly/contrib/gcc-4.7/gcc/gcc.c (revision 2bbc7733)
1e4b17023SJohn Marino /* Compiler driver program that can handle many languages.
2e4b17023SJohn Marino    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3e4b17023SJohn Marino    1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
4e4b17023SJohn Marino    2010, 2011, 2012
5e4b17023SJohn Marino    Free Software Foundation, Inc.
6e4b17023SJohn Marino 
7e4b17023SJohn Marino This file is part of GCC.
8e4b17023SJohn Marino 
9e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
10e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
11e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
12e4b17023SJohn Marino version.
13e4b17023SJohn Marino 
14e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
16e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17e4b17023SJohn Marino for more details.
18e4b17023SJohn Marino 
19e4b17023SJohn Marino You should have received a copy of the GNU General Public License
20e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
21e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
22e4b17023SJohn Marino 
23e4b17023SJohn Marino /* This program is the user interface to the C compiler and possibly to
24e4b17023SJohn Marino other compilers.  It is used because compilation is a complicated procedure
25e4b17023SJohn Marino which involves running several programs and passing temporary files between
26e4b17023SJohn Marino them, forwarding the users switches to those programs selectively,
27e4b17023SJohn Marino and deleting the temporary files at the end.
28e4b17023SJohn Marino 
29e4b17023SJohn Marino CC recognizes how to compile each input file by suffixes in the file names.
30e4b17023SJohn Marino Once it knows which kind of compilation to perform, the procedure for
31e4b17023SJohn Marino compilation is specified by a string called a "spec".  */
32e4b17023SJohn Marino 
33e4b17023SJohn Marino #include "config.h"
34e4b17023SJohn Marino #include "system.h"
35e4b17023SJohn Marino #include "coretypes.h"
36e4b17023SJohn Marino #include "multilib.h" /* before tm.h */
37e4b17023SJohn Marino #include "tm.h"
38e4b17023SJohn Marino #include "xregex.h"
39e4b17023SJohn Marino #include "obstack.h"
40e4b17023SJohn Marino #include "intl.h"
41e4b17023SJohn Marino #include "prefix.h"
42e4b17023SJohn Marino #include "gcc.h"
43e4b17023SJohn Marino #include "diagnostic.h"
44e4b17023SJohn Marino #include "flags.h"
45e4b17023SJohn Marino #include "opts.h"
46e4b17023SJohn Marino #include "params.h"
47e4b17023SJohn Marino #include "vec.h"
48e4b17023SJohn Marino #include "filenames.h"
49e4b17023SJohn Marino 
50e4b17023SJohn Marino /* By default there is no special suffix for target executables.  */
51e4b17023SJohn Marino /* FIXME: when autoconf is fixed, remove the host check - dj */
52e4b17023SJohn Marino #if defined(TARGET_EXECUTABLE_SUFFIX) && defined(HOST_EXECUTABLE_SUFFIX)
53e4b17023SJohn Marino #define HAVE_TARGET_EXECUTABLE_SUFFIX
54e4b17023SJohn Marino #endif
55e4b17023SJohn Marino 
56e4b17023SJohn Marino /* By default there is no special suffix for host executables.  */
57e4b17023SJohn Marino #ifdef HOST_EXECUTABLE_SUFFIX
58e4b17023SJohn Marino #define HAVE_HOST_EXECUTABLE_SUFFIX
59e4b17023SJohn Marino #else
60e4b17023SJohn Marino #define HOST_EXECUTABLE_SUFFIX ""
61e4b17023SJohn Marino #endif
62e4b17023SJohn Marino 
63e4b17023SJohn Marino /* By default, the suffix for target object files is ".o".  */
64e4b17023SJohn Marino #ifdef TARGET_OBJECT_SUFFIX
65e4b17023SJohn Marino #define HAVE_TARGET_OBJECT_SUFFIX
66e4b17023SJohn Marino #else
67e4b17023SJohn Marino #define TARGET_OBJECT_SUFFIX ".o"
68e4b17023SJohn Marino #endif
69e4b17023SJohn Marino 
70e4b17023SJohn Marino static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
71e4b17023SJohn Marino 
72e4b17023SJohn Marino /* Most every one is fine with LIBRARY_PATH.  For some, it conflicts.  */
73e4b17023SJohn Marino #ifndef LIBRARY_PATH_ENV
74e4b17023SJohn Marino #define LIBRARY_PATH_ENV "LIBRARY_PATH"
75e4b17023SJohn Marino #endif
76e4b17023SJohn Marino 
77e4b17023SJohn Marino /* If a stage of compilation returns an exit status >= 1,
78e4b17023SJohn Marino    compilation of that file ceases.  */
79e4b17023SJohn Marino 
80e4b17023SJohn Marino #define MIN_FATAL_STATUS 1
81e4b17023SJohn Marino 
82e4b17023SJohn Marino /* Flag set by cppspec.c to 1.  */
83e4b17023SJohn Marino int is_cpp_driver;
84e4b17023SJohn Marino 
85e4b17023SJohn Marino /* Flag set to nonzero if an @file argument has been supplied to gcc.  */
86e4b17023SJohn Marino static bool at_file_supplied;
87e4b17023SJohn Marino 
88e4b17023SJohn Marino /* Definition of string containing the arguments given to configure.  */
89e4b17023SJohn Marino #include "configargs.h"
90e4b17023SJohn Marino 
91e4b17023SJohn Marino /* Flag saying to print the command line options understood by gcc and its
92e4b17023SJohn Marino    sub-processes.  */
93e4b17023SJohn Marino 
94e4b17023SJohn Marino static int print_help_list;
95e4b17023SJohn Marino 
96e4b17023SJohn Marino /* Flag saying to print the version of gcc and its sub-processes.  */
97e4b17023SJohn Marino 
98e4b17023SJohn Marino static int print_version;
99e4b17023SJohn Marino 
100e4b17023SJohn Marino /* Flag indicating whether we should ONLY print the command and
101e4b17023SJohn Marino    arguments (like verbose_flag) without executing the command.
102e4b17023SJohn Marino    Displayed arguments are quoted so that the generated command
103e4b17023SJohn Marino    line is suitable for execution.  This is intended for use in
104e4b17023SJohn Marino    shell scripts to capture the driver-generated command line.  */
105e4b17023SJohn Marino static int verbose_only_flag;
106e4b17023SJohn Marino 
107e4b17023SJohn Marino /* Flag indicating how to print command line options of sub-processes.  */
108e4b17023SJohn Marino 
109e4b17023SJohn Marino static int print_subprocess_help;
110e4b17023SJohn Marino 
111e4b17023SJohn Marino /* Whether we should report subprocess execution times to a file.  */
112e4b17023SJohn Marino 
113e4b17023SJohn Marino FILE *report_times_to_file = NULL;
114e4b17023SJohn Marino 
115e4b17023SJohn Marino /* Nonzero means place this string before uses of /, so that include
116e4b17023SJohn Marino    and library files can be found in an alternate location.  */
117e4b17023SJohn Marino 
118e4b17023SJohn Marino #ifdef TARGET_SYSTEM_ROOT
119e4b17023SJohn Marino static const char *target_system_root = TARGET_SYSTEM_ROOT;
120e4b17023SJohn Marino #else
121e4b17023SJohn Marino static const char *target_system_root = 0;
122e4b17023SJohn Marino #endif
123e4b17023SJohn Marino 
124e4b17023SJohn Marino /* Nonzero means pass the updated target_system_root to the compiler.  */
125e4b17023SJohn Marino 
126e4b17023SJohn Marino static int target_system_root_changed;
127e4b17023SJohn Marino 
128e4b17023SJohn Marino /* Nonzero means append this string to target_system_root.  */
129e4b17023SJohn Marino 
130e4b17023SJohn Marino static const char *target_sysroot_suffix = 0;
131e4b17023SJohn Marino 
132e4b17023SJohn Marino /* Nonzero means append this string to target_system_root for headers.  */
133e4b17023SJohn Marino 
134e4b17023SJohn Marino static const char *target_sysroot_hdrs_suffix = 0;
135e4b17023SJohn Marino 
136e4b17023SJohn Marino /* Nonzero means write "temp" files in source directory
137e4b17023SJohn Marino    and use the source file's name in them, and don't delete them.  */
138e4b17023SJohn Marino 
139e4b17023SJohn Marino static enum save_temps {
140e4b17023SJohn Marino   SAVE_TEMPS_NONE,		/* no -save-temps */
141e4b17023SJohn Marino   SAVE_TEMPS_CWD,		/* -save-temps in current directory */
142*2bbc7733Szrj   SAVE_TEMPS_OBJ,		/* -save-temps in object directory */
143*2bbc7733Szrj   SAVE_TEMPS_OBJZ		/* -save-temps in object directory with mangling */
144e4b17023SJohn Marino } save_temps_flag;
145e4b17023SJohn Marino 
146e4b17023SJohn Marino /* Output file to use to get the object directory for -save-temps=obj  */
147e4b17023SJohn Marino static char *save_temps_prefix = 0;
148e4b17023SJohn Marino static size_t save_temps_length = 0;
149e4b17023SJohn Marino 
150e4b17023SJohn Marino /* The compiler version.  */
151e4b17023SJohn Marino 
152e4b17023SJohn Marino static const char *compiler_version;
153e4b17023SJohn Marino 
154e4b17023SJohn Marino /* The target version.  */
155e4b17023SJohn Marino 
156e4b17023SJohn Marino static const char *const spec_version = DEFAULT_TARGET_VERSION;
157e4b17023SJohn Marino 
158e4b17023SJohn Marino /* The target machine.  */
159e4b17023SJohn Marino 
160e4b17023SJohn Marino static const char *spec_machine = DEFAULT_TARGET_MACHINE;
161e4b17023SJohn Marino 
162e4b17023SJohn Marino /* Nonzero if cross-compiling.
163e4b17023SJohn Marino    When -b is used, the value comes from the `specs' file.  */
164e4b17023SJohn Marino 
165e4b17023SJohn Marino #ifdef CROSS_DIRECTORY_STRUCTURE
166e4b17023SJohn Marino static const char *cross_compile = "1";
167e4b17023SJohn Marino #else
168e4b17023SJohn Marino static const char *cross_compile = "0";
169e4b17023SJohn Marino #endif
170e4b17023SJohn Marino 
171e4b17023SJohn Marino /* Greatest exit code of sub-processes that has been encountered up to
172e4b17023SJohn Marino    now.  */
173e4b17023SJohn Marino static int greatest_status = 1;
174e4b17023SJohn Marino 
175e4b17023SJohn Marino /* This is the obstack which we use to allocate many strings.  */
176e4b17023SJohn Marino 
177e4b17023SJohn Marino static struct obstack obstack;
178e4b17023SJohn Marino 
179e4b17023SJohn Marino /* This is the obstack to build an environment variable to pass to
180e4b17023SJohn Marino    collect2 that describes all of the relevant switches of what to
181e4b17023SJohn Marino    pass the compiler in building the list of pointers to constructors
182e4b17023SJohn Marino    and destructors.  */
183e4b17023SJohn Marino 
184e4b17023SJohn Marino static struct obstack collect_obstack;
185e4b17023SJohn Marino 
186e4b17023SJohn Marino /* Forward declaration for prototypes.  */
187e4b17023SJohn Marino struct path_prefix;
188e4b17023SJohn Marino struct prefix_list;
189e4b17023SJohn Marino 
190e4b17023SJohn Marino static void init_spec (void);
191e4b17023SJohn Marino static void store_arg (const char *, int, int);
192e4b17023SJohn Marino static void insert_wrapper (const char *);
193e4b17023SJohn Marino static char *load_specs (const char *);
194e4b17023SJohn Marino static void read_specs (const char *, int);
195e4b17023SJohn Marino static void set_spec (const char *, const char *);
196e4b17023SJohn Marino static struct compiler *lookup_compiler (const char *, size_t, const char *);
197e4b17023SJohn Marino static char *build_search_list (const struct path_prefix *, const char *,
198e4b17023SJohn Marino 				bool, bool);
199e4b17023SJohn Marino static void xputenv (const char *);
200e4b17023SJohn Marino static void putenv_from_prefixes (const struct path_prefix *, const char *,
201e4b17023SJohn Marino 				  bool);
202e4b17023SJohn Marino static int access_check (const char *, int);
203e4b17023SJohn Marino static char *find_a_file (const struct path_prefix *, const char *, int, bool);
204e4b17023SJohn Marino static void add_prefix (struct path_prefix *, const char *, const char *,
205e4b17023SJohn Marino 			int, int, int);
206e4b17023SJohn Marino static void add_sysrooted_prefix (struct path_prefix *, const char *,
207e4b17023SJohn Marino 				  const char *, int, int, int);
208e4b17023SJohn Marino static char *skip_whitespace (char *);
209e4b17023SJohn Marino static void delete_if_ordinary (const char *);
210e4b17023SJohn Marino static void delete_temp_files (void);
211e4b17023SJohn Marino static void delete_failure_queue (void);
212e4b17023SJohn Marino static void clear_failure_queue (void);
213e4b17023SJohn Marino static int check_live_switch (int, int);
214e4b17023SJohn Marino static const char *handle_braces (const char *);
215e4b17023SJohn Marino static inline bool input_suffix_matches (const char *, const char *);
216e4b17023SJohn Marino static inline bool switch_matches (const char *, const char *, int);
217e4b17023SJohn Marino static inline void mark_matching_switches (const char *, const char *, int);
218e4b17023SJohn Marino static inline void process_marked_switches (void);
219e4b17023SJohn Marino static const char *process_brace_body (const char *, const char *, const char *, int, int);
220e4b17023SJohn Marino static const struct spec_function *lookup_spec_function (const char *);
221e4b17023SJohn Marino static const char *eval_spec_function (const char *, const char *);
222e4b17023SJohn Marino static const char *handle_spec_function (const char *);
223e4b17023SJohn Marino static char *save_string (const char *, int);
224e4b17023SJohn Marino static void set_collect_gcc_options (void);
225e4b17023SJohn Marino static int do_spec_1 (const char *, int, const char *);
226e4b17023SJohn Marino static int do_spec_2 (const char *);
227e4b17023SJohn Marino static void do_option_spec (const char *, const char *);
228e4b17023SJohn Marino static void do_self_spec (const char *);
229e4b17023SJohn Marino static const char *find_file (const char *);
230e4b17023SJohn Marino static int is_directory (const char *, bool);
231e4b17023SJohn Marino static const char *validate_switches (const char *);
232e4b17023SJohn Marino static void validate_all_switches (void);
233e4b17023SJohn Marino static inline void validate_switches_from_spec (const char *);
234e4b17023SJohn Marino static void give_switch (int, int);
235e4b17023SJohn Marino static int used_arg (const char *, int);
236e4b17023SJohn Marino static int default_arg (const char *, int);
237e4b17023SJohn Marino static void set_multilib_dir (void);
238e4b17023SJohn Marino static void print_multilib_info (void);
239e4b17023SJohn Marino static void perror_with_name (const char *);
240e4b17023SJohn Marino static void display_help (void);
241e4b17023SJohn Marino static void add_preprocessor_option (const char *, int);
242e4b17023SJohn Marino static void add_assembler_option (const char *, int);
243e4b17023SJohn Marino static void add_linker_option (const char *, int);
244e4b17023SJohn Marino static void process_command (unsigned int, struct cl_decoded_option *);
245e4b17023SJohn Marino static int execute (void);
246e4b17023SJohn Marino static void alloc_args (void);
247e4b17023SJohn Marino static void clear_args (void);
248e4b17023SJohn Marino static void fatal_signal (int);
249e4b17023SJohn Marino #if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC)
250e4b17023SJohn Marino static void init_gcc_specs (struct obstack *, const char *, const char *,
251e4b17023SJohn Marino 			    const char *);
252e4b17023SJohn Marino #endif
253e4b17023SJohn Marino #if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
254e4b17023SJohn Marino static const char *convert_filename (const char *, int, int);
255e4b17023SJohn Marino #endif
256e4b17023SJohn Marino 
257e4b17023SJohn Marino static const char *getenv_spec_function (int, const char **);
258e4b17023SJohn Marino static const char *if_exists_spec_function (int, const char **);
259e4b17023SJohn Marino static const char *if_exists_else_spec_function (int, const char **);
260e4b17023SJohn Marino static const char *replace_outfile_spec_function (int, const char **);
261e4b17023SJohn Marino static const char *remove_outfile_spec_function (int, const char **);
262e4b17023SJohn Marino static const char *version_compare_spec_function (int, const char **);
263e4b17023SJohn Marino static const char *include_spec_function (int, const char **);
264e4b17023SJohn Marino static const char *find_file_spec_function (int, const char **);
265e4b17023SJohn Marino static const char *find_plugindir_spec_function (int, const char **);
266e4b17023SJohn Marino static const char *print_asm_header_spec_function (int, const char **);
267e4b17023SJohn Marino static const char *compare_debug_dump_opt_spec_function (int, const char **);
268e4b17023SJohn Marino static const char *compare_debug_self_opt_spec_function (int, const char **);
269e4b17023SJohn Marino static const char *compare_debug_auxbase_opt_spec_function (int, const char **);
270e4b17023SJohn Marino static const char *pass_through_libs_spec_func (int, const char **);
2715ce9237cSJohn Marino static char *convert_white_space (char *);
272e4b17023SJohn Marino 
273e4b17023SJohn Marino /* The Specs Language
274e4b17023SJohn Marino 
275e4b17023SJohn Marino Specs are strings containing lines, each of which (if not blank)
276e4b17023SJohn Marino is made up of a program name, and arguments separated by spaces.
277e4b17023SJohn Marino The program name must be exact and start from root, since no path
278e4b17023SJohn Marino is searched and it is unreliable to depend on the current working directory.
279e4b17023SJohn Marino Redirection of input or output is not supported; the subprograms must
280e4b17023SJohn Marino accept filenames saying what files to read and write.
281e4b17023SJohn Marino 
282e4b17023SJohn Marino In addition, the specs can contain %-sequences to substitute variable text
283e4b17023SJohn Marino or for conditional text.  Here is a table of all defined %-sequences.
284e4b17023SJohn Marino Note that spaces are not generated automatically around the results of
285e4b17023SJohn Marino expanding these sequences; therefore, you can concatenate them together
286e4b17023SJohn Marino or with constant text in a single argument.
287e4b17023SJohn Marino 
288e4b17023SJohn Marino  %%	substitute one % into the program name or argument.
289e4b17023SJohn Marino  %i     substitute the name of the input file being processed.
290e4b17023SJohn Marino  %b     substitute the basename of the input file being processed.
291e4b17023SJohn Marino 	This is the substring up to (and not including) the last period
292e4b17023SJohn Marino 	and not including the directory unless -save-temps was specified
293e4b17023SJohn Marino 	to put temporaries in a different location.
294e4b17023SJohn Marino  %B	same as %b, but include the file suffix (text after the last period).
295e4b17023SJohn Marino  %gSUFFIX
296e4b17023SJohn Marino 	substitute a file name that has suffix SUFFIX and is chosen
297e4b17023SJohn Marino 	once per compilation, and mark the argument a la %d.  To reduce
298e4b17023SJohn Marino 	exposure to denial-of-service attacks, the file name is now
299e4b17023SJohn Marino 	chosen in a way that is hard to predict even when previously
300e4b17023SJohn Marino 	chosen file names are known.  For example, `%g.s ... %g.o ... %g.s'
301e4b17023SJohn Marino 	might turn into `ccUVUUAU.s ccXYAXZ12.o ccUVUUAU.s'.  SUFFIX matches
302e4b17023SJohn Marino 	the regexp "[.0-9A-Za-z]*%O"; "%O" is treated exactly as if it
303e4b17023SJohn Marino 	had been pre-processed.  Previously, %g was simply substituted
304e4b17023SJohn Marino 	with a file name chosen once per compilation, without regard
305e4b17023SJohn Marino 	to any appended suffix (which was therefore treated just like
306e4b17023SJohn Marino 	ordinary text), making such attacks more likely to succeed.
307e4b17023SJohn Marino  %|SUFFIX
308e4b17023SJohn Marino 	like %g, but if -pipe is in effect, expands simply to "-".
309e4b17023SJohn Marino  %mSUFFIX
310e4b17023SJohn Marino         like %g, but if -pipe is in effect, expands to nothing.  (We have both
311e4b17023SJohn Marino 	%| and %m to accommodate differences between system assemblers; see
312e4b17023SJohn Marino 	the AS_NEEDS_DASH_FOR_PIPED_INPUT target macro.)
313e4b17023SJohn Marino  %uSUFFIX
314e4b17023SJohn Marino 	like %g, but generates a new temporary file name even if %uSUFFIX
315e4b17023SJohn Marino 	was already seen.
316e4b17023SJohn Marino  %USUFFIX
317e4b17023SJohn Marino 	substitutes the last file name generated with %uSUFFIX, generating a
318e4b17023SJohn Marino 	new one if there is no such last file name.  In the absence of any
319e4b17023SJohn Marino 	%uSUFFIX, this is just like %gSUFFIX, except they don't share
320e4b17023SJohn Marino 	the same suffix "space", so `%g.s ... %U.s ... %g.s ... %U.s'
321e4b17023SJohn Marino 	would involve the generation of two distinct file names, one
322e4b17023SJohn Marino 	for each `%g.s' and another for each `%U.s'.  Previously, %U was
323e4b17023SJohn Marino 	simply substituted with a file name chosen for the previous %u,
324e4b17023SJohn Marino 	without regard to any appended suffix.
325e4b17023SJohn Marino  %jSUFFIX
326e4b17023SJohn Marino         substitutes the name of the HOST_BIT_BUCKET, if any, and if it is
327e4b17023SJohn Marino         writable, and if save-temps is off; otherwise, substitute the name
328e4b17023SJohn Marino         of a temporary file, just like %u.  This temporary file is not
329e4b17023SJohn Marino         meant for communication between processes, but rather as a junk
330e4b17023SJohn Marino         disposal mechanism.
331e4b17023SJohn Marino  %.SUFFIX
332e4b17023SJohn Marino         substitutes .SUFFIX for the suffixes of a matched switch's args when
333e4b17023SJohn Marino         it is subsequently output with %*. SUFFIX is terminated by the next
334e4b17023SJohn Marino         space or %.
335e4b17023SJohn Marino  %d	marks the argument containing or following the %d as a
336e4b17023SJohn Marino 	temporary file name, so that that file will be deleted if GCC exits
337e4b17023SJohn Marino 	successfully.  Unlike %g, this contributes no text to the argument.
338e4b17023SJohn Marino  %w	marks the argument containing or following the %w as the
339e4b17023SJohn Marino 	"output file" of this compilation.  This puts the argument
340e4b17023SJohn Marino 	into the sequence of arguments that %o will substitute later.
341e4b17023SJohn Marino  %V	indicates that this compilation produces no "output file".
342e4b17023SJohn Marino  %W{...}
343e4b17023SJohn Marino 	like %{...} but mark last argument supplied within
344e4b17023SJohn Marino 	as a file to be deleted on failure.
345e4b17023SJohn Marino  %o	substitutes the names of all the output files, with spaces
346e4b17023SJohn Marino 	automatically placed around them.  You should write spaces
347e4b17023SJohn Marino 	around the %o as well or the results are undefined.
348e4b17023SJohn Marino 	%o is for use in the specs for running the linker.
349e4b17023SJohn Marino 	Input files whose names have no recognized suffix are not compiled
350e4b17023SJohn Marino 	at all, but they are included among the output files, so they will
351e4b17023SJohn Marino 	be linked.
352e4b17023SJohn Marino  %O	substitutes the suffix for object files.  Note that this is
353e4b17023SJohn Marino         handled specially when it immediately follows %g, %u, or %U
354e4b17023SJohn Marino 	(with or without a suffix argument) because of the need for
355e4b17023SJohn Marino 	those to form complete file names.  The handling is such that
356e4b17023SJohn Marino 	%O is treated exactly as if it had already been substituted,
357e4b17023SJohn Marino 	except that %g, %u, and %U do not currently support additional
358e4b17023SJohn Marino 	SUFFIX characters following %O as they would following, for
359e4b17023SJohn Marino 	example, `.o'.
360e4b17023SJohn Marino  %I	Substitute any of -iprefix (made from GCC_EXEC_PREFIX), -isysroot
361e4b17023SJohn Marino 	(made from TARGET_SYSTEM_ROOT), -isystem (made from COMPILER_PATH
362e4b17023SJohn Marino 	and -B options) and -imultilib as necessary.
363e4b17023SJohn Marino  %s     current argument is the name of a library or startup file of some sort.
364e4b17023SJohn Marino         Search for that file in a standard list of directories
365e4b17023SJohn Marino 	and substitute the full name found.
366e4b17023SJohn Marino  %eSTR  Print STR as an error message.  STR is terminated by a newline.
367e4b17023SJohn Marino         Use this when inconsistent options are detected.
368e4b17023SJohn Marino  %nSTR  Print STR as a notice.  STR is terminated by a newline.
369e4b17023SJohn Marino  %x{OPTION}	Accumulate an option for %X.
370e4b17023SJohn Marino  %X	Output the accumulated linker options specified by compilations.
371e4b17023SJohn Marino  %Y	Output the accumulated assembler options specified by compilations.
372e4b17023SJohn Marino  %Z	Output the accumulated preprocessor options specified by compilations.
373e4b17023SJohn Marino  %a     process ASM_SPEC as a spec.
374e4b17023SJohn Marino         This allows config.h to specify part of the spec for running as.
375e4b17023SJohn Marino  %A	process ASM_FINAL_SPEC as a spec.  A capital A is actually
376e4b17023SJohn Marino 	used here.  This can be used to run a post-processor after the
377e4b17023SJohn Marino 	assembler has done its job.
378e4b17023SJohn Marino  %D	Dump out a -L option for each directory in startfile_prefixes.
379e4b17023SJohn Marino 	If multilib_dir is set, extra entries are generated with it affixed.
380e4b17023SJohn Marino  %l     process LINK_SPEC as a spec.
381e4b17023SJohn Marino  %L     process LIB_SPEC as a spec.
382e4b17023SJohn Marino  %G     process LIBGCC_SPEC as a spec.
383e4b17023SJohn Marino  %R     Output the concatenation of target_system_root and
384e4b17023SJohn Marino         target_sysroot_suffix.
385e4b17023SJohn Marino  %S     process STARTFILE_SPEC as a spec.  A capital S is actually used here.
386e4b17023SJohn Marino  %E     process ENDFILE_SPEC as a spec.  A capital E is actually used here.
387e4b17023SJohn Marino  %C     process CPP_SPEC as a spec.
388e4b17023SJohn Marino  %1	process CC1_SPEC as a spec.
389e4b17023SJohn Marino  %2	process CC1PLUS_SPEC as a spec.
390e4b17023SJohn Marino  %*	substitute the variable part of a matched option.  (See below.)
391e4b17023SJohn Marino 	Note that each comma in the substituted string is replaced by
392e4b17023SJohn Marino 	a single space.
393e4b17023SJohn Marino  %<S    remove all occurrences of -S from the command line.
394e4b17023SJohn Marino         Note - this command is position dependent.  % commands in the
395e4b17023SJohn Marino         spec string before this one will see -S, % commands in the
396e4b17023SJohn Marino         spec string after this one will not.
397e4b17023SJohn Marino  %>S	Similar to "%<S", but keep it in the GCC command line.
398e4b17023SJohn Marino  %<S*	remove all occurrences of all switches beginning with -S from the
399e4b17023SJohn Marino         command line.
400e4b17023SJohn Marino  %:function(args)
401e4b17023SJohn Marino 	Call the named function FUNCTION, passing it ARGS.  ARGS is
402e4b17023SJohn Marino 	first processed as a nested spec string, then split into an
403e4b17023SJohn Marino 	argument vector in the usual fashion.  The function returns
404e4b17023SJohn Marino 	a string which is processed as if it had appeared literally
405e4b17023SJohn Marino 	as part of the current spec.
406e4b17023SJohn Marino  %{S}   substitutes the -S switch, if that switch was given to GCC.
407e4b17023SJohn Marino 	If that switch was not specified, this substitutes nothing.
408e4b17023SJohn Marino 	Here S is a metasyntactic variable.
409e4b17023SJohn Marino  %{S*}  substitutes all the switches specified to GCC whose names start
410e4b17023SJohn Marino 	with -S.  This is used for -o, -I, etc; switches that take
411e4b17023SJohn Marino 	arguments.  GCC considers `-o foo' as being one switch whose
412e4b17023SJohn Marino 	name starts with `o'.  %{o*} would substitute this text,
413e4b17023SJohn Marino 	including the space; thus, two arguments would be generated.
414e4b17023SJohn Marino  %{S*&T*} likewise, but preserve order of S and T options (the order
415e4b17023SJohn Marino 	of S and T in the spec is not significant).  Can be any number
416e4b17023SJohn Marino 	of ampersand-separated variables; for each the wild card is
417e4b17023SJohn Marino 	optional.  Useful for CPP as %{D*&U*&A*}.
418e4b17023SJohn Marino 
419e4b17023SJohn Marino  %{S:X}   substitutes X, if the -S switch was given to GCC.
420e4b17023SJohn Marino  %{!S:X}  substitutes X, if the -S switch was NOT given to GCC.
421e4b17023SJohn Marino  %{S*:X}  substitutes X if one or more switches whose names start
422e4b17023SJohn Marino           with -S was given to GCC.  Normally X is substituted only
423e4b17023SJohn Marino           once, no matter how many such switches appeared.  However,
424e4b17023SJohn Marino           if %* appears somewhere in X, then X will be substituted
425e4b17023SJohn Marino           once for each matching switch, with the %* replaced by the
426e4b17023SJohn Marino           part of that switch that matched the '*'.
427e4b17023SJohn Marino  %{.S:X}  substitutes X, if processing a file with suffix S.
428e4b17023SJohn Marino  %{!.S:X} substitutes X, if NOT processing a file with suffix S.
429e4b17023SJohn Marino  %{,S:X}  substitutes X, if processing a file which will use spec S.
430e4b17023SJohn Marino  %{!,S:X} substitutes X, if NOT processing a file which will use spec S.
431e4b17023SJohn Marino 
432e4b17023SJohn Marino  %{S|T:X} substitutes X if either -S or -T was given to GCC.  This may be
433e4b17023SJohn Marino 	  combined with '!', '.', ',', and '*' as above binding stronger
434e4b17023SJohn Marino 	  than the OR.
435e4b17023SJohn Marino 	  If %* appears in X, all of the alternatives must be starred, and
436e4b17023SJohn Marino 	  only the first matching alternative is substituted.
437e4b17023SJohn Marino  %{S:X;   if S was given to GCC, substitutes X;
438e4b17023SJohn Marino    T:Y;   else if T was given to GCC, substitutes Y;
439e4b17023SJohn Marino     :D}   else substitutes D.  There can be as many clauses as you need.
440e4b17023SJohn Marino           This may be combined with '.', '!', ',', '|', and '*' as above.
441e4b17023SJohn Marino 
442e4b17023SJohn Marino  %(Spec) processes a specification defined in a specs file as *Spec:
443e4b17023SJohn Marino 
444e4b17023SJohn Marino The conditional text X in a %{S:X} or similar construct may contain
445e4b17023SJohn Marino other nested % constructs or spaces, or even newlines.  They are
446e4b17023SJohn Marino processed as usual, as described above.  Trailing white space in X is
447e4b17023SJohn Marino ignored.  White space may also appear anywhere on the left side of the
448e4b17023SJohn Marino colon in these constructs, except between . or * and the corresponding
449e4b17023SJohn Marino word.
450e4b17023SJohn Marino 
451e4b17023SJohn Marino The -O, -f, -m, and -W switches are handled specifically in these
452e4b17023SJohn Marino constructs.  If another value of -O or the negated form of a -f, -m, or
453e4b17023SJohn Marino -W switch is found later in the command line, the earlier switch
454e4b17023SJohn Marino value is ignored, except with {S*} where S is just one letter; this
455e4b17023SJohn Marino passes all matching options.
456e4b17023SJohn Marino 
457e4b17023SJohn Marino The character | at the beginning of the predicate text is used to indicate
458e4b17023SJohn Marino that a command should be piped to the following command, but only if -pipe
459e4b17023SJohn Marino is specified.
460e4b17023SJohn Marino 
461e4b17023SJohn Marino Note that it is built into GCC which switches take arguments and which
462e4b17023SJohn Marino do not.  You might think it would be useful to generalize this to
463e4b17023SJohn Marino allow each compiler's spec to say which switches take arguments.  But
464e4b17023SJohn Marino this cannot be done in a consistent fashion.  GCC cannot even decide
465e4b17023SJohn Marino which input files have been specified without knowing which switches
466e4b17023SJohn Marino take arguments, and it must know which input files to compile in order
467e4b17023SJohn Marino to tell which compilers to run.
468e4b17023SJohn Marino 
469e4b17023SJohn Marino GCC also knows implicitly that arguments starting in `-l' are to be
470e4b17023SJohn Marino treated as compiler output files, and passed to the linker in their
471e4b17023SJohn Marino proper position among the other output files.  */
472e4b17023SJohn Marino 
473e4b17023SJohn Marino /* Define the macros used for specs %a, %l, %L, %S, %C, %1.  */
474e4b17023SJohn Marino 
475e4b17023SJohn Marino /* config.h can define ASM_SPEC to provide extra args to the assembler
476e4b17023SJohn Marino    or extra switch-translations.  */
477e4b17023SJohn Marino #ifndef ASM_SPEC
478e4b17023SJohn Marino #define ASM_SPEC ""
479e4b17023SJohn Marino #endif
480e4b17023SJohn Marino 
481e4b17023SJohn Marino /* config.h can define ASM_FINAL_SPEC to run a post processor after
482e4b17023SJohn Marino    the assembler has run.  */
483e4b17023SJohn Marino #ifndef ASM_FINAL_SPEC
484e4b17023SJohn Marino #define ASM_FINAL_SPEC ""
485e4b17023SJohn Marino #endif
486e4b17023SJohn Marino 
487e4b17023SJohn Marino /* config.h can define CPP_SPEC to provide extra args to the C preprocessor
488e4b17023SJohn Marino    or extra switch-translations.  */
489e4b17023SJohn Marino #ifndef CPP_SPEC
490e4b17023SJohn Marino #define CPP_SPEC ""
491e4b17023SJohn Marino #endif
492e4b17023SJohn Marino 
493e4b17023SJohn Marino /* config.h can define CC1_SPEC to provide extra args to cc1 and cc1plus
494e4b17023SJohn Marino    or extra switch-translations.  */
495e4b17023SJohn Marino #ifndef CC1_SPEC
496e4b17023SJohn Marino #define CC1_SPEC ""
497e4b17023SJohn Marino #endif
498e4b17023SJohn Marino 
499e4b17023SJohn Marino /* config.h can define CC1PLUS_SPEC to provide extra args to cc1plus
500e4b17023SJohn Marino    or extra switch-translations.  */
501e4b17023SJohn Marino #ifndef CC1PLUS_SPEC
502e4b17023SJohn Marino #define CC1PLUS_SPEC ""
503e4b17023SJohn Marino #endif
504e4b17023SJohn Marino 
505e4b17023SJohn Marino /* config.h can define LINK_SPEC to provide extra args to the linker
506e4b17023SJohn Marino    or extra switch-translations.  */
507e4b17023SJohn Marino #ifndef LINK_SPEC
508e4b17023SJohn Marino #define LINK_SPEC ""
509e4b17023SJohn Marino #endif
510e4b17023SJohn Marino 
511e4b17023SJohn Marino /* config.h can define LIB_SPEC to override the default libraries.  */
512e4b17023SJohn Marino #ifndef LIB_SPEC
513e4b17023SJohn Marino #define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
514e4b17023SJohn Marino #endif
515e4b17023SJohn Marino 
516e4b17023SJohn Marino /* mudflap specs */
517e4b17023SJohn Marino #ifndef MFWRAP_SPEC
518e4b17023SJohn Marino /* XXX: valid only for GNU ld */
519e4b17023SJohn Marino /* XXX: should exactly match hooks provided by libmudflap.a */
520e4b17023SJohn Marino #define MFWRAP_SPEC " %{static: %{fmudflap|fmudflapth: \
521e4b17023SJohn Marino  --wrap=malloc --wrap=free --wrap=calloc --wrap=realloc\
522e4b17023SJohn Marino  --wrap=mmap --wrap=mmap64 --wrap=munmap --wrap=alloca\
523e4b17023SJohn Marino } %{fmudflapth: --wrap=pthread_create\
524e4b17023SJohn Marino }} %{fmudflap|fmudflapth: --wrap=main}"
525e4b17023SJohn Marino #endif
526e4b17023SJohn Marino #ifndef MFLIB_SPEC
527e4b17023SJohn Marino #define MFLIB_SPEC "%{fmudflap|fmudflapth: -export-dynamic}"
528e4b17023SJohn Marino #endif
529e4b17023SJohn Marino 
530e4b17023SJohn Marino /* When using -fsplit-stack we need to wrap pthread_create, in order
531e4b17023SJohn Marino    to initialize the stack guard.  We always use wrapping, rather than
532e4b17023SJohn Marino    shared library ordering, and we keep the wrapper function in
533e4b17023SJohn Marino    libgcc.  This is not yet a real spec, though it could become one;
534e4b17023SJohn Marino    it is currently just stuffed into LINK_SPEC.  FIXME: This wrapping
535e4b17023SJohn Marino    only works with GNU ld and gold.  FIXME: This is incompatible with
536e4b17023SJohn Marino    -fmudflap when linking statically, which wants to do its own
537e4b17023SJohn Marino    wrapping.  */
538e4b17023SJohn Marino #define STACK_SPLIT_SPEC " %{fsplit-stack: --wrap=pthread_create}"
539e4b17023SJohn Marino 
540e4b17023SJohn Marino /* config.h can define LIBGCC_SPEC to override how and when libgcc.a is
541e4b17023SJohn Marino    included.  */
542e4b17023SJohn Marino #ifndef LIBGCC_SPEC
543e4b17023SJohn Marino #if defined(REAL_LIBGCC_SPEC)
544e4b17023SJohn Marino #define LIBGCC_SPEC REAL_LIBGCC_SPEC
545e4b17023SJohn Marino #elif defined(LINK_LIBGCC_SPECIAL_1)
546e4b17023SJohn Marino /* Have gcc do the search for libgcc.a.  */
547e4b17023SJohn Marino #define LIBGCC_SPEC "libgcc.a%s"
548e4b17023SJohn Marino #else
549e4b17023SJohn Marino #define LIBGCC_SPEC "-lgcc"
550e4b17023SJohn Marino #endif
551e4b17023SJohn Marino #endif
552e4b17023SJohn Marino 
553e4b17023SJohn Marino /* config.h can define STARTFILE_SPEC to override the default crt0 files.  */
554e4b17023SJohn Marino #ifndef STARTFILE_SPEC
555e4b17023SJohn Marino #define STARTFILE_SPEC  \
556e4b17023SJohn Marino   "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}"
557e4b17023SJohn Marino #endif
558e4b17023SJohn Marino 
559e4b17023SJohn Marino /* config.h can define ENDFILE_SPEC to override the default crtn files.  */
560e4b17023SJohn Marino #ifndef ENDFILE_SPEC
561e4b17023SJohn Marino #define ENDFILE_SPEC ""
562e4b17023SJohn Marino #endif
563e4b17023SJohn Marino 
564e4b17023SJohn Marino #ifndef LINKER_NAME
565e4b17023SJohn Marino #define LINKER_NAME "collect2"
566e4b17023SJohn Marino #endif
567e4b17023SJohn Marino 
568e4b17023SJohn Marino #ifdef HAVE_AS_DEBUG_PREFIX_MAP
569e4b17023SJohn Marino #define ASM_MAP " %{fdebug-prefix-map=*:--debug-prefix-map %*}"
570e4b17023SJohn Marino #else
571e4b17023SJohn Marino #define ASM_MAP ""
572e4b17023SJohn Marino #endif
573e4b17023SJohn Marino 
574e4b17023SJohn Marino /* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g'
575e4b17023SJohn Marino    to the assembler.  */
576e4b17023SJohn Marino #ifndef ASM_DEBUG_SPEC
577e4b17023SJohn Marino # if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \
578e4b17023SJohn Marino      && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
579e4b17023SJohn Marino #  define ASM_DEBUG_SPEC						\
580e4b17023SJohn Marino       (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG				\
581e4b17023SJohn Marino        ? "%{!g0:%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}}" ASM_MAP	\
582e4b17023SJohn Marino        : "%{!g0:%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}}" ASM_MAP)
583e4b17023SJohn Marino # else
584e4b17023SJohn Marino #  if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
585e4b17023SJohn Marino #   define ASM_DEBUG_SPEC "%{g*:%{!g0:--gstabs}}" ASM_MAP
586e4b17023SJohn Marino #  endif
587e4b17023SJohn Marino #  if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG)
588e4b17023SJohn Marino #   define ASM_DEBUG_SPEC "%{g*:%{!g0:--gdwarf2}}" ASM_MAP
589e4b17023SJohn Marino #  endif
590e4b17023SJohn Marino # endif
591e4b17023SJohn Marino #endif
592e4b17023SJohn Marino #ifndef ASM_DEBUG_SPEC
593e4b17023SJohn Marino # define ASM_DEBUG_SPEC ""
594e4b17023SJohn Marino #endif
595e4b17023SJohn Marino 
596e4b17023SJohn Marino /* Here is the spec for running the linker, after compiling all files.  */
597e4b17023SJohn Marino 
598e4b17023SJohn Marino /* This is overridable by the target in case they need to specify the
599e4b17023SJohn Marino    -lgcc and -lc order specially, yet not require them to override all
600e4b17023SJohn Marino    of LINK_COMMAND_SPEC.  */
601e4b17023SJohn Marino #ifndef LINK_GCC_C_SEQUENCE_SPEC
602e4b17023SJohn Marino #define LINK_GCC_C_SEQUENCE_SPEC "%G %L %G"
603e4b17023SJohn Marino #endif
604e4b17023SJohn Marino 
605e4b17023SJohn Marino #ifndef LINK_SSP_SPEC
606e4b17023SJohn Marino #ifdef TARGET_LIBC_PROVIDES_SSP
607e4b17023SJohn Marino #define LINK_SSP_SPEC "%{fstack-protector:}"
608e4b17023SJohn Marino #else
609e4b17023SJohn Marino #define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all:-lssp_nonshared -lssp}"
610e4b17023SJohn Marino #endif
611e4b17023SJohn Marino #endif
612e4b17023SJohn Marino 
613e4b17023SJohn Marino #ifndef LINK_PIE_SPEC
614e4b17023SJohn Marino #ifdef HAVE_LD_PIE
615e4b17023SJohn Marino #define LINK_PIE_SPEC "%{pie:-pie} "
616e4b17023SJohn Marino #else
617e4b17023SJohn Marino #define LINK_PIE_SPEC "%{pie:} "
618e4b17023SJohn Marino #endif
619e4b17023SJohn Marino #endif
620e4b17023SJohn Marino 
621e4b17023SJohn Marino #ifndef LINK_BUILDID_SPEC
622e4b17023SJohn Marino # if defined(HAVE_LD_BUILDID) && defined(ENABLE_LD_BUILDID)
623e4b17023SJohn Marino #  define LINK_BUILDID_SPEC "%{!r:--build-id} "
624e4b17023SJohn Marino # endif
625e4b17023SJohn Marino #endif
626e4b17023SJohn Marino 
627e4b17023SJohn Marino /* Conditional to test whether the LTO plugin is used or not.
628e4b17023SJohn Marino    FIXME: For slim LTO we will need to enable plugin unconditionally.  This
629e4b17023SJohn Marino    still cause problems with PLUGIN_LD != LD and when plugin is built but
630e4b17023SJohn Marino    not useable.  For GCC 4.6 we don't support slim LTO and thus we can enable
631e4b17023SJohn Marino    plugin only when LTO is enabled.  We still honor explicit
632e4b17023SJohn Marino    -fuse-linker-plugin if the linker used understands -plugin.  */
633e4b17023SJohn Marino 
634e4b17023SJohn Marino /* The linker has some plugin support.  */
635e4b17023SJohn Marino #if HAVE_LTO_PLUGIN > 0
636e4b17023SJohn Marino /* The linker used has full plugin support, use LTO plugin by default.  */
637e4b17023SJohn Marino #if HAVE_LTO_PLUGIN == 2
638e4b17023SJohn Marino #define PLUGIN_COND "!fno-use-linker-plugin:%{flto|flto=*|fuse-linker-plugin"
639e4b17023SJohn Marino #define PLUGIN_COND_CLOSE "}"
640e4b17023SJohn Marino #else
641e4b17023SJohn Marino /* The linker used has limited plugin support, use LTO plugin with explicit
642e4b17023SJohn Marino    -fuse-linker-plugin.  */
643e4b17023SJohn Marino #define PLUGIN_COND "fuse-linker-plugin"
644e4b17023SJohn Marino #define PLUGIN_COND_CLOSE ""
645e4b17023SJohn Marino #endif
646e4b17023SJohn Marino #define LINK_PLUGIN_SPEC \
647e4b17023SJohn Marino     "%{"PLUGIN_COND": \
648e4b17023SJohn Marino     -plugin %(linker_plugin_file) \
649e4b17023SJohn Marino     -plugin-opt=%(lto_wrapper) \
650e4b17023SJohn Marino     -plugin-opt=-fresolution=%u.res \
651e4b17023SJohn Marino     %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} \
652e4b17023SJohn Marino     }"PLUGIN_COND_CLOSE
653e4b17023SJohn Marino #else
654e4b17023SJohn Marino /* The linker used doesn't support -plugin, reject -fuse-linker-plugin.  */
655e4b17023SJohn Marino #define LINK_PLUGIN_SPEC "%{fuse-linker-plugin:\
656e4b17023SJohn Marino     %e-fuse-linker-plugin is not supported in this configuration}"
657e4b17023SJohn Marino #endif
658e4b17023SJohn Marino 
659e4b17023SJohn Marino 
660e4b17023SJohn Marino /* -u* was put back because both BSD and SysV seem to support it.  */
661e4b17023SJohn Marino /* %{static:} simply prevents an error message if the target machine
662e4b17023SJohn Marino    doesn't handle -static.  */
663e4b17023SJohn Marino /* We want %{T*} after %{L*} and %D so that it can be used to specify linker
664e4b17023SJohn Marino    scripts which exist in user specified directories, or in standard
665e4b17023SJohn Marino    directories.  */
666e4b17023SJohn Marino /* We pass any -flto flags on to the linker, which is expected
667e4b17023SJohn Marino    to understand them.  In practice, this means it had better be collect2.  */
668e4b17023SJohn Marino /* %{e*} includes -export-dynamic; see comment in common.opt.  */
669e4b17023SJohn Marino #ifndef LINK_COMMAND_SPEC
670e4b17023SJohn Marino #define LINK_COMMAND_SPEC "\
671e4b17023SJohn Marino %{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
672e4b17023SJohn Marino     %(linker) " \
673e4b17023SJohn Marino     LINK_PLUGIN_SPEC \
674e4b17023SJohn Marino     "%{flto|flto=*:%<fcompare-debug*} \
675e4b17023SJohn Marino     %{flto} %{flto=*} %l " LINK_PIE_SPEC \
676e4b17023SJohn Marino    "%X %{o*} %{e*} %{N} %{n} %{r}\
677e4b17023SJohn Marino     %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}}\
678e4b17023SJohn Marino     %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
679e4b17023SJohn Marino     %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)}\
680e4b17023SJohn Marino     %{fgnu-tm:%:include(libitm.spec)%(link_itm)}\
681e4b17023SJohn Marino     %(mflib) " STACK_SPLIT_SPEC "\
682e4b17023SJohn Marino     %{fprofile-arcs|fprofile-generate*|coverage:-lgcov}\
683e4b17023SJohn Marino     %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
684e4b17023SJohn Marino     %{!nostdlib:%{!nostartfiles:%E}} %{T*} }}}}}}"
685e4b17023SJohn Marino #endif
686e4b17023SJohn Marino 
687e4b17023SJohn Marino #ifndef LINK_LIBGCC_SPEC
688e4b17023SJohn Marino /* Generate -L options for startfile prefix list.  */
689e4b17023SJohn Marino # define LINK_LIBGCC_SPEC "%D"
690e4b17023SJohn Marino #endif
691e4b17023SJohn Marino 
692e4b17023SJohn Marino #ifndef STARTFILE_PREFIX_SPEC
693e4b17023SJohn Marino # define STARTFILE_PREFIX_SPEC ""
694e4b17023SJohn Marino #endif
695e4b17023SJohn Marino 
696e4b17023SJohn Marino #ifndef SYSROOT_SPEC
697e4b17023SJohn Marino # define SYSROOT_SPEC "--sysroot=%R"
698e4b17023SJohn Marino #endif
699e4b17023SJohn Marino 
700e4b17023SJohn Marino #ifndef SYSROOT_SUFFIX_SPEC
701e4b17023SJohn Marino # define SYSROOT_SUFFIX_SPEC ""
702e4b17023SJohn Marino #endif
703e4b17023SJohn Marino 
704e4b17023SJohn Marino #ifndef SYSROOT_HEADERS_SUFFIX_SPEC
705e4b17023SJohn Marino # define SYSROOT_HEADERS_SUFFIX_SPEC ""
706e4b17023SJohn Marino #endif
707e4b17023SJohn Marino 
708e4b17023SJohn Marino static const char *asm_debug;
709e4b17023SJohn Marino static const char *cpp_spec = CPP_SPEC;
710e4b17023SJohn Marino static const char *cc1_spec = CC1_SPEC;
711e4b17023SJohn Marino static const char *cc1plus_spec = CC1PLUS_SPEC;
712e4b17023SJohn Marino static const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC;
713e4b17023SJohn Marino static const char *link_ssp_spec = LINK_SSP_SPEC;
714e4b17023SJohn Marino static const char *asm_spec = ASM_SPEC;
715e4b17023SJohn Marino static const char *asm_final_spec = ASM_FINAL_SPEC;
716e4b17023SJohn Marino static const char *link_spec = LINK_SPEC;
717e4b17023SJohn Marino static const char *lib_spec = LIB_SPEC;
718e4b17023SJohn Marino static const char *mfwrap_spec = MFWRAP_SPEC;
719e4b17023SJohn Marino static const char *mflib_spec = MFLIB_SPEC;
720e4b17023SJohn Marino static const char *link_gomp_spec = "";
721e4b17023SJohn Marino static const char *libgcc_spec = LIBGCC_SPEC;
722e4b17023SJohn Marino static const char *endfile_spec = ENDFILE_SPEC;
723e4b17023SJohn Marino static const char *startfile_spec = STARTFILE_SPEC;
724e4b17023SJohn Marino static const char *linker_name_spec = LINKER_NAME;
725e4b17023SJohn Marino static const char *linker_plugin_file_spec = "";
726e4b17023SJohn Marino static const char *lto_wrapper_spec = "";
727e4b17023SJohn Marino static const char *lto_gcc_spec = "";
728e4b17023SJohn Marino static const char *link_command_spec = LINK_COMMAND_SPEC;
729e4b17023SJohn Marino static const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
730e4b17023SJohn Marino static const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC;
731e4b17023SJohn Marino static const char *sysroot_spec = SYSROOT_SPEC;
732e4b17023SJohn Marino static const char *sysroot_suffix_spec = SYSROOT_SUFFIX_SPEC;
733e4b17023SJohn Marino static const char *sysroot_hdrs_suffix_spec = SYSROOT_HEADERS_SUFFIX_SPEC;
734e4b17023SJohn Marino static const char *self_spec = "";
735e4b17023SJohn Marino 
736e4b17023SJohn Marino /* Standard options to cpp, cc1, and as, to reduce duplication in specs.
737e4b17023SJohn Marino    There should be no need to override these in target dependent files,
738e4b17023SJohn Marino    but we need to copy them to the specs file so that newer versions
739e4b17023SJohn Marino    of the GCC driver can correctly drive older tool chains with the
740e4b17023SJohn Marino    appropriate -B options.  */
741e4b17023SJohn Marino 
742e4b17023SJohn Marino /* When cpplib handles traditional preprocessing, get rid of this, and
743e4b17023SJohn Marino    call cc1 (or cc1obj in objc/lang-specs.h) from the main specs so
744e4b17023SJohn Marino    that we default the front end language better.  */
745e4b17023SJohn Marino static const char *trad_capable_cpp =
746e4b17023SJohn Marino "cc1 -E %{traditional|traditional-cpp:-traditional-cpp}";
747e4b17023SJohn Marino 
748e4b17023SJohn Marino /* We don't wrap .d files in %W{} since a missing .d file, and
749e4b17023SJohn Marino    therefore no dependency entry, confuses make into thinking a .o
750e4b17023SJohn Marino    file that happens to exist is up-to-date.  */
751e4b17023SJohn Marino static const char *cpp_unique_options =
752e4b17023SJohn Marino "%{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*&F*} %{P} %I\
753e4b17023SJohn Marino  %{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\
754e4b17023SJohn Marino  %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\
755e4b17023SJohn Marino  %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\
756e4b17023SJohn Marino  %{!E:%{!M:%{!MM:%{!MT:%{!MQ:%{MD|MMD:%{o*:-MQ %*}}}}}}}\
757e4b17023SJohn Marino  %{remap} %{g3|ggdb3|gstabs3|gcoff3|gxcoff3|gvms3:-dD}\
758e4b17023SJohn Marino  %{!iplugindir*:%{fplugin*:%:find-plugindir()}}\
759e4b17023SJohn Marino  %{H} %C %{D*&U*&A*} %{i*} %Z %i\
760e4b17023SJohn Marino  %{fmudflap:-D_MUDFLAP -include mf-runtime.h}\
761e4b17023SJohn Marino  %{fmudflapth:-D_MUDFLAP -D_MUDFLAPTH -include mf-runtime.h}\
762e4b17023SJohn Marino  %{E|M|MM:%W{o*}}";
763e4b17023SJohn Marino 
764e4b17023SJohn Marino /* This contains cpp options which are common with cc1_options and are passed
765e4b17023SJohn Marino    only when preprocessing only to avoid duplication.  We pass the cc1 spec
766e4b17023SJohn Marino    options to the preprocessor so that it the cc1 spec may manipulate
767e4b17023SJohn Marino    options used to set target flags.  Those special target flags settings may
768e4b17023SJohn Marino    in turn cause preprocessor symbols to be defined specially.  */
769e4b17023SJohn Marino static const char *cpp_options =
770e4b17023SJohn Marino "%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w}\
771e4b17023SJohn Marino  %{f*} %{g*:%{!g0:%{g*} %{!fno-working-directory:-fworking-directory}}} %{O*}\
772e4b17023SJohn Marino  %{undef} %{save-temps*:-fpch-preprocess}";
773e4b17023SJohn Marino 
774e4b17023SJohn Marino /* This contains cpp options which are not passed when the preprocessor
775e4b17023SJohn Marino    output will be used by another program.  */
776e4b17023SJohn Marino static const char *cpp_debug_options = "%{d*}";
777e4b17023SJohn Marino 
778e4b17023SJohn Marino /* NB: This is shared amongst all front-ends, except for Ada.  */
779e4b17023SJohn Marino static const char *cc1_options =
780e4b17023SJohn Marino "%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
781e4b17023SJohn Marino  %{!iplugindir*:%{fplugin*:%:find-plugindir()}}\
782e4b17023SJohn Marino  %1 %{!Q:-quiet} %{!dumpbase:-dumpbase %B} %{d*} %{m*} %{aux-info*}\
783e4b17023SJohn Marino  %{fcompare-debug-second:%:compare-debug-auxbase-opt(%b)} \
784e4b17023SJohn Marino  %{!fcompare-debug-second:%{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}}%{!c:%{!S:-auxbase %b}} \
785e4b17023SJohn Marino  %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs}\
786e4b17023SJohn Marino  %{v:-version} %{pg:-p} %{p} %{f*} %{undef}\
787e4b17023SJohn Marino  %{Qn:-fno-ident} %{Qy:} %{-help:--help}\
788e4b17023SJohn Marino  %{-target-help:--target-help}\
789e4b17023SJohn Marino  %{-version:--version}\
790e4b17023SJohn Marino  %{-help=*:--help=%*}\
791e4b17023SJohn Marino  %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\
792e4b17023SJohn Marino  %{fsyntax-only:-o %j} %{-param*}\
793e4b17023SJohn Marino  %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants}\
794e4b17023SJohn Marino  %{coverage:-fprofile-arcs -ftest-coverage}";
795e4b17023SJohn Marino 
796e4b17023SJohn Marino static const char *asm_options =
797e4b17023SJohn Marino "%{-target-help:%:print-asm-header()} "
798e4b17023SJohn Marino #if HAVE_GNU_AS
799e4b17023SJohn Marino /* If GNU AS is used, then convert -w (no warnings), -I, and -v
800e4b17023SJohn Marino    to the assembler equivalents.  */
801e4b17023SJohn Marino "%{v} %{w:-W} %{I*} "
802e4b17023SJohn Marino #endif
803e4b17023SJohn Marino "%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
804e4b17023SJohn Marino 
805e4b17023SJohn Marino static const char *invoke_as =
806e4b17023SJohn Marino #ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
807e4b17023SJohn Marino "%{!fwpa:\
808e4b17023SJohn Marino    %{fcompare-debug=*|fdump-final-insns=*:%:compare-debug-dump-opt()}\
809e4b17023SJohn Marino    %{!S:-o %|.s |\n as %(asm_options) %|.s %A }\
810e4b17023SJohn Marino   }";
811e4b17023SJohn Marino #else
812e4b17023SJohn Marino "%{!fwpa:\
813e4b17023SJohn Marino    %{fcompare-debug=*|fdump-final-insns=*:%:compare-debug-dump-opt()}\
814e4b17023SJohn Marino    %{!S:-o %|.s |\n as %(asm_options) %m.s %A }\
815e4b17023SJohn Marino   }";
816e4b17023SJohn Marino #endif
817e4b17023SJohn Marino 
818e4b17023SJohn Marino /* Some compilers have limits on line lengths, and the multilib_select
819e4b17023SJohn Marino    and/or multilib_matches strings can be very long, so we build them at
820e4b17023SJohn Marino    run time.  */
821e4b17023SJohn Marino static struct obstack multilib_obstack;
822e4b17023SJohn Marino static const char *multilib_select;
823e4b17023SJohn Marino static const char *multilib_matches;
824e4b17023SJohn Marino static const char *multilib_defaults;
825e4b17023SJohn Marino static const char *multilib_exclusions;
826e4b17023SJohn Marino 
827e4b17023SJohn Marino /* Check whether a particular argument is a default argument.  */
828e4b17023SJohn Marino 
829e4b17023SJohn Marino #ifndef MULTILIB_DEFAULTS
830e4b17023SJohn Marino #define MULTILIB_DEFAULTS { "" }
831e4b17023SJohn Marino #endif
832e4b17023SJohn Marino 
833e4b17023SJohn Marino static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
834e4b17023SJohn Marino 
835e4b17023SJohn Marino #ifndef DRIVER_SELF_SPECS
836e4b17023SJohn Marino #define DRIVER_SELF_SPECS ""
837e4b17023SJohn Marino #endif
838e4b17023SJohn Marino 
839e4b17023SJohn Marino /* Adding -fopenmp should imply pthreads.  This is particularly important
840e4b17023SJohn Marino    for targets that use different start files and suchlike.  */
841e4b17023SJohn Marino #ifndef GOMP_SELF_SPECS
842e4b17023SJohn Marino #define GOMP_SELF_SPECS "%{fopenmp|ftree-parallelize-loops=*: -pthread}"
843e4b17023SJohn Marino #endif
844e4b17023SJohn Marino 
845e4b17023SJohn Marino /* Likewise for -fgnu-tm.  */
846e4b17023SJohn Marino #ifndef GTM_SELF_SPECS
847e4b17023SJohn Marino #define GTM_SELF_SPECS "%{fgnu-tm: -pthread}"
848e4b17023SJohn Marino #endif
849e4b17023SJohn Marino 
850e4b17023SJohn Marino static const char *const driver_self_specs[] = {
851e4b17023SJohn Marino   "%{fdump-final-insns:-fdump-final-insns=.} %<fdump-final-insns",
852e4b17023SJohn Marino   DRIVER_SELF_SPECS, CONFIGURE_SPECS, GOMP_SELF_SPECS, GTM_SELF_SPECS
853e4b17023SJohn Marino };
854e4b17023SJohn Marino 
855e4b17023SJohn Marino #ifndef OPTION_DEFAULT_SPECS
856e4b17023SJohn Marino #define OPTION_DEFAULT_SPECS { "", "" }
857e4b17023SJohn Marino #endif
858e4b17023SJohn Marino 
859e4b17023SJohn Marino struct default_spec
860e4b17023SJohn Marino {
861e4b17023SJohn Marino   const char *name;
862e4b17023SJohn Marino   const char *spec;
863e4b17023SJohn Marino };
864e4b17023SJohn Marino 
865e4b17023SJohn Marino static const struct default_spec
866e4b17023SJohn Marino   option_default_specs[] = { OPTION_DEFAULT_SPECS };
867e4b17023SJohn Marino 
868e4b17023SJohn Marino struct user_specs
869e4b17023SJohn Marino {
870e4b17023SJohn Marino   struct user_specs *next;
871e4b17023SJohn Marino   const char *filename;
872e4b17023SJohn Marino };
873e4b17023SJohn Marino 
874e4b17023SJohn Marino static struct user_specs *user_specs_head, *user_specs_tail;
875e4b17023SJohn Marino 
876e4b17023SJohn Marino 
877e4b17023SJohn Marino /* Record the mapping from file suffixes for compilation specs.  */
878e4b17023SJohn Marino 
879e4b17023SJohn Marino struct compiler
880e4b17023SJohn Marino {
881e4b17023SJohn Marino   const char *suffix;		/* Use this compiler for input files
882e4b17023SJohn Marino 				   whose names end in this suffix.  */
883e4b17023SJohn Marino 
884e4b17023SJohn Marino   const char *spec;		/* To use this compiler, run this spec.  */
885e4b17023SJohn Marino 
886e4b17023SJohn Marino   const char *cpp_spec;         /* If non-NULL, substitute this spec
887e4b17023SJohn Marino 				   for `%C', rather than the usual
888e4b17023SJohn Marino 				   cpp_spec.  */
889e4b17023SJohn Marino   const int combinable;          /* If nonzero, compiler can deal with
890e4b17023SJohn Marino 				    multiple source files at once (IMA).  */
891e4b17023SJohn Marino   const int needs_preprocessing; /* If nonzero, source files need to
892e4b17023SJohn Marino 				    be run through a preprocessor.  */
893e4b17023SJohn Marino };
894e4b17023SJohn Marino 
895e4b17023SJohn Marino /* Pointer to a vector of `struct compiler' that gives the spec for
896e4b17023SJohn Marino    compiling a file, based on its suffix.
897e4b17023SJohn Marino    A file that does not end in any of these suffixes will be passed
898e4b17023SJohn Marino    unchanged to the loader and nothing else will be done to it.
899e4b17023SJohn Marino 
900e4b17023SJohn Marino    An entry containing two 0s is used to terminate the vector.
901e4b17023SJohn Marino 
902e4b17023SJohn Marino    If multiple entries match a file, the last matching one is used.  */
903e4b17023SJohn Marino 
904e4b17023SJohn Marino static struct compiler *compilers;
905e4b17023SJohn Marino 
906e4b17023SJohn Marino /* Number of entries in `compilers', not counting the null terminator.  */
907e4b17023SJohn Marino 
908e4b17023SJohn Marino static int n_compilers;
909e4b17023SJohn Marino 
910e4b17023SJohn Marino /* The default list of file name suffixes and their compilation specs.  */
911e4b17023SJohn Marino 
912e4b17023SJohn Marino static const struct compiler default_compilers[] =
913e4b17023SJohn Marino {
914e4b17023SJohn Marino   /* Add lists of suffixes of known languages here.  If those languages
915e4b17023SJohn Marino      were not present when we built the driver, we will hit these copies
916e4b17023SJohn Marino      and be given a more meaningful error than "file not used since
917e4b17023SJohn Marino      linking is not done".  */
918e4b17023SJohn Marino   {".m",  "#Objective-C", 0, 0, 0}, {".mi",  "#Objective-C", 0, 0, 0},
919e4b17023SJohn Marino   {".mm", "#Objective-C++", 0, 0, 0}, {".M", "#Objective-C++", 0, 0, 0},
920e4b17023SJohn Marino   {".mii", "#Objective-C++", 0, 0, 0},
921e4b17023SJohn Marino   {".cc", "#C++", 0, 0, 0}, {".cxx", "#C++", 0, 0, 0},
922e4b17023SJohn Marino   {".cpp", "#C++", 0, 0, 0}, {".cp", "#C++", 0, 0, 0},
923e4b17023SJohn Marino   {".c++", "#C++", 0, 0, 0}, {".C", "#C++", 0, 0, 0},
924e4b17023SJohn Marino   {".CPP", "#C++", 0, 0, 0}, {".ii", "#C++", 0, 0, 0},
925e4b17023SJohn Marino   {".ads", "#Ada", 0, 0, 0}, {".adb", "#Ada", 0, 0, 0},
926e4b17023SJohn Marino   {".f", "#Fortran", 0, 0, 0}, {".F", "#Fortran", 0, 0, 0},
927e4b17023SJohn Marino   {".for", "#Fortran", 0, 0, 0}, {".FOR", "#Fortran", 0, 0, 0},
928e4b17023SJohn Marino   {".ftn", "#Fortran", 0, 0, 0}, {".FTN", "#Fortran", 0, 0, 0},
929e4b17023SJohn Marino   {".fpp", "#Fortran", 0, 0, 0}, {".FPP", "#Fortran", 0, 0, 0},
930e4b17023SJohn Marino   {".f90", "#Fortran", 0, 0, 0}, {".F90", "#Fortran", 0, 0, 0},
931e4b17023SJohn Marino   {".f95", "#Fortran", 0, 0, 0}, {".F95", "#Fortran", 0, 0, 0},
932e4b17023SJohn Marino   {".f03", "#Fortran", 0, 0, 0}, {".F03", "#Fortran", 0, 0, 0},
933e4b17023SJohn Marino   {".f08", "#Fortran", 0, 0, 0}, {".F08", "#Fortran", 0, 0, 0},
934e4b17023SJohn Marino   {".r", "#Ratfor", 0, 0, 0},
935e4b17023SJohn Marino   {".p", "#Pascal", 0, 0, 0}, {".pas", "#Pascal", 0, 0, 0},
936e4b17023SJohn Marino   {".java", "#Java", 0, 0, 0}, {".class", "#Java", 0, 0, 0},
937e4b17023SJohn Marino   {".zip", "#Java", 0, 0, 0}, {".jar", "#Java", 0, 0, 0},
938e4b17023SJohn Marino   {".go", "#Go", 0, 1, 0},
939e4b17023SJohn Marino   /* Next come the entries for C.  */
940e4b17023SJohn Marino   {".c", "@c", 0, 0, 1},
941e4b17023SJohn Marino   {"@c",
942e4b17023SJohn Marino    /* cc1 has an integrated ISO C preprocessor.  We should invoke the
943e4b17023SJohn Marino       external preprocessor if -save-temps is given.  */
944e4b17023SJohn Marino      "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
945e4b17023SJohn Marino       %{!E:%{!M:%{!MM:\
946e4b17023SJohn Marino           %{traditional:\
947e4b17023SJohn Marino %eGNU C no longer supports -traditional without -E}\
948e4b17023SJohn Marino       %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
949e4b17023SJohn Marino 	  %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\
950e4b17023SJohn Marino 	    cc1 -fpreprocessed %{save-temps*:%b.i} %{!save-temps*:%g.i} \
951e4b17023SJohn Marino 	  %(cc1_options)}\
952e4b17023SJohn Marino       %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\
953e4b17023SJohn Marino 	  cc1 %(cpp_unique_options) %(cc1_options)}}}\
954e4b17023SJohn Marino       %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 1},
955e4b17023SJohn Marino   {"-",
956e4b17023SJohn Marino    "%{!E:%e-E or -x required when input is from standard input}\
957e4b17023SJohn Marino     %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 0, 0, 0},
958e4b17023SJohn Marino   {".h", "@c-header", 0, 0, 0},
959e4b17023SJohn Marino   {"@c-header",
960e4b17023SJohn Marino    /* cc1 has an integrated ISO C preprocessor.  We should invoke the
961e4b17023SJohn Marino       external preprocessor if -save-temps is given.  */
962e4b17023SJohn Marino      "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
963e4b17023SJohn Marino       %{!E:%{!M:%{!MM:\
964e4b17023SJohn Marino 	  %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
965e4b17023SJohn Marino 		%(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\
966e4b17023SJohn Marino 		    cc1 -fpreprocessed %{save-temps*:%b.i} %{!save-temps*:%g.i} \
967e4b17023SJohn Marino 			%(cc1_options)\
968e4b17023SJohn Marino                         %{!fdump-ada-spec*:-o %g.s %{!o*:--output-pch=%i.gch}\
969e4b17023SJohn Marino                         %W{o*:--output-pch=%*}}%V}\
970e4b17023SJohn Marino 	  %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\
971e4b17023SJohn Marino 		cc1 %(cpp_unique_options) %(cc1_options)\
972e4b17023SJohn Marino                     %{!fdump-ada-spec*:-o %g.s %{!o*:--output-pch=%i.gch}\
973e4b17023SJohn Marino                     %W{o*:--output-pch=%*}}%V}}}}}}", 0, 0, 0},
974e4b17023SJohn Marino   {".i", "@cpp-output", 0, 0, 0},
975e4b17023SJohn Marino   {"@cpp-output",
976e4b17023SJohn Marino    "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
977e4b17023SJohn Marino   {".s", "@assembler", 0, 0, 0},
978e4b17023SJohn Marino   {"@assembler",
979e4b17023SJohn Marino    "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0, 0, 0},
980e4b17023SJohn Marino   {".sx", "@assembler-with-cpp", 0, 0, 0},
981e4b17023SJohn Marino   {".S", "@assembler-with-cpp", 0, 0, 0},
982e4b17023SJohn Marino   {"@assembler-with-cpp",
983e4b17023SJohn Marino #ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
984e4b17023SJohn Marino    "%(trad_capable_cpp) -lang-asm %(cpp_options) -fno-directives-only\
985e4b17023SJohn Marino       %{E|M|MM:%(cpp_debug_options)}\
986e4b17023SJohn Marino       %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
987e4b17023SJohn Marino        as %(asm_debug) %(asm_options) %|.s %A }}}}"
988e4b17023SJohn Marino #else
989e4b17023SJohn Marino    "%(trad_capable_cpp) -lang-asm %(cpp_options) -fno-directives-only\
990e4b17023SJohn Marino       %{E|M|MM:%(cpp_debug_options)}\
991e4b17023SJohn Marino       %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
992e4b17023SJohn Marino        as %(asm_debug) %(asm_options) %m.s %A }}}}"
993e4b17023SJohn Marino #endif
994e4b17023SJohn Marino    , 0, 0, 0},
995e4b17023SJohn Marino 
996e4b17023SJohn Marino #include "specs.h"
997e4b17023SJohn Marino   /* Mark end of table.  */
998e4b17023SJohn Marino   {0, 0, 0, 0, 0}
999e4b17023SJohn Marino };
1000e4b17023SJohn Marino 
1001e4b17023SJohn Marino /* Number of elements in default_compilers, not counting the terminator.  */
1002e4b17023SJohn Marino 
1003e4b17023SJohn Marino static const int n_default_compilers = ARRAY_SIZE (default_compilers) - 1;
1004e4b17023SJohn Marino 
1005e4b17023SJohn Marino typedef char *char_p; /* For DEF_VEC_P.  */
1006e4b17023SJohn Marino DEF_VEC_P(char_p);
1007e4b17023SJohn Marino DEF_VEC_ALLOC_P(char_p,heap);
1008e4b17023SJohn Marino 
1009e4b17023SJohn Marino /* A vector of options to give to the linker.
1010e4b17023SJohn Marino    These options are accumulated by %x,
1011e4b17023SJohn Marino    and substituted into the linker command with %X.  */
1012e4b17023SJohn Marino static VEC(char_p,heap) *linker_options;
1013e4b17023SJohn Marino 
1014e4b17023SJohn Marino /* A vector of options to give to the assembler.
1015e4b17023SJohn Marino    These options are accumulated by -Wa,
1016e4b17023SJohn Marino    and substituted into the assembler command with %Y.  */
1017e4b17023SJohn Marino static VEC(char_p,heap) *assembler_options;
1018e4b17023SJohn Marino 
1019e4b17023SJohn Marino /* A vector of options to give to the preprocessor.
1020e4b17023SJohn Marino    These options are accumulated by -Wp,
1021e4b17023SJohn Marino    and substituted into the preprocessor command with %Z.  */
1022e4b17023SJohn Marino static VEC(char_p,heap) *preprocessor_options;
1023e4b17023SJohn Marino 
1024e4b17023SJohn Marino static char *
skip_whitespace(char * p)1025e4b17023SJohn Marino skip_whitespace (char *p)
1026e4b17023SJohn Marino {
1027e4b17023SJohn Marino   while (1)
1028e4b17023SJohn Marino     {
1029e4b17023SJohn Marino       /* A fully-blank line is a delimiter in the SPEC file and shouldn't
1030e4b17023SJohn Marino 	 be considered whitespace.  */
1031e4b17023SJohn Marino       if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n')
1032e4b17023SJohn Marino 	return p + 1;
1033e4b17023SJohn Marino       else if (*p == '\n' || *p == ' ' || *p == '\t')
1034e4b17023SJohn Marino 	p++;
1035e4b17023SJohn Marino       else if (*p == '#')
1036e4b17023SJohn Marino 	{
1037e4b17023SJohn Marino 	  while (*p != '\n')
1038e4b17023SJohn Marino 	    p++;
1039e4b17023SJohn Marino 	  p++;
1040e4b17023SJohn Marino 	}
1041e4b17023SJohn Marino       else
1042e4b17023SJohn Marino 	break;
1043e4b17023SJohn Marino     }
1044e4b17023SJohn Marino 
1045e4b17023SJohn Marino   return p;
1046e4b17023SJohn Marino }
1047e4b17023SJohn Marino /* Structures to keep track of prefixes to try when looking for files.  */
1048e4b17023SJohn Marino 
1049e4b17023SJohn Marino struct prefix_list
1050e4b17023SJohn Marino {
1051e4b17023SJohn Marino   const char *prefix;	      /* String to prepend to the path.  */
1052e4b17023SJohn Marino   struct prefix_list *next;   /* Next in linked list.  */
1053e4b17023SJohn Marino   int require_machine_suffix; /* Don't use without machine_suffix.  */
1054e4b17023SJohn Marino   /* 2 means try both machine_suffix and just_machine_suffix.  */
1055e4b17023SJohn Marino   int priority;		      /* Sort key - priority within list.  */
1056e4b17023SJohn Marino   int os_multilib;	      /* 1 if OS multilib scheme should be used,
1057e4b17023SJohn Marino 				 0 for GCC multilib scheme.  */
1058e4b17023SJohn Marino };
1059e4b17023SJohn Marino 
1060e4b17023SJohn Marino struct path_prefix
1061e4b17023SJohn Marino {
1062e4b17023SJohn Marino   struct prefix_list *plist;  /* List of prefixes to try */
1063e4b17023SJohn Marino   int max_len;                /* Max length of a prefix in PLIST */
1064e4b17023SJohn Marino   const char *name;           /* Name of this list (used in config stuff) */
1065e4b17023SJohn Marino };
1066e4b17023SJohn Marino 
1067e4b17023SJohn Marino /* List of prefixes to try when looking for executables.  */
1068e4b17023SJohn Marino 
1069e4b17023SJohn Marino static struct path_prefix exec_prefixes = { 0, 0, "exec" };
1070e4b17023SJohn Marino 
1071e4b17023SJohn Marino /* List of prefixes to try when looking for startup (crt0) files.  */
1072e4b17023SJohn Marino 
1073e4b17023SJohn Marino static struct path_prefix startfile_prefixes = { 0, 0, "startfile" };
1074e4b17023SJohn Marino 
1075e4b17023SJohn Marino /* List of prefixes to try when looking for include files.  */
1076e4b17023SJohn Marino 
1077e4b17023SJohn Marino static struct path_prefix include_prefixes = { 0, 0, "include" };
1078e4b17023SJohn Marino 
1079e4b17023SJohn Marino /* Suffix to attach to directories searched for commands.
1080e4b17023SJohn Marino    This looks like `MACHINE/VERSION/'.  */
1081e4b17023SJohn Marino 
1082e4b17023SJohn Marino static const char *machine_suffix = 0;
1083e4b17023SJohn Marino 
1084e4b17023SJohn Marino /* Suffix to attach to directories searched for commands.
1085e4b17023SJohn Marino    This is just `MACHINE/'.  */
1086e4b17023SJohn Marino 
1087e4b17023SJohn Marino static const char *just_machine_suffix = 0;
1088e4b17023SJohn Marino 
1089e4b17023SJohn Marino /* Adjusted value of GCC_EXEC_PREFIX envvar.  */
1090e4b17023SJohn Marino 
1091e4b17023SJohn Marino static const char *gcc_exec_prefix;
1092e4b17023SJohn Marino 
1093e4b17023SJohn Marino /* Adjusted value of standard_libexec_prefix.  */
1094e4b17023SJohn Marino 
1095e4b17023SJohn Marino static const char *gcc_libexec_prefix;
1096e4b17023SJohn Marino 
1097e4b17023SJohn Marino /* Default prefixes to attach to command names.  */
1098e4b17023SJohn Marino 
1099e4b17023SJohn Marino #ifndef STANDARD_STARTFILE_PREFIX_1
1100e4b17023SJohn Marino #define STANDARD_STARTFILE_PREFIX_1 "/lib/"
1101e4b17023SJohn Marino #endif
1102e4b17023SJohn Marino #ifndef STANDARD_STARTFILE_PREFIX_2
1103e4b17023SJohn Marino #define STANDARD_STARTFILE_PREFIX_2 "/usr/lib/"
1104e4b17023SJohn Marino #endif
1105e4b17023SJohn Marino 
1106e4b17023SJohn Marino #ifdef CROSS_DIRECTORY_STRUCTURE  /* Don't use these prefixes for a cross compiler.  */
1107e4b17023SJohn Marino #undef MD_EXEC_PREFIX
1108e4b17023SJohn Marino #undef MD_STARTFILE_PREFIX
1109e4b17023SJohn Marino #undef MD_STARTFILE_PREFIX_1
1110e4b17023SJohn Marino #endif
1111e4b17023SJohn Marino 
1112e4b17023SJohn Marino /* If no prefixes defined, use the null string, which will disable them.  */
1113e4b17023SJohn Marino #ifndef MD_EXEC_PREFIX
1114e4b17023SJohn Marino #define MD_EXEC_PREFIX ""
1115e4b17023SJohn Marino #endif
1116e4b17023SJohn Marino #ifndef MD_STARTFILE_PREFIX
1117e4b17023SJohn Marino #define MD_STARTFILE_PREFIX ""
1118e4b17023SJohn Marino #endif
1119e4b17023SJohn Marino #ifndef MD_STARTFILE_PREFIX_1
1120e4b17023SJohn Marino #define MD_STARTFILE_PREFIX_1 ""
1121e4b17023SJohn Marino #endif
1122e4b17023SJohn Marino 
1123e4b17023SJohn Marino /* These directories are locations set at configure-time based on the
1124e4b17023SJohn Marino    --prefix option provided to configure.  Their initializers are
1125e4b17023SJohn Marino    defined in Makefile.in.  These paths are not *directly* used when
1126e4b17023SJohn Marino    gcc_exec_prefix is set because, in that case, we know where the
1127e4b17023SJohn Marino    compiler has been installed, and use paths relative to that
1128e4b17023SJohn Marino    location instead.  */
1129e4b17023SJohn Marino static const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX;
1130e4b17023SJohn Marino static const char *const standard_libexec_prefix = STANDARD_LIBEXEC_PREFIX;
1131e4b17023SJohn Marino static const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
1132e4b17023SJohn Marino static const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
1133e4b17023SJohn Marino 
1134e4b17023SJohn Marino /* For native compilers, these are well-known paths containing
1135e4b17023SJohn Marino    components that may be provided by the system.  For cross
1136e4b17023SJohn Marino    compilers, these paths are not used.  */
1137e4b17023SJohn Marino static const char *md_exec_prefix = MD_EXEC_PREFIX;
1138e4b17023SJohn Marino static const char *md_startfile_prefix = MD_STARTFILE_PREFIX;
1139e4b17023SJohn Marino static const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
1140e4b17023SJohn Marino static const char *const standard_startfile_prefix_1
1141e4b17023SJohn Marino   = STANDARD_STARTFILE_PREFIX_1;
1142e4b17023SJohn Marino static const char *const standard_startfile_prefix_2
1143e4b17023SJohn Marino   = STANDARD_STARTFILE_PREFIX_2;
1144e4b17023SJohn Marino 
1145e4b17023SJohn Marino /* A relative path to be used in finding the location of tools
1146e4b17023SJohn Marino    relative to the driver.  */
1147e4b17023SJohn Marino static const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
1148e4b17023SJohn Marino 
1149e4b17023SJohn Marino /* Subdirectory to use for locating libraries.  Set by
1150e4b17023SJohn Marino    set_multilib_dir based on the compilation options.  */
1151e4b17023SJohn Marino 
1152e4b17023SJohn Marino static const char *multilib_dir;
1153e4b17023SJohn Marino 
1154e4b17023SJohn Marino /* Subdirectory to use for locating libraries in OS conventions.  Set by
1155e4b17023SJohn Marino    set_multilib_dir based on the compilation options.  */
1156e4b17023SJohn Marino 
1157e4b17023SJohn Marino static const char *multilib_os_dir;
11585ce9237cSJohn Marino 
11595ce9237cSJohn Marino /* Subdirectory to use for locating libraries in multiarch conventions.  Set by
11605ce9237cSJohn Marino    set_multilib_dir based on the compilation options.  */
11615ce9237cSJohn Marino 
11625ce9237cSJohn Marino static const char *multiarch_dir;
1163e4b17023SJohn Marino 
1164e4b17023SJohn Marino /* Structure to keep track of the specs that have been defined so far.
1165e4b17023SJohn Marino    These are accessed using %(specname) in a compiler or link
1166e4b17023SJohn Marino    spec.  */
1167e4b17023SJohn Marino 
1168e4b17023SJohn Marino struct spec_list
1169e4b17023SJohn Marino {
1170e4b17023SJohn Marino 				/* The following 2 fields must be first */
1171e4b17023SJohn Marino 				/* to allow EXTRA_SPECS to be initialized */
1172e4b17023SJohn Marino   const char *name;		/* name of the spec.  */
1173e4b17023SJohn Marino   const char *ptr;		/* available ptr if no static pointer */
1174e4b17023SJohn Marino 
1175e4b17023SJohn Marino 				/* The following fields are not initialized */
1176e4b17023SJohn Marino 				/* by EXTRA_SPECS */
1177e4b17023SJohn Marino   const char **ptr_spec;	/* pointer to the spec itself.  */
1178e4b17023SJohn Marino   struct spec_list *next;	/* Next spec in linked list.  */
1179e4b17023SJohn Marino   int name_len;			/* length of the name */
1180e4b17023SJohn Marino   int alloc_p;			/* whether string was allocated */
1181e4b17023SJohn Marino };
1182e4b17023SJohn Marino 
1183e4b17023SJohn Marino #define INIT_STATIC_SPEC(NAME,PTR) \
1184e4b17023SJohn Marino { NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, 0 }
1185e4b17023SJohn Marino 
1186e4b17023SJohn Marino /* List of statically defined specs.  */
1187e4b17023SJohn Marino static struct spec_list static_specs[] =
1188e4b17023SJohn Marino {
1189e4b17023SJohn Marino   INIT_STATIC_SPEC ("asm",			&asm_spec),
1190e4b17023SJohn Marino   INIT_STATIC_SPEC ("asm_debug",		&asm_debug),
1191e4b17023SJohn Marino   INIT_STATIC_SPEC ("asm_final",		&asm_final_spec),
1192e4b17023SJohn Marino   INIT_STATIC_SPEC ("asm_options",		&asm_options),
1193e4b17023SJohn Marino   INIT_STATIC_SPEC ("invoke_as",		&invoke_as),
1194e4b17023SJohn Marino   INIT_STATIC_SPEC ("cpp",			&cpp_spec),
1195e4b17023SJohn Marino   INIT_STATIC_SPEC ("cpp_options",		&cpp_options),
1196e4b17023SJohn Marino   INIT_STATIC_SPEC ("cpp_debug_options",	&cpp_debug_options),
1197e4b17023SJohn Marino   INIT_STATIC_SPEC ("cpp_unique_options",	&cpp_unique_options),
1198e4b17023SJohn Marino   INIT_STATIC_SPEC ("trad_capable_cpp",		&trad_capable_cpp),
1199e4b17023SJohn Marino   INIT_STATIC_SPEC ("cc1",			&cc1_spec),
1200e4b17023SJohn Marino   INIT_STATIC_SPEC ("cc1_options",		&cc1_options),
1201e4b17023SJohn Marino   INIT_STATIC_SPEC ("cc1plus",			&cc1plus_spec),
1202e4b17023SJohn Marino   INIT_STATIC_SPEC ("link_gcc_c_sequence",	&link_gcc_c_sequence_spec),
1203e4b17023SJohn Marino   INIT_STATIC_SPEC ("link_ssp",			&link_ssp_spec),
1204e4b17023SJohn Marino   INIT_STATIC_SPEC ("endfile",			&endfile_spec),
1205e4b17023SJohn Marino   INIT_STATIC_SPEC ("link",			&link_spec),
1206e4b17023SJohn Marino   INIT_STATIC_SPEC ("lib",			&lib_spec),
1207e4b17023SJohn Marino   INIT_STATIC_SPEC ("mfwrap",			&mfwrap_spec),
1208e4b17023SJohn Marino   INIT_STATIC_SPEC ("mflib",			&mflib_spec),
1209e4b17023SJohn Marino   INIT_STATIC_SPEC ("link_gomp",		&link_gomp_spec),
1210e4b17023SJohn Marino   INIT_STATIC_SPEC ("libgcc",			&libgcc_spec),
1211e4b17023SJohn Marino   INIT_STATIC_SPEC ("startfile",		&startfile_spec),
1212e4b17023SJohn Marino   INIT_STATIC_SPEC ("cross_compile",		&cross_compile),
1213e4b17023SJohn Marino   INIT_STATIC_SPEC ("version",			&compiler_version),
1214e4b17023SJohn Marino   INIT_STATIC_SPEC ("multilib",			&multilib_select),
1215e4b17023SJohn Marino   INIT_STATIC_SPEC ("multilib_defaults",	&multilib_defaults),
1216e4b17023SJohn Marino   INIT_STATIC_SPEC ("multilib_extra",		&multilib_extra),
1217e4b17023SJohn Marino   INIT_STATIC_SPEC ("multilib_matches",		&multilib_matches),
1218e4b17023SJohn Marino   INIT_STATIC_SPEC ("multilib_exclusions",	&multilib_exclusions),
1219e4b17023SJohn Marino   INIT_STATIC_SPEC ("multilib_options",		&multilib_options),
1220e4b17023SJohn Marino   INIT_STATIC_SPEC ("linker",			&linker_name_spec),
1221e4b17023SJohn Marino   INIT_STATIC_SPEC ("linker_plugin_file",	&linker_plugin_file_spec),
1222e4b17023SJohn Marino   INIT_STATIC_SPEC ("lto_wrapper",		&lto_wrapper_spec),
1223e4b17023SJohn Marino   INIT_STATIC_SPEC ("lto_gcc",			&lto_gcc_spec),
1224e4b17023SJohn Marino   INIT_STATIC_SPEC ("link_libgcc",		&link_libgcc_spec),
1225e4b17023SJohn Marino   INIT_STATIC_SPEC ("md_exec_prefix",		&md_exec_prefix),
1226e4b17023SJohn Marino   INIT_STATIC_SPEC ("md_startfile_prefix",	&md_startfile_prefix),
1227e4b17023SJohn Marino   INIT_STATIC_SPEC ("md_startfile_prefix_1",	&md_startfile_prefix_1),
1228e4b17023SJohn Marino   INIT_STATIC_SPEC ("startfile_prefix_spec",	&startfile_prefix_spec),
1229e4b17023SJohn Marino   INIT_STATIC_SPEC ("sysroot_spec",             &sysroot_spec),
1230e4b17023SJohn Marino   INIT_STATIC_SPEC ("sysroot_suffix_spec",	&sysroot_suffix_spec),
1231e4b17023SJohn Marino   INIT_STATIC_SPEC ("sysroot_hdrs_suffix_spec",	&sysroot_hdrs_suffix_spec),
1232e4b17023SJohn Marino   INIT_STATIC_SPEC ("self_spec",		&self_spec),
1233e4b17023SJohn Marino };
1234e4b17023SJohn Marino 
1235e4b17023SJohn Marino #ifdef EXTRA_SPECS		/* additional specs needed */
1236e4b17023SJohn Marino /* Structure to keep track of just the first two args of a spec_list.
1237e4b17023SJohn Marino    That is all that the EXTRA_SPECS macro gives us.  */
1238e4b17023SJohn Marino struct spec_list_1
1239e4b17023SJohn Marino {
1240e4b17023SJohn Marino   const char *const name;
1241e4b17023SJohn Marino   const char *const ptr;
1242e4b17023SJohn Marino };
1243e4b17023SJohn Marino 
1244e4b17023SJohn Marino static const struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
1245e4b17023SJohn Marino static struct spec_list *extra_specs = (struct spec_list *) 0;
1246e4b17023SJohn Marino #endif
1247e4b17023SJohn Marino 
1248e4b17023SJohn Marino /* List of dynamically allocates specs that have been defined so far.  */
1249e4b17023SJohn Marino 
1250e4b17023SJohn Marino static struct spec_list *specs = (struct spec_list *) 0;
1251e4b17023SJohn Marino 
1252e4b17023SJohn Marino /* List of static spec functions.  */
1253e4b17023SJohn Marino 
1254e4b17023SJohn Marino static const struct spec_function static_spec_functions[] =
1255e4b17023SJohn Marino {
1256e4b17023SJohn Marino   { "getenv",                   getenv_spec_function },
1257e4b17023SJohn Marino   { "if-exists",		if_exists_spec_function },
1258e4b17023SJohn Marino   { "if-exists-else",		if_exists_else_spec_function },
1259e4b17023SJohn Marino   { "replace-outfile",		replace_outfile_spec_function },
1260e4b17023SJohn Marino   { "remove-outfile",		remove_outfile_spec_function },
1261e4b17023SJohn Marino   { "version-compare",		version_compare_spec_function },
1262e4b17023SJohn Marino   { "include",			include_spec_function },
1263e4b17023SJohn Marino   { "find-file",		find_file_spec_function },
1264e4b17023SJohn Marino   { "find-plugindir",		find_plugindir_spec_function },
1265e4b17023SJohn Marino   { "print-asm-header",		print_asm_header_spec_function },
1266e4b17023SJohn Marino   { "compare-debug-dump-opt",	compare_debug_dump_opt_spec_function },
1267e4b17023SJohn Marino   { "compare-debug-self-opt",	compare_debug_self_opt_spec_function },
1268e4b17023SJohn Marino   { "compare-debug-auxbase-opt", compare_debug_auxbase_opt_spec_function },
1269e4b17023SJohn Marino   { "pass-through-libs",	pass_through_libs_spec_func },
1270e4b17023SJohn Marino #ifdef EXTRA_SPEC_FUNCTIONS
1271e4b17023SJohn Marino   EXTRA_SPEC_FUNCTIONS
1272e4b17023SJohn Marino #endif
1273e4b17023SJohn Marino   { 0, 0 }
1274e4b17023SJohn Marino };
1275e4b17023SJohn Marino 
1276e4b17023SJohn Marino static int processing_spec_function;
1277e4b17023SJohn Marino 
1278e4b17023SJohn Marino /* Add appropriate libgcc specs to OBSTACK, taking into account
1279e4b17023SJohn Marino    various permutations of -shared-libgcc, -shared, and such.  */
1280e4b17023SJohn Marino 
1281e4b17023SJohn Marino #if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC)
1282e4b17023SJohn Marino 
1283e4b17023SJohn Marino #ifndef USE_LD_AS_NEEDED
1284e4b17023SJohn Marino #define USE_LD_AS_NEEDED 0
1285e4b17023SJohn Marino #endif
1286e4b17023SJohn Marino 
1287e4b17023SJohn Marino static void
init_gcc_specs(struct obstack * obstack,const char * shared_name,const char * static_name,const char * eh_name)1288e4b17023SJohn Marino init_gcc_specs (struct obstack *obstack, const char *shared_name,
1289e4b17023SJohn Marino 		const char *static_name, const char *eh_name)
1290e4b17023SJohn Marino {
1291e4b17023SJohn Marino   char *buf;
1292e4b17023SJohn Marino 
1293e4b17023SJohn Marino   buf = concat ("%{static|static-libgcc:", static_name, " ", eh_name, "}"
1294e4b17023SJohn Marino 		"%{!static:%{!static-libgcc:"
1295e4b17023SJohn Marino #if USE_LD_AS_NEEDED
1296e4b17023SJohn Marino 		"%{!shared-libgcc:",
1297e4b17023SJohn Marino 		static_name, " --as-needed ", shared_name, " --no-as-needed"
1298e4b17023SJohn Marino 		"}"
1299e4b17023SJohn Marino 		"%{shared-libgcc:",
1300e4b17023SJohn Marino 		shared_name, "%{!shared: ", static_name, "}"
1301e4b17023SJohn Marino 		"}"
1302e4b17023SJohn Marino #else
1303e4b17023SJohn Marino 		"%{!shared:"
1304e4b17023SJohn Marino 		"%{!shared-libgcc:", static_name, " ", eh_name, "}"
1305e4b17023SJohn Marino 		"%{shared-libgcc:", shared_name, " ", static_name, "}"
1306e4b17023SJohn Marino 		"}"
1307e4b17023SJohn Marino #ifdef LINK_EH_SPEC
1308e4b17023SJohn Marino 		"%{shared:"
1309e4b17023SJohn Marino 		"%{shared-libgcc:", shared_name, "}"
1310e4b17023SJohn Marino 		"%{!shared-libgcc:", static_name, "}"
1311e4b17023SJohn Marino 		"}"
1312e4b17023SJohn Marino #else
1313e4b17023SJohn Marino 		"%{shared:", shared_name, "}"
1314e4b17023SJohn Marino #endif
1315e4b17023SJohn Marino #endif
1316e4b17023SJohn Marino 		"}}", NULL);
1317e4b17023SJohn Marino 
1318e4b17023SJohn Marino   obstack_grow (obstack, buf, strlen (buf));
1319e4b17023SJohn Marino   free (buf);
1320e4b17023SJohn Marino }
1321e4b17023SJohn Marino #endif /* ENABLE_SHARED_LIBGCC */
1322e4b17023SJohn Marino 
1323e4b17023SJohn Marino /* Initialize the specs lookup routines.  */
1324e4b17023SJohn Marino 
1325e4b17023SJohn Marino static void
init_spec(void)1326e4b17023SJohn Marino init_spec (void)
1327e4b17023SJohn Marino {
1328e4b17023SJohn Marino   struct spec_list *next = (struct spec_list *) 0;
1329e4b17023SJohn Marino   struct spec_list *sl   = (struct spec_list *) 0;
1330e4b17023SJohn Marino   int i;
1331e4b17023SJohn Marino 
1332e4b17023SJohn Marino   if (specs)
1333e4b17023SJohn Marino     return;			/* Already initialized.  */
1334e4b17023SJohn Marino 
1335e4b17023SJohn Marino   if (verbose_flag)
1336e4b17023SJohn Marino     fnotice (stderr, "Using built-in specs.\n");
1337e4b17023SJohn Marino 
1338e4b17023SJohn Marino #ifdef EXTRA_SPECS
1339e4b17023SJohn Marino   extra_specs = XCNEWVEC (struct spec_list, ARRAY_SIZE (extra_specs_1));
1340e4b17023SJohn Marino 
1341e4b17023SJohn Marino   for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--)
1342e4b17023SJohn Marino     {
1343e4b17023SJohn Marino       sl = &extra_specs[i];
1344e4b17023SJohn Marino       sl->name = extra_specs_1[i].name;
1345e4b17023SJohn Marino       sl->ptr = extra_specs_1[i].ptr;
1346e4b17023SJohn Marino       sl->next = next;
1347e4b17023SJohn Marino       sl->name_len = strlen (sl->name);
1348e4b17023SJohn Marino       sl->ptr_spec = &sl->ptr;
1349e4b17023SJohn Marino       next = sl;
1350e4b17023SJohn Marino     }
1351e4b17023SJohn Marino #endif
1352e4b17023SJohn Marino 
1353e4b17023SJohn Marino   for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
1354e4b17023SJohn Marino     {
1355e4b17023SJohn Marino       sl = &static_specs[i];
1356e4b17023SJohn Marino       sl->next = next;
1357e4b17023SJohn Marino       next = sl;
1358e4b17023SJohn Marino     }
1359e4b17023SJohn Marino 
1360e4b17023SJohn Marino #if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC)
1361e4b17023SJohn Marino   /* ??? If neither -shared-libgcc nor --static-libgcc was
1362e4b17023SJohn Marino      seen, then we should be making an educated guess.  Some proposed
1363e4b17023SJohn Marino      heuristics for ELF include:
1364e4b17023SJohn Marino 
1365e4b17023SJohn Marino 	(1) If "-Wl,--export-dynamic", then it's a fair bet that the
1366e4b17023SJohn Marino 	    program will be doing dynamic loading, which will likely
1367e4b17023SJohn Marino 	    need the shared libgcc.
1368e4b17023SJohn Marino 
1369e4b17023SJohn Marino 	(2) If "-ldl", then it's also a fair bet that we're doing
1370e4b17023SJohn Marino 	    dynamic loading.
1371e4b17023SJohn Marino 
1372e4b17023SJohn Marino 	(3) For each ET_DYN we're linking against (either through -lfoo
1373e4b17023SJohn Marino 	    or /some/path/foo.so), check to see whether it or one of
1374e4b17023SJohn Marino 	    its dependencies depends on a shared libgcc.
1375e4b17023SJohn Marino 
1376e4b17023SJohn Marino 	(4) If "-shared"
1377e4b17023SJohn Marino 
1378e4b17023SJohn Marino 	    If the runtime is fixed to look for program headers instead
1379e4b17023SJohn Marino 	    of calling __register_frame_info at all, for each object,
1380e4b17023SJohn Marino 	    use the shared libgcc if any EH symbol referenced.
1381e4b17023SJohn Marino 
1382e4b17023SJohn Marino 	    If crtstuff is fixed to not invoke __register_frame_info
1383e4b17023SJohn Marino 	    automatically, for each object, use the shared libgcc if
1384e4b17023SJohn Marino 	    any non-empty unwind section found.
1385e4b17023SJohn Marino 
1386e4b17023SJohn Marino      Doing any of this probably requires invoking an external program to
1387e4b17023SJohn Marino      do the actual object file scanning.  */
1388e4b17023SJohn Marino   {
1389e4b17023SJohn Marino     const char *p = libgcc_spec;
1390e4b17023SJohn Marino     int in_sep = 1;
1391e4b17023SJohn Marino 
1392e4b17023SJohn Marino     /* Transform the extant libgcc_spec into one that uses the shared libgcc
1393e4b17023SJohn Marino        when given the proper command line arguments.  */
1394e4b17023SJohn Marino     while (*p)
1395e4b17023SJohn Marino       {
1396e4b17023SJohn Marino 	if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0)
1397e4b17023SJohn Marino 	  {
1398e4b17023SJohn Marino 	    init_gcc_specs (&obstack,
1399e4b17023SJohn Marino 			    "-lgcc_s"
1400e4b17023SJohn Marino #ifdef USE_LIBUNWIND_EXCEPTIONS
1401e4b17023SJohn Marino 			    " -lunwind"
1402e4b17023SJohn Marino #endif
1403e4b17023SJohn Marino 			    ,
1404e4b17023SJohn Marino 			    "-lgcc",
1405e4b17023SJohn Marino 			    "-lgcc_eh"
1406e4b17023SJohn Marino #ifdef USE_LIBUNWIND_EXCEPTIONS
1407e4b17023SJohn Marino # ifdef HAVE_LD_STATIC_DYNAMIC
1408e4b17023SJohn Marino 			    " %{!static:" LD_STATIC_OPTION "} -lunwind"
1409e4b17023SJohn Marino 			    " %{!static:" LD_DYNAMIC_OPTION "}"
1410e4b17023SJohn Marino # else
1411e4b17023SJohn Marino 			    " -lunwind"
1412e4b17023SJohn Marino # endif
1413e4b17023SJohn Marino #endif
1414e4b17023SJohn Marino 			    );
1415e4b17023SJohn Marino 
1416e4b17023SJohn Marino 	    p += 5;
1417e4b17023SJohn Marino 	    in_sep = 0;
1418e4b17023SJohn Marino 	  }
1419e4b17023SJohn Marino 	else if (in_sep && *p == 'l' && strncmp (p, "libgcc.a%s", 10) == 0)
1420e4b17023SJohn Marino 	  {
1421e4b17023SJohn Marino 	    /* Ug.  We don't know shared library extensions.  Hope that
1422e4b17023SJohn Marino 	       systems that use this form don't do shared libraries.  */
1423e4b17023SJohn Marino 	    init_gcc_specs (&obstack,
1424e4b17023SJohn Marino 			    "-lgcc_s",
1425e4b17023SJohn Marino 			    "libgcc.a%s",
1426e4b17023SJohn Marino 			    "libgcc_eh.a%s"
1427e4b17023SJohn Marino #ifdef USE_LIBUNWIND_EXCEPTIONS
1428e4b17023SJohn Marino 			    " -lunwind"
1429e4b17023SJohn Marino #endif
1430e4b17023SJohn Marino 			    );
1431e4b17023SJohn Marino 	    p += 10;
1432e4b17023SJohn Marino 	    in_sep = 0;
1433e4b17023SJohn Marino 	  }
1434e4b17023SJohn Marino 	else
1435e4b17023SJohn Marino 	  {
1436e4b17023SJohn Marino 	    obstack_1grow (&obstack, *p);
1437e4b17023SJohn Marino 	    in_sep = (*p == ' ');
1438e4b17023SJohn Marino 	    p += 1;
1439e4b17023SJohn Marino 	  }
1440e4b17023SJohn Marino       }
1441e4b17023SJohn Marino 
1442e4b17023SJohn Marino     obstack_1grow (&obstack, '\0');
1443e4b17023SJohn Marino     libgcc_spec = XOBFINISH (&obstack, const char *);
1444e4b17023SJohn Marino   }
1445e4b17023SJohn Marino #endif
1446e4b17023SJohn Marino #ifdef USE_AS_TRADITIONAL_FORMAT
1447e4b17023SJohn Marino   /* Prepend "--traditional-format" to whatever asm_spec we had before.  */
1448e4b17023SJohn Marino   {
1449e4b17023SJohn Marino     static const char tf[] = "--traditional-format ";
1450e4b17023SJohn Marino     obstack_grow (&obstack, tf, sizeof(tf) - 1);
1451e4b17023SJohn Marino     obstack_grow0 (&obstack, asm_spec, strlen (asm_spec));
1452e4b17023SJohn Marino     asm_spec = XOBFINISH (&obstack, const char *);
1453e4b17023SJohn Marino   }
1454e4b17023SJohn Marino #endif
1455e4b17023SJohn Marino 
1456e4b17023SJohn Marino #if defined LINK_EH_SPEC || defined LINK_BUILDID_SPEC || \
1457e4b17023SJohn Marino     defined LINKER_HASH_STYLE
1458e4b17023SJohn Marino # ifdef LINK_BUILDID_SPEC
1459e4b17023SJohn Marino   /* Prepend LINK_BUILDID_SPEC to whatever link_spec we had before.  */
1460e4b17023SJohn Marino   obstack_grow (&obstack, LINK_BUILDID_SPEC, sizeof(LINK_BUILDID_SPEC) - 1);
1461e4b17023SJohn Marino # endif
1462e4b17023SJohn Marino # ifdef LINK_EH_SPEC
1463e4b17023SJohn Marino   /* Prepend LINK_EH_SPEC to whatever link_spec we had before.  */
1464e4b17023SJohn Marino   obstack_grow (&obstack, LINK_EH_SPEC, sizeof(LINK_EH_SPEC) - 1);
1465e4b17023SJohn Marino # endif
1466e4b17023SJohn Marino # ifdef LINKER_HASH_STYLE
1467e4b17023SJohn Marino   /* Prepend --hash-style=LINKER_HASH_STYLE to whatever link_spec we had
1468e4b17023SJohn Marino      before.  */
1469e4b17023SJohn Marino   {
1470e4b17023SJohn Marino     static const char hash_style[] = "--hash-style=";
1471e4b17023SJohn Marino     obstack_grow (&obstack, hash_style, sizeof(hash_style) - 1);
1472e4b17023SJohn Marino     obstack_grow (&obstack, LINKER_HASH_STYLE, sizeof(LINKER_HASH_STYLE) - 1);
1473e4b17023SJohn Marino     obstack_1grow (&obstack, ' ');
1474e4b17023SJohn Marino   }
1475e4b17023SJohn Marino # endif
1476e4b17023SJohn Marino   obstack_grow0 (&obstack, link_spec, strlen (link_spec));
1477e4b17023SJohn Marino   link_spec = XOBFINISH (&obstack, const char *);
1478e4b17023SJohn Marino #endif
1479e4b17023SJohn Marino 
1480e4b17023SJohn Marino   specs = sl;
1481e4b17023SJohn Marino }
1482e4b17023SJohn Marino 
1483e4b17023SJohn Marino /* Change the value of spec NAME to SPEC.  If SPEC is empty, then the spec is
1484e4b17023SJohn Marino    removed; If the spec starts with a + then SPEC is added to the end of the
1485e4b17023SJohn Marino    current spec.  */
1486e4b17023SJohn Marino 
1487e4b17023SJohn Marino static void
set_spec(const char * name,const char * spec)1488e4b17023SJohn Marino set_spec (const char *name, const char *spec)
1489e4b17023SJohn Marino {
1490e4b17023SJohn Marino   struct spec_list *sl;
1491e4b17023SJohn Marino   const char *old_spec;
1492e4b17023SJohn Marino   int name_len = strlen (name);
1493e4b17023SJohn Marino   int i;
1494e4b17023SJohn Marino 
1495e4b17023SJohn Marino   /* If this is the first call, initialize the statically allocated specs.  */
1496e4b17023SJohn Marino   if (!specs)
1497e4b17023SJohn Marino     {
1498e4b17023SJohn Marino       struct spec_list *next = (struct spec_list *) 0;
1499e4b17023SJohn Marino       for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
1500e4b17023SJohn Marino 	{
1501e4b17023SJohn Marino 	  sl = &static_specs[i];
1502e4b17023SJohn Marino 	  sl->next = next;
1503e4b17023SJohn Marino 	  next = sl;
1504e4b17023SJohn Marino 	}
1505e4b17023SJohn Marino       specs = sl;
1506e4b17023SJohn Marino     }
1507e4b17023SJohn Marino 
1508e4b17023SJohn Marino   /* See if the spec already exists.  */
1509e4b17023SJohn Marino   for (sl = specs; sl; sl = sl->next)
1510e4b17023SJohn Marino     if (name_len == sl->name_len && !strcmp (sl->name, name))
1511e4b17023SJohn Marino       break;
1512e4b17023SJohn Marino 
1513e4b17023SJohn Marino   if (!sl)
1514e4b17023SJohn Marino     {
1515e4b17023SJohn Marino       /* Not found - make it.  */
1516e4b17023SJohn Marino       sl = XNEW (struct spec_list);
1517e4b17023SJohn Marino       sl->name = xstrdup (name);
1518e4b17023SJohn Marino       sl->name_len = name_len;
1519e4b17023SJohn Marino       sl->ptr_spec = &sl->ptr;
1520e4b17023SJohn Marino       sl->alloc_p = 0;
1521e4b17023SJohn Marino       *(sl->ptr_spec) = "";
1522e4b17023SJohn Marino       sl->next = specs;
1523e4b17023SJohn Marino       specs = sl;
1524e4b17023SJohn Marino     }
1525e4b17023SJohn Marino 
1526e4b17023SJohn Marino   old_spec = *(sl->ptr_spec);
1527e4b17023SJohn Marino   *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1]))
1528e4b17023SJohn Marino 		     ? concat (old_spec, spec + 1, NULL)
1529e4b17023SJohn Marino 		     : xstrdup (spec));
1530e4b17023SJohn Marino 
1531e4b17023SJohn Marino #ifdef DEBUG_SPECS
1532e4b17023SJohn Marino   if (verbose_flag)
1533e4b17023SJohn Marino     fnotice (stderr, "Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
1534e4b17023SJohn Marino #endif
1535e4b17023SJohn Marino 
1536e4b17023SJohn Marino   /* Free the old spec.  */
1537e4b17023SJohn Marino   if (old_spec && sl->alloc_p)
1538e4b17023SJohn Marino     free (CONST_CAST(char *, old_spec));
1539e4b17023SJohn Marino 
1540e4b17023SJohn Marino   sl->alloc_p = 1;
1541e4b17023SJohn Marino }
1542e4b17023SJohn Marino 
1543e4b17023SJohn Marino /* Accumulate a command (program name and args), and run it.  */
1544e4b17023SJohn Marino 
1545e4b17023SJohn Marino typedef const char *const_char_p; /* For DEF_VEC_P.  */
1546e4b17023SJohn Marino DEF_VEC_P(const_char_p);
1547e4b17023SJohn Marino DEF_VEC_ALLOC_P(const_char_p,heap);
1548e4b17023SJohn Marino 
1549e4b17023SJohn Marino /* Vector of pointers to arguments in the current line of specifications.  */
1550e4b17023SJohn Marino 
1551e4b17023SJohn Marino static VEC(const_char_p,heap) *argbuf;
1552e4b17023SJohn Marino 
1553e4b17023SJohn Marino /* Position in the argbuf vector containing the name of the output file
1554e4b17023SJohn Marino    (the value associated with the "-o" flag).  */
1555e4b17023SJohn Marino 
1556e4b17023SJohn Marino static int have_o_argbuf_index = 0;
1557e4b17023SJohn Marino 
1558e4b17023SJohn Marino /* Were the options -c, -S or -E passed.  */
1559e4b17023SJohn Marino static int have_c = 0;
1560e4b17023SJohn Marino 
1561e4b17023SJohn Marino /* Was the option -o passed.  */
1562e4b17023SJohn Marino static int have_o = 0;
1563e4b17023SJohn Marino 
1564e4b17023SJohn Marino /* This is the list of suffixes and codes (%g/%u/%U/%j) and the associated
1565e4b17023SJohn Marino    temp file.  If the HOST_BIT_BUCKET is used for %j, no entry is made for
1566e4b17023SJohn Marino    it here.  */
1567e4b17023SJohn Marino 
1568e4b17023SJohn Marino static struct temp_name {
1569e4b17023SJohn Marino   const char *suffix;	/* suffix associated with the code.  */
1570e4b17023SJohn Marino   int length;		/* strlen (suffix).  */
1571e4b17023SJohn Marino   int unique;		/* Indicates whether %g or %u/%U was used.  */
1572e4b17023SJohn Marino   const char *filename;	/* associated filename.  */
1573e4b17023SJohn Marino   int filename_length;	/* strlen (filename).  */
1574e4b17023SJohn Marino   struct temp_name *next;
1575e4b17023SJohn Marino } *temp_names;
1576e4b17023SJohn Marino 
1577e4b17023SJohn Marino /* Number of commands executed so far.  */
1578e4b17023SJohn Marino 
1579e4b17023SJohn Marino static int execution_count;
1580e4b17023SJohn Marino 
1581e4b17023SJohn Marino /* Number of commands that exited with a signal.  */
1582e4b17023SJohn Marino 
1583e4b17023SJohn Marino static int signal_count;
1584e4b17023SJohn Marino 
1585e4b17023SJohn Marino /* Allocate the argument vector.  */
1586e4b17023SJohn Marino 
1587e4b17023SJohn Marino static void
alloc_args(void)1588e4b17023SJohn Marino alloc_args (void)
1589e4b17023SJohn Marino {
1590e4b17023SJohn Marino   argbuf = VEC_alloc (const_char_p, heap, 10);
1591e4b17023SJohn Marino }
1592e4b17023SJohn Marino 
1593e4b17023SJohn Marino /* Clear out the vector of arguments (after a command is executed).  */
1594e4b17023SJohn Marino 
1595e4b17023SJohn Marino static void
clear_args(void)1596e4b17023SJohn Marino clear_args (void)
1597e4b17023SJohn Marino {
1598e4b17023SJohn Marino   VEC_truncate (const_char_p, argbuf, 0);
1599e4b17023SJohn Marino }
1600e4b17023SJohn Marino 
1601e4b17023SJohn Marino /* Add one argument to the vector at the end.
1602e4b17023SJohn Marino    This is done when a space is seen or at the end of the line.
1603e4b17023SJohn Marino    If DELETE_ALWAYS is nonzero, the arg is a filename
1604e4b17023SJohn Marino     and the file should be deleted eventually.
1605e4b17023SJohn Marino    If DELETE_FAILURE is nonzero, the arg is a filename
1606e4b17023SJohn Marino     and the file should be deleted if this compilation fails.  */
1607e4b17023SJohn Marino 
1608e4b17023SJohn Marino static void
store_arg(const char * arg,int delete_always,int delete_failure)1609e4b17023SJohn Marino store_arg (const char *arg, int delete_always, int delete_failure)
1610e4b17023SJohn Marino {
1611e4b17023SJohn Marino   VEC_safe_push (const_char_p, heap, argbuf, arg);
1612e4b17023SJohn Marino 
1613e4b17023SJohn Marino   if (strcmp (arg, "-o") == 0)
1614e4b17023SJohn Marino     have_o_argbuf_index = VEC_length (const_char_p, argbuf);
1615e4b17023SJohn Marino   if (delete_always || delete_failure)
1616e4b17023SJohn Marino     {
1617e4b17023SJohn Marino       const char *p;
1618e4b17023SJohn Marino       /* If the temporary file we should delete is specified as
1619e4b17023SJohn Marino 	 part of a joined argument extract the filename.  */
1620e4b17023SJohn Marino       if (arg[0] == '-'
1621e4b17023SJohn Marino 	  && (p = strrchr (arg, '=')))
1622e4b17023SJohn Marino 	arg = p + 1;
1623e4b17023SJohn Marino       record_temp_file (arg, delete_always, delete_failure);
1624e4b17023SJohn Marino     }
1625e4b17023SJohn Marino }
1626e4b17023SJohn Marino 
1627e4b17023SJohn Marino /* Load specs from a file name named FILENAME, replacing occurrences of
1628e4b17023SJohn Marino    various different types of line-endings, \r\n, \n\r and just \r, with
1629e4b17023SJohn Marino    a single \n.  */
1630e4b17023SJohn Marino 
1631e4b17023SJohn Marino static char *
load_specs(const char * filename)1632e4b17023SJohn Marino load_specs (const char *filename)
1633e4b17023SJohn Marino {
1634e4b17023SJohn Marino   int desc;
1635e4b17023SJohn Marino   int readlen;
1636e4b17023SJohn Marino   struct stat statbuf;
1637e4b17023SJohn Marino   char *buffer;
1638e4b17023SJohn Marino   char *buffer_p;
1639e4b17023SJohn Marino   char *specs;
1640e4b17023SJohn Marino   char *specs_p;
1641e4b17023SJohn Marino 
1642e4b17023SJohn Marino   if (verbose_flag)
1643e4b17023SJohn Marino     fnotice (stderr, "Reading specs from %s\n", filename);
1644e4b17023SJohn Marino 
1645e4b17023SJohn Marino   /* Open and stat the file.  */
1646e4b17023SJohn Marino   desc = open (filename, O_RDONLY, 0);
1647e4b17023SJohn Marino   if (desc < 0)
1648e4b17023SJohn Marino     pfatal_with_name (filename);
1649e4b17023SJohn Marino   if (stat (filename, &statbuf) < 0)
1650e4b17023SJohn Marino     pfatal_with_name (filename);
1651e4b17023SJohn Marino 
1652e4b17023SJohn Marino   /* Read contents of file into BUFFER.  */
1653e4b17023SJohn Marino   buffer = XNEWVEC (char, statbuf.st_size + 1);
1654e4b17023SJohn Marino   readlen = read (desc, buffer, (unsigned) statbuf.st_size);
1655e4b17023SJohn Marino   if (readlen < 0)
1656e4b17023SJohn Marino     pfatal_with_name (filename);
1657e4b17023SJohn Marino   buffer[readlen] = 0;
1658e4b17023SJohn Marino   close (desc);
1659e4b17023SJohn Marino 
1660e4b17023SJohn Marino   specs = XNEWVEC (char, readlen + 1);
1661e4b17023SJohn Marino   specs_p = specs;
1662e4b17023SJohn Marino   for (buffer_p = buffer; buffer_p && *buffer_p; buffer_p++)
1663e4b17023SJohn Marino     {
1664e4b17023SJohn Marino       int skip = 0;
1665e4b17023SJohn Marino       char c = *buffer_p;
1666e4b17023SJohn Marino       if (c == '\r')
1667e4b17023SJohn Marino 	{
1668e4b17023SJohn Marino 	  if (buffer_p > buffer && *(buffer_p - 1) == '\n')	/* \n\r */
1669e4b17023SJohn Marino 	    skip = 1;
1670e4b17023SJohn Marino 	  else if (*(buffer_p + 1) == '\n')			/* \r\n */
1671e4b17023SJohn Marino 	    skip = 1;
1672e4b17023SJohn Marino 	  else							/* \r */
1673e4b17023SJohn Marino 	    c = '\n';
1674e4b17023SJohn Marino 	}
1675e4b17023SJohn Marino       if (! skip)
1676e4b17023SJohn Marino 	*specs_p++ = c;
1677e4b17023SJohn Marino     }
1678e4b17023SJohn Marino   *specs_p = '\0';
1679e4b17023SJohn Marino 
1680e4b17023SJohn Marino   free (buffer);
1681e4b17023SJohn Marino   return (specs);
1682e4b17023SJohn Marino }
1683e4b17023SJohn Marino 
1684e4b17023SJohn Marino /* Read compilation specs from a file named FILENAME,
1685e4b17023SJohn Marino    replacing the default ones.
1686e4b17023SJohn Marino 
1687e4b17023SJohn Marino    A suffix which starts with `*' is a definition for
1688e4b17023SJohn Marino    one of the machine-specific sub-specs.  The "suffix" should be
1689e4b17023SJohn Marino    *asm, *cc1, *cpp, *link, *startfile, etc.
1690e4b17023SJohn Marino    The corresponding spec is stored in asm_spec, etc.,
1691e4b17023SJohn Marino    rather than in the `compilers' vector.
1692e4b17023SJohn Marino 
1693e4b17023SJohn Marino    Anything invalid in the file is a fatal error.  */
1694e4b17023SJohn Marino 
1695e4b17023SJohn Marino static void
read_specs(const char * filename,int main_p)1696e4b17023SJohn Marino read_specs (const char *filename, int main_p)
1697e4b17023SJohn Marino {
1698e4b17023SJohn Marino   char *buffer;
1699e4b17023SJohn Marino   char *p;
1700e4b17023SJohn Marino 
1701e4b17023SJohn Marino   buffer = load_specs (filename);
1702e4b17023SJohn Marino 
1703e4b17023SJohn Marino   /* Scan BUFFER for specs, putting them in the vector.  */
1704e4b17023SJohn Marino   p = buffer;
1705e4b17023SJohn Marino   while (1)
1706e4b17023SJohn Marino     {
1707e4b17023SJohn Marino       char *suffix;
1708e4b17023SJohn Marino       char *spec;
1709e4b17023SJohn Marino       char *in, *out, *p1, *p2, *p3;
1710e4b17023SJohn Marino 
1711e4b17023SJohn Marino       /* Advance P in BUFFER to the next nonblank nocomment line.  */
1712e4b17023SJohn Marino       p = skip_whitespace (p);
1713e4b17023SJohn Marino       if (*p == 0)
1714e4b17023SJohn Marino 	break;
1715e4b17023SJohn Marino 
1716e4b17023SJohn Marino       /* Is this a special command that starts with '%'? */
1717e4b17023SJohn Marino       /* Don't allow this for the main specs file, since it would
1718e4b17023SJohn Marino 	 encourage people to overwrite it.  */
1719e4b17023SJohn Marino       if (*p == '%' && !main_p)
1720e4b17023SJohn Marino 	{
1721e4b17023SJohn Marino 	  p1 = p;
1722e4b17023SJohn Marino 	  while (*p && *p != '\n')
1723e4b17023SJohn Marino 	    p++;
1724e4b17023SJohn Marino 
1725e4b17023SJohn Marino 	  /* Skip '\n'.  */
1726e4b17023SJohn Marino 	  p++;
1727e4b17023SJohn Marino 
1728e4b17023SJohn Marino 	  if (!strncmp (p1, "%include", sizeof ("%include") - 1)
1729e4b17023SJohn Marino 	      && (p1[sizeof "%include" - 1] == ' '
1730e4b17023SJohn Marino 		  || p1[sizeof "%include" - 1] == '\t'))
1731e4b17023SJohn Marino 	    {
1732e4b17023SJohn Marino 	      char *new_filename;
1733e4b17023SJohn Marino 
1734e4b17023SJohn Marino 	      p1 += sizeof ("%include");
1735e4b17023SJohn Marino 	      while (*p1 == ' ' || *p1 == '\t')
1736e4b17023SJohn Marino 		p1++;
1737e4b17023SJohn Marino 
1738e4b17023SJohn Marino 	      if (*p1++ != '<' || p[-2] != '>')
1739e4b17023SJohn Marino 		fatal_error ("specs %%include syntax malformed after "
1740e4b17023SJohn Marino 			     "%ld characters",
1741e4b17023SJohn Marino 			     (long) (p1 - buffer + 1));
1742e4b17023SJohn Marino 
1743e4b17023SJohn Marino 	      p[-2] = '\0';
1744e4b17023SJohn Marino 	      new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
1745e4b17023SJohn Marino 	      read_specs (new_filename ? new_filename : p1, FALSE);
1746e4b17023SJohn Marino 	      continue;
1747e4b17023SJohn Marino 	    }
1748e4b17023SJohn Marino 	  else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1)
1749e4b17023SJohn Marino 		   && (p1[sizeof "%include_noerr" - 1] == ' '
1750e4b17023SJohn Marino 		       || p1[sizeof "%include_noerr" - 1] == '\t'))
1751e4b17023SJohn Marino 	    {
1752e4b17023SJohn Marino 	      char *new_filename;
1753e4b17023SJohn Marino 
1754e4b17023SJohn Marino 	      p1 += sizeof "%include_noerr";
1755e4b17023SJohn Marino 	      while (*p1 == ' ' || *p1 == '\t')
1756e4b17023SJohn Marino 		p1++;
1757e4b17023SJohn Marino 
1758e4b17023SJohn Marino 	      if (*p1++ != '<' || p[-2] != '>')
1759e4b17023SJohn Marino 		fatal_error ("specs %%include syntax malformed after "
1760e4b17023SJohn Marino 			     "%ld characters",
1761e4b17023SJohn Marino 			     (long) (p1 - buffer + 1));
1762e4b17023SJohn Marino 
1763e4b17023SJohn Marino 	      p[-2] = '\0';
1764e4b17023SJohn Marino 	      new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
1765e4b17023SJohn Marino 	      if (new_filename)
1766e4b17023SJohn Marino 		read_specs (new_filename, FALSE);
1767e4b17023SJohn Marino 	      else if (verbose_flag)
1768e4b17023SJohn Marino 		fnotice (stderr, "could not find specs file %s\n", p1);
1769e4b17023SJohn Marino 	      continue;
1770e4b17023SJohn Marino 	    }
1771e4b17023SJohn Marino 	  else if (!strncmp (p1, "%rename", sizeof "%rename" - 1)
1772e4b17023SJohn Marino 		   && (p1[sizeof "%rename" - 1] == ' '
1773e4b17023SJohn Marino 		       || p1[sizeof "%rename" - 1] == '\t'))
1774e4b17023SJohn Marino 	    {
1775e4b17023SJohn Marino 	      int name_len;
1776e4b17023SJohn Marino 	      struct spec_list *sl;
1777e4b17023SJohn Marino 	      struct spec_list *newsl;
1778e4b17023SJohn Marino 
1779e4b17023SJohn Marino 	      /* Get original name.  */
1780e4b17023SJohn Marino 	      p1 += sizeof "%rename";
1781e4b17023SJohn Marino 	      while (*p1 == ' ' || *p1 == '\t')
1782e4b17023SJohn Marino 		p1++;
1783e4b17023SJohn Marino 
1784e4b17023SJohn Marino 	      if (! ISALPHA ((unsigned char) *p1))
1785e4b17023SJohn Marino 		fatal_error ("specs %%rename syntax malformed after "
1786e4b17023SJohn Marino 			     "%ld characters",
1787e4b17023SJohn Marino 			     (long) (p1 - buffer));
1788e4b17023SJohn Marino 
1789e4b17023SJohn Marino 	      p2 = p1;
1790e4b17023SJohn Marino 	      while (*p2 && !ISSPACE ((unsigned char) *p2))
1791e4b17023SJohn Marino 		p2++;
1792e4b17023SJohn Marino 
1793e4b17023SJohn Marino 	      if (*p2 != ' ' && *p2 != '\t')
1794e4b17023SJohn Marino 		fatal_error ("specs %%rename syntax malformed after "
1795e4b17023SJohn Marino 			     "%ld characters",
1796e4b17023SJohn Marino 			     (long) (p2 - buffer));
1797e4b17023SJohn Marino 
1798e4b17023SJohn Marino 	      name_len = p2 - p1;
1799e4b17023SJohn Marino 	      *p2++ = '\0';
1800e4b17023SJohn Marino 	      while (*p2 == ' ' || *p2 == '\t')
1801e4b17023SJohn Marino 		p2++;
1802e4b17023SJohn Marino 
1803e4b17023SJohn Marino 	      if (! ISALPHA ((unsigned char) *p2))
1804e4b17023SJohn Marino 		fatal_error ("specs %%rename syntax malformed after "
1805e4b17023SJohn Marino 			     "%ld characters",
1806e4b17023SJohn Marino 			     (long) (p2 - buffer));
1807e4b17023SJohn Marino 
1808e4b17023SJohn Marino 	      /* Get new spec name.  */
1809e4b17023SJohn Marino 	      p3 = p2;
1810e4b17023SJohn Marino 	      while (*p3 && !ISSPACE ((unsigned char) *p3))
1811e4b17023SJohn Marino 		p3++;
1812e4b17023SJohn Marino 
1813e4b17023SJohn Marino 	      if (p3 != p - 1)
1814e4b17023SJohn Marino 		fatal_error ("specs %%rename syntax malformed after "
1815e4b17023SJohn Marino 			     "%ld characters",
1816e4b17023SJohn Marino 			     (long) (p3 - buffer));
1817e4b17023SJohn Marino 	      *p3 = '\0';
1818e4b17023SJohn Marino 
1819e4b17023SJohn Marino 	      for (sl = specs; sl; sl = sl->next)
1820e4b17023SJohn Marino 		if (name_len == sl->name_len && !strcmp (sl->name, p1))
1821e4b17023SJohn Marino 		  break;
1822e4b17023SJohn Marino 
1823e4b17023SJohn Marino 	      if (!sl)
1824e4b17023SJohn Marino 		fatal_error ("specs %s spec was not found to be renamed", p1);
1825e4b17023SJohn Marino 
1826e4b17023SJohn Marino 	      if (strcmp (p1, p2) == 0)
1827e4b17023SJohn Marino 		continue;
1828e4b17023SJohn Marino 
1829e4b17023SJohn Marino 	      for (newsl = specs; newsl; newsl = newsl->next)
1830e4b17023SJohn Marino 		if (strcmp (newsl->name, p2) == 0)
1831e4b17023SJohn Marino 		  fatal_error ("%s: attempt to rename spec %qs to "
1832e4b17023SJohn Marino 			       "already defined spec %qs",
1833e4b17023SJohn Marino 		    filename, p1, p2);
1834e4b17023SJohn Marino 
1835e4b17023SJohn Marino 	      if (verbose_flag)
1836e4b17023SJohn Marino 		{
1837e4b17023SJohn Marino 		  fnotice (stderr, "rename spec %s to %s\n", p1, p2);
1838e4b17023SJohn Marino #ifdef DEBUG_SPECS
1839e4b17023SJohn Marino 		  fnotice (stderr, "spec is '%s'\n\n", *(sl->ptr_spec));
1840e4b17023SJohn Marino #endif
1841e4b17023SJohn Marino 		}
1842e4b17023SJohn Marino 
1843e4b17023SJohn Marino 	      set_spec (p2, *(sl->ptr_spec));
1844e4b17023SJohn Marino 	      if (sl->alloc_p)
1845e4b17023SJohn Marino 		free (CONST_CAST (char *, *(sl->ptr_spec)));
1846e4b17023SJohn Marino 
1847e4b17023SJohn Marino 	      *(sl->ptr_spec) = "";
1848e4b17023SJohn Marino 	      sl->alloc_p = 0;
1849e4b17023SJohn Marino 	      continue;
1850e4b17023SJohn Marino 	    }
1851e4b17023SJohn Marino 	  else
1852e4b17023SJohn Marino 	    fatal_error ("specs unknown %% command after %ld characters",
1853e4b17023SJohn Marino 			 (long) (p1 - buffer));
1854e4b17023SJohn Marino 	}
1855e4b17023SJohn Marino 
1856e4b17023SJohn Marino       /* Find the colon that should end the suffix.  */
1857e4b17023SJohn Marino       p1 = p;
1858e4b17023SJohn Marino       while (*p1 && *p1 != ':' && *p1 != '\n')
1859e4b17023SJohn Marino 	p1++;
1860e4b17023SJohn Marino 
1861e4b17023SJohn Marino       /* The colon shouldn't be missing.  */
1862e4b17023SJohn Marino       if (*p1 != ':')
1863e4b17023SJohn Marino 	fatal_error ("specs file malformed after %ld characters",
1864e4b17023SJohn Marino 		     (long) (p1 - buffer));
1865e4b17023SJohn Marino 
1866e4b17023SJohn Marino       /* Skip back over trailing whitespace.  */
1867e4b17023SJohn Marino       p2 = p1;
1868e4b17023SJohn Marino       while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t'))
1869e4b17023SJohn Marino 	p2--;
1870e4b17023SJohn Marino 
1871e4b17023SJohn Marino       /* Copy the suffix to a string.  */
1872e4b17023SJohn Marino       suffix = save_string (p, p2 - p);
1873e4b17023SJohn Marino       /* Find the next line.  */
1874e4b17023SJohn Marino       p = skip_whitespace (p1 + 1);
1875e4b17023SJohn Marino       if (p[1] == 0)
1876e4b17023SJohn Marino 	fatal_error ("specs file malformed after %ld characters",
1877e4b17023SJohn Marino 		     (long) (p - buffer));
1878e4b17023SJohn Marino 
1879e4b17023SJohn Marino       p1 = p;
1880e4b17023SJohn Marino       /* Find next blank line or end of string.  */
1881e4b17023SJohn Marino       while (*p1 && !(*p1 == '\n' && (p1[1] == '\n' || p1[1] == '\0')))
1882e4b17023SJohn Marino 	p1++;
1883e4b17023SJohn Marino 
1884e4b17023SJohn Marino       /* Specs end at the blank line and do not include the newline.  */
1885e4b17023SJohn Marino       spec = save_string (p, p1 - p);
1886e4b17023SJohn Marino       p = p1;
1887e4b17023SJohn Marino 
1888e4b17023SJohn Marino       /* Delete backslash-newline sequences from the spec.  */
1889e4b17023SJohn Marino       in = spec;
1890e4b17023SJohn Marino       out = spec;
1891e4b17023SJohn Marino       while (*in != 0)
1892e4b17023SJohn Marino 	{
1893e4b17023SJohn Marino 	  if (in[0] == '\\' && in[1] == '\n')
1894e4b17023SJohn Marino 	    in += 2;
1895e4b17023SJohn Marino 	  else if (in[0] == '#')
1896e4b17023SJohn Marino 	    while (*in && *in != '\n')
1897e4b17023SJohn Marino 	      in++;
1898e4b17023SJohn Marino 
1899e4b17023SJohn Marino 	  else
1900e4b17023SJohn Marino 	    *out++ = *in++;
1901e4b17023SJohn Marino 	}
1902e4b17023SJohn Marino       *out = 0;
1903e4b17023SJohn Marino 
1904e4b17023SJohn Marino       if (suffix[0] == '*')
1905e4b17023SJohn Marino 	{
1906e4b17023SJohn Marino 	  if (! strcmp (suffix, "*link_command"))
1907e4b17023SJohn Marino 	    link_command_spec = spec;
1908e4b17023SJohn Marino 	  else
1909e4b17023SJohn Marino 	    set_spec (suffix + 1, spec);
1910e4b17023SJohn Marino 	}
1911e4b17023SJohn Marino       else
1912e4b17023SJohn Marino 	{
1913e4b17023SJohn Marino 	  /* Add this pair to the vector.  */
1914e4b17023SJohn Marino 	  compilers
1915e4b17023SJohn Marino 	    = XRESIZEVEC (struct compiler, compilers, n_compilers + 2);
1916e4b17023SJohn Marino 
1917e4b17023SJohn Marino 	  compilers[n_compilers].suffix = suffix;
1918e4b17023SJohn Marino 	  compilers[n_compilers].spec = spec;
1919e4b17023SJohn Marino 	  n_compilers++;
1920e4b17023SJohn Marino 	  memset (&compilers[n_compilers], 0, sizeof compilers[n_compilers]);
1921e4b17023SJohn Marino 	}
1922e4b17023SJohn Marino 
1923e4b17023SJohn Marino       if (*suffix == 0)
1924e4b17023SJohn Marino 	link_command_spec = spec;
1925e4b17023SJohn Marino     }
1926e4b17023SJohn Marino 
1927e4b17023SJohn Marino   if (link_command_spec == 0)
1928e4b17023SJohn Marino     fatal_error ("spec file has no spec for linking");
1929e4b17023SJohn Marino }
1930e4b17023SJohn Marino 
1931e4b17023SJohn Marino /* Record the names of temporary files we tell compilers to write,
1932e4b17023SJohn Marino    and delete them at the end of the run.  */
1933e4b17023SJohn Marino 
1934e4b17023SJohn Marino /* This is the common prefix we use to make temp file names.
1935e4b17023SJohn Marino    It is chosen once for each run of this program.
1936e4b17023SJohn Marino    It is substituted into a spec by %g or %j.
1937e4b17023SJohn Marino    Thus, all temp file names contain this prefix.
1938e4b17023SJohn Marino    In practice, all temp file names start with this prefix.
1939e4b17023SJohn Marino 
1940e4b17023SJohn Marino    This prefix comes from the envvar TMPDIR if it is defined;
1941e4b17023SJohn Marino    otherwise, from the P_tmpdir macro if that is defined;
1942e4b17023SJohn Marino    otherwise, in /usr/tmp or /tmp;
1943e4b17023SJohn Marino    or finally the current directory if all else fails.  */
1944e4b17023SJohn Marino 
1945e4b17023SJohn Marino static const char *temp_filename;
1946e4b17023SJohn Marino 
1947e4b17023SJohn Marino /* Length of the prefix.  */
1948e4b17023SJohn Marino 
1949e4b17023SJohn Marino static int temp_filename_length;
1950e4b17023SJohn Marino 
1951e4b17023SJohn Marino /* Define the list of temporary files to delete.  */
1952e4b17023SJohn Marino 
1953e4b17023SJohn Marino struct temp_file
1954e4b17023SJohn Marino {
1955e4b17023SJohn Marino   const char *name;
1956e4b17023SJohn Marino   struct temp_file *next;
1957e4b17023SJohn Marino };
1958e4b17023SJohn Marino 
1959e4b17023SJohn Marino /* Queue of files to delete on success or failure of compilation.  */
1960e4b17023SJohn Marino static struct temp_file *always_delete_queue;
1961e4b17023SJohn Marino /* Queue of files to delete on failure of compilation.  */
1962e4b17023SJohn Marino static struct temp_file *failure_delete_queue;
1963e4b17023SJohn Marino 
1964e4b17023SJohn Marino /* Record FILENAME as a file to be deleted automatically.
1965e4b17023SJohn Marino    ALWAYS_DELETE nonzero means delete it if all compilation succeeds;
1966e4b17023SJohn Marino    otherwise delete it in any case.
1967e4b17023SJohn Marino    FAIL_DELETE nonzero means delete it if a compilation step fails;
1968e4b17023SJohn Marino    otherwise delete it in any case.  */
1969e4b17023SJohn Marino 
1970e4b17023SJohn Marino void
record_temp_file(const char * filename,int always_delete,int fail_delete)1971e4b17023SJohn Marino record_temp_file (const char *filename, int always_delete, int fail_delete)
1972e4b17023SJohn Marino {
1973e4b17023SJohn Marino   char *const name = xstrdup (filename);
1974e4b17023SJohn Marino 
1975e4b17023SJohn Marino   if (always_delete)
1976e4b17023SJohn Marino     {
1977e4b17023SJohn Marino       struct temp_file *temp;
1978e4b17023SJohn Marino       for (temp = always_delete_queue; temp; temp = temp->next)
1979e4b17023SJohn Marino 	if (! filename_cmp (name, temp->name))
1980e4b17023SJohn Marino 	  goto already1;
1981e4b17023SJohn Marino 
1982e4b17023SJohn Marino       temp = XNEW (struct temp_file);
1983e4b17023SJohn Marino       temp->next = always_delete_queue;
1984e4b17023SJohn Marino       temp->name = name;
1985e4b17023SJohn Marino       always_delete_queue = temp;
1986e4b17023SJohn Marino 
1987e4b17023SJohn Marino     already1:;
1988e4b17023SJohn Marino     }
1989e4b17023SJohn Marino 
1990e4b17023SJohn Marino   if (fail_delete)
1991e4b17023SJohn Marino     {
1992e4b17023SJohn Marino       struct temp_file *temp;
1993e4b17023SJohn Marino       for (temp = failure_delete_queue; temp; temp = temp->next)
1994e4b17023SJohn Marino 	if (! filename_cmp (name, temp->name))
1995e4b17023SJohn Marino 	  goto already2;
1996e4b17023SJohn Marino 
1997e4b17023SJohn Marino       temp = XNEW (struct temp_file);
1998e4b17023SJohn Marino       temp->next = failure_delete_queue;
1999e4b17023SJohn Marino       temp->name = name;
2000e4b17023SJohn Marino       failure_delete_queue = temp;
2001e4b17023SJohn Marino 
2002e4b17023SJohn Marino     already2:;
2003e4b17023SJohn Marino     }
2004e4b17023SJohn Marino }
2005e4b17023SJohn Marino 
2006e4b17023SJohn Marino /* Delete all the temporary files whose names we previously recorded.  */
2007e4b17023SJohn Marino 
2008e4b17023SJohn Marino #ifndef DELETE_IF_ORDINARY
2009e4b17023SJohn Marino #define DELETE_IF_ORDINARY(NAME,ST,VERBOSE_FLAG)        \
2010e4b17023SJohn Marino do                                                      \
2011e4b17023SJohn Marino   {                                                     \
2012e4b17023SJohn Marino     if (stat (NAME, &ST) >= 0 && S_ISREG (ST.st_mode))  \
2013e4b17023SJohn Marino       if (unlink (NAME) < 0)                            \
2014e4b17023SJohn Marino 	if (VERBOSE_FLAG)                               \
2015e4b17023SJohn Marino 	  perror_with_name (NAME);                      \
2016e4b17023SJohn Marino   } while (0)
2017e4b17023SJohn Marino #endif
2018e4b17023SJohn Marino 
2019e4b17023SJohn Marino static void
delete_if_ordinary(const char * name)2020e4b17023SJohn Marino delete_if_ordinary (const char *name)
2021e4b17023SJohn Marino {
2022e4b17023SJohn Marino   struct stat st;
2023e4b17023SJohn Marino #ifdef DEBUG
2024e4b17023SJohn Marino   int i, c;
2025e4b17023SJohn Marino 
2026e4b17023SJohn Marino   printf ("Delete %s? (y or n) ", name);
2027e4b17023SJohn Marino   fflush (stdout);
2028e4b17023SJohn Marino   i = getchar ();
2029e4b17023SJohn Marino   if (i != '\n')
2030e4b17023SJohn Marino     while ((c = getchar ()) != '\n' && c != EOF)
2031e4b17023SJohn Marino       ;
2032e4b17023SJohn Marino 
2033e4b17023SJohn Marino   if (i == 'y' || i == 'Y')
2034e4b17023SJohn Marino #endif /* DEBUG */
2035e4b17023SJohn Marino   DELETE_IF_ORDINARY (name, st, verbose_flag);
2036e4b17023SJohn Marino }
2037e4b17023SJohn Marino 
2038e4b17023SJohn Marino static void
delete_temp_files(void)2039e4b17023SJohn Marino delete_temp_files (void)
2040e4b17023SJohn Marino {
2041e4b17023SJohn Marino   struct temp_file *temp;
2042e4b17023SJohn Marino 
2043e4b17023SJohn Marino   for (temp = always_delete_queue; temp; temp = temp->next)
2044e4b17023SJohn Marino     delete_if_ordinary (temp->name);
2045e4b17023SJohn Marino   always_delete_queue = 0;
2046e4b17023SJohn Marino }
2047e4b17023SJohn Marino 
2048e4b17023SJohn Marino /* Delete all the files to be deleted on error.  */
2049e4b17023SJohn Marino 
2050e4b17023SJohn Marino static void
delete_failure_queue(void)2051e4b17023SJohn Marino delete_failure_queue (void)
2052e4b17023SJohn Marino {
2053e4b17023SJohn Marino   struct temp_file *temp;
2054e4b17023SJohn Marino 
2055e4b17023SJohn Marino   for (temp = failure_delete_queue; temp; temp = temp->next)
2056e4b17023SJohn Marino     delete_if_ordinary (temp->name);
2057e4b17023SJohn Marino }
2058e4b17023SJohn Marino 
2059e4b17023SJohn Marino static void
clear_failure_queue(void)2060e4b17023SJohn Marino clear_failure_queue (void)
2061e4b17023SJohn Marino {
2062e4b17023SJohn Marino   failure_delete_queue = 0;
2063e4b17023SJohn Marino }
2064e4b17023SJohn Marino 
2065e4b17023SJohn Marino /* Call CALLBACK for each path in PATHS, breaking out early if CALLBACK
2066e4b17023SJohn Marino    returns non-NULL.
2067e4b17023SJohn Marino    If DO_MULTI is true iterate over the paths twice, first with multilib
2068e4b17023SJohn Marino    suffix then without, otherwise iterate over the paths once without
2069e4b17023SJohn Marino    adding a multilib suffix.  When DO_MULTI is true, some attempt is made
2070e4b17023SJohn Marino    to avoid visiting the same path twice, but we could do better.  For
2071e4b17023SJohn Marino    instance, /usr/lib/../lib is considered different from /usr/lib.
2072e4b17023SJohn Marino    At least EXTRA_SPACE chars past the end of the path passed to
2073e4b17023SJohn Marino    CALLBACK are available for use by the callback.
2074e4b17023SJohn Marino    CALLBACK_INFO allows extra parameters to be passed to CALLBACK.
2075e4b17023SJohn Marino 
2076e4b17023SJohn Marino    Returns the value returned by CALLBACK.  */
2077e4b17023SJohn Marino 
2078e4b17023SJohn Marino static void *
for_each_path(const struct path_prefix * paths,bool do_multi,size_t extra_space,void * (* callback)(char *,void *),void * callback_info)2079e4b17023SJohn Marino for_each_path (const struct path_prefix *paths,
2080e4b17023SJohn Marino 	       bool do_multi,
2081e4b17023SJohn Marino 	       size_t extra_space,
2082e4b17023SJohn Marino 	       void *(*callback) (char *, void *),
2083e4b17023SJohn Marino 	       void *callback_info)
2084e4b17023SJohn Marino {
2085e4b17023SJohn Marino   struct prefix_list *pl;
2086e4b17023SJohn Marino   const char *multi_dir = NULL;
2087e4b17023SJohn Marino   const char *multi_os_dir = NULL;
20885ce9237cSJohn Marino   const char *multiarch_suffix = NULL;
2089e4b17023SJohn Marino   const char *multi_suffix;
2090e4b17023SJohn Marino   const char *just_multi_suffix;
2091e4b17023SJohn Marino   char *path = NULL;
2092e4b17023SJohn Marino   void *ret = NULL;
2093e4b17023SJohn Marino   bool skip_multi_dir = false;
2094e4b17023SJohn Marino   bool skip_multi_os_dir = false;
2095e4b17023SJohn Marino 
2096e4b17023SJohn Marino   multi_suffix = machine_suffix;
2097e4b17023SJohn Marino   just_multi_suffix = just_machine_suffix;
2098e4b17023SJohn Marino   if (do_multi && multilib_dir && strcmp (multilib_dir, ".") != 0)
2099e4b17023SJohn Marino     {
2100e4b17023SJohn Marino       multi_dir = concat (multilib_dir, dir_separator_str, NULL);
2101e4b17023SJohn Marino       multi_suffix = concat (multi_suffix, multi_dir, NULL);
2102e4b17023SJohn Marino       just_multi_suffix = concat (just_multi_suffix, multi_dir, NULL);
2103e4b17023SJohn Marino     }
2104e4b17023SJohn Marino   if (do_multi && multilib_os_dir && strcmp (multilib_os_dir, ".") != 0)
2105e4b17023SJohn Marino     multi_os_dir = concat (multilib_os_dir, dir_separator_str, NULL);
21065ce9237cSJohn Marino   if (multiarch_dir)
21075ce9237cSJohn Marino     multiarch_suffix = concat (multiarch_dir, dir_separator_str, NULL);
2108e4b17023SJohn Marino 
2109e4b17023SJohn Marino   while (1)
2110e4b17023SJohn Marino     {
2111e4b17023SJohn Marino       size_t multi_dir_len = 0;
2112e4b17023SJohn Marino       size_t multi_os_dir_len = 0;
21135ce9237cSJohn Marino       size_t multiarch_len = 0;
2114e4b17023SJohn Marino       size_t suffix_len;
2115e4b17023SJohn Marino       size_t just_suffix_len;
2116e4b17023SJohn Marino       size_t len;
2117e4b17023SJohn Marino 
2118e4b17023SJohn Marino       if (multi_dir)
2119e4b17023SJohn Marino 	multi_dir_len = strlen (multi_dir);
2120e4b17023SJohn Marino       if (multi_os_dir)
2121e4b17023SJohn Marino 	multi_os_dir_len = strlen (multi_os_dir);
21225ce9237cSJohn Marino       if (multiarch_suffix)
21235ce9237cSJohn Marino 	multiarch_len = strlen (multiarch_suffix);
2124e4b17023SJohn Marino       suffix_len = strlen (multi_suffix);
2125e4b17023SJohn Marino       just_suffix_len = strlen (just_multi_suffix);
2126e4b17023SJohn Marino 
2127e4b17023SJohn Marino       if (path == NULL)
2128e4b17023SJohn Marino 	{
2129e4b17023SJohn Marino 	  len = paths->max_len + extra_space + 1;
21305ce9237cSJohn Marino 	  len += MAX (MAX (suffix_len, multi_os_dir_len), multiarch_len);
2131e4b17023SJohn Marino 	  path = XNEWVEC (char, len);
2132e4b17023SJohn Marino 	}
2133e4b17023SJohn Marino 
2134e4b17023SJohn Marino       for (pl = paths->plist; pl != 0; pl = pl->next)
2135e4b17023SJohn Marino 	{
2136e4b17023SJohn Marino 	  len = strlen (pl->prefix);
2137e4b17023SJohn Marino 	  memcpy (path, pl->prefix, len);
2138e4b17023SJohn Marino 
2139fdc4107cSJohn Marino #if 0 /* MACHINE/VERSION isn't used anywhere DragonFly */
2140e4b17023SJohn Marino 	  /* Look first in MACHINE/VERSION subdirectory.  */
2141e4b17023SJohn Marino 	  if (!skip_multi_dir)
2142e4b17023SJohn Marino 	    {
2143e4b17023SJohn Marino 	      memcpy (path + len, multi_suffix, suffix_len + 1);
2144e4b17023SJohn Marino 	      ret = callback (path, callback_info);
2145e4b17023SJohn Marino 	      if (ret)
2146e4b17023SJohn Marino 		break;
2147e4b17023SJohn Marino 	    }
2148fdc4107cSJohn Marino #endif
2149e4b17023SJohn Marino 
2150e4b17023SJohn Marino 	  /* Some paths are tried with just the machine (ie. target)
2151e4b17023SJohn Marino 	     subdir.  This is used for finding as, ld, etc.  */
2152e4b17023SJohn Marino 	  if (!skip_multi_dir
2153e4b17023SJohn Marino 	      && pl->require_machine_suffix == 2)
2154e4b17023SJohn Marino 	    {
2155e4b17023SJohn Marino 	      memcpy (path + len, just_multi_suffix, just_suffix_len + 1);
2156e4b17023SJohn Marino 	      ret = callback (path, callback_info);
2157e4b17023SJohn Marino 	      if (ret)
2158e4b17023SJohn Marino 		break;
2159e4b17023SJohn Marino 	    }
2160e4b17023SJohn Marino 
21615ce9237cSJohn Marino 	  /* Now try the multiarch path.  */
21625ce9237cSJohn Marino 	  if (!skip_multi_dir
21635ce9237cSJohn Marino 	      && !pl->require_machine_suffix && multiarch_dir)
21645ce9237cSJohn Marino 	    {
21655ce9237cSJohn Marino 	      memcpy (path + len, multiarch_suffix, multiarch_len + 1);
21665ce9237cSJohn Marino 	      ret = callback (path, callback_info);
21675ce9237cSJohn Marino 	      if (ret)
21685ce9237cSJohn Marino 		break;
21695ce9237cSJohn Marino 	    }
21705ce9237cSJohn Marino 
2171e4b17023SJohn Marino 	  /* Now try the base path.  */
2172e4b17023SJohn Marino 	  if (!pl->require_machine_suffix
2173e4b17023SJohn Marino 	      && !(pl->os_multilib ? skip_multi_os_dir : skip_multi_dir))
2174e4b17023SJohn Marino 	    {
2175e4b17023SJohn Marino 	      const char *this_multi;
2176e4b17023SJohn Marino 	      size_t this_multi_len;
2177e4b17023SJohn Marino 
2178e4b17023SJohn Marino 	      if (pl->os_multilib)
2179e4b17023SJohn Marino 		{
2180e4b17023SJohn Marino 		  this_multi = multi_os_dir;
2181e4b17023SJohn Marino 		  this_multi_len = multi_os_dir_len;
2182e4b17023SJohn Marino 		}
2183e4b17023SJohn Marino 	      else
2184e4b17023SJohn Marino 		{
2185e4b17023SJohn Marino 		  this_multi = multi_dir;
2186e4b17023SJohn Marino 		  this_multi_len = multi_dir_len;
2187e4b17023SJohn Marino 		}
2188e4b17023SJohn Marino 
2189e4b17023SJohn Marino 	      if (this_multi_len)
2190e4b17023SJohn Marino 		memcpy (path + len, this_multi, this_multi_len + 1);
2191e4b17023SJohn Marino 	      else
2192e4b17023SJohn Marino 		path[len] = '\0';
2193e4b17023SJohn Marino 
2194e4b17023SJohn Marino 	      ret = callback (path, callback_info);
2195e4b17023SJohn Marino 	      if (ret)
2196e4b17023SJohn Marino 		break;
2197e4b17023SJohn Marino 	    }
2198e4b17023SJohn Marino 	}
2199e4b17023SJohn Marino       if (pl)
2200e4b17023SJohn Marino 	break;
2201e4b17023SJohn Marino 
2202e4b17023SJohn Marino       if (multi_dir == NULL && multi_os_dir == NULL)
2203e4b17023SJohn Marino 	break;
2204e4b17023SJohn Marino 
2205e4b17023SJohn Marino       /* Run through the paths again, this time without multilibs.
2206e4b17023SJohn Marino 	 Don't repeat any we have already seen.  */
2207e4b17023SJohn Marino       if (multi_dir)
2208e4b17023SJohn Marino 	{
2209e4b17023SJohn Marino 	  free (CONST_CAST (char *, multi_dir));
2210e4b17023SJohn Marino 	  multi_dir = NULL;
2211e4b17023SJohn Marino 	  free (CONST_CAST (char *, multi_suffix));
2212e4b17023SJohn Marino 	  multi_suffix = machine_suffix;
2213e4b17023SJohn Marino 	  free (CONST_CAST (char *, just_multi_suffix));
2214e4b17023SJohn Marino 	  just_multi_suffix = just_machine_suffix;
2215e4b17023SJohn Marino 	}
2216e4b17023SJohn Marino       else
2217e4b17023SJohn Marino 	skip_multi_dir = true;
2218e4b17023SJohn Marino       if (multi_os_dir)
2219e4b17023SJohn Marino 	{
2220e4b17023SJohn Marino 	  free (CONST_CAST (char *, multi_os_dir));
2221e4b17023SJohn Marino 	  multi_os_dir = NULL;
2222e4b17023SJohn Marino 	}
2223e4b17023SJohn Marino       else
2224e4b17023SJohn Marino 	skip_multi_os_dir = true;
2225e4b17023SJohn Marino     }
2226e4b17023SJohn Marino 
2227e4b17023SJohn Marino   if (multi_dir)
2228e4b17023SJohn Marino     {
2229e4b17023SJohn Marino       free (CONST_CAST (char *, multi_dir));
2230e4b17023SJohn Marino       free (CONST_CAST (char *, multi_suffix));
2231e4b17023SJohn Marino       free (CONST_CAST (char *, just_multi_suffix));
2232e4b17023SJohn Marino     }
2233e4b17023SJohn Marino   if (multi_os_dir)
2234e4b17023SJohn Marino     free (CONST_CAST (char *, multi_os_dir));
2235e4b17023SJohn Marino   if (ret != path)
2236e4b17023SJohn Marino     free (path);
2237e4b17023SJohn Marino   return ret;
2238e4b17023SJohn Marino }
2239e4b17023SJohn Marino 
2240e4b17023SJohn Marino /* Callback for build_search_list.  Adds path to obstack being built.  */
2241e4b17023SJohn Marino 
2242e4b17023SJohn Marino struct add_to_obstack_info {
2243e4b17023SJohn Marino   struct obstack *ob;
2244e4b17023SJohn Marino   bool check_dir;
2245e4b17023SJohn Marino   bool first_time;
2246e4b17023SJohn Marino };
2247e4b17023SJohn Marino 
2248e4b17023SJohn Marino static void *
add_to_obstack(char * path,void * data)2249e4b17023SJohn Marino add_to_obstack (char *path, void *data)
2250e4b17023SJohn Marino {
2251e4b17023SJohn Marino   struct add_to_obstack_info *info = (struct add_to_obstack_info *) data;
2252e4b17023SJohn Marino 
2253e4b17023SJohn Marino   if (info->check_dir && !is_directory (path, false))
2254e4b17023SJohn Marino     return NULL;
2255e4b17023SJohn Marino 
2256e4b17023SJohn Marino   if (!info->first_time)
2257e4b17023SJohn Marino     obstack_1grow (info->ob, PATH_SEPARATOR);
2258e4b17023SJohn Marino 
2259e4b17023SJohn Marino   obstack_grow (info->ob, path, strlen (path));
2260e4b17023SJohn Marino 
2261e4b17023SJohn Marino   info->first_time = false;
2262e4b17023SJohn Marino   return NULL;
2263e4b17023SJohn Marino }
2264e4b17023SJohn Marino 
2265e4b17023SJohn Marino /* Add or change the value of an environment variable, outputting the
2266e4b17023SJohn Marino    change to standard error if in verbose mode.  */
2267e4b17023SJohn Marino static void
xputenv(const char * string)2268e4b17023SJohn Marino xputenv (const char *string)
2269e4b17023SJohn Marino {
2270e4b17023SJohn Marino   if (verbose_flag)
2271e4b17023SJohn Marino     fnotice (stderr, "%s\n", string);
2272e4b17023SJohn Marino   putenv (CONST_CAST (char *, string));
2273e4b17023SJohn Marino }
2274e4b17023SJohn Marino 
2275e4b17023SJohn Marino /* Build a list of search directories from PATHS.
2276e4b17023SJohn Marino    PREFIX is a string to prepend to the list.
2277e4b17023SJohn Marino    If CHECK_DIR_P is true we ensure the directory exists.
2278e4b17023SJohn Marino    If DO_MULTI is true, multilib paths are output first, then
2279e4b17023SJohn Marino    non-multilib paths.
2280e4b17023SJohn Marino    This is used mostly by putenv_from_prefixes so we use `collect_obstack'.
2281e4b17023SJohn Marino    It is also used by the --print-search-dirs flag.  */
2282e4b17023SJohn Marino 
2283e4b17023SJohn Marino static char *
build_search_list(const struct path_prefix * paths,const char * prefix,bool check_dir,bool do_multi)2284e4b17023SJohn Marino build_search_list (const struct path_prefix *paths, const char *prefix,
2285e4b17023SJohn Marino 		   bool check_dir, bool do_multi)
2286e4b17023SJohn Marino {
2287e4b17023SJohn Marino   struct add_to_obstack_info info;
2288e4b17023SJohn Marino 
2289e4b17023SJohn Marino   info.ob = &collect_obstack;
2290e4b17023SJohn Marino   info.check_dir = check_dir;
2291e4b17023SJohn Marino   info.first_time = true;
2292e4b17023SJohn Marino 
2293e4b17023SJohn Marino   obstack_grow (&collect_obstack, prefix, strlen (prefix));
2294e4b17023SJohn Marino   obstack_1grow (&collect_obstack, '=');
2295e4b17023SJohn Marino 
2296e4b17023SJohn Marino   for_each_path (paths, do_multi, 0, add_to_obstack, &info);
2297e4b17023SJohn Marino 
2298e4b17023SJohn Marino   obstack_1grow (&collect_obstack, '\0');
2299e4b17023SJohn Marino   return XOBFINISH (&collect_obstack, char *);
2300e4b17023SJohn Marino }
2301e4b17023SJohn Marino 
2302e4b17023SJohn Marino /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
2303e4b17023SJohn Marino    for collect.  */
2304e4b17023SJohn Marino 
2305e4b17023SJohn Marino static void
putenv_from_prefixes(const struct path_prefix * paths,const char * env_var,bool do_multi)2306e4b17023SJohn Marino putenv_from_prefixes (const struct path_prefix *paths, const char *env_var,
2307e4b17023SJohn Marino 		      bool do_multi)
2308e4b17023SJohn Marino {
2309e4b17023SJohn Marino   xputenv (build_search_list (paths, env_var, true, do_multi));
2310e4b17023SJohn Marino }
2311e4b17023SJohn Marino 
2312e4b17023SJohn Marino /* Check whether NAME can be accessed in MODE.  This is like access,
2313e4b17023SJohn Marino    except that it never considers directories to be executable.  */
2314e4b17023SJohn Marino 
2315e4b17023SJohn Marino static int
access_check(const char * name,int mode)2316e4b17023SJohn Marino access_check (const char *name, int mode)
2317e4b17023SJohn Marino {
2318e4b17023SJohn Marino   if (mode == X_OK)
2319e4b17023SJohn Marino     {
2320e4b17023SJohn Marino       struct stat st;
2321e4b17023SJohn Marino 
2322e4b17023SJohn Marino       if (stat (name, &st) < 0
2323e4b17023SJohn Marino 	  || S_ISDIR (st.st_mode))
2324e4b17023SJohn Marino 	return -1;
2325e4b17023SJohn Marino     }
2326e4b17023SJohn Marino 
2327e4b17023SJohn Marino   return access (name, mode);
2328e4b17023SJohn Marino }
2329e4b17023SJohn Marino 
2330e4b17023SJohn Marino /* Callback for find_a_file.  Appends the file name to the directory
2331e4b17023SJohn Marino    path.  If the resulting file exists in the right mode, return the
2332e4b17023SJohn Marino    full pathname to the file.  */
2333e4b17023SJohn Marino 
2334e4b17023SJohn Marino struct file_at_path_info {
2335e4b17023SJohn Marino   const char *name;
2336e4b17023SJohn Marino   const char *suffix;
2337e4b17023SJohn Marino   int name_len;
2338e4b17023SJohn Marino   int suffix_len;
2339e4b17023SJohn Marino   int mode;
2340e4b17023SJohn Marino };
2341e4b17023SJohn Marino 
2342e4b17023SJohn Marino static void *
file_at_path(char * path,void * data)2343e4b17023SJohn Marino file_at_path (char *path, void *data)
2344e4b17023SJohn Marino {
2345e4b17023SJohn Marino   struct file_at_path_info *info = (struct file_at_path_info *) data;
2346e4b17023SJohn Marino   size_t len = strlen (path);
2347e4b17023SJohn Marino 
2348e4b17023SJohn Marino   memcpy (path + len, info->name, info->name_len);
2349e4b17023SJohn Marino   len += info->name_len;
2350e4b17023SJohn Marino 
2351e4b17023SJohn Marino   /* Some systems have a suffix for executable files.
2352e4b17023SJohn Marino      So try appending that first.  */
2353e4b17023SJohn Marino   if (info->suffix_len)
2354e4b17023SJohn Marino     {
2355e4b17023SJohn Marino       memcpy (path + len, info->suffix, info->suffix_len + 1);
2356e4b17023SJohn Marino       if (access_check (path, info->mode) == 0)
2357e4b17023SJohn Marino 	return path;
2358e4b17023SJohn Marino     }
2359e4b17023SJohn Marino 
2360e4b17023SJohn Marino   path[len] = '\0';
2361e4b17023SJohn Marino   if (access_check (path, info->mode) == 0)
2362e4b17023SJohn Marino     return path;
2363e4b17023SJohn Marino 
2364e4b17023SJohn Marino   return NULL;
2365e4b17023SJohn Marino }
2366e4b17023SJohn Marino 
2367e4b17023SJohn Marino /* Search for NAME using the prefix list PREFIXES.  MODE is passed to
2368e4b17023SJohn Marino    access to check permissions.  If DO_MULTI is true, search multilib
2369e4b17023SJohn Marino    paths then non-multilib paths, otherwise do not search multilib paths.
2370e4b17023SJohn Marino    Return 0 if not found, otherwise return its name, allocated with malloc.  */
2371e4b17023SJohn Marino 
2372e4b17023SJohn Marino static char *
find_a_file(const struct path_prefix * pprefix,const char * name,int mode,bool do_multi)2373e4b17023SJohn Marino find_a_file (const struct path_prefix *pprefix, const char *name, int mode,
2374e4b17023SJohn Marino 	     bool do_multi)
2375e4b17023SJohn Marino {
2376e4b17023SJohn Marino   struct file_at_path_info info;
2377e4b17023SJohn Marino 
2378e4b17023SJohn Marino #ifdef DEFAULT_ASSEMBLER
2379e4b17023SJohn Marino   if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0)
2380e4b17023SJohn Marino     return xstrdup (DEFAULT_ASSEMBLER);
2381e4b17023SJohn Marino #endif
2382e4b17023SJohn Marino 
2383e4b17023SJohn Marino #ifdef DEFAULT_LINKER
2384e4b17023SJohn Marino   if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0)
2385e4b17023SJohn Marino     return xstrdup (DEFAULT_LINKER);
2386e4b17023SJohn Marino #endif
2387e4b17023SJohn Marino 
2388e4b17023SJohn Marino   /* Determine the filename to execute (special case for absolute paths).  */
2389e4b17023SJohn Marino 
2390e4b17023SJohn Marino   if (IS_ABSOLUTE_PATH (name))
2391e4b17023SJohn Marino     {
2392e4b17023SJohn Marino       if (access (name, mode) == 0)
2393e4b17023SJohn Marino 	return xstrdup (name);
2394e4b17023SJohn Marino 
2395e4b17023SJohn Marino       return NULL;
2396e4b17023SJohn Marino     }
2397e4b17023SJohn Marino 
2398e4b17023SJohn Marino   info.name = name;
2399e4b17023SJohn Marino   info.suffix = (mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : "";
2400e4b17023SJohn Marino   info.name_len = strlen (info.name);
2401e4b17023SJohn Marino   info.suffix_len = strlen (info.suffix);
2402e4b17023SJohn Marino   info.mode = mode;
2403e4b17023SJohn Marino 
2404e4b17023SJohn Marino   return (char*) for_each_path (pprefix, do_multi,
2405e4b17023SJohn Marino 				info.name_len + info.suffix_len,
2406e4b17023SJohn Marino 				file_at_path, &info);
2407e4b17023SJohn Marino }
2408e4b17023SJohn Marino 
2409e4b17023SJohn Marino /* Ranking of prefixes in the sort list. -B prefixes are put before
2410e4b17023SJohn Marino    all others.  */
2411e4b17023SJohn Marino 
2412e4b17023SJohn Marino enum path_prefix_priority
2413e4b17023SJohn Marino {
2414e4b17023SJohn Marino   PREFIX_PRIORITY_B_OPT,
2415e4b17023SJohn Marino   PREFIX_PRIORITY_LAST
2416e4b17023SJohn Marino };
2417e4b17023SJohn Marino 
2418e4b17023SJohn Marino /* Add an entry for PREFIX in PLIST.  The PLIST is kept in ascending
2419e4b17023SJohn Marino    order according to PRIORITY.  Within each PRIORITY, new entries are
2420e4b17023SJohn Marino    appended.
2421e4b17023SJohn Marino 
2422e4b17023SJohn Marino    If WARN is nonzero, we will warn if no file is found
2423e4b17023SJohn Marino    through this prefix.  WARN should point to an int
2424e4b17023SJohn Marino    which will be set to 1 if this entry is used.
2425e4b17023SJohn Marino 
2426e4b17023SJohn Marino    COMPONENT is the value to be passed to update_path.
2427e4b17023SJohn Marino 
2428e4b17023SJohn Marino    REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without
2429e4b17023SJohn Marino    the complete value of machine_suffix.
2430e4b17023SJohn Marino    2 means try both machine_suffix and just_machine_suffix.  */
2431e4b17023SJohn Marino 
2432e4b17023SJohn Marino static void
add_prefix(struct path_prefix * pprefix,const char * prefix,const char * component,int priority,int require_machine_suffix,int os_multilib)2433e4b17023SJohn Marino add_prefix (struct path_prefix *pprefix, const char *prefix,
2434e4b17023SJohn Marino 	    const char *component, /* enum prefix_priority */ int priority,
2435e4b17023SJohn Marino 	    int require_machine_suffix, int os_multilib)
2436e4b17023SJohn Marino {
2437e4b17023SJohn Marino   struct prefix_list *pl, **prev;
2438e4b17023SJohn Marino   int len;
2439e4b17023SJohn Marino 
2440e4b17023SJohn Marino   for (prev = &pprefix->plist;
2441e4b17023SJohn Marino        (*prev) != NULL && (*prev)->priority <= priority;
2442e4b17023SJohn Marino        prev = &(*prev)->next)
2443e4b17023SJohn Marino     ;
2444e4b17023SJohn Marino 
2445e4b17023SJohn Marino   /* Keep track of the longest prefix.  */
2446e4b17023SJohn Marino 
2447e4b17023SJohn Marino   prefix = update_path (prefix, component);
2448e4b17023SJohn Marino   len = strlen (prefix);
2449e4b17023SJohn Marino   if (len > pprefix->max_len)
2450e4b17023SJohn Marino     pprefix->max_len = len;
2451e4b17023SJohn Marino 
2452e4b17023SJohn Marino   pl = XNEW (struct prefix_list);
2453e4b17023SJohn Marino   pl->prefix = prefix;
2454e4b17023SJohn Marino   pl->require_machine_suffix = require_machine_suffix;
2455e4b17023SJohn Marino   pl->priority = priority;
2456e4b17023SJohn Marino   pl->os_multilib = os_multilib;
2457e4b17023SJohn Marino 
2458e4b17023SJohn Marino   /* Insert after PREV.  */
2459e4b17023SJohn Marino   pl->next = (*prev);
2460e4b17023SJohn Marino   (*prev) = pl;
2461e4b17023SJohn Marino }
2462e4b17023SJohn Marino 
2463e4b17023SJohn Marino /* Same as add_prefix, but prepending target_system_root to prefix.  */
2464e4b17023SJohn Marino /* The target_system_root prefix has been relocated by gcc_exec_prefix.  */
2465e4b17023SJohn Marino static void
add_sysrooted_prefix(struct path_prefix * pprefix,const char * prefix,const char * component,int priority,int require_machine_suffix,int os_multilib)2466e4b17023SJohn Marino add_sysrooted_prefix (struct path_prefix *pprefix, const char *prefix,
2467e4b17023SJohn Marino 		      const char *component,
2468e4b17023SJohn Marino 		      /* enum prefix_priority */ int priority,
2469e4b17023SJohn Marino 		      int require_machine_suffix, int os_multilib)
2470e4b17023SJohn Marino {
2471e4b17023SJohn Marino   if (!IS_ABSOLUTE_PATH (prefix))
2472e4b17023SJohn Marino     fatal_error ("system path %qs is not absolute", prefix);
2473e4b17023SJohn Marino 
2474e4b17023SJohn Marino   if (target_system_root)
2475e4b17023SJohn Marino     {
2476e4b17023SJohn Marino       char *sysroot_no_trailing_dir_separator = xstrdup (target_system_root);
2477e4b17023SJohn Marino       size_t sysroot_len = strlen (target_system_root);
2478e4b17023SJohn Marino 
2479e4b17023SJohn Marino       if (sysroot_len > 0
2480e4b17023SJohn Marino 	  && target_system_root[sysroot_len - 1] == DIR_SEPARATOR)
2481e4b17023SJohn Marino 	sysroot_no_trailing_dir_separator[sysroot_len - 1] = '\0';
2482e4b17023SJohn Marino 
2483e4b17023SJohn Marino       if (target_sysroot_suffix)
2484e4b17023SJohn Marino 	  prefix = concat (target_sysroot_suffix, prefix, NULL);
2485e4b17023SJohn Marino       prefix = concat (sysroot_no_trailing_dir_separator, prefix, NULL);
2486e4b17023SJohn Marino       free (sysroot_no_trailing_dir_separator);
2487e4b17023SJohn Marino 
2488e4b17023SJohn Marino       /* We have to override this because GCC's notion of sysroot
2489e4b17023SJohn Marino 	 moves along with GCC.  */
2490e4b17023SJohn Marino       component = "GCC";
2491e4b17023SJohn Marino     }
2492e4b17023SJohn Marino 
2493e4b17023SJohn Marino   add_prefix (pprefix, prefix, component, priority,
2494e4b17023SJohn Marino 	      require_machine_suffix, os_multilib);
2495e4b17023SJohn Marino }
2496e4b17023SJohn Marino 
2497e4b17023SJohn Marino /* Execute the command specified by the arguments on the current line of spec.
2498e4b17023SJohn Marino    When using pipes, this includes several piped-together commands
2499e4b17023SJohn Marino    with `|' between them.
2500e4b17023SJohn Marino 
2501e4b17023SJohn Marino    Return 0 if successful, -1 if failed.  */
2502e4b17023SJohn Marino 
2503e4b17023SJohn Marino static int
execute(void)2504e4b17023SJohn Marino execute (void)
2505e4b17023SJohn Marino {
2506e4b17023SJohn Marino   int i;
2507e4b17023SJohn Marino   int n_commands;		/* # of command.  */
2508e4b17023SJohn Marino   char *string;
2509e4b17023SJohn Marino   struct pex_obj *pex;
2510e4b17023SJohn Marino   struct command
2511e4b17023SJohn Marino   {
2512e4b17023SJohn Marino     const char *prog;		/* program name.  */
2513e4b17023SJohn Marino     const char **argv;		/* vector of args.  */
2514e4b17023SJohn Marino   };
2515e4b17023SJohn Marino   const char *arg;
2516e4b17023SJohn Marino 
2517e4b17023SJohn Marino   struct command *commands;	/* each command buffer with above info.  */
2518e4b17023SJohn Marino 
2519e4b17023SJohn Marino   gcc_assert (!processing_spec_function);
2520e4b17023SJohn Marino 
2521e4b17023SJohn Marino   if (wrapper_string)
2522e4b17023SJohn Marino     {
2523e4b17023SJohn Marino       string = find_a_file (&exec_prefixes,
2524e4b17023SJohn Marino 			    VEC_index (const_char_p, argbuf, 0), X_OK, false);
2525e4b17023SJohn Marino       if (string)
2526e4b17023SJohn Marino 	VEC_replace (const_char_p, argbuf, 0, string);
2527e4b17023SJohn Marino       insert_wrapper (wrapper_string);
2528e4b17023SJohn Marino     }
2529e4b17023SJohn Marino 
2530e4b17023SJohn Marino   /* Count # of piped commands.  */
2531e4b17023SJohn Marino   for (n_commands = 1, i = 0; VEC_iterate (const_char_p, argbuf, i, arg); i++)
2532e4b17023SJohn Marino     if (strcmp (arg, "|") == 0)
2533e4b17023SJohn Marino       n_commands++;
2534e4b17023SJohn Marino 
2535e4b17023SJohn Marino   /* Get storage for each command.  */
2536e4b17023SJohn Marino   commands = (struct command *) alloca (n_commands * sizeof (struct command));
2537e4b17023SJohn Marino 
2538e4b17023SJohn Marino   /* Split argbuf into its separate piped processes,
2539e4b17023SJohn Marino      and record info about each one.
2540e4b17023SJohn Marino      Also search for the programs that are to be run.  */
2541e4b17023SJohn Marino 
2542e4b17023SJohn Marino   VEC_safe_push (const_char_p, heap, argbuf, 0);
2543e4b17023SJohn Marino 
2544e4b17023SJohn Marino   commands[0].prog = VEC_index (const_char_p, argbuf, 0); /* first command.  */
2545e4b17023SJohn Marino   commands[0].argv = VEC_address (const_char_p, argbuf);
2546e4b17023SJohn Marino 
2547e4b17023SJohn Marino   if (!wrapper_string)
2548e4b17023SJohn Marino     {
2549e4b17023SJohn Marino       string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
2550e4b17023SJohn Marino       commands[0].argv[0] = (string) ? string : commands[0].argv[0];
2551e4b17023SJohn Marino     }
2552e4b17023SJohn Marino 
2553e4b17023SJohn Marino   for (n_commands = 1, i = 0; VEC_iterate (const_char_p, argbuf, i, arg); i++)
2554e4b17023SJohn Marino     if (arg && strcmp (arg, "|") == 0)
2555e4b17023SJohn Marino       {				/* each command.  */
2556e4b17023SJohn Marino #if defined (__MSDOS__) || defined (OS2) || defined (VMS)
2557e4b17023SJohn Marino 	fatal_error ("-pipe not supported");
2558e4b17023SJohn Marino #endif
2559e4b17023SJohn Marino 	VEC_replace (const_char_p, argbuf, i, 0); /* Termination of
2560e4b17023SJohn Marino 						     command args.  */
2561e4b17023SJohn Marino 	commands[n_commands].prog = VEC_index (const_char_p, argbuf, i + 1);
2562e4b17023SJohn Marino 	commands[n_commands].argv
2563e4b17023SJohn Marino 	  = &(VEC_address (const_char_p, argbuf))[i + 1];
2564e4b17023SJohn Marino 	string = find_a_file (&exec_prefixes, commands[n_commands].prog,
2565e4b17023SJohn Marino 			      X_OK, false);
2566e4b17023SJohn Marino 	if (string)
2567e4b17023SJohn Marino 	  commands[n_commands].argv[0] = string;
2568e4b17023SJohn Marino 	n_commands++;
2569e4b17023SJohn Marino       }
2570e4b17023SJohn Marino 
2571e4b17023SJohn Marino   /* If -v, print what we are about to do, and maybe query.  */
2572e4b17023SJohn Marino 
2573e4b17023SJohn Marino   if (verbose_flag)
2574e4b17023SJohn Marino     {
2575e4b17023SJohn Marino       /* For help listings, put a blank line between sub-processes.  */
2576e4b17023SJohn Marino       if (print_help_list)
2577e4b17023SJohn Marino 	fputc ('\n', stderr);
2578e4b17023SJohn Marino 
2579e4b17023SJohn Marino       /* Print each piped command as a separate line.  */
2580e4b17023SJohn Marino       for (i = 0; i < n_commands; i++)
2581e4b17023SJohn Marino 	{
2582e4b17023SJohn Marino 	  const char *const *j;
2583e4b17023SJohn Marino 
2584e4b17023SJohn Marino 	  if (verbose_only_flag)
2585e4b17023SJohn Marino 	    {
2586e4b17023SJohn Marino 	      for (j = commands[i].argv; *j; j++)
2587e4b17023SJohn Marino 		{
2588e4b17023SJohn Marino 		  const char *p;
2589e4b17023SJohn Marino 		  for (p = *j; *p; ++p)
2590e4b17023SJohn Marino 		    if (!ISALNUM ((unsigned char) *p)
2591e4b17023SJohn Marino 			&& *p != '_' && *p != '/' && *p != '-' && *p != '.')
2592e4b17023SJohn Marino 		      break;
2593e4b17023SJohn Marino 		  if (*p || !*j)
2594e4b17023SJohn Marino 		    {
2595e4b17023SJohn Marino 		      fprintf (stderr, " \"");
2596e4b17023SJohn Marino 		      for (p = *j; *p; ++p)
2597e4b17023SJohn Marino 			{
2598e4b17023SJohn Marino 			  if (*p == '"' || *p == '\\' || *p == '$')
2599e4b17023SJohn Marino 			    fputc ('\\', stderr);
2600e4b17023SJohn Marino 			  fputc (*p, stderr);
2601e4b17023SJohn Marino 			}
2602e4b17023SJohn Marino 		      fputc ('"', stderr);
2603e4b17023SJohn Marino 		    }
2604e4b17023SJohn Marino 		  /* If it's empty, print "".  */
2605e4b17023SJohn Marino 		  else if (!**j)
2606e4b17023SJohn Marino 		    fprintf (stderr, " \"\"");
2607e4b17023SJohn Marino 		  else
2608e4b17023SJohn Marino 		    fprintf (stderr, " %s", *j);
2609e4b17023SJohn Marino 		}
2610e4b17023SJohn Marino 	    }
2611e4b17023SJohn Marino 	  else
2612e4b17023SJohn Marino 	    for (j = commands[i].argv; *j; j++)
2613e4b17023SJohn Marino 	      /* If it's empty, print "".  */
2614e4b17023SJohn Marino 	      if (!**j)
2615e4b17023SJohn Marino 		fprintf (stderr, " \"\"");
2616e4b17023SJohn Marino 	      else
2617e4b17023SJohn Marino 		fprintf (stderr, " %s", *j);
2618e4b17023SJohn Marino 
2619e4b17023SJohn Marino 	  /* Print a pipe symbol after all but the last command.  */
2620e4b17023SJohn Marino 	  if (i + 1 != n_commands)
2621e4b17023SJohn Marino 	    fprintf (stderr, " |");
2622e4b17023SJohn Marino 	  fprintf (stderr, "\n");
2623e4b17023SJohn Marino 	}
2624e4b17023SJohn Marino       fflush (stderr);
2625e4b17023SJohn Marino       if (verbose_only_flag != 0)
2626e4b17023SJohn Marino         {
2627e4b17023SJohn Marino 	  /* verbose_only_flag should act as if the spec was
2628e4b17023SJohn Marino 	     executed, so increment execution_count before
2629e4b17023SJohn Marino 	     returning.  This prevents spurious warnings about
2630e4b17023SJohn Marino 	     unused linker input files, etc.  */
2631e4b17023SJohn Marino 	  execution_count++;
2632e4b17023SJohn Marino 	  return 0;
2633e4b17023SJohn Marino         }
2634e4b17023SJohn Marino #ifdef DEBUG
2635e4b17023SJohn Marino       fnotice (stderr, "\nGo ahead? (y or n) ");
2636e4b17023SJohn Marino       fflush (stderr);
2637e4b17023SJohn Marino       i = getchar ();
2638e4b17023SJohn Marino       if (i != '\n')
2639e4b17023SJohn Marino 	while (getchar () != '\n')
2640e4b17023SJohn Marino 	  ;
2641e4b17023SJohn Marino 
2642e4b17023SJohn Marino       if (i != 'y' && i != 'Y')
2643e4b17023SJohn Marino 	return 0;
2644e4b17023SJohn Marino #endif /* DEBUG */
2645e4b17023SJohn Marino     }
2646e4b17023SJohn Marino 
2647e4b17023SJohn Marino #ifdef ENABLE_VALGRIND_CHECKING
2648e4b17023SJohn Marino   /* Run the each command through valgrind.  To simplify prepending the
2649e4b17023SJohn Marino      path to valgrind and the option "-q" (for quiet operation unless
2650e4b17023SJohn Marino      something triggers), we allocate a separate argv array.  */
2651e4b17023SJohn Marino 
2652e4b17023SJohn Marino   for (i = 0; i < n_commands; i++)
2653e4b17023SJohn Marino     {
2654e4b17023SJohn Marino       const char **argv;
2655e4b17023SJohn Marino       int argc;
2656e4b17023SJohn Marino       int j;
2657e4b17023SJohn Marino 
2658e4b17023SJohn Marino       for (argc = 0; commands[i].argv[argc] != NULL; argc++)
2659e4b17023SJohn Marino 	;
2660e4b17023SJohn Marino 
2661e4b17023SJohn Marino       argv = XALLOCAVEC (const char *, argc + 3);
2662e4b17023SJohn Marino 
2663e4b17023SJohn Marino       argv[0] = VALGRIND_PATH;
2664e4b17023SJohn Marino       argv[1] = "-q";
2665e4b17023SJohn Marino       for (j = 2; j < argc + 2; j++)
2666e4b17023SJohn Marino 	argv[j] = commands[i].argv[j - 2];
2667e4b17023SJohn Marino       argv[j] = NULL;
2668e4b17023SJohn Marino 
2669e4b17023SJohn Marino       commands[i].argv = argv;
2670e4b17023SJohn Marino       commands[i].prog = argv[0];
2671e4b17023SJohn Marino     }
2672e4b17023SJohn Marino #endif
2673e4b17023SJohn Marino 
2674e4b17023SJohn Marino   /* Run each piped subprocess.  */
2675e4b17023SJohn Marino 
2676e4b17023SJohn Marino   pex = pex_init (PEX_USE_PIPES | ((report_times || report_times_to_file)
2677e4b17023SJohn Marino 				   ? PEX_RECORD_TIMES : 0),
2678e4b17023SJohn Marino 		  progname, temp_filename);
2679e4b17023SJohn Marino   if (pex == NULL)
2680e4b17023SJohn Marino     fatal_error ("pex_init failed: %m");
2681e4b17023SJohn Marino 
2682e4b17023SJohn Marino   for (i = 0; i < n_commands; i++)
2683e4b17023SJohn Marino     {
2684e4b17023SJohn Marino       const char *errmsg;
2685e4b17023SJohn Marino       int err;
2686e4b17023SJohn Marino       const char *string = commands[i].argv[0];
2687e4b17023SJohn Marino 
2688e4b17023SJohn Marino       errmsg = pex_run (pex,
2689e4b17023SJohn Marino 			((i + 1 == n_commands ? PEX_LAST : 0)
2690e4b17023SJohn Marino 			 | (string == commands[i].prog ? PEX_SEARCH : 0)),
2691e4b17023SJohn Marino 			string, CONST_CAST (char **, commands[i].argv),
2692e4b17023SJohn Marino 			NULL, NULL, &err);
2693e4b17023SJohn Marino       if (errmsg != NULL)
2694e4b17023SJohn Marino 	{
2695e4b17023SJohn Marino 	  if (err == 0)
2696e4b17023SJohn Marino 	    fatal_error (errmsg);
2697e4b17023SJohn Marino 	  else
2698e4b17023SJohn Marino 	    {
2699e4b17023SJohn Marino 	      errno = err;
2700e4b17023SJohn Marino 	      pfatal_with_name (errmsg);
2701e4b17023SJohn Marino 	    }
2702e4b17023SJohn Marino 	}
2703e4b17023SJohn Marino 
2704e4b17023SJohn Marino       if (string != commands[i].prog)
2705e4b17023SJohn Marino 	free (CONST_CAST (char *, string));
2706e4b17023SJohn Marino     }
2707e4b17023SJohn Marino 
2708e4b17023SJohn Marino   execution_count++;
2709e4b17023SJohn Marino 
2710e4b17023SJohn Marino   /* Wait for all the subprocesses to finish.  */
2711e4b17023SJohn Marino 
2712e4b17023SJohn Marino   {
2713e4b17023SJohn Marino     int *statuses;
2714e4b17023SJohn Marino     struct pex_time *times = NULL;
2715e4b17023SJohn Marino     int ret_code = 0;
2716e4b17023SJohn Marino 
2717e4b17023SJohn Marino     statuses = (int *) alloca (n_commands * sizeof (int));
2718e4b17023SJohn Marino     if (!pex_get_status (pex, n_commands, statuses))
2719e4b17023SJohn Marino       fatal_error ("failed to get exit status: %m");
2720e4b17023SJohn Marino 
2721e4b17023SJohn Marino     if (report_times || report_times_to_file)
2722e4b17023SJohn Marino       {
2723e4b17023SJohn Marino 	times = (struct pex_time *) alloca (n_commands * sizeof (struct pex_time));
2724e4b17023SJohn Marino 	if (!pex_get_times (pex, n_commands, times))
2725e4b17023SJohn Marino 	  fatal_error ("failed to get process times: %m");
2726e4b17023SJohn Marino       }
2727e4b17023SJohn Marino 
2728e4b17023SJohn Marino     pex_free (pex);
2729e4b17023SJohn Marino 
2730e4b17023SJohn Marino     for (i = 0; i < n_commands; ++i)
2731e4b17023SJohn Marino       {
2732e4b17023SJohn Marino 	int status = statuses[i];
2733e4b17023SJohn Marino 
2734e4b17023SJohn Marino 	if (WIFSIGNALED (status))
2735e4b17023SJohn Marino 	  {
2736e4b17023SJohn Marino #ifdef SIGPIPE
2737e4b17023SJohn Marino 	    /* SIGPIPE is a special case.  It happens in -pipe mode
2738e4b17023SJohn Marino 	       when the compiler dies before the preprocessor is done,
2739e4b17023SJohn Marino 	       or the assembler dies before the compiler is done.
2740e4b17023SJohn Marino 	       There's generally been an error already, and this is
2741e4b17023SJohn Marino 	       just fallout.  So don't generate another error unless
2742e4b17023SJohn Marino 	       we would otherwise have succeeded.  */
2743e4b17023SJohn Marino 	    if (WTERMSIG (status) == SIGPIPE
2744e4b17023SJohn Marino 		&& (signal_count || greatest_status >= MIN_FATAL_STATUS))
2745e4b17023SJohn Marino 	      {
2746e4b17023SJohn Marino 		signal_count++;
2747e4b17023SJohn Marino 		ret_code = -1;
2748e4b17023SJohn Marino 	      }
2749e4b17023SJohn Marino 	    else
2750e4b17023SJohn Marino #endif
2751e4b17023SJohn Marino 	      internal_error ("%s (program %s)",
2752e4b17023SJohn Marino 			      strsignal (WTERMSIG (status)), commands[i].prog);
2753e4b17023SJohn Marino 	  }
2754e4b17023SJohn Marino 	else if (WIFEXITED (status)
2755e4b17023SJohn Marino 		 && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
2756e4b17023SJohn Marino 	  {
2757e4b17023SJohn Marino 	    if (WEXITSTATUS (status) > greatest_status)
2758e4b17023SJohn Marino 	      greatest_status = WEXITSTATUS (status);
2759e4b17023SJohn Marino 	    ret_code = -1;
2760e4b17023SJohn Marino 	  }
2761e4b17023SJohn Marino 
2762e4b17023SJohn Marino 	if (report_times || report_times_to_file)
2763e4b17023SJohn Marino 	  {
2764e4b17023SJohn Marino 	    struct pex_time *pt = &times[i];
2765e4b17023SJohn Marino 	    double ut, st;
2766e4b17023SJohn Marino 
2767e4b17023SJohn Marino 	    ut = ((double) pt->user_seconds
2768e4b17023SJohn Marino 		  + (double) pt->user_microseconds / 1.0e6);
2769e4b17023SJohn Marino 	    st = ((double) pt->system_seconds
2770e4b17023SJohn Marino 		  + (double) pt->system_microseconds / 1.0e6);
2771e4b17023SJohn Marino 
2772e4b17023SJohn Marino 	    if (ut + st != 0)
2773e4b17023SJohn Marino 	      {
2774e4b17023SJohn Marino 		if (report_times)
2775e4b17023SJohn Marino 		  fnotice (stderr, "# %s %.2f %.2f\n",
2776e4b17023SJohn Marino 			   commands[i].prog, ut, st);
2777e4b17023SJohn Marino 
2778e4b17023SJohn Marino 		if (report_times_to_file)
2779e4b17023SJohn Marino 		  {
2780e4b17023SJohn Marino 		    int c = 0;
2781e4b17023SJohn Marino 		    const char *const *j;
2782e4b17023SJohn Marino 
2783e4b17023SJohn Marino 		    fprintf (report_times_to_file, "%g %g", ut, st);
2784e4b17023SJohn Marino 
2785e4b17023SJohn Marino 		    for (j = &commands[i].prog; *j; j = &commands[i].argv[++c])
2786e4b17023SJohn Marino 		      {
2787e4b17023SJohn Marino 			const char *p;
2788e4b17023SJohn Marino 			for (p = *j; *p; ++p)
2789e4b17023SJohn Marino 			  if (*p == '"' || *p == '\\' || *p == '$'
2790e4b17023SJohn Marino 			      || ISSPACE (*p))
2791e4b17023SJohn Marino 			    break;
2792e4b17023SJohn Marino 
2793e4b17023SJohn Marino 			if (*p)
2794e4b17023SJohn Marino 			  {
2795e4b17023SJohn Marino 			    fprintf (report_times_to_file, " \"");
2796e4b17023SJohn Marino 			    for (p = *j; *p; ++p)
2797e4b17023SJohn Marino 			      {
2798e4b17023SJohn Marino 				if (*p == '"' || *p == '\\' || *p == '$')
2799e4b17023SJohn Marino 				  fputc ('\\', report_times_to_file);
2800e4b17023SJohn Marino 				fputc (*p, report_times_to_file);
2801e4b17023SJohn Marino 			      }
2802e4b17023SJohn Marino 			    fputc ('"', report_times_to_file);
2803e4b17023SJohn Marino 			  }
2804e4b17023SJohn Marino 			else
2805e4b17023SJohn Marino 			  fprintf (report_times_to_file, " %s", *j);
2806e4b17023SJohn Marino 		      }
2807e4b17023SJohn Marino 
2808e4b17023SJohn Marino 		    fputc ('\n', report_times_to_file);
2809e4b17023SJohn Marino 		  }
2810e4b17023SJohn Marino 	      }
2811e4b17023SJohn Marino 	  }
2812e4b17023SJohn Marino       }
2813e4b17023SJohn Marino 
2814e4b17023SJohn Marino     return ret_code;
2815e4b17023SJohn Marino   }
2816e4b17023SJohn Marino }
2817e4b17023SJohn Marino 
2818e4b17023SJohn Marino /* Find all the switches given to us
2819e4b17023SJohn Marino    and make a vector describing them.
2820e4b17023SJohn Marino    The elements of the vector are strings, one per switch given.
2821e4b17023SJohn Marino    If a switch uses following arguments, then the `part1' field
2822e4b17023SJohn Marino    is the switch itself and the `args' field
2823e4b17023SJohn Marino    is a null-terminated vector containing the following arguments.
2824e4b17023SJohn Marino    Bits in the `live_cond' field are:
2825e4b17023SJohn Marino    SWITCH_LIVE to indicate this switch is true in a conditional spec.
2826e4b17023SJohn Marino    SWITCH_FALSE to indicate this switch is overridden by a later switch.
2827e4b17023SJohn Marino    SWITCH_IGNORE to indicate this switch should be ignored (used in %<S).
2828e4b17023SJohn Marino    SWITCH_IGNORE_PERMANENTLY to indicate this switch should be ignored
2829e4b17023SJohn Marino    in all do_spec calls afterwards.  Used for %<S from self specs.
2830e4b17023SJohn Marino    The `validated' field is nonzero if any spec has looked at this switch;
2831e4b17023SJohn Marino    if it remains zero at the end of the run, it must be meaningless.  */
2832e4b17023SJohn Marino 
2833e4b17023SJohn Marino #define SWITCH_LIVE    			(1 << 0)
2834e4b17023SJohn Marino #define SWITCH_FALSE   			(1 << 1)
2835e4b17023SJohn Marino #define SWITCH_IGNORE			(1 << 2)
2836e4b17023SJohn Marino #define SWITCH_IGNORE_PERMANENTLY	(1 << 3)
2837e4b17023SJohn Marino #define SWITCH_KEEP_FOR_GCC		(1 << 4)
2838e4b17023SJohn Marino 
2839e4b17023SJohn Marino struct switchstr
2840e4b17023SJohn Marino {
2841e4b17023SJohn Marino   const char *part1;
2842e4b17023SJohn Marino   const char **args;
2843e4b17023SJohn Marino   unsigned int live_cond;
2844e4b17023SJohn Marino   unsigned char validated;
2845e4b17023SJohn Marino   unsigned char ordering;
2846e4b17023SJohn Marino };
2847e4b17023SJohn Marino 
2848e4b17023SJohn Marino static struct switchstr *switches;
2849e4b17023SJohn Marino 
2850e4b17023SJohn Marino static int n_switches;
2851e4b17023SJohn Marino 
2852e4b17023SJohn Marino static int n_switches_alloc;
2853e4b17023SJohn Marino 
2854e4b17023SJohn Marino /* Set to zero if -fcompare-debug is disabled, positive if it's
2855e4b17023SJohn Marino    enabled and we're running the first compilation, negative if it's
2856e4b17023SJohn Marino    enabled and we're running the second compilation.  For most of the
2857e4b17023SJohn Marino    time, it's in the range -1..1, but it can be temporarily set to 2
2858e4b17023SJohn Marino    or 3 to indicate that the -fcompare-debug flags didn't come from
2859e4b17023SJohn Marino    the command-line, but rather from the GCC_COMPARE_DEBUG environment
2860e4b17023SJohn Marino    variable, until a synthesized -fcompare-debug flag is added to the
2861e4b17023SJohn Marino    command line.  */
2862e4b17023SJohn Marino int compare_debug;
2863e4b17023SJohn Marino 
2864e4b17023SJohn Marino /* Set to nonzero if we've seen the -fcompare-debug-second flag.  */
2865e4b17023SJohn Marino int compare_debug_second;
2866e4b17023SJohn Marino 
2867e4b17023SJohn Marino /* Set to the flags that should be passed to the second compilation in
2868e4b17023SJohn Marino    a -fcompare-debug compilation.  */
2869e4b17023SJohn Marino const char *compare_debug_opt;
2870e4b17023SJohn Marino 
2871e4b17023SJohn Marino static struct switchstr *switches_debug_check[2];
2872e4b17023SJohn Marino 
2873e4b17023SJohn Marino static int n_switches_debug_check[2];
2874e4b17023SJohn Marino 
2875e4b17023SJohn Marino static int n_switches_alloc_debug_check[2];
2876e4b17023SJohn Marino 
2877e4b17023SJohn Marino static char *debug_check_temp_file[2];
2878e4b17023SJohn Marino 
2879e4b17023SJohn Marino /* Language is one of three things:
2880e4b17023SJohn Marino 
2881e4b17023SJohn Marino    1) The name of a real programming language.
2882e4b17023SJohn Marino    2) NULL, indicating that no one has figured out
2883e4b17023SJohn Marino    what it is yet.
2884e4b17023SJohn Marino    3) '*', indicating that the file should be passed
2885e4b17023SJohn Marino    to the linker.  */
2886e4b17023SJohn Marino struct infile
2887e4b17023SJohn Marino {
2888e4b17023SJohn Marino   const char *name;
2889e4b17023SJohn Marino   const char *language;
2890e4b17023SJohn Marino   struct compiler *incompiler;
2891e4b17023SJohn Marino   bool compiled;
2892e4b17023SJohn Marino   bool preprocessed;
2893e4b17023SJohn Marino };
2894e4b17023SJohn Marino 
2895e4b17023SJohn Marino /* Also a vector of input files specified.  */
2896e4b17023SJohn Marino 
2897e4b17023SJohn Marino static struct infile *infiles;
2898e4b17023SJohn Marino 
2899e4b17023SJohn Marino int n_infiles;
2900e4b17023SJohn Marino 
2901e4b17023SJohn Marino static int n_infiles_alloc;
2902e4b17023SJohn Marino 
2903e4b17023SJohn Marino /* True if multiple input files are being compiled to a single
2904e4b17023SJohn Marino    assembly file.  */
2905e4b17023SJohn Marino 
2906e4b17023SJohn Marino static bool combine_inputs;
2907e4b17023SJohn Marino 
2908e4b17023SJohn Marino /* This counts the number of libraries added by lang_specific_driver, so that
2909e4b17023SJohn Marino    we can tell if there were any user supplied any files or libraries.  */
2910e4b17023SJohn Marino 
2911e4b17023SJohn Marino static int added_libraries;
2912e4b17023SJohn Marino 
2913e4b17023SJohn Marino /* And a vector of corresponding output files is made up later.  */
2914e4b17023SJohn Marino 
2915e4b17023SJohn Marino const char **outfiles;
2916e4b17023SJohn Marino 
2917e4b17023SJohn Marino #if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
2918e4b17023SJohn Marino 
2919e4b17023SJohn Marino /* Convert NAME to a new name if it is the standard suffix.  DO_EXE
2920e4b17023SJohn Marino    is true if we should look for an executable suffix.  DO_OBJ
2921e4b17023SJohn Marino    is true if we should look for an object suffix.  */
2922e4b17023SJohn Marino 
2923e4b17023SJohn Marino static const char *
convert_filename(const char * name,int do_exe ATTRIBUTE_UNUSED,int do_obj ATTRIBUTE_UNUSED)2924e4b17023SJohn Marino convert_filename (const char *name, int do_exe ATTRIBUTE_UNUSED,
2925e4b17023SJohn Marino 		  int do_obj ATTRIBUTE_UNUSED)
2926e4b17023SJohn Marino {
2927e4b17023SJohn Marino #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
2928e4b17023SJohn Marino   int i;
2929e4b17023SJohn Marino #endif
2930e4b17023SJohn Marino   int len;
2931e4b17023SJohn Marino 
2932e4b17023SJohn Marino   if (name == NULL)
2933e4b17023SJohn Marino     return NULL;
2934e4b17023SJohn Marino 
2935e4b17023SJohn Marino   len = strlen (name);
2936e4b17023SJohn Marino 
2937e4b17023SJohn Marino #ifdef HAVE_TARGET_OBJECT_SUFFIX
2938e4b17023SJohn Marino   /* Convert x.o to x.obj if TARGET_OBJECT_SUFFIX is ".obj".  */
2939e4b17023SJohn Marino   if (do_obj && len > 2
2940e4b17023SJohn Marino       && name[len - 2] == '.'
2941e4b17023SJohn Marino       && name[len - 1] == 'o')
2942e4b17023SJohn Marino     {
2943e4b17023SJohn Marino       obstack_grow (&obstack, name, len - 2);
2944e4b17023SJohn Marino       obstack_grow0 (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
2945e4b17023SJohn Marino       name = XOBFINISH (&obstack, const char *);
2946e4b17023SJohn Marino     }
2947e4b17023SJohn Marino #endif
2948e4b17023SJohn Marino 
2949e4b17023SJohn Marino #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
2950e4b17023SJohn Marino   /* If there is no filetype, make it the executable suffix (which includes
2951e4b17023SJohn Marino      the ".").  But don't get confused if we have just "-o".  */
2952e4b17023SJohn Marino   if (! do_exe || TARGET_EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-'))
2953e4b17023SJohn Marino     return name;
2954e4b17023SJohn Marino 
2955e4b17023SJohn Marino   for (i = len - 1; i >= 0; i--)
2956e4b17023SJohn Marino     if (IS_DIR_SEPARATOR (name[i]))
2957e4b17023SJohn Marino       break;
2958e4b17023SJohn Marino 
2959e4b17023SJohn Marino   for (i++; i < len; i++)
2960e4b17023SJohn Marino     if (name[i] == '.')
2961e4b17023SJohn Marino       return name;
2962e4b17023SJohn Marino 
2963e4b17023SJohn Marino   obstack_grow (&obstack, name, len);
2964e4b17023SJohn Marino   obstack_grow0 (&obstack, TARGET_EXECUTABLE_SUFFIX,
2965e4b17023SJohn Marino 		 strlen (TARGET_EXECUTABLE_SUFFIX));
2966e4b17023SJohn Marino   name = XOBFINISH (&obstack, const char *);
2967e4b17023SJohn Marino #endif
2968e4b17023SJohn Marino 
2969e4b17023SJohn Marino   return name;
2970e4b17023SJohn Marino }
2971e4b17023SJohn Marino #endif
2972e4b17023SJohn Marino 
2973e4b17023SJohn Marino /* Display the command line switches accepted by gcc.  */
2974e4b17023SJohn Marino static void
display_help(void)2975e4b17023SJohn Marino display_help (void)
2976e4b17023SJohn Marino {
2977e4b17023SJohn Marino   printf (_("Usage: %s [options] file...\n"), progname);
2978e4b17023SJohn Marino   fputs (_("Options:\n"), stdout);
2979e4b17023SJohn Marino 
2980e4b17023SJohn Marino   fputs (_("  -pass-exit-codes         Exit with highest error code from a phase\n"), stdout);
2981e4b17023SJohn Marino   fputs (_("  --help                   Display this information\n"), stdout);
2982e4b17023SJohn Marino   fputs (_("  --target-help            Display target specific command line options\n"), stdout);
2983e4b17023SJohn Marino   fputs (_("  --help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...]\n"), stdout);
2984e4b17023SJohn Marino   fputs (_("                           Display specific types of command line options\n"), stdout);
2985e4b17023SJohn Marino   if (! verbose_flag)
2986e4b17023SJohn Marino     fputs (_("  (Use '-v --help' to display command line options of sub-processes)\n"), stdout);
2987e4b17023SJohn Marino   fputs (_("  --version                Display compiler version information\n"), stdout);
2988e4b17023SJohn Marino   fputs (_("  -dumpspecs               Display all of the built in spec strings\n"), stdout);
2989e4b17023SJohn Marino   fputs (_("  -dumpversion             Display the version of the compiler\n"), stdout);
2990e4b17023SJohn Marino   fputs (_("  -dumpmachine             Display the compiler's target processor\n"), stdout);
2991e4b17023SJohn Marino   fputs (_("  -print-search-dirs       Display the directories in the compiler's search path\n"), stdout);
2992e4b17023SJohn Marino   fputs (_("  -print-libgcc-file-name  Display the name of the compiler's companion library\n"), stdout);
2993e4b17023SJohn Marino   fputs (_("  -print-file-name=<lib>   Display the full path to library <lib>\n"), stdout);
2994e4b17023SJohn Marino   fputs (_("  -print-prog-name=<prog>  Display the full path to compiler component <prog>\n"), stdout);
29955ce9237cSJohn Marino   fputs (_("\
29965ce9237cSJohn Marino   -print-multiarch         Display the target's normalized GNU triplet, used as\n\
29975ce9237cSJohn Marino                            a component in the library path\n"), stdout);
2998e4b17023SJohn Marino   fputs (_("  -print-multi-directory   Display the root directory for versions of libgcc\n"), stdout);
2999e4b17023SJohn Marino   fputs (_("\
3000e4b17023SJohn Marino   -print-multi-lib         Display the mapping between command line options and\n\
3001e4b17023SJohn Marino                            multiple library search directories\n"), stdout);
3002e4b17023SJohn Marino   fputs (_("  -print-multi-os-directory Display the relative path to OS libraries\n"), stdout);
3003e4b17023SJohn Marino   fputs (_("  -print-sysroot           Display the target libraries directory\n"), stdout);
3004e4b17023SJohn Marino   fputs (_("  -print-sysroot-headers-suffix Display the sysroot suffix used to find headers\n"), stdout);
3005e4b17023SJohn Marino   fputs (_("  -Wa,<options>            Pass comma-separated <options> on to the assembler\n"), stdout);
3006e4b17023SJohn Marino   fputs (_("  -Wp,<options>            Pass comma-separated <options> on to the preprocessor\n"), stdout);
3007e4b17023SJohn Marino   fputs (_("  -Wl,<options>            Pass comma-separated <options> on to the linker\n"), stdout);
3008e4b17023SJohn Marino   fputs (_("  -Xassembler <arg>        Pass <arg> on to the assembler\n"), stdout);
3009e4b17023SJohn Marino   fputs (_("  -Xpreprocessor <arg>     Pass <arg> on to the preprocessor\n"), stdout);
3010e4b17023SJohn Marino   fputs (_("  -Xlinker <arg>           Pass <arg> on to the linker\n"), stdout);
3011e4b17023SJohn Marino   fputs (_("  -save-temps              Do not delete intermediate files\n"), stdout);
3012e4b17023SJohn Marino   fputs (_("  -save-temps=<arg>        Do not delete intermediate files\n"), stdout);
3013e4b17023SJohn Marino   fputs (_("\
3014e4b17023SJohn Marino   -no-canonical-prefixes   Do not canonicalize paths when building relative\n\
3015e4b17023SJohn Marino                            prefixes to other gcc components\n"), stdout);
3016e4b17023SJohn Marino   fputs (_("  -pipe                    Use pipes rather than intermediate files\n"), stdout);
3017e4b17023SJohn Marino   fputs (_("  -time                    Time the execution of each subprocess\n"), stdout);
3018e4b17023SJohn Marino   fputs (_("  -specs=<file>            Override built-in specs with the contents of <file>\n"), stdout);
3019e4b17023SJohn Marino   fputs (_("  -std=<standard>          Assume that the input sources are for <standard>\n"), stdout);
3020e4b17023SJohn Marino   fputs (_("\
3021e4b17023SJohn Marino   --sysroot=<directory>    Use <directory> as the root directory for headers\n\
3022e4b17023SJohn Marino                            and libraries\n"), stdout);
3023e4b17023SJohn Marino   fputs (_("  -B <directory>           Add <directory> to the compiler's search paths\n"), stdout);
3024e4b17023SJohn Marino   fputs (_("  -v                       Display the programs invoked by the compiler\n"), stdout);
3025e4b17023SJohn Marino   fputs (_("  -###                     Like -v but options quoted and commands not executed\n"), stdout);
3026e4b17023SJohn Marino   fputs (_("  -E                       Preprocess only; do not compile, assemble or link\n"), stdout);
3027e4b17023SJohn Marino   fputs (_("  -S                       Compile only; do not assemble or link\n"), stdout);
3028e4b17023SJohn Marino   fputs (_("  -c                       Compile and assemble, but do not link\n"), stdout);
3029e4b17023SJohn Marino   fputs (_("  -o <file>                Place the output into <file>\n"), stdout);
3030e4b17023SJohn Marino   fputs (_("  -pie                     Create a position independent executable\n"), stdout);
3031e4b17023SJohn Marino   fputs (_("  -shared                  Create a shared library\n"), stdout);
3032e4b17023SJohn Marino   fputs (_("\
3033e4b17023SJohn Marino   -x <language>            Specify the language of the following input files\n\
3034e4b17023SJohn Marino                            Permissible languages include: c c++ assembler none\n\
3035e4b17023SJohn Marino                            'none' means revert to the default behavior of\n\
3036e4b17023SJohn Marino                            guessing the language based on the file's extension\n\
3037e4b17023SJohn Marino "), stdout);
3038e4b17023SJohn Marino 
3039e4b17023SJohn Marino   printf (_("\
3040e4b17023SJohn Marino \nOptions starting with -g, -f, -m, -O, -W, or --param are automatically\n\
3041e4b17023SJohn Marino  passed on to the various sub-processes invoked by %s.  In order to pass\n\
3042e4b17023SJohn Marino  other options on to these processes the -W<letter> options must be used.\n\
3043e4b17023SJohn Marino "), progname);
3044e4b17023SJohn Marino 
3045e4b17023SJohn Marino   /* The rest of the options are displayed by invocations of the various
3046e4b17023SJohn Marino      sub-processes.  */
3047e4b17023SJohn Marino }
3048e4b17023SJohn Marino 
3049e4b17023SJohn Marino static void
add_preprocessor_option(const char * option,int len)3050e4b17023SJohn Marino add_preprocessor_option (const char *option, int len)
3051e4b17023SJohn Marino {
3052e4b17023SJohn Marino   VEC_safe_push (char_p, heap, preprocessor_options,
3053e4b17023SJohn Marino 		 save_string (option, len));
3054e4b17023SJohn Marino }
3055e4b17023SJohn Marino 
3056e4b17023SJohn Marino static void
add_assembler_option(const char * option,int len)3057e4b17023SJohn Marino add_assembler_option (const char *option, int len)
3058e4b17023SJohn Marino {
3059e4b17023SJohn Marino   VEC_safe_push (char_p, heap, assembler_options, save_string (option, len));
3060e4b17023SJohn Marino }
3061e4b17023SJohn Marino 
3062e4b17023SJohn Marino static void
add_linker_option(const char * option,int len)3063e4b17023SJohn Marino add_linker_option (const char *option, int len)
3064e4b17023SJohn Marino {
3065e4b17023SJohn Marino   VEC_safe_push (char_p, heap, linker_options, save_string (option, len));
3066e4b17023SJohn Marino }
3067e4b17023SJohn Marino 
3068e4b17023SJohn Marino /* Allocate space for an input file in infiles.  */
3069e4b17023SJohn Marino 
3070e4b17023SJohn Marino static void
alloc_infile(void)3071e4b17023SJohn Marino alloc_infile (void)
3072e4b17023SJohn Marino {
3073e4b17023SJohn Marino   if (n_infiles_alloc == 0)
3074e4b17023SJohn Marino     {
3075e4b17023SJohn Marino       n_infiles_alloc = 16;
3076e4b17023SJohn Marino       infiles = XNEWVEC (struct infile, n_infiles_alloc);
3077e4b17023SJohn Marino     }
3078e4b17023SJohn Marino   else if (n_infiles_alloc == n_infiles)
3079e4b17023SJohn Marino     {
3080e4b17023SJohn Marino       n_infiles_alloc *= 2;
3081e4b17023SJohn Marino       infiles = XRESIZEVEC (struct infile, infiles, n_infiles_alloc);
3082e4b17023SJohn Marino     }
3083e4b17023SJohn Marino }
3084e4b17023SJohn Marino 
3085e4b17023SJohn Marino /* Store an input file with the given NAME and LANGUAGE in
3086e4b17023SJohn Marino    infiles.  */
3087e4b17023SJohn Marino 
3088e4b17023SJohn Marino static void
add_infile(const char * name,const char * language)3089e4b17023SJohn Marino add_infile (const char *name, const char *language)
3090e4b17023SJohn Marino {
3091e4b17023SJohn Marino   alloc_infile ();
3092e4b17023SJohn Marino   infiles[n_infiles].name = name;
3093e4b17023SJohn Marino   infiles[n_infiles++].language = language;
3094e4b17023SJohn Marino }
3095e4b17023SJohn Marino 
3096e4b17023SJohn Marino /* Allocate space for a switch in switches.  */
3097e4b17023SJohn Marino 
3098e4b17023SJohn Marino static void
alloc_switch(void)3099e4b17023SJohn Marino alloc_switch (void)
3100e4b17023SJohn Marino {
3101e4b17023SJohn Marino   if (n_switches_alloc == 0)
3102e4b17023SJohn Marino     {
3103e4b17023SJohn Marino       n_switches_alloc = 16;
3104e4b17023SJohn Marino       switches = XNEWVEC (struct switchstr, n_switches_alloc);
3105e4b17023SJohn Marino     }
3106e4b17023SJohn Marino   else if (n_switches_alloc == n_switches)
3107e4b17023SJohn Marino     {
3108e4b17023SJohn Marino       n_switches_alloc *= 2;
3109e4b17023SJohn Marino       switches = XRESIZEVEC (struct switchstr, switches, n_switches_alloc);
3110e4b17023SJohn Marino     }
3111e4b17023SJohn Marino }
3112e4b17023SJohn Marino 
3113e4b17023SJohn Marino /* Save an option OPT with N_ARGS arguments in array ARGS, marking it
3114e4b17023SJohn Marino    as validated if VALIDATED.  */
3115e4b17023SJohn Marino 
3116e4b17023SJohn Marino static void
save_switch(const char * opt,size_t n_args,const char * const * args,bool validated)3117e4b17023SJohn Marino save_switch (const char *opt, size_t n_args, const char *const *args,
3118e4b17023SJohn Marino 	     bool validated)
3119e4b17023SJohn Marino {
3120e4b17023SJohn Marino   alloc_switch ();
3121e4b17023SJohn Marino   switches[n_switches].part1 = opt + 1;
3122e4b17023SJohn Marino   if (n_args == 0)
3123e4b17023SJohn Marino     switches[n_switches].args = 0;
3124e4b17023SJohn Marino   else
3125e4b17023SJohn Marino     {
3126e4b17023SJohn Marino       switches[n_switches].args = XNEWVEC (const char *, n_args + 1);
3127e4b17023SJohn Marino       memcpy (switches[n_switches].args, args, n_args * sizeof (const char *));
3128e4b17023SJohn Marino       switches[n_switches].args[n_args] = NULL;
3129e4b17023SJohn Marino     }
3130e4b17023SJohn Marino 
3131e4b17023SJohn Marino   switches[n_switches].live_cond = 0;
3132e4b17023SJohn Marino   switches[n_switches].validated = validated;
3133e4b17023SJohn Marino   switches[n_switches].ordering = 0;
3134e4b17023SJohn Marino   n_switches++;
3135e4b17023SJohn Marino }
3136e4b17023SJohn Marino 
3137e4b17023SJohn Marino /* Handle an option DECODED that is unknown to the option-processing
3138e4b17023SJohn Marino    machinery.  */
3139e4b17023SJohn Marino 
3140e4b17023SJohn Marino static bool
driver_unknown_option_callback(const struct cl_decoded_option * decoded)3141e4b17023SJohn Marino driver_unknown_option_callback (const struct cl_decoded_option *decoded)
3142e4b17023SJohn Marino {
3143e4b17023SJohn Marino   const char *opt = decoded->arg;
3144e4b17023SJohn Marino   if (opt[1] == 'W' && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-'
3145e4b17023SJohn Marino       && !(decoded->errors & CL_ERR_NEGATIVE))
3146e4b17023SJohn Marino     {
3147e4b17023SJohn Marino       /* Leave unknown -Wno-* options for the compiler proper, to be
3148e4b17023SJohn Marino 	 diagnosed only if there are warnings.  */
3149e4b17023SJohn Marino       save_switch (decoded->canonical_option[0],
3150e4b17023SJohn Marino 		   decoded->canonical_option_num_elements - 1,
3151e4b17023SJohn Marino 		   &decoded->canonical_option[1], false);
3152e4b17023SJohn Marino       return false;
3153e4b17023SJohn Marino     }
3154e4b17023SJohn Marino   else
3155e4b17023SJohn Marino     return true;
3156e4b17023SJohn Marino }
3157e4b17023SJohn Marino 
3158e4b17023SJohn Marino /* Handle an option DECODED that is not marked as CL_DRIVER.
3159e4b17023SJohn Marino    LANG_MASK will always be CL_DRIVER.  */
3160e4b17023SJohn Marino 
3161e4b17023SJohn Marino static void
driver_wrong_lang_callback(const struct cl_decoded_option * decoded,unsigned int lang_mask ATTRIBUTE_UNUSED)3162e4b17023SJohn Marino driver_wrong_lang_callback (const struct cl_decoded_option *decoded,
3163e4b17023SJohn Marino 			    unsigned int lang_mask ATTRIBUTE_UNUSED)
3164e4b17023SJohn Marino {
3165e4b17023SJohn Marino   /* At this point, non-driver options are accepted (and expected to
3166e4b17023SJohn Marino      be passed down by specs) unless marked to be rejected by the
3167e4b17023SJohn Marino      driver.  Options to be rejected by the driver but accepted by the
3168e4b17023SJohn Marino      compilers proper are treated just like completely unknown
3169e4b17023SJohn Marino      options.  */
3170e4b17023SJohn Marino   const struct cl_option *option = &cl_options[decoded->opt_index];
3171e4b17023SJohn Marino 
3172e4b17023SJohn Marino   if (option->cl_reject_driver)
3173e4b17023SJohn Marino     error ("unrecognized command line option %qs",
3174e4b17023SJohn Marino 	   decoded->orig_option_with_args_text);
3175e4b17023SJohn Marino   else
3176e4b17023SJohn Marino     save_switch (decoded->canonical_option[0],
3177e4b17023SJohn Marino 		 decoded->canonical_option_num_elements - 1,
3178e4b17023SJohn Marino 		 &decoded->canonical_option[1], false);
3179e4b17023SJohn Marino }
3180e4b17023SJohn Marino 
3181e4b17023SJohn Marino static const char *spec_lang = 0;
3182e4b17023SJohn Marino static int last_language_n_infiles;
3183e4b17023SJohn Marino 
3184e4b17023SJohn Marino /* Handle a driver option; arguments and return value as for
3185e4b17023SJohn Marino    handle_option.  */
3186e4b17023SJohn Marino 
3187e4b17023SJohn Marino static bool
driver_handle_option(struct gcc_options * opts,struct gcc_options * opts_set,const struct cl_decoded_option * decoded,unsigned int lang_mask ATTRIBUTE_UNUSED,int kind,location_t loc,const struct cl_option_handlers * handlers ATTRIBUTE_UNUSED,diagnostic_context * dc)3188e4b17023SJohn Marino driver_handle_option (struct gcc_options *opts,
3189e4b17023SJohn Marino 		      struct gcc_options *opts_set,
3190e4b17023SJohn Marino 		      const struct cl_decoded_option *decoded,
3191e4b17023SJohn Marino 		      unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
3192e4b17023SJohn Marino 		      location_t loc,
3193e4b17023SJohn Marino 		      const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED,
3194e4b17023SJohn Marino 		      diagnostic_context *dc)
3195e4b17023SJohn Marino {
3196e4b17023SJohn Marino   size_t opt_index = decoded->opt_index;
3197e4b17023SJohn Marino   const char *arg = decoded->arg;
3198e4b17023SJohn Marino   const char *compare_debug_replacement_opt;
3199e4b17023SJohn Marino   int value = decoded->value;
3200e4b17023SJohn Marino   bool validated = false;
3201e4b17023SJohn Marino   bool do_save = true;
3202e4b17023SJohn Marino 
3203e4b17023SJohn Marino   gcc_assert (opts == &global_options);
3204e4b17023SJohn Marino   gcc_assert (opts_set == &global_options_set);
3205e4b17023SJohn Marino   gcc_assert (kind == DK_UNSPECIFIED);
3206e4b17023SJohn Marino   gcc_assert (loc == UNKNOWN_LOCATION);
3207e4b17023SJohn Marino   gcc_assert (dc == global_dc);
3208e4b17023SJohn Marino 
3209e4b17023SJohn Marino   switch (opt_index)
3210e4b17023SJohn Marino     {
3211e4b17023SJohn Marino     case OPT_dumpspecs:
3212e4b17023SJohn Marino       {
3213e4b17023SJohn Marino 	struct spec_list *sl;
3214e4b17023SJohn Marino 	init_spec ();
3215e4b17023SJohn Marino 	for (sl = specs; sl; sl = sl->next)
3216e4b17023SJohn Marino 	  printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec));
3217e4b17023SJohn Marino 	if (link_command_spec)
3218e4b17023SJohn Marino 	  printf ("*link_command:\n%s\n\n", link_command_spec);
3219e4b17023SJohn Marino 	exit (0);
3220e4b17023SJohn Marino       }
3221e4b17023SJohn Marino 
3222e4b17023SJohn Marino     case OPT_dumpversion:
3223e4b17023SJohn Marino       printf ("%s\n", spec_version);
3224e4b17023SJohn Marino       exit (0);
3225e4b17023SJohn Marino 
3226e4b17023SJohn Marino     case OPT_dumpmachine:
3227e4b17023SJohn Marino       printf ("%s\n", spec_machine);
3228e4b17023SJohn Marino       exit (0);
3229e4b17023SJohn Marino 
3230e4b17023SJohn Marino     case OPT__version:
3231e4b17023SJohn Marino       print_version = 1;
3232e4b17023SJohn Marino 
3233e4b17023SJohn Marino       /* CPP driver cannot obtain switch from cc1_options.  */
3234e4b17023SJohn Marino       if (is_cpp_driver)
3235e4b17023SJohn Marino 	add_preprocessor_option ("--version", strlen ("--version"));
3236e4b17023SJohn Marino       add_assembler_option ("--version", strlen ("--version"));
3237e4b17023SJohn Marino       add_linker_option ("--version", strlen ("--version"));
3238e4b17023SJohn Marino       break;
3239e4b17023SJohn Marino 
3240e4b17023SJohn Marino     case OPT__help:
3241e4b17023SJohn Marino       print_help_list = 1;
3242e4b17023SJohn Marino 
3243e4b17023SJohn Marino       /* CPP driver cannot obtain switch from cc1_options.  */
3244e4b17023SJohn Marino       if (is_cpp_driver)
3245e4b17023SJohn Marino 	add_preprocessor_option ("--help", 6);
3246e4b17023SJohn Marino       add_assembler_option ("--help", 6);
3247e4b17023SJohn Marino       add_linker_option ("--help", 6);
3248e4b17023SJohn Marino       break;
3249e4b17023SJohn Marino 
3250e4b17023SJohn Marino     case OPT__help_:
3251e4b17023SJohn Marino       print_subprocess_help = 2;
3252e4b17023SJohn Marino       break;
3253e4b17023SJohn Marino 
3254e4b17023SJohn Marino     case OPT__target_help:
3255e4b17023SJohn Marino       print_subprocess_help = 1;
3256e4b17023SJohn Marino 
3257e4b17023SJohn Marino       /* CPP driver cannot obtain switch from cc1_options.  */
3258e4b17023SJohn Marino       if (is_cpp_driver)
3259e4b17023SJohn Marino 	add_preprocessor_option ("--target-help", 13);
3260e4b17023SJohn Marino       add_assembler_option ("--target-help", 13);
3261e4b17023SJohn Marino       add_linker_option ("--target-help", 13);
3262e4b17023SJohn Marino       break;
3263e4b17023SJohn Marino 
3264e4b17023SJohn Marino     case OPT_pass_exit_codes:
3265e4b17023SJohn Marino     case OPT_print_search_dirs:
3266e4b17023SJohn Marino     case OPT_print_file_name_:
3267e4b17023SJohn Marino     case OPT_print_prog_name_:
3268e4b17023SJohn Marino     case OPT_print_multi_lib:
3269e4b17023SJohn Marino     case OPT_print_multi_directory:
3270e4b17023SJohn Marino     case OPT_print_sysroot:
3271e4b17023SJohn Marino     case OPT_print_multi_os_directory:
32725ce9237cSJohn Marino     case OPT_print_multiarch:
3273e4b17023SJohn Marino     case OPT_print_sysroot_headers_suffix:
3274e4b17023SJohn Marino     case OPT_time:
3275e4b17023SJohn Marino     case OPT_wrapper:
3276e4b17023SJohn Marino       /* These options set the variables specified in common.opt
3277e4b17023SJohn Marino 	 automatically, and do not need to be saved for spec
3278e4b17023SJohn Marino 	 processing.  */
3279e4b17023SJohn Marino       do_save = false;
3280e4b17023SJohn Marino       break;
3281e4b17023SJohn Marino 
3282e4b17023SJohn Marino     case OPT_print_libgcc_file_name:
3283e4b17023SJohn Marino       print_file_name = "libgcc.a";
3284e4b17023SJohn Marino       do_save = false;
3285e4b17023SJohn Marino       break;
3286e4b17023SJohn Marino 
3287e4b17023SJohn Marino     case OPT_fcompare_debug_second:
3288e4b17023SJohn Marino       compare_debug_second = 1;
3289e4b17023SJohn Marino       break;
3290e4b17023SJohn Marino 
3291e4b17023SJohn Marino     case OPT_fcompare_debug:
3292e4b17023SJohn Marino       switch (value)
3293e4b17023SJohn Marino 	{
3294e4b17023SJohn Marino 	case 0:
3295e4b17023SJohn Marino 	  compare_debug_replacement_opt = "-fcompare-debug=";
3296e4b17023SJohn Marino 	  arg = "";
3297e4b17023SJohn Marino 	  goto compare_debug_with_arg;
3298e4b17023SJohn Marino 
3299e4b17023SJohn Marino 	case 1:
3300e4b17023SJohn Marino 	  compare_debug_replacement_opt = "-fcompare-debug=-gtoggle";
3301e4b17023SJohn Marino 	  arg = "-gtoggle";
3302e4b17023SJohn Marino 	  goto compare_debug_with_arg;
3303e4b17023SJohn Marino 
3304e4b17023SJohn Marino 	default:
3305e4b17023SJohn Marino 	  gcc_unreachable ();
3306e4b17023SJohn Marino 	}
3307e4b17023SJohn Marino       break;
3308e4b17023SJohn Marino 
3309e4b17023SJohn Marino     case OPT_fcompare_debug_:
3310e4b17023SJohn Marino       compare_debug_replacement_opt = decoded->canonical_option[0];
3311e4b17023SJohn Marino     compare_debug_with_arg:
3312e4b17023SJohn Marino       gcc_assert (decoded->canonical_option_num_elements == 1);
3313e4b17023SJohn Marino       gcc_assert (arg != NULL);
3314e4b17023SJohn Marino       if (*arg)
3315e4b17023SJohn Marino 	compare_debug = 1;
3316e4b17023SJohn Marino       else
3317e4b17023SJohn Marino 	compare_debug = -1;
3318e4b17023SJohn Marino       if (compare_debug < 0)
3319e4b17023SJohn Marino 	compare_debug_opt = NULL;
3320e4b17023SJohn Marino       else
3321e4b17023SJohn Marino 	compare_debug_opt = arg;
3322e4b17023SJohn Marino       save_switch (compare_debug_replacement_opt, 0, NULL, validated);
3323e4b17023SJohn Marino       return true;
3324e4b17023SJohn Marino 
3325e4b17023SJohn Marino     case OPT_Wa_:
3326e4b17023SJohn Marino       {
3327e4b17023SJohn Marino 	int prev, j;
3328e4b17023SJohn Marino 	/* Pass the rest of this option to the assembler.  */
3329e4b17023SJohn Marino 
3330e4b17023SJohn Marino 	/* Split the argument at commas.  */
3331e4b17023SJohn Marino 	prev = 0;
3332e4b17023SJohn Marino 	for (j = 0; arg[j]; j++)
3333e4b17023SJohn Marino 	  if (arg[j] == ',')
3334e4b17023SJohn Marino 	    {
3335e4b17023SJohn Marino 	      add_assembler_option (arg + prev, j - prev);
3336e4b17023SJohn Marino 	      prev = j + 1;
3337e4b17023SJohn Marino 	    }
3338e4b17023SJohn Marino 
3339e4b17023SJohn Marino 	/* Record the part after the last comma.  */
3340e4b17023SJohn Marino 	add_assembler_option (arg + prev, j - prev);
3341e4b17023SJohn Marino       }
3342e4b17023SJohn Marino       do_save = false;
3343e4b17023SJohn Marino       break;
3344e4b17023SJohn Marino 
3345e4b17023SJohn Marino     case OPT_Wp_:
3346e4b17023SJohn Marino       {
3347e4b17023SJohn Marino 	int prev, j;
3348e4b17023SJohn Marino 	/* Pass the rest of this option to the preprocessor.  */
3349e4b17023SJohn Marino 
3350e4b17023SJohn Marino 	/* Split the argument at commas.  */
3351e4b17023SJohn Marino 	prev = 0;
3352e4b17023SJohn Marino 	for (j = 0; arg[j]; j++)
3353e4b17023SJohn Marino 	  if (arg[j] == ',')
3354e4b17023SJohn Marino 	    {
3355e4b17023SJohn Marino 	      add_preprocessor_option (arg + prev, j - prev);
3356e4b17023SJohn Marino 	      prev = j + 1;
3357e4b17023SJohn Marino 	    }
3358e4b17023SJohn Marino 
3359e4b17023SJohn Marino 	/* Record the part after the last comma.  */
3360e4b17023SJohn Marino 	add_preprocessor_option (arg + prev, j - prev);
3361e4b17023SJohn Marino       }
3362e4b17023SJohn Marino       do_save = false;
3363e4b17023SJohn Marino       break;
3364e4b17023SJohn Marino 
3365e4b17023SJohn Marino     case OPT_Wl_:
3366e4b17023SJohn Marino       {
3367e4b17023SJohn Marino 	int prev, j;
3368e4b17023SJohn Marino 	/* Split the argument at commas.  */
3369e4b17023SJohn Marino 	prev = 0;
3370e4b17023SJohn Marino 	for (j = 0; arg[j]; j++)
3371e4b17023SJohn Marino 	  if (arg[j] == ',')
3372e4b17023SJohn Marino 	    {
3373e4b17023SJohn Marino 	      add_infile (save_string (arg + prev, j - prev), "*");
3374e4b17023SJohn Marino 	      prev = j + 1;
3375e4b17023SJohn Marino 	    }
3376e4b17023SJohn Marino 	/* Record the part after the last comma.  */
3377e4b17023SJohn Marino 	add_infile (arg + prev, "*");
3378e4b17023SJohn Marino       }
3379e4b17023SJohn Marino       do_save = false;
3380e4b17023SJohn Marino       break;
3381e4b17023SJohn Marino 
3382e4b17023SJohn Marino     case OPT_Xlinker:
3383e4b17023SJohn Marino       add_infile (arg, "*");
3384e4b17023SJohn Marino       do_save = false;
3385e4b17023SJohn Marino       break;
3386e4b17023SJohn Marino 
3387e4b17023SJohn Marino     case OPT_Xpreprocessor:
3388e4b17023SJohn Marino       add_preprocessor_option (arg, strlen (arg));
3389e4b17023SJohn Marino       do_save = false;
3390e4b17023SJohn Marino       break;
3391e4b17023SJohn Marino 
3392e4b17023SJohn Marino     case OPT_Xassembler:
3393e4b17023SJohn Marino       add_assembler_option (arg, strlen (arg));
3394e4b17023SJohn Marino       do_save = false;
3395e4b17023SJohn Marino       break;
3396e4b17023SJohn Marino 
3397e4b17023SJohn Marino     case OPT_l:
3398e4b17023SJohn Marino       /* POSIX allows separation of -l and the lib arg; canonicalize
3399e4b17023SJohn Marino 	 by concatenating -l with its arg */
3400e4b17023SJohn Marino       add_infile (concat ("-l", arg, NULL), "*");
3401e4b17023SJohn Marino       do_save = false;
3402e4b17023SJohn Marino       break;
3403e4b17023SJohn Marino 
3404e4b17023SJohn Marino     case OPT_L:
3405e4b17023SJohn Marino       /* Similarly, canonicalize -L for linkers that may not accept
3406e4b17023SJohn Marino 	 separate arguments.  */
3407e4b17023SJohn Marino       save_switch (concat ("-L", arg, NULL), 0, NULL, validated);
3408e4b17023SJohn Marino       return true;
3409e4b17023SJohn Marino 
3410e4b17023SJohn Marino     case OPT_F:
3411e4b17023SJohn Marino       /* Likewise -F.  */
3412e4b17023SJohn Marino       save_switch (concat ("-F", arg, NULL), 0, NULL, validated);
3413e4b17023SJohn Marino       return true;
3414e4b17023SJohn Marino 
3415e4b17023SJohn Marino     case OPT_save_temps:
3416e4b17023SJohn Marino       save_temps_flag = SAVE_TEMPS_CWD;
3417e4b17023SJohn Marino       validated = true;
3418e4b17023SJohn Marino       break;
3419e4b17023SJohn Marino 
3420e4b17023SJohn Marino     case OPT_save_temps_:
3421e4b17023SJohn Marino       if (strcmp (arg, "cwd") == 0)
3422e4b17023SJohn Marino 	save_temps_flag = SAVE_TEMPS_CWD;
3423e4b17023SJohn Marino       else if (strcmp (arg, "obj") == 0
3424e4b17023SJohn Marino 	       || strcmp (arg, "object") == 0)
3425e4b17023SJohn Marino 	save_temps_flag = SAVE_TEMPS_OBJ;
3426*2bbc7733Szrj       else if (strcmp (arg, "objects") == 0)
3427*2bbc7733Szrj 	save_temps_flag = SAVE_TEMPS_OBJZ;
3428e4b17023SJohn Marino       else
3429e4b17023SJohn Marino 	fatal_error ("%qs is an unknown -save-temps option",
3430e4b17023SJohn Marino 		     decoded->orig_option_with_args_text);
3431e4b17023SJohn Marino       break;
3432e4b17023SJohn Marino 
3433e4b17023SJohn Marino     case OPT_no_canonical_prefixes:
3434e4b17023SJohn Marino       /* Already handled as a special case, so ignored here.  */
3435e4b17023SJohn Marino       do_save = false;
3436e4b17023SJohn Marino       break;
3437e4b17023SJohn Marino 
3438e4b17023SJohn Marino     case OPT_pipe:
3439e4b17023SJohn Marino       validated = true;
3440e4b17023SJohn Marino       /* These options set the variables specified in common.opt
3441e4b17023SJohn Marino 	 automatically, but do need to be saved for spec
3442e4b17023SJohn Marino 	 processing.  */
3443e4b17023SJohn Marino       break;
3444e4b17023SJohn Marino 
3445e4b17023SJohn Marino     case OPT_specs_:
3446e4b17023SJohn Marino       {
3447e4b17023SJohn Marino 	struct user_specs *user = XNEW (struct user_specs);
3448e4b17023SJohn Marino 
3449e4b17023SJohn Marino 	user->next = (struct user_specs *) 0;
3450e4b17023SJohn Marino 	user->filename = arg;
3451e4b17023SJohn Marino 	if (user_specs_tail)
3452e4b17023SJohn Marino 	  user_specs_tail->next = user;
3453e4b17023SJohn Marino 	else
3454e4b17023SJohn Marino 	  user_specs_head = user;
3455e4b17023SJohn Marino 	user_specs_tail = user;
3456e4b17023SJohn Marino       }
3457e4b17023SJohn Marino       do_save = false;
3458e4b17023SJohn Marino       break;
3459e4b17023SJohn Marino 
3460e4b17023SJohn Marino     case OPT__sysroot_:
3461e4b17023SJohn Marino       target_system_root = arg;
3462e4b17023SJohn Marino       target_system_root_changed = 1;
3463e4b17023SJohn Marino       do_save = false;
3464e4b17023SJohn Marino       break;
3465e4b17023SJohn Marino 
3466e4b17023SJohn Marino     case OPT_time_:
3467e4b17023SJohn Marino       if (report_times_to_file)
3468e4b17023SJohn Marino 	fclose (report_times_to_file);
3469e4b17023SJohn Marino       report_times_to_file = fopen (arg, "a");
3470e4b17023SJohn Marino       do_save = false;
3471e4b17023SJohn Marino       break;
3472e4b17023SJohn Marino 
3473e4b17023SJohn Marino     case OPT____:
3474e4b17023SJohn Marino       /* "-###"
3475e4b17023SJohn Marino 	 This is similar to -v except that there is no execution
3476e4b17023SJohn Marino 	 of the commands and the echoed arguments are quoted.  It
3477e4b17023SJohn Marino 	 is intended for use in shell scripts to capture the
3478e4b17023SJohn Marino 	 driver-generated command line.  */
3479e4b17023SJohn Marino       verbose_only_flag++;
3480e4b17023SJohn Marino       verbose_flag = 1;
3481e4b17023SJohn Marino       do_save = false;
3482e4b17023SJohn Marino       break;
3483e4b17023SJohn Marino 
3484e4b17023SJohn Marino     case OPT_B:
3485e4b17023SJohn Marino       {
3486e4b17023SJohn Marino 	size_t len = strlen (arg);
3487e4b17023SJohn Marino 
3488e4b17023SJohn Marino 	/* Catch the case where the user has forgotten to append a
3489e4b17023SJohn Marino 	   directory separator to the path.  Note, they may be using
3490e4b17023SJohn Marino 	   -B to add an executable name prefix, eg "i386-elf-", in
3491e4b17023SJohn Marino 	   order to distinguish between multiple installations of
3492e4b17023SJohn Marino 	   GCC in the same directory.  Hence we must check to see
3493e4b17023SJohn Marino 	   if appending a directory separator actually makes a
3494e4b17023SJohn Marino 	   valid directory name.  */
3495e4b17023SJohn Marino 	if (!IS_DIR_SEPARATOR (arg[len - 1])
3496e4b17023SJohn Marino 	    && is_directory (arg, false))
3497e4b17023SJohn Marino 	  {
3498e4b17023SJohn Marino 	    char *tmp = XNEWVEC (char, len + 2);
3499e4b17023SJohn Marino 	    strcpy (tmp, arg);
3500e4b17023SJohn Marino 	    tmp[len] = DIR_SEPARATOR;
3501e4b17023SJohn Marino 	    tmp[++len] = 0;
3502e4b17023SJohn Marino 	    arg = tmp;
3503e4b17023SJohn Marino 	  }
3504e4b17023SJohn Marino 
3505e4b17023SJohn Marino 	add_prefix (&exec_prefixes, arg, NULL,
3506e4b17023SJohn Marino 		    PREFIX_PRIORITY_B_OPT, 0, 0);
3507e4b17023SJohn Marino 	add_prefix (&startfile_prefixes, arg, NULL,
3508e4b17023SJohn Marino 		    PREFIX_PRIORITY_B_OPT, 0, 0);
3509e4b17023SJohn Marino 	add_prefix (&include_prefixes, arg, NULL,
3510e4b17023SJohn Marino 		    PREFIX_PRIORITY_B_OPT, 0, 0);
3511e4b17023SJohn Marino       }
3512e4b17023SJohn Marino       validated = true;
3513e4b17023SJohn Marino       break;
3514e4b17023SJohn Marino 
3515e4b17023SJohn Marino     case OPT_x:
3516e4b17023SJohn Marino       spec_lang = arg;
3517e4b17023SJohn Marino       if (!strcmp (spec_lang, "none"))
3518e4b17023SJohn Marino 	/* Suppress the warning if -xnone comes after the last input
3519e4b17023SJohn Marino 	   file, because alternate command interfaces like g++ might
3520e4b17023SJohn Marino 	   find it useful to place -xnone after each input file.  */
3521e4b17023SJohn Marino 	spec_lang = 0;
3522e4b17023SJohn Marino       else
3523e4b17023SJohn Marino 	last_language_n_infiles = n_infiles;
3524e4b17023SJohn Marino       do_save = false;
3525e4b17023SJohn Marino       break;
3526e4b17023SJohn Marino 
3527e4b17023SJohn Marino     case OPT_o:
3528e4b17023SJohn Marino       have_o = 1;
3529e4b17023SJohn Marino #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX)
3530e4b17023SJohn Marino       arg = convert_filename (arg, ! have_c, 0);
3531e4b17023SJohn Marino #endif
3532e4b17023SJohn Marino       /* Save the output name in case -save-temps=obj was used.  */
3533e4b17023SJohn Marino       save_temps_prefix = xstrdup (arg);
3534e4b17023SJohn Marino       /* On some systems, ld cannot handle "-o" without a space.  So
3535e4b17023SJohn Marino 	 split the option from its argument.  */
3536e4b17023SJohn Marino       save_switch ("-o", 1, &arg, validated);
3537e4b17023SJohn Marino       return true;
3538e4b17023SJohn Marino 
3539e4b17023SJohn Marino     case OPT_static_libgcc:
3540e4b17023SJohn Marino     case OPT_shared_libgcc:
3541e4b17023SJohn Marino     case OPT_static_libgfortran:
3542e4b17023SJohn Marino     case OPT_static_libstdc__:
3543e4b17023SJohn Marino       /* These are always valid, since gcc.c itself understands the
3544e4b17023SJohn Marino 	 first two, gfortranspec.c understands -static-libgfortran and
3545e4b17023SJohn Marino 	 g++spec.c understands -static-libstdc++ */
3546e4b17023SJohn Marino       validated = true;
3547e4b17023SJohn Marino       break;
3548e4b17023SJohn Marino 
3549e4b17023SJohn Marino     default:
3550e4b17023SJohn Marino       /* Various driver options need no special processing at this
3551e4b17023SJohn Marino 	 point, having been handled in a prescan above or being
3552e4b17023SJohn Marino 	 handled by specs.  */
3553e4b17023SJohn Marino       break;
3554e4b17023SJohn Marino     }
3555e4b17023SJohn Marino 
3556e4b17023SJohn Marino   if (do_save)
3557e4b17023SJohn Marino     save_switch (decoded->canonical_option[0],
3558e4b17023SJohn Marino 		 decoded->canonical_option_num_elements - 1,
3559e4b17023SJohn Marino 		 &decoded->canonical_option[1], validated);
3560e4b17023SJohn Marino   return true;
3561e4b17023SJohn Marino }
3562e4b17023SJohn Marino 
3563e4b17023SJohn Marino /* Put the driver's standard set of option handlers in *HANDLERS.  */
3564e4b17023SJohn Marino 
3565e4b17023SJohn Marino static void
set_option_handlers(struct cl_option_handlers * handlers)3566e4b17023SJohn Marino set_option_handlers (struct cl_option_handlers *handlers)
3567e4b17023SJohn Marino {
3568e4b17023SJohn Marino   handlers->unknown_option_callback = driver_unknown_option_callback;
3569e4b17023SJohn Marino   handlers->wrong_lang_callback = driver_wrong_lang_callback;
3570e4b17023SJohn Marino   handlers->num_handlers = 3;
3571e4b17023SJohn Marino   handlers->handlers[0].handler = driver_handle_option;
3572e4b17023SJohn Marino   handlers->handlers[0].mask = CL_DRIVER;
3573e4b17023SJohn Marino   handlers->handlers[1].handler = common_handle_option;
3574e4b17023SJohn Marino   handlers->handlers[1].mask = CL_COMMON;
3575e4b17023SJohn Marino   handlers->handlers[2].handler = target_handle_option;
3576e4b17023SJohn Marino   handlers->handlers[2].mask = CL_TARGET;
3577e4b17023SJohn Marino }
3578e4b17023SJohn Marino 
3579e4b17023SJohn Marino /* Create the vector `switches' and its contents.
3580e4b17023SJohn Marino    Store its length in `n_switches'.  */
3581e4b17023SJohn Marino 
3582e4b17023SJohn Marino static void
process_command(unsigned int decoded_options_count,struct cl_decoded_option * decoded_options)3583e4b17023SJohn Marino process_command (unsigned int decoded_options_count,
3584e4b17023SJohn Marino 		 struct cl_decoded_option *decoded_options)
3585e4b17023SJohn Marino {
3586e4b17023SJohn Marino   const char *temp;
3587e4b17023SJohn Marino   char *temp1;
3588e4b17023SJohn Marino   const char *tooldir_prefix;
3589e4b17023SJohn Marino   char *(*get_relative_prefix) (const char *, const char *,
3590e4b17023SJohn Marino 				const char *) = NULL;
3591e4b17023SJohn Marino   struct cl_option_handlers handlers;
3592e4b17023SJohn Marino   unsigned int j;
3593e4b17023SJohn Marino 
3594e4b17023SJohn Marino   gcc_exec_prefix = getenv ("GCC_EXEC_PREFIX");
3595e4b17023SJohn Marino 
3596e4b17023SJohn Marino   n_switches = 0;
3597e4b17023SJohn Marino   n_infiles = 0;
3598e4b17023SJohn Marino   added_libraries = 0;
3599e4b17023SJohn Marino 
3600e4b17023SJohn Marino   /* Figure compiler version from version string.  */
3601e4b17023SJohn Marino 
3602e4b17023SJohn Marino   compiler_version = temp1 = xstrdup (version_string);
3603e4b17023SJohn Marino 
3604e4b17023SJohn Marino   for (; *temp1; ++temp1)
3605e4b17023SJohn Marino     {
3606e4b17023SJohn Marino       if (*temp1 == ' ')
3607e4b17023SJohn Marino 	{
3608e4b17023SJohn Marino 	  *temp1 = '\0';
3609e4b17023SJohn Marino 	  break;
3610e4b17023SJohn Marino 	}
3611e4b17023SJohn Marino     }
3612e4b17023SJohn Marino 
3613e4b17023SJohn Marino   /* Handle any -no-canonical-prefixes flag early, to assign the function
3614e4b17023SJohn Marino      that builds relative prefixes.  This function creates default search
3615e4b17023SJohn Marino      paths that are needed later in normal option handling.  */
3616e4b17023SJohn Marino 
3617e4b17023SJohn Marino   for (j = 1; j < decoded_options_count; j++)
3618e4b17023SJohn Marino     {
3619e4b17023SJohn Marino       if (decoded_options[j].opt_index == OPT_no_canonical_prefixes)
3620e4b17023SJohn Marino 	{
3621e4b17023SJohn Marino 	  get_relative_prefix = make_relative_prefix_ignore_links;
3622e4b17023SJohn Marino 	  break;
3623e4b17023SJohn Marino 	}
3624e4b17023SJohn Marino     }
3625e4b17023SJohn Marino   if (! get_relative_prefix)
3626e4b17023SJohn Marino     get_relative_prefix = make_relative_prefix;
3627e4b17023SJohn Marino 
3628e4b17023SJohn Marino   /* Set up the default search paths.  If there is no GCC_EXEC_PREFIX,
3629e4b17023SJohn Marino      see if we can create it from the pathname specified in
3630e4b17023SJohn Marino      decoded_options[0].arg.  */
3631e4b17023SJohn Marino 
3632e4b17023SJohn Marino   gcc_libexec_prefix = standard_libexec_prefix;
3633e4b17023SJohn Marino #ifndef VMS
3634e4b17023SJohn Marino   /* FIXME: make_relative_prefix doesn't yet work for VMS.  */
3635e4b17023SJohn Marino   if (!gcc_exec_prefix)
3636e4b17023SJohn Marino     {
3637fdc4107cSJohn Marino #if 0  /* Never use relative prefix (not bootstrapped) */
3638e4b17023SJohn Marino       gcc_exec_prefix = get_relative_prefix (decoded_options[0].arg,
3639e4b17023SJohn Marino 					     standard_bindir_prefix,
3640e4b17023SJohn Marino 					     standard_exec_prefix);
3641e4b17023SJohn Marino       gcc_libexec_prefix = get_relative_prefix (decoded_options[0].arg,
3642e4b17023SJohn Marino 					     standard_bindir_prefix,
3643e4b17023SJohn Marino 					     standard_libexec_prefix);
3644e4b17023SJohn Marino       if (gcc_exec_prefix)
3645e4b17023SJohn Marino 	xputenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL));
3646fdc4107cSJohn Marino #endif
3647e4b17023SJohn Marino     }
3648e4b17023SJohn Marino   else
3649e4b17023SJohn Marino     {
3650e4b17023SJohn Marino       /* make_relative_prefix requires a program name, but
3651e4b17023SJohn Marino 	 GCC_EXEC_PREFIX is typically a directory name with a trailing
3652e4b17023SJohn Marino 	 / (which is ignored by make_relative_prefix), so append a
3653e4b17023SJohn Marino 	 program name.  */
3654e4b17023SJohn Marino       char *tmp_prefix = concat (gcc_exec_prefix, "gcc", NULL);
3655e4b17023SJohn Marino       gcc_libexec_prefix = get_relative_prefix (tmp_prefix,
3656e4b17023SJohn Marino 						standard_exec_prefix,
3657e4b17023SJohn Marino 						standard_libexec_prefix);
3658e4b17023SJohn Marino 
3659e4b17023SJohn Marino       /* The path is unrelocated, so fallback to the original setting.  */
3660e4b17023SJohn Marino       if (!gcc_libexec_prefix)
3661e4b17023SJohn Marino 	gcc_libexec_prefix = standard_libexec_prefix;
3662e4b17023SJohn Marino 
3663e4b17023SJohn Marino       free (tmp_prefix);
3664e4b17023SJohn Marino     }
3665e4b17023SJohn Marino #else
3666e4b17023SJohn Marino #endif
3667e4b17023SJohn Marino   /* From this point onward, gcc_exec_prefix is non-null if the toolchain
3668e4b17023SJohn Marino      is relocated. The toolchain was either relocated using GCC_EXEC_PREFIX
3669e4b17023SJohn Marino      or an automatically created GCC_EXEC_PREFIX from
3670e4b17023SJohn Marino      decoded_options[0].arg.  */
3671e4b17023SJohn Marino 
3672e4b17023SJohn Marino   /* Do language-specific adjustment/addition of flags.  */
3673e4b17023SJohn Marino   lang_specific_driver (&decoded_options, &decoded_options_count,
3674e4b17023SJohn Marino 			&added_libraries);
3675e4b17023SJohn Marino 
3676e4b17023SJohn Marino   if (gcc_exec_prefix)
3677e4b17023SJohn Marino     {
3678e4b17023SJohn Marino       int len = strlen (gcc_exec_prefix);
3679e4b17023SJohn Marino 
3680e4b17023SJohn Marino       if (len > (int) sizeof ("/lib/gcc/") - 1
3681e4b17023SJohn Marino 	  && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1])))
3682e4b17023SJohn Marino 	{
3683e4b17023SJohn Marino 	  temp = gcc_exec_prefix + len - sizeof ("/lib/gcc/") + 1;
3684e4b17023SJohn Marino 	  if (IS_DIR_SEPARATOR (*temp)
3685e4b17023SJohn Marino 	      && filename_ncmp (temp + 1, "lib", 3) == 0
3686e4b17023SJohn Marino 	      && IS_DIR_SEPARATOR (temp[4])
3687e4b17023SJohn Marino 	      && filename_ncmp (temp + 5, "gcc", 3) == 0)
3688e4b17023SJohn Marino 	    len -= sizeof ("/lib/gcc/") - 1;
3689e4b17023SJohn Marino 	}
3690e4b17023SJohn Marino 
3691fdc4107cSJohn Marino #if 0  /* Bad Paths */
3692e4b17023SJohn Marino       set_std_prefix (gcc_exec_prefix, len);
3693e4b17023SJohn Marino       add_prefix (&exec_prefixes, gcc_libexec_prefix, "GCC",
3694e4b17023SJohn Marino 		  PREFIX_PRIORITY_LAST, 0, 0);
3695e4b17023SJohn Marino       add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC",
3696e4b17023SJohn Marino 		  PREFIX_PRIORITY_LAST, 0, 0);
3697fdc4107cSJohn Marino #endif
3698e4b17023SJohn Marino     }
3699e4b17023SJohn Marino 
3700e4b17023SJohn Marino   /* COMPILER_PATH and LIBRARY_PATH have values
3701e4b17023SJohn Marino      that are lists of directory names with colons.  */
3702e4b17023SJohn Marino 
3703e4b17023SJohn Marino   temp = getenv ("COMPILER_PATH");
3704e4b17023SJohn Marino   if (temp)
3705e4b17023SJohn Marino     {
3706e4b17023SJohn Marino       const char *startp, *endp;
3707e4b17023SJohn Marino       char *nstore = (char *) alloca (strlen (temp) + 3);
3708e4b17023SJohn Marino 
3709e4b17023SJohn Marino       startp = endp = temp;
3710e4b17023SJohn Marino       while (1)
3711e4b17023SJohn Marino 	{
3712e4b17023SJohn Marino 	  if (*endp == PATH_SEPARATOR || *endp == 0)
3713e4b17023SJohn Marino 	    {
3714e4b17023SJohn Marino 	      strncpy (nstore, startp, endp - startp);
3715e4b17023SJohn Marino 	      if (endp == startp)
3716e4b17023SJohn Marino 		strcpy (nstore, concat (".", dir_separator_str, NULL));
3717e4b17023SJohn Marino 	      else if (!IS_DIR_SEPARATOR (endp[-1]))
3718e4b17023SJohn Marino 		{
3719e4b17023SJohn Marino 		  nstore[endp - startp] = DIR_SEPARATOR;
3720e4b17023SJohn Marino 		  nstore[endp - startp + 1] = 0;
3721e4b17023SJohn Marino 		}
3722e4b17023SJohn Marino 	      else
3723e4b17023SJohn Marino 		nstore[endp - startp] = 0;
3724e4b17023SJohn Marino 	      add_prefix (&exec_prefixes, nstore, 0,
3725e4b17023SJohn Marino 			  PREFIX_PRIORITY_LAST, 0, 0);
3726e4b17023SJohn Marino 	      add_prefix (&include_prefixes, nstore, 0,
3727e4b17023SJohn Marino 			  PREFIX_PRIORITY_LAST, 0, 0);
3728e4b17023SJohn Marino 	      if (*endp == 0)
3729e4b17023SJohn Marino 		break;
3730e4b17023SJohn Marino 	      endp = startp = endp + 1;
3731e4b17023SJohn Marino 	    }
3732e4b17023SJohn Marino 	  else
3733e4b17023SJohn Marino 	    endp++;
3734e4b17023SJohn Marino 	}
3735e4b17023SJohn Marino     }
3736e4b17023SJohn Marino 
3737e4b17023SJohn Marino   temp = getenv (LIBRARY_PATH_ENV);
3738e4b17023SJohn Marino   if (temp && *cross_compile == '0')
3739e4b17023SJohn Marino     {
3740e4b17023SJohn Marino       const char *startp, *endp;
3741e4b17023SJohn Marino       char *nstore = (char *) alloca (strlen (temp) + 3);
3742e4b17023SJohn Marino 
3743e4b17023SJohn Marino       startp = endp = temp;
3744e4b17023SJohn Marino       while (1)
3745e4b17023SJohn Marino 	{
3746e4b17023SJohn Marino 	  if (*endp == PATH_SEPARATOR || *endp == 0)
3747e4b17023SJohn Marino 	    {
3748e4b17023SJohn Marino 	      strncpy (nstore, startp, endp - startp);
3749e4b17023SJohn Marino 	      if (endp == startp)
3750e4b17023SJohn Marino 		strcpy (nstore, concat (".", dir_separator_str, NULL));
3751e4b17023SJohn Marino 	      else if (!IS_DIR_SEPARATOR (endp[-1]))
3752e4b17023SJohn Marino 		{
3753e4b17023SJohn Marino 		  nstore[endp - startp] = DIR_SEPARATOR;
3754e4b17023SJohn Marino 		  nstore[endp - startp + 1] = 0;
3755e4b17023SJohn Marino 		}
3756e4b17023SJohn Marino 	      else
3757e4b17023SJohn Marino 		nstore[endp - startp] = 0;
3758e4b17023SJohn Marino 	      add_prefix (&startfile_prefixes, nstore, NULL,
3759e4b17023SJohn Marino 			  PREFIX_PRIORITY_LAST, 0, 1);
3760e4b17023SJohn Marino 	      if (*endp == 0)
3761e4b17023SJohn Marino 		break;
3762e4b17023SJohn Marino 	      endp = startp = endp + 1;
3763e4b17023SJohn Marino 	    }
3764e4b17023SJohn Marino 	  else
3765e4b17023SJohn Marino 	    endp++;
3766e4b17023SJohn Marino 	}
3767e4b17023SJohn Marino     }
3768e4b17023SJohn Marino 
3769e4b17023SJohn Marino   /* Use LPATH like LIBRARY_PATH (for the CMU build program).  */
3770e4b17023SJohn Marino   temp = getenv ("LPATH");
3771e4b17023SJohn Marino   if (temp && *cross_compile == '0')
3772e4b17023SJohn Marino     {
3773e4b17023SJohn Marino       const char *startp, *endp;
3774e4b17023SJohn Marino       char *nstore = (char *) alloca (strlen (temp) + 3);
3775e4b17023SJohn Marino 
3776e4b17023SJohn Marino       startp = endp = temp;
3777e4b17023SJohn Marino       while (1)
3778e4b17023SJohn Marino 	{
3779e4b17023SJohn Marino 	  if (*endp == PATH_SEPARATOR || *endp == 0)
3780e4b17023SJohn Marino 	    {
3781e4b17023SJohn Marino 	      strncpy (nstore, startp, endp - startp);
3782e4b17023SJohn Marino 	      if (endp == startp)
3783e4b17023SJohn Marino 		strcpy (nstore, concat (".", dir_separator_str, NULL));
3784e4b17023SJohn Marino 	      else if (!IS_DIR_SEPARATOR (endp[-1]))
3785e4b17023SJohn Marino 		{
3786e4b17023SJohn Marino 		  nstore[endp - startp] = DIR_SEPARATOR;
3787e4b17023SJohn Marino 		  nstore[endp - startp + 1] = 0;
3788e4b17023SJohn Marino 		}
3789e4b17023SJohn Marino 	      else
3790e4b17023SJohn Marino 		nstore[endp - startp] = 0;
3791e4b17023SJohn Marino 	      add_prefix (&startfile_prefixes, nstore, NULL,
3792e4b17023SJohn Marino 			  PREFIX_PRIORITY_LAST, 0, 1);
3793e4b17023SJohn Marino 	      if (*endp == 0)
3794e4b17023SJohn Marino 		break;
3795e4b17023SJohn Marino 	      endp = startp = endp + 1;
3796e4b17023SJohn Marino 	    }
3797e4b17023SJohn Marino 	  else
3798e4b17023SJohn Marino 	    endp++;
3799e4b17023SJohn Marino 	}
3800e4b17023SJohn Marino     }
3801e4b17023SJohn Marino 
3802e4b17023SJohn Marino   /* Process the options and store input files and switches in their
3803e4b17023SJohn Marino      vectors.  */
3804e4b17023SJohn Marino 
3805e4b17023SJohn Marino   last_language_n_infiles = -1;
3806e4b17023SJohn Marino 
3807e4b17023SJohn Marino   set_option_handlers (&handlers);
3808e4b17023SJohn Marino 
3809e4b17023SJohn Marino   for (j = 1; j < decoded_options_count; j++)
3810e4b17023SJohn Marino     {
3811e4b17023SJohn Marino       switch (decoded_options[j].opt_index)
3812e4b17023SJohn Marino 	{
3813e4b17023SJohn Marino 	case OPT_S:
3814e4b17023SJohn Marino 	case OPT_c:
3815e4b17023SJohn Marino 	case OPT_E:
3816e4b17023SJohn Marino 	  have_c = 1;
3817e4b17023SJohn Marino 	  break;
3818e4b17023SJohn Marino 	}
3819e4b17023SJohn Marino       if (have_c)
3820e4b17023SJohn Marino 	break;
3821e4b17023SJohn Marino     }
3822e4b17023SJohn Marino 
3823e4b17023SJohn Marino   for (j = 1; j < decoded_options_count; j++)
3824e4b17023SJohn Marino     {
3825e4b17023SJohn Marino       if (decoded_options[j].opt_index == OPT_SPECIAL_input_file)
3826e4b17023SJohn Marino 	{
3827e4b17023SJohn Marino 	  const char *arg = decoded_options[j].arg;
3828e4b17023SJohn Marino           const char *p = strrchr (arg, '@');
3829e4b17023SJohn Marino           char *fname;
3830e4b17023SJohn Marino 	  long offset;
3831e4b17023SJohn Marino 	  int consumed;
3832e4b17023SJohn Marino #ifdef HAVE_TARGET_OBJECT_SUFFIX
3833e4b17023SJohn Marino 	  arg = convert_filename (arg, 0, access (arg, F_OK));
3834e4b17023SJohn Marino #endif
3835e4b17023SJohn Marino 	  /* For LTO static archive support we handle input file
3836e4b17023SJohn Marino 	     specifications that are composed of a filename and
3837e4b17023SJohn Marino 	     an offset like FNAME@OFFSET.  */
3838e4b17023SJohn Marino 	  if (p
3839e4b17023SJohn Marino 	      && p != arg
3840e4b17023SJohn Marino 	      && sscanf (p, "@%li%n", &offset, &consumed) >= 1
3841e4b17023SJohn Marino 	      && strlen (p) == (unsigned int)consumed)
3842e4b17023SJohn Marino 	    {
3843e4b17023SJohn Marino               fname = (char *)xmalloc (p - arg + 1);
3844e4b17023SJohn Marino               memcpy (fname, arg, p - arg);
3845e4b17023SJohn Marino               fname[p - arg] = '\0';
3846e4b17023SJohn Marino 	      /* Only accept non-stdin and existing FNAME parts, otherwise
3847e4b17023SJohn Marino 		 try with the full name.  */
3848e4b17023SJohn Marino 	      if (strcmp (fname, "-") == 0 || access (fname, F_OK) < 0)
3849e4b17023SJohn Marino 		{
3850e4b17023SJohn Marino 		  free (fname);
3851e4b17023SJohn Marino 		  fname = xstrdup (arg);
3852e4b17023SJohn Marino 		}
3853e4b17023SJohn Marino 	    }
3854e4b17023SJohn Marino 	  else
3855e4b17023SJohn Marino 	    fname = xstrdup (arg);
3856e4b17023SJohn Marino 
3857e4b17023SJohn Marino           if (strcmp (fname, "-") != 0 && access (fname, F_OK) < 0)
3858e4b17023SJohn Marino 	    perror_with_name (fname);
3859e4b17023SJohn Marino           else
3860e4b17023SJohn Marino 	    add_infile (arg, spec_lang);
3861e4b17023SJohn Marino 
3862e4b17023SJohn Marino           free (fname);
3863e4b17023SJohn Marino 	  continue;
3864e4b17023SJohn Marino 	}
3865e4b17023SJohn Marino 
3866e4b17023SJohn Marino       read_cmdline_option (&global_options, &global_options_set,
3867e4b17023SJohn Marino 			   decoded_options + j, UNKNOWN_LOCATION,
3868e4b17023SJohn Marino 			   CL_DRIVER, &handlers, global_dc);
3869e4b17023SJohn Marino     }
3870e4b17023SJohn Marino 
3871e4b17023SJohn Marino   /* If -save-temps=obj and -o name, create the prefix to use for %b.
3872e4b17023SJohn Marino      Otherwise just make -save-temps=obj the same as -save-temps=cwd.  */
3873e4b17023SJohn Marino   if (save_temps_flag == SAVE_TEMPS_OBJ && save_temps_prefix != NULL)
3874e4b17023SJohn Marino     {
3875e4b17023SJohn Marino       save_temps_length = strlen (save_temps_prefix);
3876e4b17023SJohn Marino       temp = strrchr (lbasename (save_temps_prefix), '.');
3877e4b17023SJohn Marino       if (temp)
3878e4b17023SJohn Marino 	{
3879e4b17023SJohn Marino 	  save_temps_length -= strlen (temp);
3880e4b17023SJohn Marino 	  save_temps_prefix[save_temps_length] = '\0';
3881e4b17023SJohn Marino 	}
3882e4b17023SJohn Marino 
3883e4b17023SJohn Marino     }
3884*2bbc7733Szrj   else if (save_temps_flag == SAVE_TEMPS_OBJZ && save_temps_prefix != NULL)
3885*2bbc7733Szrj     {
3886*2bbc7733Szrj       save_temps_length = strlen (save_temps_prefix);
3887*2bbc7733Szrj     }
3888e4b17023SJohn Marino   else if (save_temps_prefix != NULL)
3889e4b17023SJohn Marino     {
3890e4b17023SJohn Marino       free (save_temps_prefix);
3891e4b17023SJohn Marino       save_temps_prefix = NULL;
3892e4b17023SJohn Marino     }
3893e4b17023SJohn Marino 
3894e4b17023SJohn Marino   if (save_temps_flag && use_pipes)
3895e4b17023SJohn Marino     {
3896e4b17023SJohn Marino       /* -save-temps overrides -pipe, so that temp files are produced */
3897e4b17023SJohn Marino       if (save_temps_flag)
3898e4b17023SJohn Marino 	warning (0, "-pipe ignored because -save-temps specified");
3899e4b17023SJohn Marino       use_pipes = 0;
3900e4b17023SJohn Marino     }
3901e4b17023SJohn Marino 
3902e4b17023SJohn Marino   if (!compare_debug)
3903e4b17023SJohn Marino     {
3904e4b17023SJohn Marino       const char *gcd = getenv ("GCC_COMPARE_DEBUG");
3905e4b17023SJohn Marino 
3906e4b17023SJohn Marino       if (gcd && gcd[0] == '-')
3907e4b17023SJohn Marino 	{
3908e4b17023SJohn Marino 	  compare_debug = 2;
3909e4b17023SJohn Marino 	  compare_debug_opt = gcd;
3910e4b17023SJohn Marino 	}
3911e4b17023SJohn Marino       else if (gcd && *gcd && strcmp (gcd, "0"))
3912e4b17023SJohn Marino 	{
3913e4b17023SJohn Marino 	  compare_debug = 3;
3914e4b17023SJohn Marino 	  compare_debug_opt = "-gtoggle";
3915e4b17023SJohn Marino 	}
3916e4b17023SJohn Marino     }
3917e4b17023SJohn Marino   else if (compare_debug < 0)
3918e4b17023SJohn Marino     {
3919e4b17023SJohn Marino       compare_debug = 0;
3920e4b17023SJohn Marino       gcc_assert (!compare_debug_opt);
3921e4b17023SJohn Marino     }
3922e4b17023SJohn Marino 
3923e4b17023SJohn Marino   /* Set up the search paths.  We add directories that we expect to
3924e4b17023SJohn Marino      contain GNU Toolchain components before directories specified by
3925e4b17023SJohn Marino      the machine description so that we will find GNU components (like
3926e4b17023SJohn Marino      the GNU assembler) before those of the host system.  */
3927e4b17023SJohn Marino 
3928e4b17023SJohn Marino   /* If we don't know where the toolchain has been installed, use the
3929e4b17023SJohn Marino      configured-in locations.  */
3930e4b17023SJohn Marino   if (!gcc_exec_prefix)
3931e4b17023SJohn Marino     {
3932e4b17023SJohn Marino #ifndef OS2
3933fdc4107cSJohn Marino       add_prefix (&exec_prefixes, standard_libexec_prefix, NULL,
3934fdc4107cSJohn Marino 		  PREFIX_PRIORITY_LAST, 0, 0);
3935fdc4107cSJohn Marino #if 0  /* Bad paths */
3936e4b17023SJohn Marino       add_prefix (&exec_prefixes, standard_libexec_prefix, "GCC",
3937e4b17023SJohn Marino 		  PREFIX_PRIORITY_LAST, 1, 0);
3938e4b17023SJohn Marino       add_prefix (&exec_prefixes, standard_libexec_prefix, "BINUTILS",
3939e4b17023SJohn Marino 		  PREFIX_PRIORITY_LAST, 2, 0);
3940e4b17023SJohn Marino       add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS",
3941e4b17023SJohn Marino 		  PREFIX_PRIORITY_LAST, 2, 0);
3942e4b17023SJohn Marino #endif
3943fdc4107cSJohn Marino #endif
3944fdc4107cSJohn Marino #if 0  /* Bad paths */
3945e4b17023SJohn Marino       add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS",
3946e4b17023SJohn Marino 		  PREFIX_PRIORITY_LAST, 1, 0);
3947fdc4107cSJohn Marino #endif
3948e4b17023SJohn Marino     }
3949e4b17023SJohn Marino 
3950e4b17023SJohn Marino   gcc_assert (!IS_ABSOLUTE_PATH (tooldir_base_prefix));
3951e4b17023SJohn Marino   tooldir_prefix = concat (tooldir_base_prefix, spec_machine,
3952e4b17023SJohn Marino 			   dir_separator_str, NULL);
3953e4b17023SJohn Marino 
3954e4b17023SJohn Marino   /* Look for tools relative to the location from which the driver is
3955e4b17023SJohn Marino      running, or, if that is not available, the configured prefix.  */
3956e4b17023SJohn Marino   tooldir_prefix
3957e4b17023SJohn Marino     = concat (gcc_exec_prefix ? gcc_exec_prefix : standard_exec_prefix,
3958e4b17023SJohn Marino 	      spec_machine, dir_separator_str,
3959e4b17023SJohn Marino 	      spec_version, dir_separator_str, tooldir_prefix, NULL);
3960e4b17023SJohn Marino 
3961fdc4107cSJohn Marino #if 0  /* Bad paths */
3962e4b17023SJohn Marino   add_prefix (&exec_prefixes,
3963e4b17023SJohn Marino 	      concat (tooldir_prefix, "bin", dir_separator_str, NULL),
3964e4b17023SJohn Marino 	      "BINUTILS", PREFIX_PRIORITY_LAST, 0, 0);
3965e4b17023SJohn Marino   add_prefix (&startfile_prefixes,
3966e4b17023SJohn Marino 	      concat (tooldir_prefix, "lib", dir_separator_str, NULL),
3967e4b17023SJohn Marino 	      "BINUTILS", PREFIX_PRIORITY_LAST, 0, 1);
3968fdc4107cSJohn Marino #endif
3969e4b17023SJohn Marino 
3970e4b17023SJohn Marino #if defined(TARGET_SYSTEM_ROOT_RELOCATABLE) && !defined(VMS)
3971e4b17023SJohn Marino   /* If the normal TARGET_SYSTEM_ROOT is inside of $exec_prefix,
3972e4b17023SJohn Marino      then consider it to relocate with the rest of the GCC installation
3973e4b17023SJohn Marino      if GCC_EXEC_PREFIX is set.
3974e4b17023SJohn Marino      ``make_relative_prefix'' is not compiled for VMS, so don't call it.  */
3975e4b17023SJohn Marino   if (target_system_root && !target_system_root_changed && gcc_exec_prefix)
3976e4b17023SJohn Marino     {
3977e4b17023SJohn Marino       char *tmp_prefix = get_relative_prefix (decoded_options[0].arg,
3978e4b17023SJohn Marino 					      standard_bindir_prefix,
3979e4b17023SJohn Marino 					      target_system_root);
3980e4b17023SJohn Marino       if (tmp_prefix && access_check (tmp_prefix, F_OK) == 0)
3981e4b17023SJohn Marino 	{
3982e4b17023SJohn Marino 	  target_system_root = tmp_prefix;
3983e4b17023SJohn Marino 	  target_system_root_changed = 1;
3984e4b17023SJohn Marino 	}
3985e4b17023SJohn Marino     }
3986e4b17023SJohn Marino #endif
3987e4b17023SJohn Marino 
3988e4b17023SJohn Marino   /* More prefixes are enabled in main, after we read the specs file
3989e4b17023SJohn Marino      and determine whether this is cross-compilation or not.  */
3990e4b17023SJohn Marino 
3991e4b17023SJohn Marino   if (n_infiles == last_language_n_infiles && spec_lang != 0)
3992e4b17023SJohn Marino     warning (0, "%<-x %s%> after last input file has no effect", spec_lang);
3993e4b17023SJohn Marino 
3994e4b17023SJohn Marino   if (compare_debug == 2 || compare_debug == 3)
3995e4b17023SJohn Marino     {
3996e4b17023SJohn Marino       alloc_switch ();
3997e4b17023SJohn Marino       switches[n_switches].part1 = concat ("fcompare-debug=",
3998e4b17023SJohn Marino 					   compare_debug_opt,
3999e4b17023SJohn Marino 					   NULL);
4000e4b17023SJohn Marino       switches[n_switches].args = 0;
4001e4b17023SJohn Marino       switches[n_switches].live_cond = 0;
4002e4b17023SJohn Marino       switches[n_switches].validated = 0;
4003e4b17023SJohn Marino       switches[n_switches].ordering = 0;
4004e4b17023SJohn Marino       n_switches++;
4005e4b17023SJohn Marino       compare_debug = 1;
4006e4b17023SJohn Marino     }
4007e4b17023SJohn Marino 
4008e4b17023SJohn Marino   /* Ensure we only invoke each subprocess once.  */
4009e4b17023SJohn Marino   if (print_subprocess_help || print_help_list || print_version)
4010e4b17023SJohn Marino     {
4011e4b17023SJohn Marino       n_infiles = 0;
4012e4b17023SJohn Marino 
4013e4b17023SJohn Marino       /* Create a dummy input file, so that we can pass
4014e4b17023SJohn Marino 	 the help option on to the various sub-processes.  */
4015e4b17023SJohn Marino       add_infile ("help-dummy", "c");
4016e4b17023SJohn Marino     }
4017e4b17023SJohn Marino 
4018e4b17023SJohn Marino   alloc_switch ();
4019e4b17023SJohn Marino   switches[n_switches].part1 = 0;
4020e4b17023SJohn Marino   alloc_infile ();
4021e4b17023SJohn Marino   infiles[n_infiles].name = 0;
4022e4b17023SJohn Marino }
4023e4b17023SJohn Marino 
4024e4b17023SJohn Marino /* Store switches not filtered out by %<S in spec in COLLECT_GCC_OPTIONS
4025e4b17023SJohn Marino    and place that in the environment.  */
4026e4b17023SJohn Marino 
4027e4b17023SJohn Marino static void
set_collect_gcc_options(void)4028e4b17023SJohn Marino set_collect_gcc_options (void)
4029e4b17023SJohn Marino {
4030e4b17023SJohn Marino   int i;
4031e4b17023SJohn Marino   int first_time;
4032e4b17023SJohn Marino 
4033e4b17023SJohn Marino   /* Build COLLECT_GCC_OPTIONS to have all of the options specified to
4034e4b17023SJohn Marino      the compiler.  */
4035e4b17023SJohn Marino   obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
4036e4b17023SJohn Marino 		sizeof ("COLLECT_GCC_OPTIONS=") - 1);
4037e4b17023SJohn Marino 
4038e4b17023SJohn Marino   first_time = TRUE;
4039e4b17023SJohn Marino   for (i = 0; (int) i < n_switches; i++)
4040e4b17023SJohn Marino     {
4041e4b17023SJohn Marino       const char *const *args;
4042e4b17023SJohn Marino       const char *p, *q;
4043e4b17023SJohn Marino       if (!first_time)
4044e4b17023SJohn Marino 	obstack_grow (&collect_obstack, " ", 1);
4045e4b17023SJohn Marino 
4046e4b17023SJohn Marino       first_time = FALSE;
4047e4b17023SJohn Marino 
4048e4b17023SJohn Marino       /* Ignore elided switches.  */
4049e4b17023SJohn Marino       if ((switches[i].live_cond
4050e4b17023SJohn Marino 	   & (SWITCH_IGNORE | SWITCH_KEEP_FOR_GCC))
4051e4b17023SJohn Marino 	  == SWITCH_IGNORE)
4052e4b17023SJohn Marino 	continue;
4053e4b17023SJohn Marino 
4054e4b17023SJohn Marino       obstack_grow (&collect_obstack, "'-", 2);
4055e4b17023SJohn Marino       q = switches[i].part1;
4056e4b17023SJohn Marino       while ((p = strchr (q, '\'')))
4057e4b17023SJohn Marino 	{
4058e4b17023SJohn Marino 	  obstack_grow (&collect_obstack, q, p - q);
4059e4b17023SJohn Marino 	  obstack_grow (&collect_obstack, "'\\''", 4);
4060e4b17023SJohn Marino 	  q = ++p;
4061e4b17023SJohn Marino 	}
4062e4b17023SJohn Marino       obstack_grow (&collect_obstack, q, strlen (q));
4063e4b17023SJohn Marino       obstack_grow (&collect_obstack, "'", 1);
4064e4b17023SJohn Marino 
4065e4b17023SJohn Marino       for (args = switches[i].args; args && *args; args++)
4066e4b17023SJohn Marino 	{
4067e4b17023SJohn Marino 	  obstack_grow (&collect_obstack, " '", 2);
4068e4b17023SJohn Marino 	  q = *args;
4069e4b17023SJohn Marino 	  while ((p = strchr (q, '\'')))
4070e4b17023SJohn Marino 	    {
4071e4b17023SJohn Marino 	      obstack_grow (&collect_obstack, q, p - q);
4072e4b17023SJohn Marino 	      obstack_grow (&collect_obstack, "'\\''", 4);
4073e4b17023SJohn Marino 	      q = ++p;
4074e4b17023SJohn Marino 	    }
4075e4b17023SJohn Marino 	  obstack_grow (&collect_obstack, q, strlen (q));
4076e4b17023SJohn Marino 	  obstack_grow (&collect_obstack, "'", 1);
4077e4b17023SJohn Marino 	}
4078e4b17023SJohn Marino     }
4079e4b17023SJohn Marino   obstack_grow (&collect_obstack, "\0", 1);
4080e4b17023SJohn Marino   xputenv (XOBFINISH (&collect_obstack, char *));
4081e4b17023SJohn Marino }
4082e4b17023SJohn Marino 
4083e4b17023SJohn Marino /* Process a spec string, accumulating and running commands.  */
4084e4b17023SJohn Marino 
4085e4b17023SJohn Marino /* These variables describe the input file name.
4086e4b17023SJohn Marino    input_file_number is the index on outfiles of this file,
4087e4b17023SJohn Marino    so that the output file name can be stored for later use by %o.
4088e4b17023SJohn Marino    input_basename is the start of the part of the input file
4089e4b17023SJohn Marino    sans all directory names, and basename_length is the number
4090e4b17023SJohn Marino    of characters starting there excluding the suffix .c or whatever.  */
4091e4b17023SJohn Marino 
4092e4b17023SJohn Marino static const char *gcc_input_filename;
4093e4b17023SJohn Marino static int input_file_number;
4094e4b17023SJohn Marino size_t input_filename_length;
4095e4b17023SJohn Marino static int basename_length;
4096e4b17023SJohn Marino static int suffixed_basename_length;
4097e4b17023SJohn Marino static const char *input_basename;
4098e4b17023SJohn Marino static const char *input_suffix;
4099e4b17023SJohn Marino #ifndef HOST_LACKS_INODE_NUMBERS
4100e4b17023SJohn Marino static struct stat input_stat;
4101e4b17023SJohn Marino #endif
4102e4b17023SJohn Marino static int input_stat_set;
4103e4b17023SJohn Marino 
4104e4b17023SJohn Marino /* The compiler used to process the current input file.  */
4105e4b17023SJohn Marino static struct compiler *input_file_compiler;
4106e4b17023SJohn Marino 
4107e4b17023SJohn Marino /* These are variables used within do_spec and do_spec_1.  */
4108e4b17023SJohn Marino 
4109e4b17023SJohn Marino /* Nonzero if an arg has been started and not yet terminated
4110e4b17023SJohn Marino    (with space, tab or newline).  */
4111e4b17023SJohn Marino static int arg_going;
4112e4b17023SJohn Marino 
4113e4b17023SJohn Marino /* Nonzero means %d or %g has been seen; the next arg to be terminated
4114e4b17023SJohn Marino    is a temporary file name.  */
4115e4b17023SJohn Marino static int delete_this_arg;
4116e4b17023SJohn Marino 
4117e4b17023SJohn Marino /* Nonzero means %w has been seen; the next arg to be terminated
4118e4b17023SJohn Marino    is the output file name of this compilation.  */
4119e4b17023SJohn Marino static int this_is_output_file;
4120e4b17023SJohn Marino 
4121e4b17023SJohn Marino /* Nonzero means %s has been seen; the next arg to be terminated
4122e4b17023SJohn Marino    is the name of a library file and we should try the standard
4123e4b17023SJohn Marino    search dirs for it.  */
4124e4b17023SJohn Marino static int this_is_library_file;
4125e4b17023SJohn Marino 
4126e4b17023SJohn Marino /* Nonzero means %T has been seen; the next arg to be terminated
4127e4b17023SJohn Marino    is the name of a linker script and we should try all of the
4128e4b17023SJohn Marino    standard search dirs for it.  If it is found insert a --script
4129e4b17023SJohn Marino    command line switch and then substitute the full path in place,
4130e4b17023SJohn Marino    otherwise generate an error message.  */
4131e4b17023SJohn Marino static int this_is_linker_script;
4132e4b17023SJohn Marino 
4133e4b17023SJohn Marino /* Nonzero means that the input of this command is coming from a pipe.  */
4134e4b17023SJohn Marino static int input_from_pipe;
4135e4b17023SJohn Marino 
4136e4b17023SJohn Marino /* Nonnull means substitute this for any suffix when outputting a switches
4137e4b17023SJohn Marino    arguments.  */
4138e4b17023SJohn Marino static const char *suffix_subst;
4139e4b17023SJohn Marino 
4140e4b17023SJohn Marino /* If there is an argument being accumulated, terminate it and store it.  */
4141e4b17023SJohn Marino 
4142e4b17023SJohn Marino static void
end_going_arg(void)4143e4b17023SJohn Marino end_going_arg (void)
4144e4b17023SJohn Marino {
4145e4b17023SJohn Marino   if (arg_going)
4146e4b17023SJohn Marino     {
4147e4b17023SJohn Marino       const char *string;
4148e4b17023SJohn Marino 
4149e4b17023SJohn Marino       obstack_1grow (&obstack, 0);
4150e4b17023SJohn Marino       string = XOBFINISH (&obstack, const char *);
4151e4b17023SJohn Marino       if (this_is_library_file)
4152e4b17023SJohn Marino 	string = find_file (string);
4153e4b17023SJohn Marino       if (this_is_linker_script)
4154e4b17023SJohn Marino 	{
4155e4b17023SJohn Marino 	  char * full_script_path = find_a_file (&startfile_prefixes, string, R_OK, true);
4156e4b17023SJohn Marino 
4157e4b17023SJohn Marino 	  if (full_script_path == NULL)
4158e4b17023SJohn Marino 	    {
4159e4b17023SJohn Marino 	      error ("unable to locate default linker script %qs in the library search paths", string);
4160e4b17023SJohn Marino 	      /* Script was not found on search path.  */
4161e4b17023SJohn Marino 	      return;
4162e4b17023SJohn Marino 	    }
4163e4b17023SJohn Marino 	  store_arg ("--script", false, false);
4164e4b17023SJohn Marino 	  string = full_script_path;
4165e4b17023SJohn Marino 	}
4166e4b17023SJohn Marino       store_arg (string, delete_this_arg, this_is_output_file);
4167e4b17023SJohn Marino       if (this_is_output_file)
4168e4b17023SJohn Marino 	outfiles[input_file_number] = string;
4169e4b17023SJohn Marino       arg_going = 0;
4170e4b17023SJohn Marino     }
4171e4b17023SJohn Marino }
4172e4b17023SJohn Marino 
4173e4b17023SJohn Marino 
4174e4b17023SJohn Marino /* Parse the WRAPPER string which is a comma separated list of the command line
4175e4b17023SJohn Marino    and insert them into the beginning of argbuf.  */
4176e4b17023SJohn Marino 
4177e4b17023SJohn Marino static void
insert_wrapper(const char * wrapper)4178e4b17023SJohn Marino insert_wrapper (const char *wrapper)
4179e4b17023SJohn Marino {
4180e4b17023SJohn Marino   int n = 0;
4181e4b17023SJohn Marino   int i;
4182e4b17023SJohn Marino   char *buf = xstrdup (wrapper);
4183e4b17023SJohn Marino   char *p = buf;
4184e4b17023SJohn Marino   unsigned int old_length = VEC_length (const_char_p, argbuf);
4185e4b17023SJohn Marino 
4186e4b17023SJohn Marino   do
4187e4b17023SJohn Marino     {
4188e4b17023SJohn Marino       n++;
4189e4b17023SJohn Marino       while (*p == ',')
4190e4b17023SJohn Marino         p++;
4191e4b17023SJohn Marino     }
4192e4b17023SJohn Marino   while ((p = strchr (p, ',')) != NULL);
4193e4b17023SJohn Marino 
4194e4b17023SJohn Marino   VEC_safe_grow (const_char_p, heap, argbuf, old_length + n);
4195e4b17023SJohn Marino   memmove (VEC_address (const_char_p, argbuf) + n,
4196e4b17023SJohn Marino 	   VEC_address (const_char_p, argbuf),
4197e4b17023SJohn Marino 	   old_length * sizeof (const_char_p));
4198e4b17023SJohn Marino 
4199e4b17023SJohn Marino   i = 0;
4200e4b17023SJohn Marino   p = buf;
4201e4b17023SJohn Marino   do
4202e4b17023SJohn Marino     {
4203e4b17023SJohn Marino       while (*p == ',')
4204e4b17023SJohn Marino         {
4205e4b17023SJohn Marino           *p = 0;
4206e4b17023SJohn Marino           p++;
4207e4b17023SJohn Marino         }
4208e4b17023SJohn Marino       VEC_replace (const_char_p, argbuf, i, p);
4209e4b17023SJohn Marino       i++;
4210e4b17023SJohn Marino     }
4211e4b17023SJohn Marino   while ((p = strchr (p, ',')) != NULL);
4212e4b17023SJohn Marino   gcc_assert (i == n);
4213e4b17023SJohn Marino }
4214e4b17023SJohn Marino 
4215e4b17023SJohn Marino /* Process the spec SPEC and run the commands specified therein.
4216e4b17023SJohn Marino    Returns 0 if the spec is successfully processed; -1 if failed.  */
4217e4b17023SJohn Marino 
4218e4b17023SJohn Marino int
do_spec(const char * spec)4219e4b17023SJohn Marino do_spec (const char *spec)
4220e4b17023SJohn Marino {
4221e4b17023SJohn Marino   int value;
4222e4b17023SJohn Marino 
4223e4b17023SJohn Marino   value = do_spec_2 (spec);
4224e4b17023SJohn Marino 
4225e4b17023SJohn Marino   /* Force out any unfinished command.
4226e4b17023SJohn Marino      If -pipe, this forces out the last command if it ended in `|'.  */
4227e4b17023SJohn Marino   if (value == 0)
4228e4b17023SJohn Marino     {
4229e4b17023SJohn Marino       if (VEC_length (const_char_p, argbuf) > 0
4230e4b17023SJohn Marino 	  && !strcmp (VEC_last (const_char_p, argbuf), "|"))
4231e4b17023SJohn Marino 	VEC_pop (const_char_p, argbuf);
4232e4b17023SJohn Marino 
4233e4b17023SJohn Marino       set_collect_gcc_options ();
4234e4b17023SJohn Marino 
4235e4b17023SJohn Marino       if (VEC_length (const_char_p, argbuf) > 0)
4236e4b17023SJohn Marino 	value = execute ();
4237e4b17023SJohn Marino     }
4238e4b17023SJohn Marino 
4239e4b17023SJohn Marino   return value;
4240e4b17023SJohn Marino }
4241e4b17023SJohn Marino 
4242e4b17023SJohn Marino static int
do_spec_2(const char * spec)4243e4b17023SJohn Marino do_spec_2 (const char *spec)
4244e4b17023SJohn Marino {
4245e4b17023SJohn Marino   int result;
4246e4b17023SJohn Marino 
4247e4b17023SJohn Marino   clear_args ();
4248e4b17023SJohn Marino   arg_going = 0;
4249e4b17023SJohn Marino   delete_this_arg = 0;
4250e4b17023SJohn Marino   this_is_output_file = 0;
4251e4b17023SJohn Marino   this_is_library_file = 0;
4252e4b17023SJohn Marino   this_is_linker_script = 0;
4253e4b17023SJohn Marino   input_from_pipe = 0;
4254e4b17023SJohn Marino   suffix_subst = NULL;
4255e4b17023SJohn Marino 
4256e4b17023SJohn Marino   result = do_spec_1 (spec, 0, NULL);
4257e4b17023SJohn Marino 
4258e4b17023SJohn Marino   end_going_arg ();
4259e4b17023SJohn Marino 
4260e4b17023SJohn Marino   return result;
4261e4b17023SJohn Marino }
4262e4b17023SJohn Marino 
4263e4b17023SJohn Marino 
4264e4b17023SJohn Marino /* Process the given spec string and add any new options to the end
4265e4b17023SJohn Marino    of the switches/n_switches array.  */
4266e4b17023SJohn Marino 
4267e4b17023SJohn Marino static void
do_option_spec(const char * name,const char * spec)4268e4b17023SJohn Marino do_option_spec (const char *name, const char *spec)
4269e4b17023SJohn Marino {
4270e4b17023SJohn Marino   unsigned int i, value_count, value_len;
4271e4b17023SJohn Marino   const char *p, *q, *value;
4272e4b17023SJohn Marino   char *tmp_spec, *tmp_spec_p;
4273e4b17023SJohn Marino 
4274e4b17023SJohn Marino   if (configure_default_options[0].name == NULL)
4275e4b17023SJohn Marino     return;
4276e4b17023SJohn Marino 
4277e4b17023SJohn Marino   for (i = 0; i < ARRAY_SIZE (configure_default_options); i++)
4278e4b17023SJohn Marino     if (strcmp (configure_default_options[i].name, name) == 0)
4279e4b17023SJohn Marino       break;
4280e4b17023SJohn Marino   if (i == ARRAY_SIZE (configure_default_options))
4281e4b17023SJohn Marino     return;
4282e4b17023SJohn Marino 
4283e4b17023SJohn Marino   value = configure_default_options[i].value;
4284e4b17023SJohn Marino   value_len = strlen (value);
4285e4b17023SJohn Marino 
4286e4b17023SJohn Marino   /* Compute the size of the final spec.  */
4287e4b17023SJohn Marino   value_count = 0;
4288e4b17023SJohn Marino   p = spec;
4289e4b17023SJohn Marino   while ((p = strstr (p, "%(VALUE)")) != NULL)
4290e4b17023SJohn Marino     {
4291e4b17023SJohn Marino       p ++;
4292e4b17023SJohn Marino       value_count ++;
4293e4b17023SJohn Marino     }
4294e4b17023SJohn Marino 
4295e4b17023SJohn Marino   /* Replace each %(VALUE) by the specified value.  */
4296e4b17023SJohn Marino   tmp_spec = (char *) alloca (strlen (spec) + 1
4297e4b17023SJohn Marino 		     + value_count * (value_len - strlen ("%(VALUE)")));
4298e4b17023SJohn Marino   tmp_spec_p = tmp_spec;
4299e4b17023SJohn Marino   q = spec;
4300e4b17023SJohn Marino   while ((p = strstr (q, "%(VALUE)")) != NULL)
4301e4b17023SJohn Marino     {
4302e4b17023SJohn Marino       memcpy (tmp_spec_p, q, p - q);
4303e4b17023SJohn Marino       tmp_spec_p = tmp_spec_p + (p - q);
4304e4b17023SJohn Marino       memcpy (tmp_spec_p, value, value_len);
4305e4b17023SJohn Marino       tmp_spec_p += value_len;
4306e4b17023SJohn Marino       q = p + strlen ("%(VALUE)");
4307e4b17023SJohn Marino     }
4308e4b17023SJohn Marino   strcpy (tmp_spec_p, q);
4309e4b17023SJohn Marino 
4310e4b17023SJohn Marino   do_self_spec (tmp_spec);
4311e4b17023SJohn Marino }
4312e4b17023SJohn Marino 
4313e4b17023SJohn Marino /* Process the given spec string and add any new options to the end
4314e4b17023SJohn Marino    of the switches/n_switches array.  */
4315e4b17023SJohn Marino 
4316e4b17023SJohn Marino static void
do_self_spec(const char * spec)4317e4b17023SJohn Marino do_self_spec (const char *spec)
4318e4b17023SJohn Marino {
4319e4b17023SJohn Marino   int i;
4320e4b17023SJohn Marino 
4321e4b17023SJohn Marino   do_spec_2 (spec);
4322e4b17023SJohn Marino   do_spec_1 (" ", 0, NULL);
4323e4b17023SJohn Marino 
4324e4b17023SJohn Marino   /* Mark %<S switches processed by do_self_spec to be ignored permanently.
4325e4b17023SJohn Marino      do_self_specs adds the replacements to switches array, so it shouldn't
4326e4b17023SJohn Marino      be processed afterwards.  */
4327e4b17023SJohn Marino   for (i = 0; i < n_switches; i++)
4328e4b17023SJohn Marino     if ((switches[i].live_cond & SWITCH_IGNORE))
4329e4b17023SJohn Marino       switches[i].live_cond |= SWITCH_IGNORE_PERMANENTLY;
4330e4b17023SJohn Marino 
4331e4b17023SJohn Marino   if (VEC_length (const_char_p, argbuf) > 0)
4332e4b17023SJohn Marino     {
4333e4b17023SJohn Marino       const char **argbuf_copy;
4334e4b17023SJohn Marino       struct cl_decoded_option *decoded_options;
4335e4b17023SJohn Marino       struct cl_option_handlers handlers;
4336e4b17023SJohn Marino       unsigned int decoded_options_count;
4337e4b17023SJohn Marino       unsigned int j;
4338e4b17023SJohn Marino 
4339e4b17023SJohn Marino       /* Create a copy of argbuf with a dummy argv[0] entry for
4340e4b17023SJohn Marino 	 decode_cmdline_options_to_array.  */
4341e4b17023SJohn Marino       argbuf_copy = XNEWVEC (const char *,
4342e4b17023SJohn Marino 			     VEC_length (const_char_p, argbuf) + 1);
4343e4b17023SJohn Marino       argbuf_copy[0] = "";
4344e4b17023SJohn Marino       memcpy (argbuf_copy + 1, VEC_address (const_char_p, argbuf),
4345e4b17023SJohn Marino 	      VEC_length (const_char_p, argbuf) * sizeof (const char *));
4346e4b17023SJohn Marino 
4347e4b17023SJohn Marino       decode_cmdline_options_to_array (VEC_length (const_char_p, argbuf) + 1,
4348e4b17023SJohn Marino 				       argbuf_copy,
4349e4b17023SJohn Marino 				       CL_DRIVER, &decoded_options,
4350e4b17023SJohn Marino 				       &decoded_options_count);
4351e4b17023SJohn Marino 
4352e4b17023SJohn Marino       set_option_handlers (&handlers);
4353e4b17023SJohn Marino 
4354e4b17023SJohn Marino       for (j = 1; j < decoded_options_count; j++)
4355e4b17023SJohn Marino 	{
4356e4b17023SJohn Marino 	  switch (decoded_options[j].opt_index)
4357e4b17023SJohn Marino 	    {
4358e4b17023SJohn Marino 	    case OPT_SPECIAL_input_file:
4359e4b17023SJohn Marino 	      /* Specs should only generate options, not input
4360e4b17023SJohn Marino 		 files.  */
4361e4b17023SJohn Marino 	      if (strcmp (decoded_options[j].arg, "-") != 0)
4362e4b17023SJohn Marino 		fatal_error ("switch %qs does not start with %<-%>",
4363e4b17023SJohn Marino 			     decoded_options[j].arg);
4364e4b17023SJohn Marino 	      else
4365e4b17023SJohn Marino 		fatal_error ("spec-generated switch is just %<-%>");
4366e4b17023SJohn Marino 	      break;
4367e4b17023SJohn Marino 
4368e4b17023SJohn Marino 	    case OPT_fcompare_debug_second:
4369e4b17023SJohn Marino 	    case OPT_fcompare_debug:
4370e4b17023SJohn Marino 	    case OPT_fcompare_debug_:
4371e4b17023SJohn Marino 	    case OPT_o:
4372e4b17023SJohn Marino 	      /* Avoid duplicate processing of some options from
4373e4b17023SJohn Marino 		 compare-debug specs; just save them here.  */
4374e4b17023SJohn Marino 	      save_switch (decoded_options[j].canonical_option[0],
4375e4b17023SJohn Marino 			   (decoded_options[j].canonical_option_num_elements
4376e4b17023SJohn Marino 			    - 1),
4377e4b17023SJohn Marino 			   &decoded_options[j].canonical_option[1], false);
4378e4b17023SJohn Marino 	      break;
4379e4b17023SJohn Marino 
4380e4b17023SJohn Marino 	    default:
4381e4b17023SJohn Marino 	      read_cmdline_option (&global_options, &global_options_set,
4382e4b17023SJohn Marino 				   decoded_options + j, UNKNOWN_LOCATION,
4383e4b17023SJohn Marino 				   CL_DRIVER, &handlers, global_dc);
4384e4b17023SJohn Marino 	      break;
4385e4b17023SJohn Marino 	    }
4386e4b17023SJohn Marino 	}
4387e4b17023SJohn Marino 
4388e4b17023SJohn Marino       alloc_switch ();
4389e4b17023SJohn Marino       switches[n_switches].part1 = 0;
4390e4b17023SJohn Marino     }
4391e4b17023SJohn Marino }
4392e4b17023SJohn Marino 
4393e4b17023SJohn Marino /* Callback for processing %D and %I specs.  */
4394e4b17023SJohn Marino 
4395e4b17023SJohn Marino struct spec_path_info {
4396e4b17023SJohn Marino   const char *option;
4397e4b17023SJohn Marino   const char *append;
4398e4b17023SJohn Marino   size_t append_len;
4399e4b17023SJohn Marino   bool omit_relative;
4400e4b17023SJohn Marino   bool separate_options;
4401e4b17023SJohn Marino };
4402e4b17023SJohn Marino 
4403e4b17023SJohn Marino static void *
spec_path(char * path,void * data)4404e4b17023SJohn Marino spec_path (char *path, void *data)
4405e4b17023SJohn Marino {
4406e4b17023SJohn Marino   struct spec_path_info *info = (struct spec_path_info *) data;
4407e4b17023SJohn Marino   size_t len = 0;
4408e4b17023SJohn Marino   char save = 0;
4409e4b17023SJohn Marino 
4410e4b17023SJohn Marino   if (info->omit_relative && !IS_ABSOLUTE_PATH (path))
4411e4b17023SJohn Marino     return NULL;
4412e4b17023SJohn Marino 
4413e4b17023SJohn Marino   if (info->append_len != 0)
4414e4b17023SJohn Marino     {
4415e4b17023SJohn Marino       len = strlen (path);
4416e4b17023SJohn Marino       memcpy (path + len, info->append, info->append_len + 1);
4417e4b17023SJohn Marino     }
4418e4b17023SJohn Marino 
4419e4b17023SJohn Marino   if (!is_directory (path, true))
4420e4b17023SJohn Marino     return NULL;
4421e4b17023SJohn Marino 
4422e4b17023SJohn Marino   do_spec_1 (info->option, 1, NULL);
4423e4b17023SJohn Marino   if (info->separate_options)
4424e4b17023SJohn Marino     do_spec_1 (" ", 0, NULL);
4425e4b17023SJohn Marino 
4426e4b17023SJohn Marino   if (info->append_len == 0)
4427e4b17023SJohn Marino     {
4428e4b17023SJohn Marino       len = strlen (path);
4429e4b17023SJohn Marino       save = path[len - 1];
4430e4b17023SJohn Marino       if (IS_DIR_SEPARATOR (path[len - 1]))
4431e4b17023SJohn Marino 	path[len - 1] = '\0';
4432e4b17023SJohn Marino     }
4433e4b17023SJohn Marino 
4434e4b17023SJohn Marino   do_spec_1 (path, 1, NULL);
4435e4b17023SJohn Marino   do_spec_1 (" ", 0, NULL);
4436e4b17023SJohn Marino 
4437e4b17023SJohn Marino   /* Must not damage the original path.  */
4438e4b17023SJohn Marino   if (info->append_len == 0)
4439e4b17023SJohn Marino     path[len - 1] = save;
4440e4b17023SJohn Marino 
4441e4b17023SJohn Marino   return NULL;
4442e4b17023SJohn Marino }
4443e4b17023SJohn Marino 
4444e4b17023SJohn Marino /* Create a temporary FILE with the contents of ARGV. Add @FILE to the
4445e4b17023SJohn Marino    argument list. */
4446e4b17023SJohn Marino 
4447e4b17023SJohn Marino static void
create_at_file(char ** argv)4448e4b17023SJohn Marino create_at_file (char **argv)
4449e4b17023SJohn Marino {
4450e4b17023SJohn Marino   char *temp_file = make_temp_file ("");
4451e4b17023SJohn Marino   char *at_argument = concat ("@", temp_file, NULL);
4452e4b17023SJohn Marino   FILE *f = fopen (temp_file, "w");
4453e4b17023SJohn Marino   int status;
4454e4b17023SJohn Marino 
4455e4b17023SJohn Marino   if (f == NULL)
4456e4b17023SJohn Marino     fatal_error ("could not open temporary response file %s",
4457e4b17023SJohn Marino 		 temp_file);
4458e4b17023SJohn Marino 
4459e4b17023SJohn Marino   status = writeargv (argv, f);
4460e4b17023SJohn Marino 
4461e4b17023SJohn Marino   if (status)
4462e4b17023SJohn Marino     fatal_error ("could not write to temporary response file %s",
4463e4b17023SJohn Marino 		 temp_file);
4464e4b17023SJohn Marino 
4465e4b17023SJohn Marino   status = fclose (f);
4466e4b17023SJohn Marino 
4467e4b17023SJohn Marino   if (EOF == status)
4468e4b17023SJohn Marino     fatal_error ("could not close temporary response file %s",
4469e4b17023SJohn Marino 		 temp_file);
4470e4b17023SJohn Marino 
4471e4b17023SJohn Marino   store_arg (at_argument, 0, 0);
4472e4b17023SJohn Marino 
4473e4b17023SJohn Marino   record_temp_file (temp_file, !save_temps_flag, !save_temps_flag);
4474e4b17023SJohn Marino }
4475e4b17023SJohn Marino 
4476e4b17023SJohn Marino /* True if we should compile INFILE. */
4477e4b17023SJohn Marino 
4478e4b17023SJohn Marino static bool
compile_input_file_p(struct infile * infile)4479e4b17023SJohn Marino compile_input_file_p (struct infile *infile)
4480e4b17023SJohn Marino {
4481e4b17023SJohn Marino   if ((!infile->language) || (infile->language[0] != '*'))
4482e4b17023SJohn Marino     if (infile->incompiler == input_file_compiler)
4483e4b17023SJohn Marino       return true;
4484e4b17023SJohn Marino   return false;
4485e4b17023SJohn Marino }
4486e4b17023SJohn Marino 
4487e4b17023SJohn Marino /* Process each member of VEC as a spec.  */
4488e4b17023SJohn Marino 
4489e4b17023SJohn Marino static void
do_specs_vec(VEC (char_p,heap)* vec)4490e4b17023SJohn Marino do_specs_vec (VEC(char_p,heap) *vec)
4491e4b17023SJohn Marino {
4492e4b17023SJohn Marino   unsigned ix;
4493e4b17023SJohn Marino   char *opt;
4494e4b17023SJohn Marino 
4495e4b17023SJohn Marino   FOR_EACH_VEC_ELT (char_p, vec, ix, opt)
4496e4b17023SJohn Marino     {
4497e4b17023SJohn Marino       do_spec_1 (opt, 1, NULL);
4498e4b17023SJohn Marino       /* Make each accumulated option a separate argument.  */
4499e4b17023SJohn Marino       do_spec_1 (" ", 0, NULL);
4500e4b17023SJohn Marino     }
4501e4b17023SJohn Marino }
4502e4b17023SJohn Marino 
4503e4b17023SJohn Marino /* Process the sub-spec SPEC as a portion of a larger spec.
4504e4b17023SJohn Marino    This is like processing a whole spec except that we do
4505e4b17023SJohn Marino    not initialize at the beginning and we do not supply a
4506e4b17023SJohn Marino    newline by default at the end.
4507e4b17023SJohn Marino    INSWITCH nonzero means don't process %-sequences in SPEC;
4508e4b17023SJohn Marino    in this case, % is treated as an ordinary character.
4509e4b17023SJohn Marino    This is used while substituting switches.
4510e4b17023SJohn Marino    INSWITCH nonzero also causes SPC not to terminate an argument.
4511e4b17023SJohn Marino 
4512e4b17023SJohn Marino    Value is zero unless a line was finished
4513e4b17023SJohn Marino    and the command on that line reported an error.  */
4514e4b17023SJohn Marino 
4515e4b17023SJohn Marino static int
do_spec_1(const char * spec,int inswitch,const char * soft_matched_part)4516e4b17023SJohn Marino do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
4517e4b17023SJohn Marino {
4518e4b17023SJohn Marino   const char *p = spec;
4519e4b17023SJohn Marino   int c;
4520e4b17023SJohn Marino   int i;
4521e4b17023SJohn Marino   int value;
4522e4b17023SJohn Marino 
4523e4b17023SJohn Marino   /* If it's an empty string argument to a switch, keep it as is.  */
4524e4b17023SJohn Marino   if (inswitch && !*p)
4525e4b17023SJohn Marino     arg_going = 1;
4526e4b17023SJohn Marino 
4527e4b17023SJohn Marino   while ((c = *p++))
4528e4b17023SJohn Marino     /* If substituting a switch, treat all chars like letters.
4529e4b17023SJohn Marino        Otherwise, NL, SPC, TAB and % are special.  */
4530e4b17023SJohn Marino     switch (inswitch ? 'a' : c)
4531e4b17023SJohn Marino       {
4532e4b17023SJohn Marino       case '\n':
4533e4b17023SJohn Marino 	end_going_arg ();
4534e4b17023SJohn Marino 
4535e4b17023SJohn Marino 	if (VEC_length (const_char_p, argbuf) > 0
4536e4b17023SJohn Marino 	    && !strcmp (VEC_last (const_char_p, argbuf), "|"))
4537e4b17023SJohn Marino 	  {
4538e4b17023SJohn Marino 	    /* A `|' before the newline means use a pipe here,
4539e4b17023SJohn Marino 	       but only if -pipe was specified.
4540e4b17023SJohn Marino 	       Otherwise, execute now and don't pass the `|' as an arg.  */
4541e4b17023SJohn Marino 	    if (use_pipes)
4542e4b17023SJohn Marino 	      {
4543e4b17023SJohn Marino 		input_from_pipe = 1;
4544e4b17023SJohn Marino 		break;
4545e4b17023SJohn Marino 	      }
4546e4b17023SJohn Marino 	    else
4547e4b17023SJohn Marino 	      VEC_pop (const_char_p, argbuf);
4548e4b17023SJohn Marino 	  }
4549e4b17023SJohn Marino 
4550e4b17023SJohn Marino 	set_collect_gcc_options ();
4551e4b17023SJohn Marino 
4552e4b17023SJohn Marino 	if (VEC_length (const_char_p, argbuf) > 0)
4553e4b17023SJohn Marino 	  {
4554e4b17023SJohn Marino 	    value = execute ();
4555e4b17023SJohn Marino 	    if (value)
4556e4b17023SJohn Marino 	      return value;
4557e4b17023SJohn Marino 	  }
4558e4b17023SJohn Marino 	/* Reinitialize for a new command, and for a new argument.  */
4559e4b17023SJohn Marino 	clear_args ();
4560e4b17023SJohn Marino 	arg_going = 0;
4561e4b17023SJohn Marino 	delete_this_arg = 0;
4562e4b17023SJohn Marino 	this_is_output_file = 0;
4563e4b17023SJohn Marino 	this_is_library_file = 0;
4564e4b17023SJohn Marino 	this_is_linker_script = 0;
4565e4b17023SJohn Marino 	input_from_pipe = 0;
4566e4b17023SJohn Marino 	break;
4567e4b17023SJohn Marino 
4568e4b17023SJohn Marino       case '|':
4569e4b17023SJohn Marino 	end_going_arg ();
4570e4b17023SJohn Marino 
4571e4b17023SJohn Marino 	/* Use pipe */
4572e4b17023SJohn Marino 	obstack_1grow (&obstack, c);
4573e4b17023SJohn Marino 	arg_going = 1;
4574e4b17023SJohn Marino 	break;
4575e4b17023SJohn Marino 
4576e4b17023SJohn Marino       case '\t':
4577e4b17023SJohn Marino       case ' ':
4578e4b17023SJohn Marino 	end_going_arg ();
4579e4b17023SJohn Marino 
4580e4b17023SJohn Marino 	/* Reinitialize for a new argument.  */
4581e4b17023SJohn Marino 	delete_this_arg = 0;
4582e4b17023SJohn Marino 	this_is_output_file = 0;
4583e4b17023SJohn Marino 	this_is_library_file = 0;
4584e4b17023SJohn Marino 	this_is_linker_script = 0;
4585e4b17023SJohn Marino 	break;
4586e4b17023SJohn Marino 
4587e4b17023SJohn Marino       case '%':
4588e4b17023SJohn Marino 	switch (c = *p++)
4589e4b17023SJohn Marino 	  {
4590e4b17023SJohn Marino 	  case 0:
4591e4b17023SJohn Marino 	    fatal_error ("spec %qs invalid", spec);
4592e4b17023SJohn Marino 
4593e4b17023SJohn Marino 	  case 'b':
4594e4b17023SJohn Marino 	    if (save_temps_length)
4595e4b17023SJohn Marino 	      obstack_grow (&obstack, save_temps_prefix, save_temps_length);
4596e4b17023SJohn Marino 	    else
4597e4b17023SJohn Marino 	      obstack_grow (&obstack, input_basename, basename_length);
4598e4b17023SJohn Marino 	    if (compare_debug < 0)
4599e4b17023SJohn Marino 	      obstack_grow (&obstack, ".gk", 3);
4600e4b17023SJohn Marino 	    arg_going = 1;
4601e4b17023SJohn Marino 	    break;
4602e4b17023SJohn Marino 
4603e4b17023SJohn Marino 	  case 'B':
4604e4b17023SJohn Marino 	    if (save_temps_length)
4605e4b17023SJohn Marino 	      obstack_grow (&obstack, save_temps_prefix, save_temps_length);
4606e4b17023SJohn Marino 	    else
4607e4b17023SJohn Marino 	      obstack_grow (&obstack, input_basename, suffixed_basename_length);
4608e4b17023SJohn Marino 	    if (compare_debug < 0)
4609e4b17023SJohn Marino 	      obstack_grow (&obstack, ".gk", 3);
4610e4b17023SJohn Marino 	    arg_going = 1;
4611e4b17023SJohn Marino 	    break;
4612e4b17023SJohn Marino 
4613e4b17023SJohn Marino 	  case 'd':
4614e4b17023SJohn Marino 	    delete_this_arg = 2;
4615e4b17023SJohn Marino 	    break;
4616e4b17023SJohn Marino 
4617e4b17023SJohn Marino 	  /* Dump out the directories specified with LIBRARY_PATH,
4618e4b17023SJohn Marino 	     followed by the absolute directories
4619e4b17023SJohn Marino 	     that we search for startfiles.  */
4620e4b17023SJohn Marino 	  case 'D':
4621e4b17023SJohn Marino 	    {
4622e4b17023SJohn Marino 	      struct spec_path_info info;
4623e4b17023SJohn Marino 
4624e4b17023SJohn Marino 	      info.option = "-L";
4625e4b17023SJohn Marino 	      info.append_len = 0;
4626e4b17023SJohn Marino #ifdef RELATIVE_PREFIX_NOT_LINKDIR
4627e4b17023SJohn Marino 	      /* Used on systems which record the specified -L dirs
4628e4b17023SJohn Marino 		 and use them to search for dynamic linking.
4629e4b17023SJohn Marino 		 Relative directories always come from -B,
4630e4b17023SJohn Marino 		 and it is better not to use them for searching
4631e4b17023SJohn Marino 		 at run time.  In particular, stage1 loses.  */
4632e4b17023SJohn Marino 	      info.omit_relative = true;
4633e4b17023SJohn Marino #else
4634e4b17023SJohn Marino 	      info.omit_relative = false;
4635e4b17023SJohn Marino #endif
4636e4b17023SJohn Marino 	      info.separate_options = false;
4637e4b17023SJohn Marino 
4638e4b17023SJohn Marino 	      for_each_path (&startfile_prefixes, true, 0, spec_path, &info);
4639e4b17023SJohn Marino 	    }
4640e4b17023SJohn Marino 	    break;
4641e4b17023SJohn Marino 
4642e4b17023SJohn Marino 	  case 'e':
4643e4b17023SJohn Marino 	    /* %efoo means report an error with `foo' as error message
4644e4b17023SJohn Marino 	       and don't execute any more commands for this file.  */
4645e4b17023SJohn Marino 	    {
4646e4b17023SJohn Marino 	      const char *q = p;
4647e4b17023SJohn Marino 	      char *buf;
4648e4b17023SJohn Marino 	      while (*p != 0 && *p != '\n')
4649e4b17023SJohn Marino 		p++;
4650e4b17023SJohn Marino 	      buf = (char *) alloca (p - q + 1);
4651e4b17023SJohn Marino 	      strncpy (buf, q, p - q);
4652e4b17023SJohn Marino 	      buf[p - q] = 0;
4653e4b17023SJohn Marino 	      error ("%s", _(buf));
4654e4b17023SJohn Marino 	      return -1;
4655e4b17023SJohn Marino 	    }
4656e4b17023SJohn Marino 	    break;
4657e4b17023SJohn Marino 	  case 'n':
4658e4b17023SJohn Marino 	    /* %nfoo means report a notice with `foo' on stderr.  */
4659e4b17023SJohn Marino 	    {
4660e4b17023SJohn Marino 	      const char *q = p;
4661e4b17023SJohn Marino 	      char *buf;
4662e4b17023SJohn Marino 	      while (*p != 0 && *p != '\n')
4663e4b17023SJohn Marino 		p++;
4664e4b17023SJohn Marino 	      buf = (char *) alloca (p - q + 1);
4665e4b17023SJohn Marino 	      strncpy (buf, q, p - q);
4666e4b17023SJohn Marino 	      buf[p - q] = 0;
4667e4b17023SJohn Marino 	      inform (0, "%s", _(buf));
4668e4b17023SJohn Marino 	      if (*p)
4669e4b17023SJohn Marino 		p++;
4670e4b17023SJohn Marino 	    }
4671e4b17023SJohn Marino 	    break;
4672e4b17023SJohn Marino 
4673e4b17023SJohn Marino 	  case 'j':
4674e4b17023SJohn Marino 	    {
4675e4b17023SJohn Marino 	      struct stat st;
4676e4b17023SJohn Marino 
4677e4b17023SJohn Marino 	      /* If save_temps_flag is off, and the HOST_BIT_BUCKET is
4678e4b17023SJohn Marino 		 defined, and it is not a directory, and it is
4679e4b17023SJohn Marino 		 writable, use it.  Otherwise, treat this like any
4680e4b17023SJohn Marino 		 other temporary file.  */
4681e4b17023SJohn Marino 
4682e4b17023SJohn Marino 	      if ((!save_temps_flag)
4683e4b17023SJohn Marino 		  && (stat (HOST_BIT_BUCKET, &st) == 0) && (!S_ISDIR (st.st_mode))
4684e4b17023SJohn Marino 		  && (access (HOST_BIT_BUCKET, W_OK) == 0))
4685e4b17023SJohn Marino 		{
4686e4b17023SJohn Marino 		  obstack_grow (&obstack, HOST_BIT_BUCKET,
4687e4b17023SJohn Marino 				strlen (HOST_BIT_BUCKET));
4688e4b17023SJohn Marino 		  delete_this_arg = 0;
4689e4b17023SJohn Marino 		  arg_going = 1;
4690e4b17023SJohn Marino 		  break;
4691e4b17023SJohn Marino 		}
4692e4b17023SJohn Marino 	    }
4693e4b17023SJohn Marino 	    goto create_temp_file;
4694e4b17023SJohn Marino 	  case '|':
4695e4b17023SJohn Marino 	    if (use_pipes)
4696e4b17023SJohn Marino 	      {
4697e4b17023SJohn Marino 		obstack_1grow (&obstack, '-');
4698e4b17023SJohn Marino 		delete_this_arg = 0;
4699e4b17023SJohn Marino 		arg_going = 1;
4700e4b17023SJohn Marino 
4701e4b17023SJohn Marino 		/* consume suffix */
4702e4b17023SJohn Marino 		while (*p == '.' || ISALNUM ((unsigned char) *p))
4703e4b17023SJohn Marino 		  p++;
4704e4b17023SJohn Marino 		if (p[0] == '%' && p[1] == 'O')
4705e4b17023SJohn Marino 		  p += 2;
4706e4b17023SJohn Marino 
4707e4b17023SJohn Marino 		break;
4708e4b17023SJohn Marino 	      }
4709e4b17023SJohn Marino 	    goto create_temp_file;
4710e4b17023SJohn Marino 	  case 'm':
4711e4b17023SJohn Marino 	    if (use_pipes)
4712e4b17023SJohn Marino 	      {
4713e4b17023SJohn Marino 		/* consume suffix */
4714e4b17023SJohn Marino 		while (*p == '.' || ISALNUM ((unsigned char) *p))
4715e4b17023SJohn Marino 		  p++;
4716e4b17023SJohn Marino 		if (p[0] == '%' && p[1] == 'O')
4717e4b17023SJohn Marino 		  p += 2;
4718e4b17023SJohn Marino 
4719e4b17023SJohn Marino 		break;
4720e4b17023SJohn Marino 	      }
4721e4b17023SJohn Marino 	    goto create_temp_file;
4722e4b17023SJohn Marino 	  case 'g':
4723e4b17023SJohn Marino 	  case 'u':
4724e4b17023SJohn Marino 	  case 'U':
4725e4b17023SJohn Marino 	  create_temp_file:
4726e4b17023SJohn Marino 	      {
4727e4b17023SJohn Marino 		struct temp_name *t;
4728e4b17023SJohn Marino 		int suffix_length;
4729e4b17023SJohn Marino 		const char *suffix = p;
4730e4b17023SJohn Marino 		char *saved_suffix = NULL;
4731e4b17023SJohn Marino 
4732e4b17023SJohn Marino 		while (*p == '.' || ISALNUM ((unsigned char) *p))
4733e4b17023SJohn Marino 		  p++;
4734e4b17023SJohn Marino 		suffix_length = p - suffix;
4735e4b17023SJohn Marino 		if (p[0] == '%' && p[1] == 'O')
4736e4b17023SJohn Marino 		  {
4737e4b17023SJohn Marino 		    p += 2;
4738e4b17023SJohn Marino 		    /* We don't support extra suffix characters after %O.  */
4739e4b17023SJohn Marino 		    if (*p == '.' || ISALNUM ((unsigned char) *p))
4740e4b17023SJohn Marino 		      fatal_error ("spec %qs has invalid %<%%0%c%>", spec, *p);
4741e4b17023SJohn Marino 		    if (suffix_length == 0)
4742e4b17023SJohn Marino 		      suffix = TARGET_OBJECT_SUFFIX;
4743e4b17023SJohn Marino 		    else
4744e4b17023SJohn Marino 		      {
4745e4b17023SJohn Marino 			saved_suffix
4746e4b17023SJohn Marino 			  = XNEWVEC (char, suffix_length
4747e4b17023SJohn Marino 				     + strlen (TARGET_OBJECT_SUFFIX));
4748e4b17023SJohn Marino 			strncpy (saved_suffix, suffix, suffix_length);
4749e4b17023SJohn Marino 			strcpy (saved_suffix + suffix_length,
4750e4b17023SJohn Marino 				TARGET_OBJECT_SUFFIX);
4751e4b17023SJohn Marino 		      }
4752e4b17023SJohn Marino 		    suffix_length += strlen (TARGET_OBJECT_SUFFIX);
4753e4b17023SJohn Marino 		  }
4754e4b17023SJohn Marino 
4755e4b17023SJohn Marino 		if (compare_debug < 0)
4756e4b17023SJohn Marino 		  {
4757e4b17023SJohn Marino 		    suffix = concat (".gk", suffix, NULL);
4758e4b17023SJohn Marino 		    suffix_length += 3;
4759e4b17023SJohn Marino 		  }
4760e4b17023SJohn Marino 
4761e4b17023SJohn Marino 		/* If -save-temps=obj and -o were specified, use that for the
4762e4b17023SJohn Marino 		   temp file.  */
4763e4b17023SJohn Marino 		if (save_temps_length)
4764e4b17023SJohn Marino 		  {
4765e4b17023SJohn Marino 		    char *tmp;
4766e4b17023SJohn Marino 		    temp_filename_length
4767e4b17023SJohn Marino 		      = save_temps_length + suffix_length + 1;
4768e4b17023SJohn Marino 		    tmp = (char *) alloca (temp_filename_length);
4769e4b17023SJohn Marino 		    memcpy (tmp, save_temps_prefix, save_temps_length);
4770e4b17023SJohn Marino 		    memcpy (tmp + save_temps_length, suffix, suffix_length);
4771e4b17023SJohn Marino 		    tmp[save_temps_length + suffix_length] = '\0';
4772e4b17023SJohn Marino 		    temp_filename = save_string (tmp,
4773e4b17023SJohn Marino 						 temp_filename_length + 1);
4774e4b17023SJohn Marino 		    obstack_grow (&obstack, temp_filename,
4775e4b17023SJohn Marino 				  temp_filename_length);
4776e4b17023SJohn Marino 		    arg_going = 1;
4777e4b17023SJohn Marino 		    delete_this_arg = 0;
4778e4b17023SJohn Marino 		    break;
4779e4b17023SJohn Marino 		  }
4780e4b17023SJohn Marino 
4781e4b17023SJohn Marino 		/* If the gcc_input_filename has the same suffix specified
4782e4b17023SJohn Marino 		   for the %g, %u, or %U, and -save-temps is specified,
4783e4b17023SJohn Marino 		   we could end up using that file as an intermediate
4784e4b17023SJohn Marino 		   thus clobbering the user's source file (.e.g.,
4785e4b17023SJohn Marino 		   gcc -save-temps foo.s would clobber foo.s with the
4786e4b17023SJohn Marino 		   output of cpp0).  So check for this condition and
4787e4b17023SJohn Marino 		   generate a temp file as the intermediate.  */
4788e4b17023SJohn Marino 
4789e4b17023SJohn Marino 		if (save_temps_flag)
4790e4b17023SJohn Marino 		  {
4791e4b17023SJohn Marino 		    char *tmp;
4792e4b17023SJohn Marino 		    temp_filename_length = basename_length + suffix_length + 1;
4793e4b17023SJohn Marino 		    tmp = (char *) alloca (temp_filename_length);
4794e4b17023SJohn Marino 		    memcpy (tmp, input_basename, basename_length);
4795e4b17023SJohn Marino 		    memcpy (tmp + basename_length, suffix, suffix_length);
4796e4b17023SJohn Marino 		    tmp[basename_length + suffix_length] = '\0';
4797e4b17023SJohn Marino 		    temp_filename = tmp;
4798e4b17023SJohn Marino 
4799e4b17023SJohn Marino 		    if (filename_cmp (temp_filename, gcc_input_filename) != 0)
4800e4b17023SJohn Marino 		      {
4801e4b17023SJohn Marino #ifndef HOST_LACKS_INODE_NUMBERS
4802e4b17023SJohn Marino 			struct stat st_temp;
4803e4b17023SJohn Marino 
4804e4b17023SJohn Marino 			/* Note, set_input() resets input_stat_set to 0.  */
4805e4b17023SJohn Marino 			if (input_stat_set == 0)
4806e4b17023SJohn Marino 			  {
4807e4b17023SJohn Marino 			    input_stat_set = stat (gcc_input_filename,
4808e4b17023SJohn Marino 						   &input_stat);
4809e4b17023SJohn Marino 			    if (input_stat_set >= 0)
4810e4b17023SJohn Marino 			      input_stat_set = 1;
4811e4b17023SJohn Marino 			  }
4812e4b17023SJohn Marino 
4813e4b17023SJohn Marino 			/* If we have the stat for the gcc_input_filename
4814e4b17023SJohn Marino 			   and we can do the stat for the temp_filename
4815e4b17023SJohn Marino 			   then the they could still refer to the same
4816e4b17023SJohn Marino 			   file if st_dev/st_ino's are the same.  */
4817e4b17023SJohn Marino 			if (input_stat_set != 1
4818e4b17023SJohn Marino 			    || stat (temp_filename, &st_temp) < 0
4819e4b17023SJohn Marino 			    || input_stat.st_dev != st_temp.st_dev
4820e4b17023SJohn Marino 			    || input_stat.st_ino != st_temp.st_ino)
4821e4b17023SJohn Marino #else
4822e4b17023SJohn Marino 			/* Just compare canonical pathnames.  */
4823e4b17023SJohn Marino 			char* input_realname = lrealpath (gcc_input_filename);
4824e4b17023SJohn Marino 			char* temp_realname = lrealpath (temp_filename);
4825e4b17023SJohn Marino 			bool files_differ = filename_cmp (input_realname, temp_realname);
4826e4b17023SJohn Marino 			free (input_realname);
4827e4b17023SJohn Marino 			free (temp_realname);
4828e4b17023SJohn Marino 			if (files_differ)
4829e4b17023SJohn Marino #endif
4830e4b17023SJohn Marino 			  {
4831e4b17023SJohn Marino 			    temp_filename = save_string (temp_filename,
4832e4b17023SJohn Marino 							 temp_filename_length + 1);
4833e4b17023SJohn Marino 			    obstack_grow (&obstack, temp_filename,
4834e4b17023SJohn Marino 						    temp_filename_length);
4835e4b17023SJohn Marino 			    arg_going = 1;
4836e4b17023SJohn Marino 			    delete_this_arg = 0;
4837e4b17023SJohn Marino 			    break;
4838e4b17023SJohn Marino 			  }
4839e4b17023SJohn Marino 		      }
4840e4b17023SJohn Marino 		  }
4841e4b17023SJohn Marino 
4842e4b17023SJohn Marino 		/* See if we already have an association of %g/%u/%U and
4843e4b17023SJohn Marino 		   suffix.  */
4844e4b17023SJohn Marino 		for (t = temp_names; t; t = t->next)
4845e4b17023SJohn Marino 		  if (t->length == suffix_length
4846e4b17023SJohn Marino 		      && strncmp (t->suffix, suffix, suffix_length) == 0
4847e4b17023SJohn Marino 		      && t->unique == (c == 'u' || c == 'U' || c == 'j'))
4848e4b17023SJohn Marino 		    break;
4849e4b17023SJohn Marino 
4850e4b17023SJohn Marino 		/* Make a new association if needed.  %u and %j
4851e4b17023SJohn Marino 		   require one.  */
4852e4b17023SJohn Marino 		if (t == 0 || c == 'u' || c == 'j')
4853e4b17023SJohn Marino 		  {
4854e4b17023SJohn Marino 		    if (t == 0)
4855e4b17023SJohn Marino 		      {
4856e4b17023SJohn Marino 			t = XNEW (struct temp_name);
4857e4b17023SJohn Marino 			t->next = temp_names;
4858e4b17023SJohn Marino 			temp_names = t;
4859e4b17023SJohn Marino 		      }
4860e4b17023SJohn Marino 		    t->length = suffix_length;
4861e4b17023SJohn Marino 		    if (saved_suffix)
4862e4b17023SJohn Marino 		      {
4863e4b17023SJohn Marino 			t->suffix = saved_suffix;
4864e4b17023SJohn Marino 			saved_suffix = NULL;
4865e4b17023SJohn Marino 		      }
4866e4b17023SJohn Marino 		    else
4867e4b17023SJohn Marino 		      t->suffix = save_string (suffix, suffix_length);
4868e4b17023SJohn Marino 		    t->unique = (c == 'u' || c == 'U' || c == 'j');
4869e4b17023SJohn Marino 		    temp_filename = make_temp_file (t->suffix);
4870e4b17023SJohn Marino 		    temp_filename_length = strlen (temp_filename);
4871e4b17023SJohn Marino 		    t->filename = temp_filename;
4872e4b17023SJohn Marino 		    t->filename_length = temp_filename_length;
4873e4b17023SJohn Marino 		  }
4874e4b17023SJohn Marino 
4875e4b17023SJohn Marino 		free (saved_suffix);
4876e4b17023SJohn Marino 
4877e4b17023SJohn Marino 		obstack_grow (&obstack, t->filename, t->filename_length);
4878e4b17023SJohn Marino 		delete_this_arg = 1;
4879e4b17023SJohn Marino 	      }
4880e4b17023SJohn Marino 	    arg_going = 1;
4881e4b17023SJohn Marino 	    break;
4882e4b17023SJohn Marino 
4883e4b17023SJohn Marino 	  case 'i':
4884e4b17023SJohn Marino 	    if (combine_inputs)
4885e4b17023SJohn Marino 	      {
4886e4b17023SJohn Marino 		if (at_file_supplied)
4887e4b17023SJohn Marino 		  {
4888e4b17023SJohn Marino 		    /* We are going to expand `%i' to `@FILE', where FILE
4889e4b17023SJohn Marino 		       is a newly-created temporary filename.  The filenames
4890e4b17023SJohn Marino 		       that would usually be expanded in place of %o will be
4891e4b17023SJohn Marino 		       written to the temporary file.  */
4892e4b17023SJohn Marino 		    char **argv;
4893e4b17023SJohn Marino 		    int n_files = 0;
4894e4b17023SJohn Marino 		    int j;
4895e4b17023SJohn Marino 
4896e4b17023SJohn Marino 		    for (i = 0; i < n_infiles; i++)
4897e4b17023SJohn Marino 		      if (compile_input_file_p (&infiles[i]))
4898e4b17023SJohn Marino 			n_files++;
4899e4b17023SJohn Marino 
4900e4b17023SJohn Marino 		    argv = (char **) alloca (sizeof (char *) * (n_files + 1));
4901e4b17023SJohn Marino 
4902e4b17023SJohn Marino 		    /* Copy the strings over.  */
4903e4b17023SJohn Marino 		    for (i = 0, j = 0; i < n_infiles; i++)
4904e4b17023SJohn Marino 		      if (compile_input_file_p (&infiles[i]))
4905e4b17023SJohn Marino 			{
4906e4b17023SJohn Marino 			  argv[j] = CONST_CAST (char *, infiles[i].name);
4907e4b17023SJohn Marino 			  infiles[i].compiled = true;
4908e4b17023SJohn Marino 			  j++;
4909e4b17023SJohn Marino 			}
4910e4b17023SJohn Marino 		    argv[j] = NULL;
4911e4b17023SJohn Marino 
4912e4b17023SJohn Marino 		    create_at_file (argv);
4913e4b17023SJohn Marino 		  }
4914e4b17023SJohn Marino 		else
4915e4b17023SJohn Marino 		  for (i = 0; (int) i < n_infiles; i++)
4916e4b17023SJohn Marino 		    if (compile_input_file_p (&infiles[i]))
4917e4b17023SJohn Marino 		      {
4918e4b17023SJohn Marino 			store_arg (infiles[i].name, 0, 0);
4919e4b17023SJohn Marino 			infiles[i].compiled = true;
4920e4b17023SJohn Marino 		      }
4921e4b17023SJohn Marino 	      }
4922e4b17023SJohn Marino 	    else
4923e4b17023SJohn Marino 	      {
4924e4b17023SJohn Marino 		obstack_grow (&obstack, gcc_input_filename,
4925e4b17023SJohn Marino 			      input_filename_length);
4926e4b17023SJohn Marino 		arg_going = 1;
4927e4b17023SJohn Marino 	      }
4928e4b17023SJohn Marino 	    break;
4929e4b17023SJohn Marino 
4930e4b17023SJohn Marino 	  case 'I':
4931e4b17023SJohn Marino 	    {
4932e4b17023SJohn Marino 	      struct spec_path_info info;
4933e4b17023SJohn Marino 
4934e4b17023SJohn Marino 	      if (multilib_dir)
4935e4b17023SJohn Marino 		{
4936e4b17023SJohn Marino 		  do_spec_1 ("-imultilib", 1, NULL);
4937e4b17023SJohn Marino 		  /* Make this a separate argument.  */
4938e4b17023SJohn Marino 		  do_spec_1 (" ", 0, NULL);
4939e4b17023SJohn Marino 		  do_spec_1 (multilib_dir, 1, NULL);
4940e4b17023SJohn Marino 		  do_spec_1 (" ", 0, NULL);
4941e4b17023SJohn Marino 		}
4942e4b17023SJohn Marino 
49435ce9237cSJohn Marino 	      if (multiarch_dir)
49445ce9237cSJohn Marino 		{
49455ce9237cSJohn Marino 		  do_spec_1 ("-imultiarch", 1, NULL);
49465ce9237cSJohn Marino 		  /* Make this a separate argument.  */
49475ce9237cSJohn Marino 		  do_spec_1 (" ", 0, NULL);
49485ce9237cSJohn Marino 		  do_spec_1 (multiarch_dir, 1, NULL);
49495ce9237cSJohn Marino 		  do_spec_1 (" ", 0, NULL);
49505ce9237cSJohn Marino 		}
49515ce9237cSJohn Marino 
4952e4b17023SJohn Marino 	      if (gcc_exec_prefix)
4953e4b17023SJohn Marino 		{
4954e4b17023SJohn Marino 		  do_spec_1 ("-iprefix", 1, NULL);
4955e4b17023SJohn Marino 		  /* Make this a separate argument.  */
4956e4b17023SJohn Marino 		  do_spec_1 (" ", 0, NULL);
4957e4b17023SJohn Marino 		  do_spec_1 (gcc_exec_prefix, 1, NULL);
4958e4b17023SJohn Marino 		  do_spec_1 (" ", 0, NULL);
4959e4b17023SJohn Marino 		}
4960e4b17023SJohn Marino 
4961e4b17023SJohn Marino 	      if (target_system_root_changed ||
4962e4b17023SJohn Marino 		  (target_system_root && target_sysroot_hdrs_suffix))
4963e4b17023SJohn Marino 		{
4964e4b17023SJohn Marino 		  do_spec_1 ("-isysroot", 1, NULL);
4965e4b17023SJohn Marino 		  /* Make this a separate argument.  */
4966e4b17023SJohn Marino 		  do_spec_1 (" ", 0, NULL);
4967e4b17023SJohn Marino 		  do_spec_1 (target_system_root, 1, NULL);
4968e4b17023SJohn Marino 		  if (target_sysroot_hdrs_suffix)
4969e4b17023SJohn Marino 		    do_spec_1 (target_sysroot_hdrs_suffix, 1, NULL);
4970e4b17023SJohn Marino 		  do_spec_1 (" ", 0, NULL);
4971e4b17023SJohn Marino 		}
4972e4b17023SJohn Marino 
4973e4b17023SJohn Marino 	      info.option = "-isystem";
4974e4b17023SJohn Marino 	      info.append = "include";
4975e4b17023SJohn Marino 	      info.append_len = strlen (info.append);
4976e4b17023SJohn Marino 	      info.omit_relative = false;
4977e4b17023SJohn Marino 	      info.separate_options = true;
4978e4b17023SJohn Marino 
4979e4b17023SJohn Marino 	      for_each_path (&include_prefixes, false, info.append_len,
4980e4b17023SJohn Marino 			     spec_path, &info);
4981e4b17023SJohn Marino 
4982e4b17023SJohn Marino 	      info.append = "include-fixed";
4983e4b17023SJohn Marino 	      if (*sysroot_hdrs_suffix_spec)
4984e4b17023SJohn Marino 		info.append = concat (info.append, dir_separator_str,
4985e4b17023SJohn Marino 				      multilib_dir, NULL);
4986e4b17023SJohn Marino 	      info.append_len = strlen (info.append);
4987e4b17023SJohn Marino 	      for_each_path (&include_prefixes, false, info.append_len,
4988e4b17023SJohn Marino 			     spec_path, &info);
4989e4b17023SJohn Marino 	    }
4990e4b17023SJohn Marino 	    break;
4991e4b17023SJohn Marino 
4992e4b17023SJohn Marino 	  case 'o':
4993e4b17023SJohn Marino 	    {
4994e4b17023SJohn Marino 	      int max = n_infiles;
4995e4b17023SJohn Marino 	      max += lang_specific_extra_outfiles;
4996e4b17023SJohn Marino 
4997e4b17023SJohn Marino               if (HAVE_GNU_LD && at_file_supplied)
4998e4b17023SJohn Marino                 {
4999e4b17023SJohn Marino                   /* We are going to expand `%o' to `@FILE', where FILE
5000e4b17023SJohn Marino                      is a newly-created temporary filename.  The filenames
5001e4b17023SJohn Marino                      that would usually be expanded in place of %o will be
5002e4b17023SJohn Marino                      written to the temporary file.  */
5003e4b17023SJohn Marino 
5004e4b17023SJohn Marino                   char **argv;
5005e4b17023SJohn Marino                   int n_files, j;
5006e4b17023SJohn Marino 
5007e4b17023SJohn Marino                   /* Convert OUTFILES into a form suitable for writeargv.  */
5008e4b17023SJohn Marino 
5009e4b17023SJohn Marino                   /* Determine how many are non-NULL.  */
5010e4b17023SJohn Marino                   for (n_files = 0, i = 0; i < max; i++)
5011e4b17023SJohn Marino                     n_files += outfiles[i] != NULL;
5012e4b17023SJohn Marino 
5013e4b17023SJohn Marino                   argv = (char **) alloca (sizeof (char *) * (n_files + 1));
5014e4b17023SJohn Marino 
5015e4b17023SJohn Marino                   /* Copy the strings over.  */
5016e4b17023SJohn Marino                   for (i = 0, j = 0; i < max; i++)
5017e4b17023SJohn Marino                     if (outfiles[i])
5018e4b17023SJohn Marino                       {
5019e4b17023SJohn Marino                         argv[j] = CONST_CAST (char *, outfiles[i]);
5020e4b17023SJohn Marino                         j++;
5021e4b17023SJohn Marino                       }
5022e4b17023SJohn Marino                   argv[j] = NULL;
5023e4b17023SJohn Marino 
5024e4b17023SJohn Marino 		  create_at_file (argv);
5025e4b17023SJohn Marino                 }
5026e4b17023SJohn Marino               else
5027e4b17023SJohn Marino                 for (i = 0; i < max; i++)
5028e4b17023SJohn Marino 	          if (outfiles[i])
5029e4b17023SJohn Marino 		    store_arg (outfiles[i], 0, 0);
5030e4b17023SJohn Marino 	      break;
5031e4b17023SJohn Marino 	    }
5032e4b17023SJohn Marino 
5033e4b17023SJohn Marino 	  case 'O':
5034e4b17023SJohn Marino 	    obstack_grow (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
5035e4b17023SJohn Marino 	    arg_going = 1;
5036e4b17023SJohn Marino 	    break;
5037e4b17023SJohn Marino 
5038e4b17023SJohn Marino 	  case 's':
5039e4b17023SJohn Marino 	    this_is_library_file = 1;
5040e4b17023SJohn Marino 	    break;
5041e4b17023SJohn Marino 
5042e4b17023SJohn Marino 	  case 'T':
5043e4b17023SJohn Marino 	    this_is_linker_script = 1;
5044e4b17023SJohn Marino 	    break;
5045e4b17023SJohn Marino 
5046e4b17023SJohn Marino 	  case 'V':
5047e4b17023SJohn Marino 	    outfiles[input_file_number] = NULL;
5048e4b17023SJohn Marino 	    break;
5049e4b17023SJohn Marino 
5050e4b17023SJohn Marino 	  case 'w':
5051e4b17023SJohn Marino 	    this_is_output_file = 1;
5052e4b17023SJohn Marino 	    break;
5053e4b17023SJohn Marino 
5054e4b17023SJohn Marino 	  case 'W':
5055e4b17023SJohn Marino 	    {
5056e4b17023SJohn Marino 	      unsigned int cur_index = VEC_length (const_char_p, argbuf);
5057e4b17023SJohn Marino 	      /* Handle the {...} following the %W.  */
5058e4b17023SJohn Marino 	      if (*p != '{')
5059e4b17023SJohn Marino 		fatal_error ("spec %qs has invalid %<%%W%c%>", spec, *p);
5060e4b17023SJohn Marino 	      p = handle_braces (p + 1);
5061e4b17023SJohn Marino 	      if (p == 0)
5062e4b17023SJohn Marino 		return -1;
5063e4b17023SJohn Marino 	      end_going_arg ();
5064e4b17023SJohn Marino 	      /* If any args were output, mark the last one for deletion
5065e4b17023SJohn Marino 		 on failure.  */
5066e4b17023SJohn Marino 	      if (VEC_length (const_char_p, argbuf) != cur_index)
5067e4b17023SJohn Marino 		record_temp_file (VEC_last (const_char_p, argbuf), 0, 1);
5068e4b17023SJohn Marino 	      break;
5069e4b17023SJohn Marino 	    }
5070e4b17023SJohn Marino 
5071e4b17023SJohn Marino 	  /* %x{OPTION} records OPTION for %X to output.  */
5072e4b17023SJohn Marino 	  case 'x':
5073e4b17023SJohn Marino 	    {
5074e4b17023SJohn Marino 	      const char *p1 = p;
5075e4b17023SJohn Marino 	      char *string;
5076e4b17023SJohn Marino 	      char *opt;
5077e4b17023SJohn Marino 	      unsigned ix;
5078e4b17023SJohn Marino 
5079e4b17023SJohn Marino 	      /* Skip past the option value and make a copy.  */
5080e4b17023SJohn Marino 	      if (*p != '{')
5081e4b17023SJohn Marino 		fatal_error ("spec %qs has invalid %<%%x%c%>", spec, *p);
5082e4b17023SJohn Marino 	      while (*p++ != '}')
5083e4b17023SJohn Marino 		;
5084e4b17023SJohn Marino 	      string = save_string (p1 + 1, p - p1 - 2);
5085e4b17023SJohn Marino 
5086e4b17023SJohn Marino 	      /* See if we already recorded this option.  */
5087e4b17023SJohn Marino 	      FOR_EACH_VEC_ELT (char_p, linker_options, ix, opt)
5088e4b17023SJohn Marino 		if (! strcmp (string, opt))
5089e4b17023SJohn Marino 		  {
5090e4b17023SJohn Marino 		    free (string);
5091e4b17023SJohn Marino 		    return 0;
5092e4b17023SJohn Marino 		  }
5093e4b17023SJohn Marino 
5094e4b17023SJohn Marino 	      /* This option is new; add it.  */
5095e4b17023SJohn Marino 	      add_linker_option (string, strlen (string));
5096e4b17023SJohn Marino 	    }
5097e4b17023SJohn Marino 	    break;
5098e4b17023SJohn Marino 
5099e4b17023SJohn Marino 	  /* Dump out the options accumulated previously using %x.  */
5100e4b17023SJohn Marino 	  case 'X':
5101e4b17023SJohn Marino 	    do_specs_vec (linker_options);
5102e4b17023SJohn Marino 	    break;
5103e4b17023SJohn Marino 
5104e4b17023SJohn Marino 	  /* Dump out the options accumulated previously using -Wa,.  */
5105e4b17023SJohn Marino 	  case 'Y':
5106e4b17023SJohn Marino 	    do_specs_vec (assembler_options);
5107e4b17023SJohn Marino 	    break;
5108e4b17023SJohn Marino 
5109e4b17023SJohn Marino 	  /* Dump out the options accumulated previously using -Wp,.  */
5110e4b17023SJohn Marino 	  case 'Z':
5111e4b17023SJohn Marino 	    do_specs_vec (preprocessor_options);
5112e4b17023SJohn Marino 	    break;
5113e4b17023SJohn Marino 
5114e4b17023SJohn Marino 	    /* Here are digits and numbers that just process
5115e4b17023SJohn Marino 	       a certain constant string as a spec.  */
5116e4b17023SJohn Marino 
5117e4b17023SJohn Marino 	  case '1':
5118e4b17023SJohn Marino 	    value = do_spec_1 (cc1_spec, 0, NULL);
5119e4b17023SJohn Marino 	    if (value != 0)
5120e4b17023SJohn Marino 	      return value;
5121e4b17023SJohn Marino 	    break;
5122e4b17023SJohn Marino 
5123e4b17023SJohn Marino 	  case '2':
5124e4b17023SJohn Marino 	    value = do_spec_1 (cc1plus_spec, 0, NULL);
5125e4b17023SJohn Marino 	    if (value != 0)
5126e4b17023SJohn Marino 	      return value;
5127e4b17023SJohn Marino 	    break;
5128e4b17023SJohn Marino 
5129e4b17023SJohn Marino 	  case 'a':
5130e4b17023SJohn Marino 	    value = do_spec_1 (asm_spec, 0, NULL);
5131e4b17023SJohn Marino 	    if (value != 0)
5132e4b17023SJohn Marino 	      return value;
5133e4b17023SJohn Marino 	    break;
5134e4b17023SJohn Marino 
5135e4b17023SJohn Marino 	  case 'A':
5136e4b17023SJohn Marino 	    value = do_spec_1 (asm_final_spec, 0, NULL);
5137e4b17023SJohn Marino 	    if (value != 0)
5138e4b17023SJohn Marino 	      return value;
5139e4b17023SJohn Marino 	    break;
5140e4b17023SJohn Marino 
5141e4b17023SJohn Marino 	  case 'C':
5142e4b17023SJohn Marino 	    {
5143e4b17023SJohn Marino 	      const char *const spec
5144e4b17023SJohn Marino 		= (input_file_compiler->cpp_spec
5145e4b17023SJohn Marino 		   ? input_file_compiler->cpp_spec
5146e4b17023SJohn Marino 		   : cpp_spec);
5147e4b17023SJohn Marino 	      value = do_spec_1 (spec, 0, NULL);
5148e4b17023SJohn Marino 	      if (value != 0)
5149e4b17023SJohn Marino 		return value;
5150e4b17023SJohn Marino 	    }
5151e4b17023SJohn Marino 	    break;
5152e4b17023SJohn Marino 
5153e4b17023SJohn Marino 	  case 'E':
5154e4b17023SJohn Marino 	    value = do_spec_1 (endfile_spec, 0, NULL);
5155e4b17023SJohn Marino 	    if (value != 0)
5156e4b17023SJohn Marino 	      return value;
5157e4b17023SJohn Marino 	    break;
5158e4b17023SJohn Marino 
5159e4b17023SJohn Marino 	  case 'l':
5160e4b17023SJohn Marino 	    value = do_spec_1 (link_spec, 0, NULL);
5161e4b17023SJohn Marino 	    if (value != 0)
5162e4b17023SJohn Marino 	      return value;
5163e4b17023SJohn Marino 	    break;
5164e4b17023SJohn Marino 
5165e4b17023SJohn Marino 	  case 'L':
5166e4b17023SJohn Marino 	    value = do_spec_1 (lib_spec, 0, NULL);
5167e4b17023SJohn Marino 	    if (value != 0)
5168e4b17023SJohn Marino 	      return value;
5169e4b17023SJohn Marino 	    break;
5170e4b17023SJohn Marino 
5171e4b17023SJohn Marino 	  case 'G':
5172e4b17023SJohn Marino 	    value = do_spec_1 (libgcc_spec, 0, NULL);
5173e4b17023SJohn Marino 	    if (value != 0)
5174e4b17023SJohn Marino 	      return value;
5175e4b17023SJohn Marino 	    break;
5176e4b17023SJohn Marino 
5177e4b17023SJohn Marino 	  case 'R':
5178e4b17023SJohn Marino 	    /* We assume there is a directory
5179e4b17023SJohn Marino 	       separator at the end of this string.  */
5180e4b17023SJohn Marino 	    if (target_system_root)
5181e4b17023SJohn Marino 	      {
5182e4b17023SJohn Marino 	        obstack_grow (&obstack, target_system_root,
5183e4b17023SJohn Marino 			      strlen (target_system_root));
5184e4b17023SJohn Marino 		if (target_sysroot_suffix)
5185e4b17023SJohn Marino 		  obstack_grow (&obstack, target_sysroot_suffix,
5186e4b17023SJohn Marino 				strlen (target_sysroot_suffix));
5187e4b17023SJohn Marino 	      }
5188e4b17023SJohn Marino 	    break;
5189e4b17023SJohn Marino 
5190e4b17023SJohn Marino 	  case 'S':
5191e4b17023SJohn Marino 	    value = do_spec_1 (startfile_spec, 0, NULL);
5192e4b17023SJohn Marino 	    if (value != 0)
5193e4b17023SJohn Marino 	      return value;
5194e4b17023SJohn Marino 	    break;
5195e4b17023SJohn Marino 
5196e4b17023SJohn Marino 	    /* Here we define characters other than letters and digits.  */
5197e4b17023SJohn Marino 
5198e4b17023SJohn Marino 	  case '{':
5199e4b17023SJohn Marino 	    p = handle_braces (p);
5200e4b17023SJohn Marino 	    if (p == 0)
5201e4b17023SJohn Marino 	      return -1;
5202e4b17023SJohn Marino 	    break;
5203e4b17023SJohn Marino 
5204e4b17023SJohn Marino 	  case ':':
5205e4b17023SJohn Marino 	    p = handle_spec_function (p);
5206e4b17023SJohn Marino 	    if (p == 0)
5207e4b17023SJohn Marino 	      return -1;
5208e4b17023SJohn Marino 	    break;
5209e4b17023SJohn Marino 
5210e4b17023SJohn Marino 	  case '%':
5211e4b17023SJohn Marino 	    obstack_1grow (&obstack, '%');
5212e4b17023SJohn Marino 	    break;
5213e4b17023SJohn Marino 
5214e4b17023SJohn Marino 	  case '.':
5215e4b17023SJohn Marino 	    {
5216e4b17023SJohn Marino 	      unsigned len = 0;
5217e4b17023SJohn Marino 
5218e4b17023SJohn Marino 	      while (p[len] && p[len] != ' ' && p[len] != '%')
5219e4b17023SJohn Marino 		len++;
5220e4b17023SJohn Marino 	      suffix_subst = save_string (p - 1, len + 1);
5221e4b17023SJohn Marino 	      p += len;
5222e4b17023SJohn Marino 	    }
5223e4b17023SJohn Marino 	   break;
5224e4b17023SJohn Marino 
5225e4b17023SJohn Marino 	   /* Henceforth ignore the option(s) matching the pattern
5226e4b17023SJohn Marino 	      after the %<.  */
5227e4b17023SJohn Marino 	  case '<':
5228e4b17023SJohn Marino 	  case '>':
5229e4b17023SJohn Marino 	    {
5230e4b17023SJohn Marino 	      unsigned len = 0;
5231e4b17023SJohn Marino 	      int have_wildcard = 0;
5232e4b17023SJohn Marino 	      int i;
5233e4b17023SJohn Marino 	      int switch_option;
5234e4b17023SJohn Marino 
5235e4b17023SJohn Marino 	      if (c == '>')
5236e4b17023SJohn Marino 		switch_option = SWITCH_IGNORE | SWITCH_KEEP_FOR_GCC;
5237e4b17023SJohn Marino 	      else
5238e4b17023SJohn Marino 		switch_option = SWITCH_IGNORE;
5239e4b17023SJohn Marino 
5240e4b17023SJohn Marino 	      while (p[len] && p[len] != ' ' && p[len] != '\t')
5241e4b17023SJohn Marino 		len++;
5242e4b17023SJohn Marino 
5243e4b17023SJohn Marino 	      if (p[len-1] == '*')
5244e4b17023SJohn Marino 		have_wildcard = 1;
5245e4b17023SJohn Marino 
5246e4b17023SJohn Marino 	      for (i = 0; i < n_switches; i++)
5247e4b17023SJohn Marino 		if (!strncmp (switches[i].part1, p, len - have_wildcard)
5248e4b17023SJohn Marino 		    && (have_wildcard || switches[i].part1[len] == '\0'))
5249e4b17023SJohn Marino 		  {
5250e4b17023SJohn Marino 		    switches[i].live_cond |= switch_option;
5251e4b17023SJohn Marino 		    switches[i].validated = 1;
5252e4b17023SJohn Marino 		  }
5253e4b17023SJohn Marino 
5254e4b17023SJohn Marino 	      p += len;
5255e4b17023SJohn Marino 	    }
5256e4b17023SJohn Marino 	    break;
5257e4b17023SJohn Marino 
5258e4b17023SJohn Marino 	  case '*':
5259e4b17023SJohn Marino 	    if (soft_matched_part)
5260e4b17023SJohn Marino 	      {
5261e4b17023SJohn Marino 		if (soft_matched_part[0])
5262e4b17023SJohn Marino 		  do_spec_1 (soft_matched_part, 1, NULL);
5263e4b17023SJohn Marino 		do_spec_1 (" ", 0, NULL);
5264e4b17023SJohn Marino 	      }
5265e4b17023SJohn Marino 	    else
5266e4b17023SJohn Marino 	      /* Catch the case where a spec string contains something like
5267e4b17023SJohn Marino 		 '%{foo:%*}'.  i.e. there is no * in the pattern on the left
5268e4b17023SJohn Marino 		 hand side of the :.  */
5269e4b17023SJohn Marino 	      error ("spec failure: %<%%*%> has not been initialized by pattern match");
5270e4b17023SJohn Marino 	    break;
5271e4b17023SJohn Marino 
5272e4b17023SJohn Marino 	    /* Process a string found as the value of a spec given by name.
5273e4b17023SJohn Marino 	       This feature allows individual machine descriptions
5274e4b17023SJohn Marino 	       to add and use their own specs.  */
5275e4b17023SJohn Marino 	  case '(':
5276e4b17023SJohn Marino 	    {
5277e4b17023SJohn Marino 	      const char *name = p;
5278e4b17023SJohn Marino 	      struct spec_list *sl;
5279e4b17023SJohn Marino 	      int len;
5280e4b17023SJohn Marino 
5281e4b17023SJohn Marino 	      /* The string after the S/P is the name of a spec that is to be
5282e4b17023SJohn Marino 		 processed.  */
5283e4b17023SJohn Marino 	      while (*p && *p != ')')
5284e4b17023SJohn Marino 		p++;
5285e4b17023SJohn Marino 
5286e4b17023SJohn Marino 	      /* See if it's in the list.  */
5287e4b17023SJohn Marino 	      for (len = p - name, sl = specs; sl; sl = sl->next)
5288e4b17023SJohn Marino 		if (sl->name_len == len && !strncmp (sl->name, name, len))
5289e4b17023SJohn Marino 		  {
5290e4b17023SJohn Marino 		    name = *(sl->ptr_spec);
5291e4b17023SJohn Marino #ifdef DEBUG_SPECS
5292e4b17023SJohn Marino 		    fnotice (stderr, "Processing spec (%s), which is '%s'\n",
5293e4b17023SJohn Marino 			     sl->name, name);
5294e4b17023SJohn Marino #endif
5295e4b17023SJohn Marino 		    break;
5296e4b17023SJohn Marino 		  }
5297e4b17023SJohn Marino 
5298e4b17023SJohn Marino 	      if (sl)
5299e4b17023SJohn Marino 		{
5300e4b17023SJohn Marino 		  value = do_spec_1 (name, 0, NULL);
5301e4b17023SJohn Marino 		  if (value != 0)
5302e4b17023SJohn Marino 		    return value;
5303e4b17023SJohn Marino 		}
5304e4b17023SJohn Marino 
5305e4b17023SJohn Marino 	      /* Discard the closing paren.  */
5306e4b17023SJohn Marino 	      if (*p)
5307e4b17023SJohn Marino 		p++;
5308e4b17023SJohn Marino 	    }
5309e4b17023SJohn Marino 	    break;
5310e4b17023SJohn Marino 
5311e4b17023SJohn Marino 	  default:
5312e4b17023SJohn Marino 	    error ("spec failure: unrecognized spec option %qc", c);
5313e4b17023SJohn Marino 	    break;
5314e4b17023SJohn Marino 	  }
5315e4b17023SJohn Marino 	break;
5316e4b17023SJohn Marino 
5317e4b17023SJohn Marino       case '\\':
5318e4b17023SJohn Marino 	/* Backslash: treat next character as ordinary.  */
5319e4b17023SJohn Marino 	c = *p++;
5320e4b17023SJohn Marino 
5321e4b17023SJohn Marino 	/* Fall through.  */
5322e4b17023SJohn Marino       default:
5323e4b17023SJohn Marino 	/* Ordinary character: put it into the current argument.  */
5324e4b17023SJohn Marino 	obstack_1grow (&obstack, c);
5325e4b17023SJohn Marino 	arg_going = 1;
5326e4b17023SJohn Marino       }
5327e4b17023SJohn Marino 
5328e4b17023SJohn Marino   /* End of string.  If we are processing a spec function, we need to
5329e4b17023SJohn Marino      end any pending argument.  */
5330e4b17023SJohn Marino   if (processing_spec_function)
5331e4b17023SJohn Marino     end_going_arg ();
5332e4b17023SJohn Marino 
5333e4b17023SJohn Marino   return 0;
5334e4b17023SJohn Marino }
5335e4b17023SJohn Marino 
5336e4b17023SJohn Marino /* Look up a spec function.  */
5337e4b17023SJohn Marino 
5338e4b17023SJohn Marino static const struct spec_function *
lookup_spec_function(const char * name)5339e4b17023SJohn Marino lookup_spec_function (const char *name)
5340e4b17023SJohn Marino {
5341e4b17023SJohn Marino   const struct spec_function *sf;
5342e4b17023SJohn Marino 
5343e4b17023SJohn Marino   for (sf = static_spec_functions; sf->name != NULL; sf++)
5344e4b17023SJohn Marino     if (strcmp (sf->name, name) == 0)
5345e4b17023SJohn Marino       return sf;
5346e4b17023SJohn Marino 
5347e4b17023SJohn Marino   return NULL;
5348e4b17023SJohn Marino }
5349e4b17023SJohn Marino 
5350e4b17023SJohn Marino /* Evaluate a spec function.  */
5351e4b17023SJohn Marino 
5352e4b17023SJohn Marino static const char *
eval_spec_function(const char * func,const char * args)5353e4b17023SJohn Marino eval_spec_function (const char *func, const char *args)
5354e4b17023SJohn Marino {
5355e4b17023SJohn Marino   const struct spec_function *sf;
5356e4b17023SJohn Marino   const char *funcval;
5357e4b17023SJohn Marino 
5358e4b17023SJohn Marino   /* Saved spec processing context.  */
5359e4b17023SJohn Marino   VEC(const_char_p,heap) *save_argbuf;
5360e4b17023SJohn Marino 
5361e4b17023SJohn Marino   int save_arg_going;
5362e4b17023SJohn Marino   int save_delete_this_arg;
5363e4b17023SJohn Marino   int save_this_is_output_file;
5364e4b17023SJohn Marino   int save_this_is_library_file;
5365e4b17023SJohn Marino   int save_input_from_pipe;
5366e4b17023SJohn Marino   int save_this_is_linker_script;
5367e4b17023SJohn Marino   const char *save_suffix_subst;
5368e4b17023SJohn Marino 
5369e4b17023SJohn Marino 
5370e4b17023SJohn Marino   sf = lookup_spec_function (func);
5371e4b17023SJohn Marino   if (sf == NULL)
5372e4b17023SJohn Marino     fatal_error ("unknown spec function %qs", func);
5373e4b17023SJohn Marino 
5374e4b17023SJohn Marino   /* Push the spec processing context.  */
5375e4b17023SJohn Marino   save_argbuf = argbuf;
5376e4b17023SJohn Marino 
5377e4b17023SJohn Marino   save_arg_going = arg_going;
5378e4b17023SJohn Marino   save_delete_this_arg = delete_this_arg;
5379e4b17023SJohn Marino   save_this_is_output_file = this_is_output_file;
5380e4b17023SJohn Marino   save_this_is_library_file = this_is_library_file;
5381e4b17023SJohn Marino   save_this_is_linker_script = this_is_linker_script;
5382e4b17023SJohn Marino   save_input_from_pipe = input_from_pipe;
5383e4b17023SJohn Marino   save_suffix_subst = suffix_subst;
5384e4b17023SJohn Marino 
5385e4b17023SJohn Marino   /* Create a new spec processing context, and build the function
5386e4b17023SJohn Marino      arguments.  */
5387e4b17023SJohn Marino 
5388e4b17023SJohn Marino   alloc_args ();
5389e4b17023SJohn Marino   if (do_spec_2 (args) < 0)
5390e4b17023SJohn Marino     fatal_error ("error in args to spec function %qs", func);
5391e4b17023SJohn Marino 
5392e4b17023SJohn Marino   /* argbuf_index is an index for the next argument to be inserted, and
5393e4b17023SJohn Marino      so contains the count of the args already inserted.  */
5394e4b17023SJohn Marino 
5395e4b17023SJohn Marino   funcval = (*sf->func) (VEC_length (const_char_p, argbuf),
5396e4b17023SJohn Marino 			 VEC_address (const_char_p, argbuf));
5397e4b17023SJohn Marino 
5398e4b17023SJohn Marino   /* Pop the spec processing context.  */
5399e4b17023SJohn Marino   VEC_free (const_char_p, heap, argbuf);
5400e4b17023SJohn Marino   argbuf = save_argbuf;
5401e4b17023SJohn Marino 
5402e4b17023SJohn Marino   arg_going = save_arg_going;
5403e4b17023SJohn Marino   delete_this_arg = save_delete_this_arg;
5404e4b17023SJohn Marino   this_is_output_file = save_this_is_output_file;
5405e4b17023SJohn Marino   this_is_library_file = save_this_is_library_file;
5406e4b17023SJohn Marino   this_is_linker_script = save_this_is_linker_script;
5407e4b17023SJohn Marino   input_from_pipe = save_input_from_pipe;
5408e4b17023SJohn Marino   suffix_subst = save_suffix_subst;
5409e4b17023SJohn Marino 
5410e4b17023SJohn Marino   return funcval;
5411e4b17023SJohn Marino }
5412e4b17023SJohn Marino 
5413e4b17023SJohn Marino /* Handle a spec function call of the form:
5414e4b17023SJohn Marino 
5415e4b17023SJohn Marino    %:function(args)
5416e4b17023SJohn Marino 
5417e4b17023SJohn Marino    ARGS is processed as a spec in a separate context and split into an
5418e4b17023SJohn Marino    argument vector in the normal fashion.  The function returns a string
5419e4b17023SJohn Marino    containing a spec which we then process in the caller's context, or
5420e4b17023SJohn Marino    NULL if no processing is required.  */
5421e4b17023SJohn Marino 
5422e4b17023SJohn Marino static const char *
handle_spec_function(const char * p)5423e4b17023SJohn Marino handle_spec_function (const char *p)
5424e4b17023SJohn Marino {
5425e4b17023SJohn Marino   char *func, *args;
5426e4b17023SJohn Marino   const char *endp, *funcval;
5427e4b17023SJohn Marino   int count;
5428e4b17023SJohn Marino 
5429e4b17023SJohn Marino   processing_spec_function++;
5430e4b17023SJohn Marino 
5431e4b17023SJohn Marino   /* Get the function name.  */
5432e4b17023SJohn Marino   for (endp = p; *endp != '\0'; endp++)
5433e4b17023SJohn Marino     {
5434e4b17023SJohn Marino       if (*endp == '(')		/* ) */
5435e4b17023SJohn Marino         break;
5436e4b17023SJohn Marino       /* Only allow [A-Za-z0-9], -, and _ in function names.  */
5437e4b17023SJohn Marino       if (!ISALNUM (*endp) && !(*endp == '-' || *endp == '_'))
5438e4b17023SJohn Marino 	fatal_error ("malformed spec function name");
5439e4b17023SJohn Marino     }
5440e4b17023SJohn Marino   if (*endp != '(')		/* ) */
5441e4b17023SJohn Marino     fatal_error ("no arguments for spec function");
5442e4b17023SJohn Marino   func = save_string (p, endp - p);
5443e4b17023SJohn Marino   p = ++endp;
5444e4b17023SJohn Marino 
5445e4b17023SJohn Marino   /* Get the arguments.  */
5446e4b17023SJohn Marino   for (count = 0; *endp != '\0'; endp++)
5447e4b17023SJohn Marino     {
5448e4b17023SJohn Marino       /* ( */
5449e4b17023SJohn Marino       if (*endp == ')')
5450e4b17023SJohn Marino 	{
5451e4b17023SJohn Marino 	  if (count == 0)
5452e4b17023SJohn Marino 	    break;
5453e4b17023SJohn Marino 	  count--;
5454e4b17023SJohn Marino 	}
5455e4b17023SJohn Marino       else if (*endp == '(')	/* ) */
5456e4b17023SJohn Marino 	count++;
5457e4b17023SJohn Marino     }
5458e4b17023SJohn Marino   /* ( */
5459e4b17023SJohn Marino   if (*endp != ')')
5460e4b17023SJohn Marino     fatal_error ("malformed spec function arguments");
5461e4b17023SJohn Marino   args = save_string (p, endp - p);
5462e4b17023SJohn Marino   p = ++endp;
5463e4b17023SJohn Marino 
5464e4b17023SJohn Marino   /* p now points to just past the end of the spec function expression.  */
5465e4b17023SJohn Marino 
5466e4b17023SJohn Marino   funcval = eval_spec_function (func, args);
5467e4b17023SJohn Marino   if (funcval != NULL && do_spec_1 (funcval, 0, NULL) < 0)
5468e4b17023SJohn Marino     p = NULL;
5469e4b17023SJohn Marino 
5470e4b17023SJohn Marino   free (func);
5471e4b17023SJohn Marino   free (args);
5472e4b17023SJohn Marino 
5473e4b17023SJohn Marino   processing_spec_function--;
5474e4b17023SJohn Marino 
5475e4b17023SJohn Marino   return p;
5476e4b17023SJohn Marino }
5477e4b17023SJohn Marino 
5478e4b17023SJohn Marino /* Inline subroutine of handle_braces.  Returns true if the current
5479e4b17023SJohn Marino    input suffix matches the atom bracketed by ATOM and END_ATOM.  */
5480e4b17023SJohn Marino static inline bool
input_suffix_matches(const char * atom,const char * end_atom)5481e4b17023SJohn Marino input_suffix_matches (const char *atom, const char *end_atom)
5482e4b17023SJohn Marino {
5483e4b17023SJohn Marino   return (input_suffix
5484e4b17023SJohn Marino 	  && !strncmp (input_suffix, atom, end_atom - atom)
5485e4b17023SJohn Marino 	  && input_suffix[end_atom - atom] == '\0');
5486e4b17023SJohn Marino }
5487e4b17023SJohn Marino 
5488e4b17023SJohn Marino /* Subroutine of handle_braces.  Returns true if the current
5489e4b17023SJohn Marino    input file's spec name matches the atom bracketed by ATOM and END_ATOM.  */
5490e4b17023SJohn Marino static bool
input_spec_matches(const char * atom,const char * end_atom)5491e4b17023SJohn Marino input_spec_matches (const char *atom, const char *end_atom)
5492e4b17023SJohn Marino {
5493e4b17023SJohn Marino   return (input_file_compiler
5494e4b17023SJohn Marino 	  && input_file_compiler->suffix
5495e4b17023SJohn Marino 	  && input_file_compiler->suffix[0] != '\0'
5496e4b17023SJohn Marino 	  && !strncmp (input_file_compiler->suffix + 1, atom,
5497e4b17023SJohn Marino 		       end_atom - atom)
5498e4b17023SJohn Marino 	  && input_file_compiler->suffix[end_atom - atom + 1] == '\0');
5499e4b17023SJohn Marino }
5500e4b17023SJohn Marino 
5501e4b17023SJohn Marino /* Subroutine of handle_braces.  Returns true if a switch
5502e4b17023SJohn Marino    matching the atom bracketed by ATOM and END_ATOM appeared on the
5503e4b17023SJohn Marino    command line.  */
5504e4b17023SJohn Marino static bool
switch_matches(const char * atom,const char * end_atom,int starred)5505e4b17023SJohn Marino switch_matches (const char *atom, const char *end_atom, int starred)
5506e4b17023SJohn Marino {
5507e4b17023SJohn Marino   int i;
5508e4b17023SJohn Marino   int len = end_atom - atom;
5509e4b17023SJohn Marino   int plen = starred ? len : -1;
5510e4b17023SJohn Marino 
5511e4b17023SJohn Marino   for (i = 0; i < n_switches; i++)
5512e4b17023SJohn Marino     if (!strncmp (switches[i].part1, atom, len)
5513e4b17023SJohn Marino 	&& (starred || switches[i].part1[len] == '\0')
5514e4b17023SJohn Marino 	&& check_live_switch (i, plen))
5515e4b17023SJohn Marino       return true;
5516e4b17023SJohn Marino 
5517e4b17023SJohn Marino     /* Check if a switch with separated form matching the atom.
5518e4b17023SJohn Marino        We check -D and -U switches. */
5519e4b17023SJohn Marino     else if (switches[i].args != 0)
5520e4b17023SJohn Marino       {
5521e4b17023SJohn Marino 	if ((*switches[i].part1 == 'D' || *switches[i].part1 == 'U')
5522e4b17023SJohn Marino 	    && *switches[i].part1 == atom[0])
5523e4b17023SJohn Marino 	  {
5524e4b17023SJohn Marino 	    if (!strncmp (switches[i].args[0], &atom[1], len - 1)
5525e4b17023SJohn Marino 		&& (starred || (switches[i].part1[1] == '\0'
5526e4b17023SJohn Marino 				&& switches[i].args[0][len - 1] == '\0'))
5527e4b17023SJohn Marino 		&& check_live_switch (i, (starred ? 1 : -1)))
5528e4b17023SJohn Marino 	      return true;
5529e4b17023SJohn Marino 	  }
5530e4b17023SJohn Marino       }
5531e4b17023SJohn Marino 
5532e4b17023SJohn Marino   return false;
5533e4b17023SJohn Marino }
5534e4b17023SJohn Marino 
5535e4b17023SJohn Marino /* Inline subroutine of handle_braces.  Mark all of the switches which
5536e4b17023SJohn Marino    match ATOM (extends to END_ATOM; STARRED indicates whether there
5537e4b17023SJohn Marino    was a star after the atom) for later processing.  */
5538e4b17023SJohn Marino static inline void
mark_matching_switches(const char * atom,const char * end_atom,int starred)5539e4b17023SJohn Marino mark_matching_switches (const char *atom, const char *end_atom, int starred)
5540e4b17023SJohn Marino {
5541e4b17023SJohn Marino   int i;
5542e4b17023SJohn Marino   int len = end_atom - atom;
5543e4b17023SJohn Marino   int plen = starred ? len : -1;
5544e4b17023SJohn Marino 
5545e4b17023SJohn Marino   for (i = 0; i < n_switches; i++)
5546e4b17023SJohn Marino     if (!strncmp (switches[i].part1, atom, len)
5547e4b17023SJohn Marino 	&& (starred || switches[i].part1[len] == '\0')
5548e4b17023SJohn Marino 	&& check_live_switch (i, plen))
5549e4b17023SJohn Marino       switches[i].ordering = 1;
5550e4b17023SJohn Marino }
5551e4b17023SJohn Marino 
5552e4b17023SJohn Marino /* Inline subroutine of handle_braces.  Process all the currently
5553e4b17023SJohn Marino    marked switches through give_switch, and clear the marks.  */
5554e4b17023SJohn Marino static inline void
process_marked_switches(void)5555e4b17023SJohn Marino process_marked_switches (void)
5556e4b17023SJohn Marino {
5557e4b17023SJohn Marino   int i;
5558e4b17023SJohn Marino 
5559e4b17023SJohn Marino   for (i = 0; i < n_switches; i++)
5560e4b17023SJohn Marino     if (switches[i].ordering == 1)
5561e4b17023SJohn Marino       {
5562e4b17023SJohn Marino 	switches[i].ordering = 0;
5563e4b17023SJohn Marino 	give_switch (i, 0);
5564e4b17023SJohn Marino       }
5565e4b17023SJohn Marino }
5566e4b17023SJohn Marino 
5567e4b17023SJohn Marino /* Handle a %{ ... } construct.  P points just inside the leading {.
5568e4b17023SJohn Marino    Returns a pointer one past the end of the brace block, or 0
5569e4b17023SJohn Marino    if we call do_spec_1 and that returns -1.  */
5570e4b17023SJohn Marino 
5571e4b17023SJohn Marino static const char *
handle_braces(const char * p)5572e4b17023SJohn Marino handle_braces (const char *p)
5573e4b17023SJohn Marino {
5574e4b17023SJohn Marino   const char *atom, *end_atom;
5575e4b17023SJohn Marino   const char *d_atom = NULL, *d_end_atom = NULL;
5576e4b17023SJohn Marino   const char *orig = p;
5577e4b17023SJohn Marino 
5578e4b17023SJohn Marino   bool a_is_suffix;
5579e4b17023SJohn Marino   bool a_is_spectype;
5580e4b17023SJohn Marino   bool a_is_starred;
5581e4b17023SJohn Marino   bool a_is_negated;
5582e4b17023SJohn Marino   bool a_matched;
5583e4b17023SJohn Marino 
5584e4b17023SJohn Marino   bool a_must_be_last = false;
5585e4b17023SJohn Marino   bool ordered_set    = false;
5586e4b17023SJohn Marino   bool disjunct_set   = false;
5587e4b17023SJohn Marino   bool disj_matched   = false;
5588e4b17023SJohn Marino   bool disj_starred   = true;
5589e4b17023SJohn Marino   bool n_way_choice   = false;
5590e4b17023SJohn Marino   bool n_way_matched  = false;
5591e4b17023SJohn Marino 
5592e4b17023SJohn Marino #define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0)
5593e4b17023SJohn Marino 
5594e4b17023SJohn Marino   do
5595e4b17023SJohn Marino     {
5596e4b17023SJohn Marino       if (a_must_be_last)
5597e4b17023SJohn Marino 	goto invalid;
5598e4b17023SJohn Marino 
5599e4b17023SJohn Marino       /* Scan one "atom" (S in the description above of %{}, possibly
5600e4b17023SJohn Marino 	 with '!', '.', '@', ',', or '*' modifiers).  */
5601e4b17023SJohn Marino       a_matched = false;
5602e4b17023SJohn Marino       a_is_suffix = false;
5603e4b17023SJohn Marino       a_is_starred = false;
5604e4b17023SJohn Marino       a_is_negated = false;
5605e4b17023SJohn Marino       a_is_spectype = false;
5606e4b17023SJohn Marino 
5607e4b17023SJohn Marino       SKIP_WHITE();
5608e4b17023SJohn Marino       if (*p == '!')
5609e4b17023SJohn Marino 	p++, a_is_negated = true;
5610e4b17023SJohn Marino 
5611e4b17023SJohn Marino       SKIP_WHITE();
5612e4b17023SJohn Marino       if (*p == '.')
5613e4b17023SJohn Marino 	p++, a_is_suffix = true;
5614e4b17023SJohn Marino       else if (*p == ',')
5615e4b17023SJohn Marino 	p++, a_is_spectype = true;
5616e4b17023SJohn Marino 
5617e4b17023SJohn Marino       atom = p;
5618e4b17023SJohn Marino       while (ISIDNUM(*p) || *p == '-' || *p == '+' || *p == '='
5619e4b17023SJohn Marino 	     || *p == ',' || *p == '.' || *p == '@')
5620e4b17023SJohn Marino 	p++;
5621e4b17023SJohn Marino       end_atom = p;
5622e4b17023SJohn Marino 
5623e4b17023SJohn Marino       if (*p == '*')
5624e4b17023SJohn Marino 	p++, a_is_starred = 1;
5625e4b17023SJohn Marino 
5626e4b17023SJohn Marino       SKIP_WHITE();
5627e4b17023SJohn Marino       switch (*p)
5628e4b17023SJohn Marino 	{
5629e4b17023SJohn Marino 	case '&': case '}':
5630e4b17023SJohn Marino 	  /* Substitute the switch(es) indicated by the current atom.  */
5631e4b17023SJohn Marino 	  ordered_set = true;
5632e4b17023SJohn Marino 	  if (disjunct_set || n_way_choice || a_is_negated || a_is_suffix
5633e4b17023SJohn Marino 	      || a_is_spectype || atom == end_atom)
5634e4b17023SJohn Marino 	    goto invalid;
5635e4b17023SJohn Marino 
5636e4b17023SJohn Marino 	  mark_matching_switches (atom, end_atom, a_is_starred);
5637e4b17023SJohn Marino 
5638e4b17023SJohn Marino 	  if (*p == '}')
5639e4b17023SJohn Marino 	    process_marked_switches ();
5640e4b17023SJohn Marino 	  break;
5641e4b17023SJohn Marino 
5642e4b17023SJohn Marino 	case '|': case ':':
5643e4b17023SJohn Marino 	  /* Substitute some text if the current atom appears as a switch
5644e4b17023SJohn Marino 	     or suffix.  */
5645e4b17023SJohn Marino 	  disjunct_set = true;
5646e4b17023SJohn Marino 	  if (ordered_set)
5647e4b17023SJohn Marino 	    goto invalid;
5648e4b17023SJohn Marino 
5649e4b17023SJohn Marino 	  if (atom == end_atom)
5650e4b17023SJohn Marino 	    {
5651e4b17023SJohn Marino 	      if (!n_way_choice || disj_matched || *p == '|'
5652e4b17023SJohn Marino 		  || a_is_negated || a_is_suffix || a_is_spectype
5653e4b17023SJohn Marino 		  || a_is_starred)
5654e4b17023SJohn Marino 		goto invalid;
5655e4b17023SJohn Marino 
5656e4b17023SJohn Marino 	      /* An empty term may appear as the last choice of an
5657e4b17023SJohn Marino 		 N-way choice set; it means "otherwise".  */
5658e4b17023SJohn Marino 	      a_must_be_last = true;
5659e4b17023SJohn Marino 	      disj_matched = !n_way_matched;
5660e4b17023SJohn Marino 	      disj_starred = false;
5661e4b17023SJohn Marino 	    }
5662e4b17023SJohn Marino 	  else
5663e4b17023SJohn Marino 	    {
5664e4b17023SJohn Marino 	      if ((a_is_suffix || a_is_spectype) && a_is_starred)
5665e4b17023SJohn Marino 		goto invalid;
5666e4b17023SJohn Marino 
5667e4b17023SJohn Marino 	      if (!a_is_starred)
5668e4b17023SJohn Marino 		disj_starred = false;
5669e4b17023SJohn Marino 
5670e4b17023SJohn Marino 	      /* Don't bother testing this atom if we already have a
5671e4b17023SJohn Marino 		 match.  */
5672e4b17023SJohn Marino 	      if (!disj_matched && !n_way_matched)
5673e4b17023SJohn Marino 		{
5674e4b17023SJohn Marino 		  if (a_is_suffix)
5675e4b17023SJohn Marino 		    a_matched = input_suffix_matches (atom, end_atom);
5676e4b17023SJohn Marino 		  else if (a_is_spectype)
5677e4b17023SJohn Marino 		    a_matched = input_spec_matches (atom, end_atom);
5678e4b17023SJohn Marino 		  else
5679e4b17023SJohn Marino 		    a_matched = switch_matches (atom, end_atom, a_is_starred);
5680e4b17023SJohn Marino 
5681e4b17023SJohn Marino 		  if (a_matched != a_is_negated)
5682e4b17023SJohn Marino 		    {
5683e4b17023SJohn Marino 		      disj_matched = true;
5684e4b17023SJohn Marino 		      d_atom = atom;
5685e4b17023SJohn Marino 		      d_end_atom = end_atom;
5686e4b17023SJohn Marino 		    }
5687e4b17023SJohn Marino 		}
5688e4b17023SJohn Marino 	    }
5689e4b17023SJohn Marino 
5690e4b17023SJohn Marino 	  if (*p == ':')
5691e4b17023SJohn Marino 	    {
5692e4b17023SJohn Marino 	      /* Found the body, that is, the text to substitute if the
5693e4b17023SJohn Marino 		 current disjunction matches.  */
5694e4b17023SJohn Marino 	      p = process_brace_body (p + 1, d_atom, d_end_atom, disj_starred,
5695e4b17023SJohn Marino 				      disj_matched && !n_way_matched);
5696e4b17023SJohn Marino 	      if (p == 0)
5697e4b17023SJohn Marino 		return 0;
5698e4b17023SJohn Marino 
5699e4b17023SJohn Marino 	      /* If we have an N-way choice, reset state for the next
5700e4b17023SJohn Marino 		 disjunction.  */
5701e4b17023SJohn Marino 	      if (*p == ';')
5702e4b17023SJohn Marino 		{
5703e4b17023SJohn Marino 		  n_way_choice = true;
5704e4b17023SJohn Marino 		  n_way_matched |= disj_matched;
5705e4b17023SJohn Marino 		  disj_matched = false;
5706e4b17023SJohn Marino 		  disj_starred = true;
5707e4b17023SJohn Marino 		  d_atom = d_end_atom = NULL;
5708e4b17023SJohn Marino 		}
5709e4b17023SJohn Marino 	    }
5710e4b17023SJohn Marino 	  break;
5711e4b17023SJohn Marino 
5712e4b17023SJohn Marino 	default:
5713e4b17023SJohn Marino 	  goto invalid;
5714e4b17023SJohn Marino 	}
5715e4b17023SJohn Marino     }
5716e4b17023SJohn Marino   while (*p++ != '}');
5717e4b17023SJohn Marino 
5718e4b17023SJohn Marino   return p;
5719e4b17023SJohn Marino 
5720e4b17023SJohn Marino  invalid:
5721e4b17023SJohn Marino   fatal_error ("braced spec %qs is invalid at %qc", orig, *p);
5722e4b17023SJohn Marino 
5723e4b17023SJohn Marino #undef SKIP_WHITE
5724e4b17023SJohn Marino }
5725e4b17023SJohn Marino 
5726e4b17023SJohn Marino /* Subroutine of handle_braces.  Scan and process a brace substitution body
5727e4b17023SJohn Marino    (X in the description of %{} syntax).  P points one past the colon;
5728e4b17023SJohn Marino    ATOM and END_ATOM bracket the first atom which was found to be true
5729e4b17023SJohn Marino    (present) in the current disjunction; STARRED indicates whether all
5730e4b17023SJohn Marino    the atoms in the current disjunction were starred (for syntax validation);
5731e4b17023SJohn Marino    MATCHED indicates whether the disjunction matched or not, and therefore
5732e4b17023SJohn Marino    whether or not the body is to be processed through do_spec_1 or just
5733e4b17023SJohn Marino    skipped.  Returns a pointer to the closing } or ;, or 0 if do_spec_1
5734e4b17023SJohn Marino    returns -1.  */
5735e4b17023SJohn Marino 
5736e4b17023SJohn Marino static const char *
process_brace_body(const char * p,const char * atom,const char * end_atom,int starred,int matched)5737e4b17023SJohn Marino process_brace_body (const char *p, const char *atom, const char *end_atom,
5738e4b17023SJohn Marino 		    int starred, int matched)
5739e4b17023SJohn Marino {
5740e4b17023SJohn Marino   const char *body, *end_body;
5741e4b17023SJohn Marino   unsigned int nesting_level;
5742e4b17023SJohn Marino   bool have_subst     = false;
5743e4b17023SJohn Marino 
5744e4b17023SJohn Marino   /* Locate the closing } or ;, honoring nested braces.
5745e4b17023SJohn Marino      Trim trailing whitespace.  */
5746e4b17023SJohn Marino   body = p;
5747e4b17023SJohn Marino   nesting_level = 1;
5748e4b17023SJohn Marino   for (;;)
5749e4b17023SJohn Marino     {
5750e4b17023SJohn Marino       if (*p == '{')
5751e4b17023SJohn Marino 	nesting_level++;
5752e4b17023SJohn Marino       else if (*p == '}')
5753e4b17023SJohn Marino 	{
5754e4b17023SJohn Marino 	  if (!--nesting_level)
5755e4b17023SJohn Marino 	    break;
5756e4b17023SJohn Marino 	}
5757e4b17023SJohn Marino       else if (*p == ';' && nesting_level == 1)
5758e4b17023SJohn Marino 	break;
5759e4b17023SJohn Marino       else if (*p == '%' && p[1] == '*' && nesting_level == 1)
5760e4b17023SJohn Marino 	have_subst = true;
5761e4b17023SJohn Marino       else if (*p == '\0')
5762e4b17023SJohn Marino 	goto invalid;
5763e4b17023SJohn Marino       p++;
5764e4b17023SJohn Marino     }
5765e4b17023SJohn Marino 
5766e4b17023SJohn Marino   end_body = p;
5767e4b17023SJohn Marino   while (end_body[-1] == ' ' || end_body[-1] == '\t')
5768e4b17023SJohn Marino     end_body--;
5769e4b17023SJohn Marino 
5770e4b17023SJohn Marino   if (have_subst && !starred)
5771e4b17023SJohn Marino     goto invalid;
5772e4b17023SJohn Marino 
5773e4b17023SJohn Marino   if (matched)
5774e4b17023SJohn Marino     {
5775e4b17023SJohn Marino       /* Copy the substitution body to permanent storage and execute it.
5776e4b17023SJohn Marino 	 If have_subst is false, this is a simple matter of running the
5777e4b17023SJohn Marino 	 body through do_spec_1...  */
5778e4b17023SJohn Marino       char *string = save_string (body, end_body - body);
5779e4b17023SJohn Marino       if (!have_subst)
5780e4b17023SJohn Marino 	{
5781e4b17023SJohn Marino 	  if (do_spec_1 (string, 0, NULL) < 0)
5782e4b17023SJohn Marino 	    return 0;
5783e4b17023SJohn Marino 	}
5784e4b17023SJohn Marino       else
5785e4b17023SJohn Marino 	{
5786e4b17023SJohn Marino 	  /* ... but if have_subst is true, we have to process the
5787e4b17023SJohn Marino 	     body once for each matching switch, with %* set to the
5788e4b17023SJohn Marino 	     variant part of the switch.  */
5789e4b17023SJohn Marino 	  unsigned int hard_match_len = end_atom - atom;
5790e4b17023SJohn Marino 	  int i;
5791e4b17023SJohn Marino 
5792e4b17023SJohn Marino 	  for (i = 0; i < n_switches; i++)
5793e4b17023SJohn Marino 	    if (!strncmp (switches[i].part1, atom, hard_match_len)
5794e4b17023SJohn Marino 		&& check_live_switch (i, hard_match_len))
5795e4b17023SJohn Marino 	      {
5796e4b17023SJohn Marino 		if (do_spec_1 (string, 0,
5797e4b17023SJohn Marino 			       &switches[i].part1[hard_match_len]) < 0)
5798e4b17023SJohn Marino 		  return 0;
5799e4b17023SJohn Marino 		/* Pass any arguments this switch has.  */
5800e4b17023SJohn Marino 		give_switch (i, 1);
5801e4b17023SJohn Marino 		suffix_subst = NULL;
5802e4b17023SJohn Marino 	      }
5803e4b17023SJohn Marino 	}
5804e4b17023SJohn Marino     }
5805e4b17023SJohn Marino 
5806e4b17023SJohn Marino   return p;
5807e4b17023SJohn Marino 
5808e4b17023SJohn Marino  invalid:
5809e4b17023SJohn Marino   fatal_error ("braced spec body %qs is invalid", body);
5810e4b17023SJohn Marino }
5811e4b17023SJohn Marino 
5812e4b17023SJohn Marino /* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch
5813e4b17023SJohn Marino    on the command line.  PREFIX_LENGTH is the length of XXX in an {XXX*}
5814e4b17023SJohn Marino    spec, or -1 if either exact match or %* is used.
5815e4b17023SJohn Marino 
5816e4b17023SJohn Marino    A -O switch is obsoleted by a later -O switch.  A -f, -m, or -W switch
5817e4b17023SJohn Marino    whose value does not begin with "no-" is obsoleted by the same value
5818e4b17023SJohn Marino    with the "no-", similarly for a switch with the "no-" prefix.  */
5819e4b17023SJohn Marino 
5820e4b17023SJohn Marino static int
check_live_switch(int switchnum,int prefix_length)5821e4b17023SJohn Marino check_live_switch (int switchnum, int prefix_length)
5822e4b17023SJohn Marino {
5823e4b17023SJohn Marino   const char *name = switches[switchnum].part1;
5824e4b17023SJohn Marino   int i;
5825e4b17023SJohn Marino 
5826e4b17023SJohn Marino   /* If we already processed this switch and determined if it was
5827e4b17023SJohn Marino      live or not, return our past determination.  */
5828e4b17023SJohn Marino   if (switches[switchnum].live_cond != 0)
5829e4b17023SJohn Marino     return ((switches[switchnum].live_cond & SWITCH_LIVE) != 0
5830e4b17023SJohn Marino 	    && (switches[switchnum].live_cond & SWITCH_FALSE) == 0
5831e4b17023SJohn Marino 	    && (switches[switchnum].live_cond & SWITCH_IGNORE_PERMANENTLY)
5832e4b17023SJohn Marino 	       == 0);
5833e4b17023SJohn Marino 
5834e4b17023SJohn Marino   /* In the common case of {<at-most-one-letter>*}, a negating
5835e4b17023SJohn Marino      switch would always match, so ignore that case.  We will just
5836e4b17023SJohn Marino      send the conflicting switches to the compiler phase.  */
5837e4b17023SJohn Marino   if (prefix_length >= 0 && prefix_length <= 1)
5838e4b17023SJohn Marino     return 1;
5839e4b17023SJohn Marino 
5840e4b17023SJohn Marino   /* Now search for duplicate in a manner that depends on the name.  */
5841e4b17023SJohn Marino   switch (*name)
5842e4b17023SJohn Marino     {
5843e4b17023SJohn Marino     case 'O':
5844e4b17023SJohn Marino       for (i = switchnum + 1; i < n_switches; i++)
5845e4b17023SJohn Marino 	if (switches[i].part1[0] == 'O')
5846e4b17023SJohn Marino 	  {
5847e4b17023SJohn Marino 	    switches[switchnum].validated = 1;
5848e4b17023SJohn Marino 	    switches[switchnum].live_cond = SWITCH_FALSE;
5849e4b17023SJohn Marino 	    return 0;
5850e4b17023SJohn Marino 	  }
5851e4b17023SJohn Marino       break;
5852e4b17023SJohn Marino 
5853e4b17023SJohn Marino     case 'W':  case 'f':  case 'm':
5854e4b17023SJohn Marino       if (! strncmp (name + 1, "no-", 3))
5855e4b17023SJohn Marino 	{
5856e4b17023SJohn Marino 	  /* We have Xno-YYY, search for XYYY.  */
5857e4b17023SJohn Marino 	  for (i = switchnum + 1; i < n_switches; i++)
5858e4b17023SJohn Marino 	    if (switches[i].part1[0] == name[0]
5859e4b17023SJohn Marino 		&& ! strcmp (&switches[i].part1[1], &name[4]))
5860e4b17023SJohn Marino 	      {
5861e4b17023SJohn Marino 		switches[switchnum].validated = 1;
5862e4b17023SJohn Marino 		switches[switchnum].live_cond = SWITCH_FALSE;
5863e4b17023SJohn Marino 		return 0;
5864e4b17023SJohn Marino 	      }
5865e4b17023SJohn Marino 	}
5866e4b17023SJohn Marino       else
5867e4b17023SJohn Marino 	{
5868e4b17023SJohn Marino 	  /* We have XYYY, search for Xno-YYY.  */
5869e4b17023SJohn Marino 	  for (i = switchnum + 1; i < n_switches; i++)
5870e4b17023SJohn Marino 	    if (switches[i].part1[0] == name[0]
5871e4b17023SJohn Marino 		&& switches[i].part1[1] == 'n'
5872e4b17023SJohn Marino 		&& switches[i].part1[2] == 'o'
5873e4b17023SJohn Marino 		&& switches[i].part1[3] == '-'
5874e4b17023SJohn Marino 		&& !strcmp (&switches[i].part1[4], &name[1]))
5875e4b17023SJohn Marino 	      {
5876e4b17023SJohn Marino 		switches[switchnum].validated = 1;
5877e4b17023SJohn Marino 		switches[switchnum].live_cond = SWITCH_FALSE;
5878e4b17023SJohn Marino 		return 0;
5879e4b17023SJohn Marino 	      }
5880e4b17023SJohn Marino 	}
5881e4b17023SJohn Marino       break;
5882e4b17023SJohn Marino     }
5883e4b17023SJohn Marino 
5884e4b17023SJohn Marino   /* Otherwise the switch is live.  */
5885e4b17023SJohn Marino   switches[switchnum].live_cond |= SWITCH_LIVE;
5886e4b17023SJohn Marino   return 1;
5887e4b17023SJohn Marino }
5888e4b17023SJohn Marino 
5889e4b17023SJohn Marino /* Pass a switch to the current accumulating command
5890e4b17023SJohn Marino    in the same form that we received it.
5891e4b17023SJohn Marino    SWITCHNUM identifies the switch; it is an index into
5892e4b17023SJohn Marino    the vector of switches gcc received, which is `switches'.
5893e4b17023SJohn Marino    This cannot fail since it never finishes a command line.
5894e4b17023SJohn Marino 
5895e4b17023SJohn Marino    If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument.  */
5896e4b17023SJohn Marino 
5897e4b17023SJohn Marino static void
give_switch(int switchnum,int omit_first_word)5898e4b17023SJohn Marino give_switch (int switchnum, int omit_first_word)
5899e4b17023SJohn Marino {
5900e4b17023SJohn Marino   if ((switches[switchnum].live_cond & SWITCH_IGNORE) != 0)
5901e4b17023SJohn Marino     return;
5902e4b17023SJohn Marino 
5903e4b17023SJohn Marino   if (!omit_first_word)
5904e4b17023SJohn Marino     {
5905e4b17023SJohn Marino       do_spec_1 ("-", 0, NULL);
5906e4b17023SJohn Marino       do_spec_1 (switches[switchnum].part1, 1, NULL);
5907e4b17023SJohn Marino     }
5908e4b17023SJohn Marino 
5909e4b17023SJohn Marino   if (switches[switchnum].args != 0)
5910e4b17023SJohn Marino     {
5911e4b17023SJohn Marino       const char **p;
5912e4b17023SJohn Marino       for (p = switches[switchnum].args; *p; p++)
5913e4b17023SJohn Marino 	{
5914e4b17023SJohn Marino 	  const char *arg = *p;
5915e4b17023SJohn Marino 
5916e4b17023SJohn Marino 	  do_spec_1 (" ", 0, NULL);
5917e4b17023SJohn Marino 	  if (suffix_subst)
5918e4b17023SJohn Marino 	    {
5919e4b17023SJohn Marino 	      unsigned length = strlen (arg);
5920e4b17023SJohn Marino 	      int dot = 0;
5921e4b17023SJohn Marino 
5922e4b17023SJohn Marino 	      while (length-- && !IS_DIR_SEPARATOR (arg[length]))
5923e4b17023SJohn Marino 		if (arg[length] == '.')
5924e4b17023SJohn Marino 		  {
5925e4b17023SJohn Marino 		    (CONST_CAST(char *, arg))[length] = 0;
5926e4b17023SJohn Marino 		    dot = 1;
5927e4b17023SJohn Marino 		    break;
5928e4b17023SJohn Marino 		  }
5929e4b17023SJohn Marino 	      do_spec_1 (arg, 1, NULL);
5930e4b17023SJohn Marino 	      if (dot)
5931e4b17023SJohn Marino 		(CONST_CAST(char *, arg))[length] = '.';
5932e4b17023SJohn Marino 	      do_spec_1 (suffix_subst, 1, NULL);
5933e4b17023SJohn Marino 	    }
5934e4b17023SJohn Marino 	  else
5935e4b17023SJohn Marino 	    do_spec_1 (arg, 1, NULL);
5936e4b17023SJohn Marino 	}
5937e4b17023SJohn Marino     }
5938e4b17023SJohn Marino 
5939e4b17023SJohn Marino   do_spec_1 (" ", 0, NULL);
5940e4b17023SJohn Marino   switches[switchnum].validated = 1;
5941e4b17023SJohn Marino }
5942e4b17023SJohn Marino 
5943e4b17023SJohn Marino /* Search for a file named NAME trying various prefixes including the
5944e4b17023SJohn Marino    user's -B prefix and some standard ones.
5945e4b17023SJohn Marino    Return the absolute file name found.  If nothing is found, return NAME.  */
5946e4b17023SJohn Marino 
5947e4b17023SJohn Marino static const char *
find_file(const char * name)5948e4b17023SJohn Marino find_file (const char *name)
5949e4b17023SJohn Marino {
5950e4b17023SJohn Marino   char *newname = find_a_file (&startfile_prefixes, name, R_OK, true);
5951e4b17023SJohn Marino   return newname ? newname : name;
5952e4b17023SJohn Marino }
5953e4b17023SJohn Marino 
5954e4b17023SJohn Marino /* Determine whether a directory exists.  If LINKER, return 0 for
5955e4b17023SJohn Marino    certain fixed names not needed by the linker.  */
5956e4b17023SJohn Marino 
5957e4b17023SJohn Marino static int
is_directory(const char * path1,bool linker)5958e4b17023SJohn Marino is_directory (const char *path1, bool linker)
5959e4b17023SJohn Marino {
5960e4b17023SJohn Marino   int len1;
5961e4b17023SJohn Marino   char *path;
5962e4b17023SJohn Marino   char *cp;
5963e4b17023SJohn Marino   struct stat st;
5964e4b17023SJohn Marino 
5965e4b17023SJohn Marino   /* Ensure the string ends with "/.".  The resulting path will be a
5966e4b17023SJohn Marino      directory even if the given path is a symbolic link.  */
5967e4b17023SJohn Marino   len1 = strlen (path1);
5968e4b17023SJohn Marino   path = (char *) alloca (3 + len1);
5969e4b17023SJohn Marino   memcpy (path, path1, len1);
5970e4b17023SJohn Marino   cp = path + len1;
5971e4b17023SJohn Marino   if (!IS_DIR_SEPARATOR (cp[-1]))
5972e4b17023SJohn Marino     *cp++ = DIR_SEPARATOR;
5973e4b17023SJohn Marino   *cp++ = '.';
5974e4b17023SJohn Marino   *cp = '\0';
5975e4b17023SJohn Marino 
5976e4b17023SJohn Marino   /* Exclude directories that the linker is known to search.  */
5977e4b17023SJohn Marino   if (linker
5978e4b17023SJohn Marino       && IS_DIR_SEPARATOR (path[0])
5979e4b17023SJohn Marino       && ((cp - path == 6
5980e4b17023SJohn Marino 	   && filename_ncmp (path + 1, "lib", 3) == 0)
5981e4b17023SJohn Marino 	  || (cp - path == 10
5982e4b17023SJohn Marino 	      && filename_ncmp (path + 1, "usr", 3) == 0
5983e4b17023SJohn Marino 	      && IS_DIR_SEPARATOR (path[4])
5984e4b17023SJohn Marino 	      && filename_ncmp (path + 5, "lib", 3) == 0)))
5985e4b17023SJohn Marino     return 0;
5986e4b17023SJohn Marino 
5987e4b17023SJohn Marino   return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
5988e4b17023SJohn Marino }
5989e4b17023SJohn Marino 
5990e4b17023SJohn Marino /* Set up the various global variables to indicate that we're processing
5991e4b17023SJohn Marino    the input file named FILENAME.  */
5992e4b17023SJohn Marino 
5993e4b17023SJohn Marino void
set_input(const char * filename)5994e4b17023SJohn Marino set_input (const char *filename)
5995e4b17023SJohn Marino {
5996e4b17023SJohn Marino   const char *p;
5997e4b17023SJohn Marino 
5998e4b17023SJohn Marino   gcc_input_filename = filename;
5999e4b17023SJohn Marino   input_filename_length = strlen (gcc_input_filename);
6000e4b17023SJohn Marino   input_basename = lbasename (gcc_input_filename);
6001e4b17023SJohn Marino 
6002e4b17023SJohn Marino   /* Find a suffix starting with the last period,
6003e4b17023SJohn Marino      and set basename_length to exclude that suffix.  */
6004e4b17023SJohn Marino   basename_length = strlen (input_basename);
6005e4b17023SJohn Marino   suffixed_basename_length = basename_length;
6006e4b17023SJohn Marino   p = input_basename + basename_length;
6007e4b17023SJohn Marino   while (p != input_basename && *p != '.')
6008e4b17023SJohn Marino     --p;
6009e4b17023SJohn Marino   if (*p == '.' && p != input_basename)
6010e4b17023SJohn Marino     {
6011e4b17023SJohn Marino       basename_length = p - input_basename;
6012e4b17023SJohn Marino       input_suffix = p + 1;
6013e4b17023SJohn Marino     }
6014e4b17023SJohn Marino   else
6015e4b17023SJohn Marino     input_suffix = "";
6016e4b17023SJohn Marino 
6017e4b17023SJohn Marino   /* If a spec for 'g', 'u', or 'U' is seen with -save-temps then
6018e4b17023SJohn Marino      we will need to do a stat on the gcc_input_filename.  The
6019e4b17023SJohn Marino      INPUT_STAT_SET signals that the stat is needed.  */
6020e4b17023SJohn Marino   input_stat_set = 0;
6021e4b17023SJohn Marino }
6022e4b17023SJohn Marino 
6023e4b17023SJohn Marino /* On fatal signals, delete all the temporary files.  */
6024e4b17023SJohn Marino 
6025e4b17023SJohn Marino static void
fatal_signal(int signum)6026e4b17023SJohn Marino fatal_signal (int signum)
6027e4b17023SJohn Marino {
6028e4b17023SJohn Marino   signal (signum, SIG_DFL);
6029e4b17023SJohn Marino   delete_failure_queue ();
6030e4b17023SJohn Marino   delete_temp_files ();
6031e4b17023SJohn Marino   /* Get the same signal again, this time not handled,
6032e4b17023SJohn Marino      so its normal effect occurs.  */
6033e4b17023SJohn Marino   kill (getpid (), signum);
6034e4b17023SJohn Marino }
6035e4b17023SJohn Marino 
6036e4b17023SJohn Marino /* Compare the contents of the two files named CMPFILE[0] and
6037e4b17023SJohn Marino    CMPFILE[1].  Return zero if they're identical, nonzero
6038e4b17023SJohn Marino    otherwise.  */
6039e4b17023SJohn Marino 
6040e4b17023SJohn Marino static int
compare_files(char * cmpfile[])6041e4b17023SJohn Marino compare_files (char *cmpfile[])
6042e4b17023SJohn Marino {
6043e4b17023SJohn Marino   int ret = 0;
6044e4b17023SJohn Marino   FILE *temp[2] = { NULL, NULL };
6045e4b17023SJohn Marino   int i;
6046e4b17023SJohn Marino 
6047e4b17023SJohn Marino #if HAVE_MMAP_FILE
6048e4b17023SJohn Marino   {
6049e4b17023SJohn Marino     size_t length[2];
6050e4b17023SJohn Marino     void *map[2] = { NULL, NULL };
6051e4b17023SJohn Marino 
6052e4b17023SJohn Marino     for (i = 0; i < 2; i++)
6053e4b17023SJohn Marino       {
6054e4b17023SJohn Marino 	struct stat st;
6055e4b17023SJohn Marino 
6056e4b17023SJohn Marino 	if (stat (cmpfile[i], &st) < 0 || !S_ISREG (st.st_mode))
6057e4b17023SJohn Marino 	  {
6058e4b17023SJohn Marino 	    error ("%s: could not determine length of compare-debug file %s",
6059e4b17023SJohn Marino 		   gcc_input_filename, cmpfile[i]);
6060e4b17023SJohn Marino 	    ret = 1;
6061e4b17023SJohn Marino 	    break;
6062e4b17023SJohn Marino 	  }
6063e4b17023SJohn Marino 
6064e4b17023SJohn Marino 	length[i] = st.st_size;
6065e4b17023SJohn Marino       }
6066e4b17023SJohn Marino 
6067e4b17023SJohn Marino     if (!ret && length[0] != length[1])
6068e4b17023SJohn Marino       {
6069e4b17023SJohn Marino 	error ("%s: -fcompare-debug failure (length)", gcc_input_filename);
6070e4b17023SJohn Marino 	ret = 1;
6071e4b17023SJohn Marino       }
6072e4b17023SJohn Marino 
6073e4b17023SJohn Marino     if (!ret)
6074e4b17023SJohn Marino       for (i = 0; i < 2; i++)
6075e4b17023SJohn Marino 	{
6076e4b17023SJohn Marino 	  int fd = open (cmpfile[i], O_RDONLY);
6077e4b17023SJohn Marino 	  if (fd < 0)
6078e4b17023SJohn Marino 	    {
6079e4b17023SJohn Marino 	      error ("%s: could not open compare-debug file %s",
6080e4b17023SJohn Marino 		     gcc_input_filename, cmpfile[i]);
6081e4b17023SJohn Marino 	      ret = 1;
6082e4b17023SJohn Marino 	      break;
6083e4b17023SJohn Marino 	    }
6084e4b17023SJohn Marino 
6085e4b17023SJohn Marino 	  map[i] = mmap (NULL, length[i], PROT_READ, MAP_PRIVATE, fd, 0);
6086e4b17023SJohn Marino 	  close (fd);
6087e4b17023SJohn Marino 
6088e4b17023SJohn Marino 	  if (map[i] == (void *) MAP_FAILED)
6089e4b17023SJohn Marino 	    {
6090e4b17023SJohn Marino 	      ret = -1;
6091e4b17023SJohn Marino 	      break;
6092e4b17023SJohn Marino 	    }
6093e4b17023SJohn Marino 	}
6094e4b17023SJohn Marino 
6095e4b17023SJohn Marino     if (!ret)
6096e4b17023SJohn Marino       {
6097e4b17023SJohn Marino 	if (memcmp (map[0], map[1], length[0]) != 0)
6098e4b17023SJohn Marino 	  {
6099e4b17023SJohn Marino 	    error ("%s: -fcompare-debug failure", gcc_input_filename);
6100e4b17023SJohn Marino 	    ret = 1;
6101e4b17023SJohn Marino 	  }
6102e4b17023SJohn Marino       }
6103e4b17023SJohn Marino 
6104e4b17023SJohn Marino     for (i = 0; i < 2; i++)
6105e4b17023SJohn Marino       if (map[i])
6106e4b17023SJohn Marino 	munmap ((caddr_t) map[i], length[i]);
6107e4b17023SJohn Marino 
6108e4b17023SJohn Marino     if (ret >= 0)
6109e4b17023SJohn Marino       return ret;
6110e4b17023SJohn Marino 
6111e4b17023SJohn Marino     ret = 0;
6112e4b17023SJohn Marino   }
6113e4b17023SJohn Marino #endif
6114e4b17023SJohn Marino 
6115e4b17023SJohn Marino   for (i = 0; i < 2; i++)
6116e4b17023SJohn Marino     {
6117e4b17023SJohn Marino       temp[i] = fopen (cmpfile[i], "r");
6118e4b17023SJohn Marino       if (!temp[i])
6119e4b17023SJohn Marino 	{
6120e4b17023SJohn Marino 	  error ("%s: could not open compare-debug file %s",
6121e4b17023SJohn Marino 		 gcc_input_filename, cmpfile[i]);
6122e4b17023SJohn Marino 	  ret = 1;
6123e4b17023SJohn Marino 	  break;
6124e4b17023SJohn Marino 	}
6125e4b17023SJohn Marino     }
6126e4b17023SJohn Marino 
6127e4b17023SJohn Marino   if (!ret && temp[0] && temp[1])
6128e4b17023SJohn Marino     for (;;)
6129e4b17023SJohn Marino       {
6130e4b17023SJohn Marino 	int c0, c1;
6131e4b17023SJohn Marino 	c0 = fgetc (temp[0]);
6132e4b17023SJohn Marino 	c1 = fgetc (temp[1]);
6133e4b17023SJohn Marino 
6134e4b17023SJohn Marino 	if (c0 != c1)
6135e4b17023SJohn Marino 	  {
6136e4b17023SJohn Marino 	    error ("%s: -fcompare-debug failure",
6137e4b17023SJohn Marino 		   gcc_input_filename);
6138e4b17023SJohn Marino 	    ret = 1;
6139e4b17023SJohn Marino 	    break;
6140e4b17023SJohn Marino 	  }
6141e4b17023SJohn Marino 
6142e4b17023SJohn Marino 	if (c0 == EOF)
6143e4b17023SJohn Marino 	  break;
6144e4b17023SJohn Marino       }
6145e4b17023SJohn Marino 
6146e4b17023SJohn Marino   for (i = 1; i >= 0; i--)
6147e4b17023SJohn Marino     {
6148e4b17023SJohn Marino       if (temp[i])
6149e4b17023SJohn Marino 	fclose (temp[i]);
6150e4b17023SJohn Marino     }
6151e4b17023SJohn Marino 
6152e4b17023SJohn Marino   return ret;
6153e4b17023SJohn Marino }
6154e4b17023SJohn Marino 
6155e4b17023SJohn Marino extern int main (int, char **);
6156e4b17023SJohn Marino 
6157e4b17023SJohn Marino int
main(int argc,char ** argv)6158e4b17023SJohn Marino main (int argc, char **argv)
6159e4b17023SJohn Marino {
6160e4b17023SJohn Marino   size_t i;
6161e4b17023SJohn Marino   int value;
6162e4b17023SJohn Marino   int linker_was_run = 0;
6163e4b17023SJohn Marino   int lang_n_infiles = 0;
6164e4b17023SJohn Marino   int num_linker_inputs = 0;
6165e4b17023SJohn Marino   char *explicit_link_files;
6166e4b17023SJohn Marino   char *specs_file;
6167e4b17023SJohn Marino   char *lto_wrapper_file;
6168e4b17023SJohn Marino   const char *p;
6169e4b17023SJohn Marino   struct user_specs *uptr;
6170e4b17023SJohn Marino   char **old_argv = argv;
6171e4b17023SJohn Marino   struct cl_decoded_option *decoded_options;
6172e4b17023SJohn Marino   unsigned int decoded_options_count;
6173e4b17023SJohn Marino 
6174e4b17023SJohn Marino   /* Initialize here, not in definition.  The IRIX 6 O32 cc sometimes chokes
6175e4b17023SJohn Marino      on ?: in file-scope variable initializations.  */
6176e4b17023SJohn Marino   asm_debug = ASM_DEBUG_SPEC;
6177e4b17023SJohn Marino 
6178e4b17023SJohn Marino   p = argv[0] + strlen (argv[0]);
6179e4b17023SJohn Marino   while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
6180e4b17023SJohn Marino     --p;
6181e4b17023SJohn Marino   progname = p;
6182e4b17023SJohn Marino 
6183e4b17023SJohn Marino   xmalloc_set_program_name (progname);
6184e4b17023SJohn Marino 
6185e4b17023SJohn Marino   expandargv (&argc, &argv);
6186e4b17023SJohn Marino 
6187e4b17023SJohn Marino   /* Determine if any expansions were made.  */
6188e4b17023SJohn Marino   if (argv != old_argv)
6189e4b17023SJohn Marino     at_file_supplied = true;
6190e4b17023SJohn Marino 
6191e4b17023SJohn Marino   /* Register the language-independent parameters.  */
6192e4b17023SJohn Marino   global_init_params ();
6193e4b17023SJohn Marino   finish_params ();
6194e4b17023SJohn Marino 
6195e4b17023SJohn Marino   init_options_struct (&global_options, &global_options_set);
6196e4b17023SJohn Marino 
6197e4b17023SJohn Marino   decode_cmdline_options_to_array (argc, CONST_CAST2 (const char **, char **,
6198e4b17023SJohn Marino 						      argv),
6199e4b17023SJohn Marino 				   CL_DRIVER,
6200e4b17023SJohn Marino 				   &decoded_options, &decoded_options_count);
6201e4b17023SJohn Marino 
6202e4b17023SJohn Marino #ifdef GCC_DRIVER_HOST_INITIALIZATION
6203e4b17023SJohn Marino   /* Perform host dependent initialization when needed.  */
6204e4b17023SJohn Marino   GCC_DRIVER_HOST_INITIALIZATION;
6205e4b17023SJohn Marino #endif
6206e4b17023SJohn Marino 
6207e4b17023SJohn Marino   /* Unlock the stdio streams.  */
6208e4b17023SJohn Marino   unlock_std_streams ();
6209e4b17023SJohn Marino 
6210e4b17023SJohn Marino   gcc_init_libintl ();
6211e4b17023SJohn Marino 
6212e4b17023SJohn Marino   diagnostic_initialize (global_dc, 0);
6213e4b17023SJohn Marino   if (atexit (delete_temp_files) != 0)
6214e4b17023SJohn Marino     fatal_error ("atexit failed");
6215e4b17023SJohn Marino 
6216e4b17023SJohn Marino   if (signal (SIGINT, SIG_IGN) != SIG_IGN)
6217e4b17023SJohn Marino     signal (SIGINT, fatal_signal);
6218e4b17023SJohn Marino #ifdef SIGHUP
6219e4b17023SJohn Marino   if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
6220e4b17023SJohn Marino     signal (SIGHUP, fatal_signal);
6221e4b17023SJohn Marino #endif
6222e4b17023SJohn Marino   if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
6223e4b17023SJohn Marino     signal (SIGTERM, fatal_signal);
6224e4b17023SJohn Marino #ifdef SIGPIPE
6225e4b17023SJohn Marino   if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
6226e4b17023SJohn Marino     signal (SIGPIPE, fatal_signal);
6227e4b17023SJohn Marino #endif
6228e4b17023SJohn Marino #ifdef SIGCHLD
6229e4b17023SJohn Marino   /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
6230e4b17023SJohn Marino      receive the signal.  A different setting is inheritable */
6231e4b17023SJohn Marino   signal (SIGCHLD, SIG_DFL);
6232e4b17023SJohn Marino #endif
6233e4b17023SJohn Marino 
6234e4b17023SJohn Marino   /* Parsing and gimplification sometimes need quite large stack.
6235e4b17023SJohn Marino      Increase stack size limits if possible.  */
6236e4b17023SJohn Marino   stack_limit_increase (64 * 1024 * 1024);
6237e4b17023SJohn Marino 
6238e4b17023SJohn Marino   /* Allocate the argument vector.  */
6239e4b17023SJohn Marino   alloc_args ();
6240e4b17023SJohn Marino 
6241e4b17023SJohn Marino   obstack_init (&obstack);
6242e4b17023SJohn Marino 
6243e4b17023SJohn Marino   /* Build multilib_select, et. al from the separate lines that make up each
6244e4b17023SJohn Marino      multilib selection.  */
6245e4b17023SJohn Marino   {
6246e4b17023SJohn Marino     const char *const *q = multilib_raw;
6247e4b17023SJohn Marino     int need_space;
6248e4b17023SJohn Marino 
6249e4b17023SJohn Marino     obstack_init (&multilib_obstack);
6250e4b17023SJohn Marino     while ((p = *q++) != (char *) 0)
6251e4b17023SJohn Marino       obstack_grow (&multilib_obstack, p, strlen (p));
6252e4b17023SJohn Marino 
6253e4b17023SJohn Marino     obstack_1grow (&multilib_obstack, 0);
6254e4b17023SJohn Marino     multilib_select = XOBFINISH (&multilib_obstack, const char *);
6255e4b17023SJohn Marino 
6256e4b17023SJohn Marino     q = multilib_matches_raw;
6257e4b17023SJohn Marino     while ((p = *q++) != (char *) 0)
6258e4b17023SJohn Marino       obstack_grow (&multilib_obstack, p, strlen (p));
6259e4b17023SJohn Marino 
6260e4b17023SJohn Marino     obstack_1grow (&multilib_obstack, 0);
6261e4b17023SJohn Marino     multilib_matches = XOBFINISH (&multilib_obstack, const char *);
6262e4b17023SJohn Marino 
6263e4b17023SJohn Marino     q = multilib_exclusions_raw;
6264e4b17023SJohn Marino     while ((p = *q++) != (char *) 0)
6265e4b17023SJohn Marino       obstack_grow (&multilib_obstack, p, strlen (p));
6266e4b17023SJohn Marino 
6267e4b17023SJohn Marino     obstack_1grow (&multilib_obstack, 0);
6268e4b17023SJohn Marino     multilib_exclusions = XOBFINISH (&multilib_obstack, const char *);
6269e4b17023SJohn Marino 
6270e4b17023SJohn Marino     need_space = FALSE;
6271e4b17023SJohn Marino     for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++)
6272e4b17023SJohn Marino       {
6273e4b17023SJohn Marino 	if (need_space)
6274e4b17023SJohn Marino 	  obstack_1grow (&multilib_obstack, ' ');
6275e4b17023SJohn Marino 	obstack_grow (&multilib_obstack,
6276e4b17023SJohn Marino 		      multilib_defaults_raw[i],
6277e4b17023SJohn Marino 		      strlen (multilib_defaults_raw[i]));
6278e4b17023SJohn Marino 	need_space = TRUE;
6279e4b17023SJohn Marino       }
6280e4b17023SJohn Marino 
6281e4b17023SJohn Marino     obstack_1grow (&multilib_obstack, 0);
6282e4b17023SJohn Marino     multilib_defaults = XOBFINISH (&multilib_obstack, const char *);
6283e4b17023SJohn Marino   }
6284e4b17023SJohn Marino 
6285e4b17023SJohn Marino #ifdef INIT_ENVIRONMENT
6286e4b17023SJohn Marino   /* Set up any other necessary machine specific environment variables.  */
6287e4b17023SJohn Marino   xputenv (INIT_ENVIRONMENT);
6288e4b17023SJohn Marino #endif
6289e4b17023SJohn Marino 
6290e4b17023SJohn Marino   /* Make a table of what switches there are (switches, n_switches).
6291e4b17023SJohn Marino      Make a table of specified input files (infiles, n_infiles).
6292e4b17023SJohn Marino      Decode switches that are handled locally.  */
6293e4b17023SJohn Marino 
6294e4b17023SJohn Marino   process_command (decoded_options_count, decoded_options);
6295e4b17023SJohn Marino 
6296e4b17023SJohn Marino   /* Initialize the vector of specs to just the default.
6297e4b17023SJohn Marino      This means one element containing 0s, as a terminator.  */
6298e4b17023SJohn Marino 
6299e4b17023SJohn Marino   compilers = XNEWVAR (struct compiler, sizeof default_compilers);
6300e4b17023SJohn Marino   memcpy (compilers, default_compilers, sizeof default_compilers);
6301e4b17023SJohn Marino   n_compilers = n_default_compilers;
6302e4b17023SJohn Marino 
6303e4b17023SJohn Marino   /* Read specs from a file if there is one.  */
6304e4b17023SJohn Marino 
6305e4b17023SJohn Marino   machine_suffix = concat (spec_machine, dir_separator_str,
6306e4b17023SJohn Marino 			   spec_version, dir_separator_str, NULL);
6307e4b17023SJohn Marino   just_machine_suffix = concat (spec_machine, dir_separator_str, NULL);
6308e4b17023SJohn Marino 
6309e4b17023SJohn Marino   specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, true);
6310e4b17023SJohn Marino   /* Read the specs file unless it is a default one.  */
6311e4b17023SJohn Marino   if (specs_file != 0 && strcmp (specs_file, "specs"))
6312e4b17023SJohn Marino     read_specs (specs_file, TRUE);
6313e4b17023SJohn Marino   else
6314e4b17023SJohn Marino     init_spec ();
6315e4b17023SJohn Marino 
6316e4b17023SJohn Marino   /* We need to check standard_exec_prefix/just_machine_suffix/specs
6317e4b17023SJohn Marino      for any override of as, ld and libraries.  */
6318e4b17023SJohn Marino   specs_file = (char *) alloca (strlen (standard_exec_prefix)
6319e4b17023SJohn Marino 		       + strlen (just_machine_suffix) + sizeof ("specs"));
6320e4b17023SJohn Marino 
6321e4b17023SJohn Marino   strcpy (specs_file, standard_exec_prefix);
6322e4b17023SJohn Marino   strcat (specs_file, just_machine_suffix);
6323e4b17023SJohn Marino   strcat (specs_file, "specs");
6324e4b17023SJohn Marino   if (access (specs_file, R_OK) == 0)
6325e4b17023SJohn Marino     read_specs (specs_file, TRUE);
6326e4b17023SJohn Marino 
6327e4b17023SJohn Marino   /* Process any configure-time defaults specified for the command line
6328e4b17023SJohn Marino      options, via OPTION_DEFAULT_SPECS.  */
6329e4b17023SJohn Marino   for (i = 0; i < ARRAY_SIZE (option_default_specs); i++)
6330e4b17023SJohn Marino     do_option_spec (option_default_specs[i].name,
6331e4b17023SJohn Marino 		    option_default_specs[i].spec);
6332e4b17023SJohn Marino 
6333e4b17023SJohn Marino   /* Process DRIVER_SELF_SPECS, adding any new options to the end
6334e4b17023SJohn Marino      of the command line.  */
6335e4b17023SJohn Marino 
6336e4b17023SJohn Marino   for (i = 0; i < ARRAY_SIZE (driver_self_specs); i++)
6337e4b17023SJohn Marino     do_self_spec (driver_self_specs[i]);
6338e4b17023SJohn Marino 
6339e4b17023SJohn Marino   /* If not cross-compiling, look for executables in the standard
6340e4b17023SJohn Marino      places.  */
6341e4b17023SJohn Marino   if (*cross_compile == '0')
6342e4b17023SJohn Marino     {
6343e4b17023SJohn Marino       if (*md_exec_prefix)
6344e4b17023SJohn Marino 	{
6345e4b17023SJohn Marino 	  add_prefix (&exec_prefixes, md_exec_prefix, "GCC",
6346e4b17023SJohn Marino 		      PREFIX_PRIORITY_LAST, 0, 0);
6347e4b17023SJohn Marino 	}
6348e4b17023SJohn Marino     }
6349e4b17023SJohn Marino 
6350e4b17023SJohn Marino   /* Process sysroot_suffix_spec.  */
6351e4b17023SJohn Marino   if (*sysroot_suffix_spec != 0
6352e4b17023SJohn Marino       && do_spec_2 (sysroot_suffix_spec) == 0)
6353e4b17023SJohn Marino     {
6354e4b17023SJohn Marino       if (VEC_length (const_char_p, argbuf) > 1)
6355e4b17023SJohn Marino         error ("spec failure: more than one arg to SYSROOT_SUFFIX_SPEC");
6356e4b17023SJohn Marino       else if (VEC_length (const_char_p, argbuf) == 1)
6357e4b17023SJohn Marino         target_sysroot_suffix = xstrdup (VEC_last (const_char_p, argbuf));
6358e4b17023SJohn Marino     }
6359e4b17023SJohn Marino 
6360e4b17023SJohn Marino #ifdef HAVE_LD_SYSROOT
6361e4b17023SJohn Marino   /* Pass the --sysroot option to the linker, if it supports that.  If
6362e4b17023SJohn Marino      there is a sysroot_suffix_spec, it has already been processed by
6363e4b17023SJohn Marino      this point, so target_system_root really is the system root we
6364e4b17023SJohn Marino      should be using.  */
6365e4b17023SJohn Marino   if (target_system_root)
6366e4b17023SJohn Marino     {
6367e4b17023SJohn Marino       obstack_grow (&obstack, "%(sysroot_spec) ", strlen ("%(sysroot_spec) "));
6368e4b17023SJohn Marino       obstack_grow0 (&obstack, link_spec, strlen (link_spec));
6369e4b17023SJohn Marino       set_spec ("link", XOBFINISH (&obstack, const char *));
6370e4b17023SJohn Marino     }
6371e4b17023SJohn Marino #endif
6372e4b17023SJohn Marino 
6373e4b17023SJohn Marino   /* Process sysroot_hdrs_suffix_spec.  */
6374e4b17023SJohn Marino   if (*sysroot_hdrs_suffix_spec != 0
6375e4b17023SJohn Marino       && do_spec_2 (sysroot_hdrs_suffix_spec) == 0)
6376e4b17023SJohn Marino     {
6377e4b17023SJohn Marino       if (VEC_length (const_char_p, argbuf) > 1)
6378e4b17023SJohn Marino         error ("spec failure: more than one arg to SYSROOT_HEADERS_SUFFIX_SPEC");
6379e4b17023SJohn Marino       else if (VEC_length (const_char_p, argbuf) == 1)
6380e4b17023SJohn Marino         target_sysroot_hdrs_suffix = xstrdup (VEC_last (const_char_p, argbuf));
6381e4b17023SJohn Marino     }
6382e4b17023SJohn Marino 
6383e4b17023SJohn Marino   /* Look for startfiles in the standard places.  */
6384e4b17023SJohn Marino   if (*startfile_prefix_spec != 0
6385e4b17023SJohn Marino       && do_spec_2 (startfile_prefix_spec) == 0
6386e4b17023SJohn Marino       && do_spec_1 (" ", 0, NULL) == 0)
6387e4b17023SJohn Marino     {
6388e4b17023SJohn Marino       const char *arg;
6389e4b17023SJohn Marino       int ndx;
6390e4b17023SJohn Marino       FOR_EACH_VEC_ELT (const_char_p, argbuf, ndx, arg)
6391e4b17023SJohn Marino 	add_sysrooted_prefix (&startfile_prefixes, arg, "BINUTILS",
6392e4b17023SJohn Marino 			      PREFIX_PRIORITY_LAST, 0, 1);
6393e4b17023SJohn Marino     }
6394e4b17023SJohn Marino   /* We should eventually get rid of all these and stick to
6395e4b17023SJohn Marino      startfile_prefix_spec exclusively.  */
6396e4b17023SJohn Marino   else if (*cross_compile == '0' || target_system_root)
6397e4b17023SJohn Marino     {
6398e4b17023SJohn Marino       if (*md_startfile_prefix)
6399e4b17023SJohn Marino 	add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix,
6400e4b17023SJohn Marino 			      "GCC", PREFIX_PRIORITY_LAST, 0, 1);
6401e4b17023SJohn Marino 
6402e4b17023SJohn Marino       if (*md_startfile_prefix_1)
6403e4b17023SJohn Marino 	add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix_1,
6404e4b17023SJohn Marino 			      "GCC", PREFIX_PRIORITY_LAST, 0, 1);
6405e4b17023SJohn Marino 
6406e4b17023SJohn Marino       /* If standard_startfile_prefix is relative, base it on
6407e4b17023SJohn Marino 	 standard_exec_prefix.  This lets us move the installed tree
6408e4b17023SJohn Marino 	 as a unit.  If GCC_EXEC_PREFIX is defined, base
6409e4b17023SJohn Marino 	 standard_startfile_prefix on that as well.
6410e4b17023SJohn Marino 
6411e4b17023SJohn Marino          If the prefix is relative, only search it for native compilers;
6412e4b17023SJohn Marino          otherwise we will search a directory containing host libraries.  */
6413e4b17023SJohn Marino       if (IS_ABSOLUTE_PATH (standard_startfile_prefix))
6414e4b17023SJohn Marino 	add_sysrooted_prefix (&startfile_prefixes,
6415e4b17023SJohn Marino 			      standard_startfile_prefix, "BINUTILS",
6416e4b17023SJohn Marino 			      PREFIX_PRIORITY_LAST, 0, 1);
6417e4b17023SJohn Marino       else if (*cross_compile == '0')
6418e4b17023SJohn Marino 	{
6419e4b17023SJohn Marino 	  add_prefix (&startfile_prefixes,
6420e4b17023SJohn Marino 		      concat (gcc_exec_prefix
6421e4b17023SJohn Marino 			      ? gcc_exec_prefix : standard_exec_prefix,
6422e4b17023SJohn Marino 			      machine_suffix,
6423e4b17023SJohn Marino 			      standard_startfile_prefix, NULL),
6424e4b17023SJohn Marino 		      NULL, PREFIX_PRIORITY_LAST, 0, 1);
6425e4b17023SJohn Marino 	}
6426e4b17023SJohn Marino 
6427e4b17023SJohn Marino       /* Sysrooted prefixes are relocated because target_system_root is
6428e4b17023SJohn Marino 	 also relocated by gcc_exec_prefix.  */
6429e4b17023SJohn Marino       if (*standard_startfile_prefix_1)
6430e4b17023SJohn Marino  	add_sysrooted_prefix (&startfile_prefixes,
6431e4b17023SJohn Marino 			      standard_startfile_prefix_1, "BINUTILS",
6432e4b17023SJohn Marino 			      PREFIX_PRIORITY_LAST, 0, 1);
6433e4b17023SJohn Marino       if (*standard_startfile_prefix_2)
6434e4b17023SJohn Marino 	add_sysrooted_prefix (&startfile_prefixes,
6435e4b17023SJohn Marino 			      standard_startfile_prefix_2, "BINUTILS",
6436e4b17023SJohn Marino 			      PREFIX_PRIORITY_LAST, 0, 1);
6437e4b17023SJohn Marino     }
6438e4b17023SJohn Marino 
6439e4b17023SJohn Marino   /* Process any user specified specs in the order given on the command
6440e4b17023SJohn Marino      line.  */
6441e4b17023SJohn Marino   for (uptr = user_specs_head; uptr; uptr = uptr->next)
6442e4b17023SJohn Marino     {
6443e4b17023SJohn Marino       char *filename = find_a_file (&startfile_prefixes, uptr->filename,
6444e4b17023SJohn Marino 				    R_OK, true);
6445e4b17023SJohn Marino       read_specs (filename ? filename : uptr->filename, FALSE);
6446e4b17023SJohn Marino     }
6447e4b17023SJohn Marino 
6448e4b17023SJohn Marino   /* Process any user self specs.  */
6449e4b17023SJohn Marino   {
6450e4b17023SJohn Marino     struct spec_list *sl;
6451e4b17023SJohn Marino     for (sl = specs; sl; sl = sl->next)
6452e4b17023SJohn Marino       if (sl->name_len == sizeof "self_spec" - 1
6453e4b17023SJohn Marino 	  && !strcmp (sl->name, "self_spec"))
6454e4b17023SJohn Marino 	do_self_spec (*sl->ptr_spec);
6455e4b17023SJohn Marino   }
6456e4b17023SJohn Marino 
6457e4b17023SJohn Marino   if (compare_debug)
6458e4b17023SJohn Marino     {
6459e4b17023SJohn Marino       enum save_temps save;
6460e4b17023SJohn Marino 
6461e4b17023SJohn Marino       if (!compare_debug_second)
6462e4b17023SJohn Marino 	{
6463e4b17023SJohn Marino 	  n_switches_debug_check[1] = n_switches;
6464e4b17023SJohn Marino 	  n_switches_alloc_debug_check[1] = n_switches_alloc;
6465e4b17023SJohn Marino 	  switches_debug_check[1] = XDUPVEC (struct switchstr, switches,
6466e4b17023SJohn Marino 					     n_switches_alloc);
6467e4b17023SJohn Marino 
6468e4b17023SJohn Marino 	  do_self_spec ("%:compare-debug-self-opt()");
6469e4b17023SJohn Marino 	  n_switches_debug_check[0] = n_switches;
6470e4b17023SJohn Marino 	  n_switches_alloc_debug_check[0] = n_switches_alloc;
6471e4b17023SJohn Marino 	  switches_debug_check[0] = switches;
6472e4b17023SJohn Marino 
6473e4b17023SJohn Marino 	  n_switches = n_switches_debug_check[1];
6474e4b17023SJohn Marino 	  n_switches_alloc = n_switches_alloc_debug_check[1];
6475e4b17023SJohn Marino 	  switches = switches_debug_check[1];
6476e4b17023SJohn Marino 	}
6477e4b17023SJohn Marino 
6478e4b17023SJohn Marino       /* Avoid crash when computing %j in this early.  */
6479e4b17023SJohn Marino       save = save_temps_flag;
6480e4b17023SJohn Marino       save_temps_flag = SAVE_TEMPS_NONE;
6481e4b17023SJohn Marino 
6482e4b17023SJohn Marino       compare_debug = -compare_debug;
6483e4b17023SJohn Marino       do_self_spec ("%:compare-debug-self-opt()");
6484e4b17023SJohn Marino 
6485e4b17023SJohn Marino       save_temps_flag = save;
6486e4b17023SJohn Marino 
6487e4b17023SJohn Marino       if (!compare_debug_second)
6488e4b17023SJohn Marino 	{
6489e4b17023SJohn Marino 	  n_switches_debug_check[1] = n_switches;
6490e4b17023SJohn Marino 	  n_switches_alloc_debug_check[1] = n_switches_alloc;
6491e4b17023SJohn Marino 	  switches_debug_check[1] = switches;
6492e4b17023SJohn Marino 	  compare_debug = -compare_debug;
6493e4b17023SJohn Marino 	  n_switches = n_switches_debug_check[0];
6494e4b17023SJohn Marino 	  n_switches_alloc = n_switches_debug_check[0];
6495e4b17023SJohn Marino 	  switches = switches_debug_check[0];
6496e4b17023SJohn Marino 	}
6497e4b17023SJohn Marino     }
6498e4b17023SJohn Marino 
6499e4b17023SJohn Marino 
6500e4b17023SJohn Marino   /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake.  */
6501e4b17023SJohn Marino   if (gcc_exec_prefix)
6502e4b17023SJohn Marino     gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
6503e4b17023SJohn Marino 			      spec_version, dir_separator_str, NULL);
6504e4b17023SJohn Marino 
6505e4b17023SJohn Marino   /* Now we have the specs.
6506e4b17023SJohn Marino      Set the `valid' bits for switches that match anything in any spec.  */
6507e4b17023SJohn Marino 
6508e4b17023SJohn Marino   validate_all_switches ();
6509e4b17023SJohn Marino 
6510e4b17023SJohn Marino   /* Now that we have the switches and the specs, set
6511e4b17023SJohn Marino      the subdirectory based on the options.  */
6512e4b17023SJohn Marino   set_multilib_dir ();
6513e4b17023SJohn Marino 
6514e4b17023SJohn Marino   /* Set up to remember the pathname of gcc and any options
6515e4b17023SJohn Marino      needed for collect.  We use argv[0] instead of progname because
6516e4b17023SJohn Marino      we need the complete pathname.  */
6517e4b17023SJohn Marino   obstack_init (&collect_obstack);
6518e4b17023SJohn Marino   obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1);
6519e4b17023SJohn Marino   obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1);
6520e4b17023SJohn Marino   xputenv (XOBFINISH (&collect_obstack, char *));
6521e4b17023SJohn Marino 
6522e4b17023SJohn Marino   /* Set up to remember the pathname of the lto wrapper. */
6523e4b17023SJohn Marino 
6524e4b17023SJohn Marino   if (have_c)
6525e4b17023SJohn Marino     lto_wrapper_file = NULL;
6526e4b17023SJohn Marino   else
6527e4b17023SJohn Marino     lto_wrapper_file = find_a_file (&exec_prefixes, "lto-wrapper",
6528e4b17023SJohn Marino 				    X_OK, false);
6529e4b17023SJohn Marino   if (lto_wrapper_file)
6530e4b17023SJohn Marino     {
65315ce9237cSJohn Marino       lto_wrapper_file = convert_white_space (lto_wrapper_file);
6532e4b17023SJohn Marino       lto_wrapper_spec = lto_wrapper_file;
6533e4b17023SJohn Marino       obstack_init (&collect_obstack);
6534e4b17023SJohn Marino       obstack_grow (&collect_obstack, "COLLECT_LTO_WRAPPER=",
6535e4b17023SJohn Marino 		    sizeof ("COLLECT_LTO_WRAPPER=") - 1);
6536e4b17023SJohn Marino       obstack_grow (&collect_obstack, lto_wrapper_spec,
6537e4b17023SJohn Marino 		    strlen (lto_wrapper_spec) + 1);
6538e4b17023SJohn Marino       xputenv (XOBFINISH (&collect_obstack, char *));
6539e4b17023SJohn Marino     }
6540e4b17023SJohn Marino 
6541e4b17023SJohn Marino   /* Warn about any switches that no pass was interested in.  */
6542e4b17023SJohn Marino 
6543e4b17023SJohn Marino   for (i = 0; (int) i < n_switches; i++)
6544e4b17023SJohn Marino     if (! switches[i].validated)
6545e4b17023SJohn Marino       error ("unrecognized option %<-%s%>", switches[i].part1);
6546e4b17023SJohn Marino 
6547e4b17023SJohn Marino   /* Obey some of the options.  */
6548e4b17023SJohn Marino 
6549e4b17023SJohn Marino   if (print_search_dirs)
6550e4b17023SJohn Marino     {
6551fdc4107cSJohn Marino       printf (_("install: %s\n"), STD_EXEC_PATH);
6552e4b17023SJohn Marino       printf (_("programs: %s\n"),
6553e4b17023SJohn Marino 	      build_search_list (&exec_prefixes, "", false, false));
6554e4b17023SJohn Marino       printf (_("libraries: %s\n"),
6555e4b17023SJohn Marino 	      build_search_list (&startfile_prefixes, "", false, true));
6556e4b17023SJohn Marino       return (0);
6557e4b17023SJohn Marino     }
6558e4b17023SJohn Marino 
6559e4b17023SJohn Marino   if (print_file_name)
6560e4b17023SJohn Marino     {
6561e4b17023SJohn Marino       printf ("%s\n", find_file (print_file_name));
6562e4b17023SJohn Marino       return (0);
6563e4b17023SJohn Marino     }
6564e4b17023SJohn Marino 
6565e4b17023SJohn Marino   if (print_prog_name)
6566e4b17023SJohn Marino     {
6567e4b17023SJohn Marino       char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK, 0);
6568e4b17023SJohn Marino       printf ("%s\n", (newname ? newname : print_prog_name));
6569e4b17023SJohn Marino       return (0);
6570e4b17023SJohn Marino     }
6571e4b17023SJohn Marino 
6572e4b17023SJohn Marino   if (print_multi_lib)
6573e4b17023SJohn Marino     {
6574e4b17023SJohn Marino       print_multilib_info ();
6575e4b17023SJohn Marino       return (0);
6576e4b17023SJohn Marino     }
6577e4b17023SJohn Marino 
6578e4b17023SJohn Marino   if (print_multi_directory)
6579e4b17023SJohn Marino     {
6580e4b17023SJohn Marino       if (multilib_dir == NULL)
6581e4b17023SJohn Marino 	printf (".\n");
6582e4b17023SJohn Marino       else
6583e4b17023SJohn Marino 	printf ("%s\n", multilib_dir);
6584e4b17023SJohn Marino       return (0);
6585e4b17023SJohn Marino     }
6586e4b17023SJohn Marino 
65875ce9237cSJohn Marino   if (print_multiarch)
65885ce9237cSJohn Marino     {
65895ce9237cSJohn Marino       if (multiarch_dir == NULL)
65905ce9237cSJohn Marino 	printf ("\n");
65915ce9237cSJohn Marino       else
65925ce9237cSJohn Marino 	printf ("%s\n", multiarch_dir);
65935ce9237cSJohn Marino       return (0);
65945ce9237cSJohn Marino     }
65955ce9237cSJohn Marino 
6596e4b17023SJohn Marino   if (print_sysroot)
6597e4b17023SJohn Marino     {
6598e4b17023SJohn Marino       if (target_system_root)
6599e4b17023SJohn Marino 	{
6600e4b17023SJohn Marino           if (target_sysroot_suffix)
6601e4b17023SJohn Marino 	    printf ("%s%s\n", target_system_root, target_sysroot_suffix);
6602e4b17023SJohn Marino           else
6603e4b17023SJohn Marino 	    printf ("%s\n", target_system_root);
6604e4b17023SJohn Marino 	}
6605e4b17023SJohn Marino       return (0);
6606e4b17023SJohn Marino     }
6607e4b17023SJohn Marino 
6608e4b17023SJohn Marino   if (print_multi_os_directory)
6609e4b17023SJohn Marino     {
6610e4b17023SJohn Marino       if (multilib_os_dir == NULL)
6611e4b17023SJohn Marino 	printf (".\n");
6612e4b17023SJohn Marino       else
6613e4b17023SJohn Marino 	printf ("%s\n", multilib_os_dir);
6614e4b17023SJohn Marino       return (0);
6615e4b17023SJohn Marino     }
6616e4b17023SJohn Marino 
6617e4b17023SJohn Marino   if (print_sysroot_headers_suffix)
6618e4b17023SJohn Marino     {
6619e4b17023SJohn Marino       if (*sysroot_hdrs_suffix_spec)
6620e4b17023SJohn Marino 	{
6621e4b17023SJohn Marino 	  printf("%s\n", (target_sysroot_hdrs_suffix
6622e4b17023SJohn Marino 			  ? target_sysroot_hdrs_suffix
6623e4b17023SJohn Marino 			  : ""));
6624e4b17023SJohn Marino 	  return (0);
6625e4b17023SJohn Marino 	}
6626e4b17023SJohn Marino       else
6627e4b17023SJohn Marino 	/* The error status indicates that only one set of fixed
6628e4b17023SJohn Marino 	   headers should be built.  */
6629e4b17023SJohn Marino 	fatal_error ("not configured with sysroot headers suffix");
6630e4b17023SJohn Marino     }
6631e4b17023SJohn Marino 
6632e4b17023SJohn Marino   if (print_help_list)
6633e4b17023SJohn Marino     {
6634e4b17023SJohn Marino       display_help ();
6635e4b17023SJohn Marino 
6636e4b17023SJohn Marino       if (! verbose_flag)
6637e4b17023SJohn Marino 	{
6638e4b17023SJohn Marino 	  printf (_("\nFor bug reporting instructions, please see:\n"));
6639e4b17023SJohn Marino 	  printf ("%s.\n", bug_report_url);
6640e4b17023SJohn Marino 
6641e4b17023SJohn Marino 	  return (0);
6642e4b17023SJohn Marino 	}
6643e4b17023SJohn Marino 
6644e4b17023SJohn Marino       /* We do not exit here.  Instead we have created a fake input file
6645e4b17023SJohn Marino 	 called 'help-dummy' which needs to be compiled, and we pass this
6646e4b17023SJohn Marino 	 on the various sub-processes, along with the --help switch.
6647e4b17023SJohn Marino 	 Ensure their output appears after ours.  */
6648e4b17023SJohn Marino       fputc ('\n', stdout);
6649e4b17023SJohn Marino       fflush (stdout);
6650e4b17023SJohn Marino     }
6651e4b17023SJohn Marino 
6652e4b17023SJohn Marino   if (print_version)
6653e4b17023SJohn Marino     {
6654e4b17023SJohn Marino       printf (_("%s %s%s\n"), progname, pkgversion_string,
6655e4b17023SJohn Marino 	      version_string);
6656e4b17023SJohn Marino       printf ("Copyright %s 2012 Free Software Foundation, Inc.\n",
6657e4b17023SJohn Marino 	      _("(C)"));
6658e4b17023SJohn Marino       fputs (_("This is free software; see the source for copying conditions.  There is NO\n\
6659e4b17023SJohn Marino warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
6660e4b17023SJohn Marino 	     stdout);
6661e4b17023SJohn Marino       if (! verbose_flag)
6662e4b17023SJohn Marino 	return 0;
6663e4b17023SJohn Marino 
6664e4b17023SJohn Marino       /* We do not exit here. We use the same mechanism of --help to print
6665e4b17023SJohn Marino 	 the version of the sub-processes. */
6666e4b17023SJohn Marino       fputc ('\n', stdout);
6667e4b17023SJohn Marino       fflush (stdout);
6668e4b17023SJohn Marino     }
6669e4b17023SJohn Marino 
6670e4b17023SJohn Marino   if (verbose_flag)
6671e4b17023SJohn Marino     {
6672e4b17023SJohn Marino       int n;
6673e4b17023SJohn Marino       const char *thrmod;
6674e4b17023SJohn Marino 
6675e4b17023SJohn Marino       fnotice (stderr, "Target: %s\n", spec_machine);
6676e4b17023SJohn Marino       fnotice (stderr, "Configured with: %s\n", configuration_arguments);
6677e4b17023SJohn Marino 
6678e4b17023SJohn Marino #ifdef THREAD_MODEL_SPEC
6679e4b17023SJohn Marino       /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
6680e4b17023SJohn Marino 	 but there's no point in doing all this processing just to get
6681e4b17023SJohn Marino 	 thread_model back.  */
6682e4b17023SJohn Marino       obstack_init (&obstack);
6683e4b17023SJohn Marino       do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
6684e4b17023SJohn Marino       obstack_1grow (&obstack, '\0');
6685e4b17023SJohn Marino       thrmod = XOBFINISH (&obstack, const char *);
6686e4b17023SJohn Marino #else
6687e4b17023SJohn Marino       thrmod = thread_model;
6688e4b17023SJohn Marino #endif
6689e4b17023SJohn Marino 
6690e4b17023SJohn Marino       fnotice (stderr, "Thread model: %s\n", thrmod);
6691e4b17023SJohn Marino 
6692e4b17023SJohn Marino       /* compiler_version is truncated at the first space when initialized
6693e4b17023SJohn Marino 	 from version string, so truncate version_string at the first space
6694e4b17023SJohn Marino 	 before comparing.  */
6695e4b17023SJohn Marino       for (n = 0; version_string[n]; n++)
6696e4b17023SJohn Marino 	if (version_string[n] == ' ')
6697e4b17023SJohn Marino 	  break;
6698e4b17023SJohn Marino 
6699e4b17023SJohn Marino       if (! strncmp (version_string, compiler_version, n)
6700e4b17023SJohn Marino 	  && compiler_version[n] == 0)
6701e4b17023SJohn Marino 	fnotice (stderr, "gcc version %s %s\n", version_string,
6702e4b17023SJohn Marino 		 pkgversion_string);
6703e4b17023SJohn Marino       else
6704e4b17023SJohn Marino 	fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n",
6705e4b17023SJohn Marino 		 version_string, pkgversion_string, compiler_version);
6706e4b17023SJohn Marino 
6707e4b17023SJohn Marino       if (n_infiles == 0)
6708e4b17023SJohn Marino 	return (0);
6709e4b17023SJohn Marino     }
6710e4b17023SJohn Marino 
6711e4b17023SJohn Marino   if (n_infiles == added_libraries)
6712e4b17023SJohn Marino     fatal_error ("no input files");
6713e4b17023SJohn Marino 
6714e4b17023SJohn Marino   if (seen_error ())
6715e4b17023SJohn Marino     goto out;
6716e4b17023SJohn Marino 
6717e4b17023SJohn Marino   /* Make a place to record the compiler output file names
6718e4b17023SJohn Marino      that correspond to the input files.  */
6719e4b17023SJohn Marino 
6720e4b17023SJohn Marino   i = n_infiles;
6721e4b17023SJohn Marino   i += lang_specific_extra_outfiles;
6722e4b17023SJohn Marino   outfiles = XCNEWVEC (const char *, i);
6723e4b17023SJohn Marino 
6724e4b17023SJohn Marino   /* Record which files were specified explicitly as link input.  */
6725e4b17023SJohn Marino 
6726e4b17023SJohn Marino   explicit_link_files = XCNEWVEC (char, n_infiles);
6727e4b17023SJohn Marino 
6728e4b17023SJohn Marino   combine_inputs = have_o || flag_wpa;
6729e4b17023SJohn Marino 
6730e4b17023SJohn Marino   for (i = 0; (int) i < n_infiles; i++)
6731e4b17023SJohn Marino     {
6732e4b17023SJohn Marino       const char *name = infiles[i].name;
6733e4b17023SJohn Marino       struct compiler *compiler = lookup_compiler (name,
6734e4b17023SJohn Marino 						   strlen (name),
6735e4b17023SJohn Marino 						   infiles[i].language);
6736e4b17023SJohn Marino 
6737e4b17023SJohn Marino       if (compiler && !(compiler->combinable))
6738e4b17023SJohn Marino 	combine_inputs = false;
6739e4b17023SJohn Marino 
6740e4b17023SJohn Marino       if (lang_n_infiles > 0 && compiler != input_file_compiler
6741e4b17023SJohn Marino 	  && infiles[i].language && infiles[i].language[0] != '*')
6742e4b17023SJohn Marino 	infiles[i].incompiler = compiler;
6743e4b17023SJohn Marino       else if (compiler)
6744e4b17023SJohn Marino 	{
6745e4b17023SJohn Marino 	  lang_n_infiles++;
6746e4b17023SJohn Marino 	  input_file_compiler = compiler;
6747e4b17023SJohn Marino 	  infiles[i].incompiler = compiler;
6748e4b17023SJohn Marino 	}
6749e4b17023SJohn Marino       else
6750e4b17023SJohn Marino 	{
6751e4b17023SJohn Marino 	  /* Since there is no compiler for this input file, assume it is a
6752e4b17023SJohn Marino 	     linker file.  */
6753e4b17023SJohn Marino 	  explicit_link_files[i] = 1;
6754e4b17023SJohn Marino 	  infiles[i].incompiler = NULL;
6755e4b17023SJohn Marino 	}
6756e4b17023SJohn Marino       infiles[i].compiled = false;
6757e4b17023SJohn Marino       infiles[i].preprocessed = false;
6758e4b17023SJohn Marino     }
6759e4b17023SJohn Marino 
6760e4b17023SJohn Marino   if (!combine_inputs && have_c && have_o && lang_n_infiles > 1)
6761e4b17023SJohn Marino     fatal_error ("cannot specify -o with -c, -S or -E with multiple files");
6762e4b17023SJohn Marino 
6763e4b17023SJohn Marino   for (i = 0; (int) i < n_infiles; i++)
6764e4b17023SJohn Marino     {
6765e4b17023SJohn Marino       int this_file_error = 0;
6766e4b17023SJohn Marino 
6767e4b17023SJohn Marino       /* Tell do_spec what to substitute for %i.  */
6768e4b17023SJohn Marino 
6769e4b17023SJohn Marino       input_file_number = i;
6770e4b17023SJohn Marino       set_input (infiles[i].name);
6771e4b17023SJohn Marino 
6772e4b17023SJohn Marino       if (infiles[i].compiled)
6773e4b17023SJohn Marino 	continue;
6774e4b17023SJohn Marino 
6775e4b17023SJohn Marino       /* Use the same thing in %o, unless cp->spec says otherwise.  */
6776e4b17023SJohn Marino 
6777e4b17023SJohn Marino       outfiles[i] = gcc_input_filename;
6778e4b17023SJohn Marino 
6779e4b17023SJohn Marino       /* Figure out which compiler from the file's suffix.  */
6780e4b17023SJohn Marino 
6781e4b17023SJohn Marino       input_file_compiler
6782e4b17023SJohn Marino 	= lookup_compiler (infiles[i].name, input_filename_length,
6783e4b17023SJohn Marino 			   infiles[i].language);
6784e4b17023SJohn Marino 
6785e4b17023SJohn Marino       if (input_file_compiler)
6786e4b17023SJohn Marino 	{
6787e4b17023SJohn Marino 	  /* Ok, we found an applicable compiler.  Run its spec.  */
6788e4b17023SJohn Marino 
6789e4b17023SJohn Marino 	  if (input_file_compiler->spec[0] == '#')
6790e4b17023SJohn Marino 	    {
6791e4b17023SJohn Marino 	      error ("%s: %s compiler not installed on this system",
6792e4b17023SJohn Marino 		     gcc_input_filename, &input_file_compiler->spec[1]);
6793e4b17023SJohn Marino 	      this_file_error = 1;
6794e4b17023SJohn Marino 	    }
6795e4b17023SJohn Marino 	  else
6796e4b17023SJohn Marino 	    {
6797e4b17023SJohn Marino 	      if (compare_debug)
6798e4b17023SJohn Marino 		{
6799e4b17023SJohn Marino 		  free (debug_check_temp_file[0]);
6800e4b17023SJohn Marino 		  debug_check_temp_file[0] = NULL;
6801e4b17023SJohn Marino 
6802e4b17023SJohn Marino 		  free (debug_check_temp_file[1]);
6803e4b17023SJohn Marino 		  debug_check_temp_file[1] = NULL;
6804e4b17023SJohn Marino 		}
6805e4b17023SJohn Marino 
6806e4b17023SJohn Marino 	      value = do_spec (input_file_compiler->spec);
6807e4b17023SJohn Marino 	      infiles[i].compiled = true;
6808e4b17023SJohn Marino 	      if (value < 0)
6809e4b17023SJohn Marino 		this_file_error = 1;
6810e4b17023SJohn Marino 	      else if (compare_debug && debug_check_temp_file[0])
6811e4b17023SJohn Marino 		{
6812e4b17023SJohn Marino 		  if (verbose_flag)
6813e4b17023SJohn Marino 		    inform (0, "recompiling with -fcompare-debug");
6814e4b17023SJohn Marino 
6815e4b17023SJohn Marino 		  compare_debug = -compare_debug;
6816e4b17023SJohn Marino 		  n_switches = n_switches_debug_check[1];
6817e4b17023SJohn Marino 		  n_switches_alloc = n_switches_alloc_debug_check[1];
6818e4b17023SJohn Marino 		  switches = switches_debug_check[1];
6819e4b17023SJohn Marino 
6820e4b17023SJohn Marino 		  value = do_spec (input_file_compiler->spec);
6821e4b17023SJohn Marino 
6822e4b17023SJohn Marino 		  compare_debug = -compare_debug;
6823e4b17023SJohn Marino 		  n_switches = n_switches_debug_check[0];
6824e4b17023SJohn Marino 		  n_switches_alloc = n_switches_alloc_debug_check[0];
6825e4b17023SJohn Marino 		  switches = switches_debug_check[0];
6826e4b17023SJohn Marino 
6827e4b17023SJohn Marino 		  if (value < 0)
6828e4b17023SJohn Marino 		    {
6829e4b17023SJohn Marino 		      error ("during -fcompare-debug recompilation");
6830e4b17023SJohn Marino 		      this_file_error = 1;
6831e4b17023SJohn Marino 		    }
6832e4b17023SJohn Marino 
6833e4b17023SJohn Marino 		  gcc_assert (debug_check_temp_file[1]
6834e4b17023SJohn Marino 			      && filename_cmp (debug_check_temp_file[0],
6835e4b17023SJohn Marino 					       debug_check_temp_file[1]));
6836e4b17023SJohn Marino 
6837e4b17023SJohn Marino 		  if (verbose_flag)
6838e4b17023SJohn Marino 		    inform (0, "comparing final insns dumps");
6839e4b17023SJohn Marino 
6840e4b17023SJohn Marino 		  if (compare_files (debug_check_temp_file))
6841e4b17023SJohn Marino 		    this_file_error = 1;
6842e4b17023SJohn Marino 		}
6843e4b17023SJohn Marino 
6844e4b17023SJohn Marino 	      if (compare_debug)
6845e4b17023SJohn Marino 		{
6846e4b17023SJohn Marino 		  free (debug_check_temp_file[0]);
6847e4b17023SJohn Marino 		  debug_check_temp_file[0] = NULL;
6848e4b17023SJohn Marino 
6849e4b17023SJohn Marino 		  free (debug_check_temp_file[1]);
6850e4b17023SJohn Marino 		  debug_check_temp_file[1] = NULL;
6851e4b17023SJohn Marino 		}
6852e4b17023SJohn Marino 	    }
6853e4b17023SJohn Marino 	}
6854e4b17023SJohn Marino 
6855e4b17023SJohn Marino       /* If this file's name does not contain a recognized suffix,
6856e4b17023SJohn Marino 	 record it as explicit linker input.  */
6857e4b17023SJohn Marino 
6858e4b17023SJohn Marino       else
6859e4b17023SJohn Marino 	explicit_link_files[i] = 1;
6860e4b17023SJohn Marino 
6861e4b17023SJohn Marino       /* Clear the delete-on-failure queue, deleting the files in it
6862e4b17023SJohn Marino 	 if this compilation failed.  */
6863e4b17023SJohn Marino 
6864e4b17023SJohn Marino       if (this_file_error)
6865e4b17023SJohn Marino 	{
6866e4b17023SJohn Marino 	  delete_failure_queue ();
6867e4b17023SJohn Marino 	  errorcount++;
6868e4b17023SJohn Marino 	}
6869e4b17023SJohn Marino       /* If this compilation succeeded, don't delete those files later.  */
6870e4b17023SJohn Marino       clear_failure_queue ();
6871e4b17023SJohn Marino     }
6872e4b17023SJohn Marino 
6873e4b17023SJohn Marino   /* Reset the input file name to the first compile/object file name, for use
6874e4b17023SJohn Marino      with %b in LINK_SPEC. We use the first input file that we can find
6875e4b17023SJohn Marino      a compiler to compile it instead of using infiles.language since for
6876e4b17023SJohn Marino      languages other than C we use aliases that we then lookup later.  */
6877e4b17023SJohn Marino   if (n_infiles > 0)
6878e4b17023SJohn Marino     {
6879e4b17023SJohn Marino       int i;
6880e4b17023SJohn Marino 
6881e4b17023SJohn Marino       for (i = 0; i < n_infiles ; i++)
6882e4b17023SJohn Marino 	if (infiles[i].incompiler
6883e4b17023SJohn Marino 	    || (infiles[i].language && infiles[i].language[0] != '*'))
6884e4b17023SJohn Marino 	  {
6885e4b17023SJohn Marino 	    set_input (infiles[i].name);
6886e4b17023SJohn Marino 	    break;
6887e4b17023SJohn Marino 	  }
6888e4b17023SJohn Marino     }
6889e4b17023SJohn Marino 
6890e4b17023SJohn Marino   if (!seen_error ())
6891e4b17023SJohn Marino     {
6892e4b17023SJohn Marino       /* Make sure INPUT_FILE_NUMBER points to first available open
6893e4b17023SJohn Marino 	 slot.  */
6894e4b17023SJohn Marino       input_file_number = n_infiles;
6895e4b17023SJohn Marino       if (lang_specific_pre_link ())
6896e4b17023SJohn Marino 	errorcount++;
6897e4b17023SJohn Marino     }
6898e4b17023SJohn Marino 
6899e4b17023SJohn Marino   /* Determine if there are any linker input files.  */
6900e4b17023SJohn Marino   num_linker_inputs = 0;
6901e4b17023SJohn Marino   for (i = 0; (int) i < n_infiles; i++)
6902e4b17023SJohn Marino     if (explicit_link_files[i] || outfiles[i] != NULL)
6903e4b17023SJohn Marino       num_linker_inputs++;
6904e4b17023SJohn Marino 
6905e4b17023SJohn Marino   /* Run ld to link all the compiler output files.  */
6906e4b17023SJohn Marino 
6907e4b17023SJohn Marino   if (num_linker_inputs > 0 && !seen_error () && print_subprocess_help < 2)
6908e4b17023SJohn Marino     {
6909e4b17023SJohn Marino       int tmp = execution_count;
6910e4b17023SJohn Marino 
6911e4b17023SJohn Marino       if (! have_c)
6912e4b17023SJohn Marino 	{
6913e4b17023SJohn Marino #if HAVE_LTO_PLUGIN > 0
6914e4b17023SJohn Marino #if HAVE_LTO_PLUGIN == 2
6915e4b17023SJohn Marino 	  const char *fno_use_linker_plugin = "fno-use-linker-plugin";
6916e4b17023SJohn Marino #else
6917e4b17023SJohn Marino 	  const char *fuse_linker_plugin = "fuse-linker-plugin";
6918e4b17023SJohn Marino #endif
6919e4b17023SJohn Marino #endif
6920e4b17023SJohn Marino 
6921e4b17023SJohn Marino 	  /* We'll use ld if we can't find collect2.  */
6922e4b17023SJohn Marino 	  if (! strcmp (linker_name_spec, "collect2"))
6923e4b17023SJohn Marino 	    {
6924e4b17023SJohn Marino 	      char *s = find_a_file (&exec_prefixes, "collect2", X_OK, false);
6925e4b17023SJohn Marino 	      if (s == NULL)
6926e4b17023SJohn Marino 		linker_name_spec = "ld";
6927e4b17023SJohn Marino 	    }
6928e4b17023SJohn Marino 
6929e4b17023SJohn Marino #if HAVE_LTO_PLUGIN > 0
6930e4b17023SJohn Marino #if HAVE_LTO_PLUGIN == 2
6931e4b17023SJohn Marino 	  if (!switch_matches (fno_use_linker_plugin,
6932e4b17023SJohn Marino 			       fno_use_linker_plugin
6933e4b17023SJohn Marino 			       + strlen (fno_use_linker_plugin), 0))
6934e4b17023SJohn Marino #else
6935e4b17023SJohn Marino 	  if (switch_matches (fuse_linker_plugin,
6936e4b17023SJohn Marino 			      fuse_linker_plugin
6937e4b17023SJohn Marino 			      + strlen (fuse_linker_plugin), 0))
6938e4b17023SJohn Marino #endif
6939e4b17023SJohn Marino 	    {
69405ce9237cSJohn Marino 	      char *temp_spec = find_a_file (&exec_prefixes,
6941e4b17023SJohn Marino 					     LTOPLUGINSONAME, R_OK,
6942e4b17023SJohn Marino 					     false);
69435ce9237cSJohn Marino 	      if (!temp_spec)
6944e4b17023SJohn Marino 		fatal_error ("-fuse-linker-plugin, but %s not found",
6945e4b17023SJohn Marino 			     LTOPLUGINSONAME);
69465ce9237cSJohn Marino 	      linker_plugin_file_spec = convert_white_space (temp_spec);
6947e4b17023SJohn Marino 	    }
6948e4b17023SJohn Marino #endif
6949e4b17023SJohn Marino 	  lto_gcc_spec = argv[0];
6950e4b17023SJohn Marino 	}
6951e4b17023SJohn Marino 
6952e4b17023SJohn Marino       /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
6953e4b17023SJohn Marino 	 for collect.  */
6954e4b17023SJohn Marino       putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH", false);
6955e4b17023SJohn Marino       putenv_from_prefixes (&startfile_prefixes, LIBRARY_PATH_ENV, true);
6956e4b17023SJohn Marino 
6957e4b17023SJohn Marino       if (print_subprocess_help == 1)
6958e4b17023SJohn Marino 	{
6959e4b17023SJohn Marino 	  printf (_("\nLinker options\n==============\n\n"));
6960e4b17023SJohn Marino 	  printf (_("Use \"-Wl,OPTION\" to pass \"OPTION\""
6961e4b17023SJohn Marino 		    " to the linker.\n\n"));
6962e4b17023SJohn Marino 	  fflush (stdout);
6963e4b17023SJohn Marino 	}
6964e4b17023SJohn Marino       value = do_spec (link_command_spec);
6965e4b17023SJohn Marino       if (value < 0)
6966e4b17023SJohn Marino 	errorcount = 1;
6967e4b17023SJohn Marino       linker_was_run = (tmp != execution_count);
6968e4b17023SJohn Marino     }
6969e4b17023SJohn Marino 
6970e4b17023SJohn Marino   /* If options said don't run linker,
6971e4b17023SJohn Marino      complain about input files to be given to the linker.  */
6972e4b17023SJohn Marino 
6973e4b17023SJohn Marino   if (! linker_was_run && !seen_error ())
6974e4b17023SJohn Marino     for (i = 0; (int) i < n_infiles; i++)
6975e4b17023SJohn Marino       if (explicit_link_files[i]
6976e4b17023SJohn Marino 	  && !(infiles[i].language && infiles[i].language[0] == '*'))
6977e4b17023SJohn Marino 	warning (0, "%s: linker input file unused because linking not done",
6978e4b17023SJohn Marino 		 outfiles[i]);
6979e4b17023SJohn Marino 
6980e4b17023SJohn Marino   /* Delete some or all of the temporary files we made.  */
6981e4b17023SJohn Marino 
6982e4b17023SJohn Marino   if (seen_error ())
6983e4b17023SJohn Marino     delete_failure_queue ();
6984e4b17023SJohn Marino   delete_temp_files ();
6985e4b17023SJohn Marino 
6986e4b17023SJohn Marino   if (print_help_list)
6987e4b17023SJohn Marino     {
6988e4b17023SJohn Marino       printf (("\nFor bug reporting instructions, please see:\n"));
6989e4b17023SJohn Marino       printf ("%s\n", bug_report_url);
6990e4b17023SJohn Marino     }
6991e4b17023SJohn Marino 
6992e4b17023SJohn Marino  out:
6993e4b17023SJohn Marino   return (signal_count != 0 ? 2
6994e4b17023SJohn Marino 	  : seen_error () ? (pass_exit_codes ? greatest_status : 1)
6995e4b17023SJohn Marino 	  : 0);
6996e4b17023SJohn Marino }
6997e4b17023SJohn Marino 
6998e4b17023SJohn Marino /* Find the proper compilation spec for the file name NAME,
6999e4b17023SJohn Marino    whose length is LENGTH.  LANGUAGE is the specified language,
7000e4b17023SJohn Marino    or 0 if this file is to be passed to the linker.  */
7001e4b17023SJohn Marino 
7002e4b17023SJohn Marino static struct compiler *
lookup_compiler(const char * name,size_t length,const char * language)7003e4b17023SJohn Marino lookup_compiler (const char *name, size_t length, const char *language)
7004e4b17023SJohn Marino {
7005e4b17023SJohn Marino   struct compiler *cp;
7006e4b17023SJohn Marino 
7007e4b17023SJohn Marino   /* If this was specified by the user to be a linker input, indicate that.  */
7008e4b17023SJohn Marino   if (language != 0 && language[0] == '*')
7009e4b17023SJohn Marino     return 0;
7010e4b17023SJohn Marino 
7011e4b17023SJohn Marino   /* Otherwise, look for the language, if one is spec'd.  */
7012e4b17023SJohn Marino   if (language != 0)
7013e4b17023SJohn Marino     {
7014e4b17023SJohn Marino       for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
7015e4b17023SJohn Marino 	if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language))
7016e4b17023SJohn Marino 	  return cp;
7017e4b17023SJohn Marino 
7018e4b17023SJohn Marino       error ("language %s not recognized", language);
7019e4b17023SJohn Marino       return 0;
7020e4b17023SJohn Marino     }
7021e4b17023SJohn Marino 
7022e4b17023SJohn Marino   /* Look for a suffix.  */
7023e4b17023SJohn Marino   for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
7024e4b17023SJohn Marino     {
7025e4b17023SJohn Marino       if (/* The suffix `-' matches only the file name `-'.  */
7026e4b17023SJohn Marino 	  (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
7027e4b17023SJohn Marino 	  || (strlen (cp->suffix) < length
7028e4b17023SJohn Marino 	      /* See if the suffix matches the end of NAME.  */
7029e4b17023SJohn Marino 	      && !strcmp (cp->suffix,
7030e4b17023SJohn Marino 			  name + length - strlen (cp->suffix))
7031e4b17023SJohn Marino 	 ))
7032e4b17023SJohn Marino 	break;
7033e4b17023SJohn Marino     }
7034e4b17023SJohn Marino 
7035e4b17023SJohn Marino #if defined (OS2) ||defined (HAVE_DOS_BASED_FILE_SYSTEM)
7036e4b17023SJohn Marino   /* Look again, but case-insensitively this time.  */
7037e4b17023SJohn Marino   if (cp < compilers)
7038e4b17023SJohn Marino     for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
7039e4b17023SJohn Marino       {
7040e4b17023SJohn Marino 	if (/* The suffix `-' matches only the file name `-'.  */
7041e4b17023SJohn Marino 	    (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
7042e4b17023SJohn Marino 	    || (strlen (cp->suffix) < length
7043e4b17023SJohn Marino 		/* See if the suffix matches the end of NAME.  */
7044e4b17023SJohn Marino 		&& ((!strcmp (cp->suffix,
7045e4b17023SJohn Marino 			     name + length - strlen (cp->suffix))
7046e4b17023SJohn Marino 		     || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
7047e4b17023SJohn Marino 		    && !strcasecmp (cp->suffix,
7048e4b17023SJohn Marino 				    name + length - strlen (cp->suffix)))
7049e4b17023SJohn Marino 	   ))
7050e4b17023SJohn Marino 	  break;
7051e4b17023SJohn Marino       }
7052e4b17023SJohn Marino #endif
7053e4b17023SJohn Marino 
7054e4b17023SJohn Marino   if (cp >= compilers)
7055e4b17023SJohn Marino     {
7056e4b17023SJohn Marino       if (cp->spec[0] != '@')
7057e4b17023SJohn Marino 	/* A non-alias entry: return it.  */
7058e4b17023SJohn Marino 	return cp;
7059e4b17023SJohn Marino 
7060e4b17023SJohn Marino       /* An alias entry maps a suffix to a language.
7061e4b17023SJohn Marino 	 Search for the language; pass 0 for NAME and LENGTH
7062e4b17023SJohn Marino 	 to avoid infinite recursion if language not found.  */
7063e4b17023SJohn Marino       return lookup_compiler (NULL, 0, cp->spec + 1);
7064e4b17023SJohn Marino     }
7065e4b17023SJohn Marino   return 0;
7066e4b17023SJohn Marino }
7067e4b17023SJohn Marino 
7068e4b17023SJohn Marino static char *
save_string(const char * s,int len)7069e4b17023SJohn Marino save_string (const char *s, int len)
7070e4b17023SJohn Marino {
7071e4b17023SJohn Marino   char *result = XNEWVEC (char, len + 1);
7072e4b17023SJohn Marino 
7073e4b17023SJohn Marino   memcpy (result, s, len);
7074e4b17023SJohn Marino   result[len] = 0;
7075e4b17023SJohn Marino   return result;
7076e4b17023SJohn Marino }
7077e4b17023SJohn Marino 
7078e4b17023SJohn Marino void
pfatal_with_name(const char * name)7079e4b17023SJohn Marino pfatal_with_name (const char *name)
7080e4b17023SJohn Marino {
7081e4b17023SJohn Marino   perror_with_name (name);
7082e4b17023SJohn Marino   delete_temp_files ();
7083e4b17023SJohn Marino   exit (1);
7084e4b17023SJohn Marino }
7085e4b17023SJohn Marino 
7086e4b17023SJohn Marino static void
perror_with_name(const char * name)7087e4b17023SJohn Marino perror_with_name (const char *name)
7088e4b17023SJohn Marino {
7089e4b17023SJohn Marino   error ("%s: %m", name);
7090e4b17023SJohn Marino }
7091e4b17023SJohn Marino 
7092e4b17023SJohn Marino static inline void
validate_switches_from_spec(const char * spec)7093e4b17023SJohn Marino validate_switches_from_spec (const char *spec)
7094e4b17023SJohn Marino {
7095e4b17023SJohn Marino   const char *p = spec;
7096e4b17023SJohn Marino   char c;
7097e4b17023SJohn Marino   while ((c = *p++))
7098e4b17023SJohn Marino     if (c == '%' && (*p == '{' || *p == '<' || (*p == 'W' && *++p == '{')))
7099e4b17023SJohn Marino       /* We have a switch spec.  */
7100e4b17023SJohn Marino       p = validate_switches (p + 1);
7101e4b17023SJohn Marino }
7102e4b17023SJohn Marino 
7103e4b17023SJohn Marino static void
validate_all_switches(void)7104e4b17023SJohn Marino validate_all_switches (void)
7105e4b17023SJohn Marino {
7106e4b17023SJohn Marino   struct compiler *comp;
7107e4b17023SJohn Marino   struct spec_list *spec;
7108e4b17023SJohn Marino 
7109e4b17023SJohn Marino   for (comp = compilers; comp->spec; comp++)
7110e4b17023SJohn Marino     validate_switches_from_spec (comp->spec);
7111e4b17023SJohn Marino 
7112e4b17023SJohn Marino   /* Look through the linked list of specs read from the specs file.  */
7113e4b17023SJohn Marino   for (spec = specs; spec; spec = spec->next)
7114e4b17023SJohn Marino     validate_switches_from_spec (*spec->ptr_spec);
7115e4b17023SJohn Marino 
7116e4b17023SJohn Marino   validate_switches_from_spec (link_command_spec);
7117e4b17023SJohn Marino }
7118e4b17023SJohn Marino 
7119e4b17023SJohn Marino /* Look at the switch-name that comes after START
7120e4b17023SJohn Marino    and mark as valid all supplied switches that match it.  */
7121e4b17023SJohn Marino 
7122e4b17023SJohn Marino static const char *
validate_switches(const char * start)7123e4b17023SJohn Marino validate_switches (const char *start)
7124e4b17023SJohn Marino {
7125e4b17023SJohn Marino   const char *p = start;
7126e4b17023SJohn Marino   const char *atom;
7127e4b17023SJohn Marino   size_t len;
7128e4b17023SJohn Marino   int i;
7129e4b17023SJohn Marino   bool suffix = false;
7130e4b17023SJohn Marino   bool starred = false;
7131e4b17023SJohn Marino 
7132e4b17023SJohn Marino #define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0)
7133e4b17023SJohn Marino 
7134e4b17023SJohn Marino next_member:
7135e4b17023SJohn Marino   SKIP_WHITE ();
7136e4b17023SJohn Marino 
7137e4b17023SJohn Marino   if (*p == '!')
7138e4b17023SJohn Marino     p++;
7139e4b17023SJohn Marino 
7140e4b17023SJohn Marino   SKIP_WHITE ();
7141e4b17023SJohn Marino   if (*p == '.' || *p == ',')
7142e4b17023SJohn Marino     suffix = true, p++;
7143e4b17023SJohn Marino 
7144e4b17023SJohn Marino   atom = p;
7145e4b17023SJohn Marino   while (ISIDNUM (*p) || *p == '-' || *p == '+' || *p == '='
7146e4b17023SJohn Marino 	 || *p == ',' || *p == '.' || *p == '@')
7147e4b17023SJohn Marino     p++;
7148e4b17023SJohn Marino   len = p - atom;
7149e4b17023SJohn Marino 
7150e4b17023SJohn Marino   if (*p == '*')
7151e4b17023SJohn Marino     starred = true, p++;
7152e4b17023SJohn Marino 
7153e4b17023SJohn Marino   SKIP_WHITE ();
7154e4b17023SJohn Marino 
7155e4b17023SJohn Marino   if (!suffix)
7156e4b17023SJohn Marino     {
7157e4b17023SJohn Marino       /* Mark all matching switches as valid.  */
7158e4b17023SJohn Marino       for (i = 0; i < n_switches; i++)
7159e4b17023SJohn Marino 	if (!strncmp (switches[i].part1, atom, len)
7160e4b17023SJohn Marino 	    && (starred || switches[i].part1[len] == 0))
7161e4b17023SJohn Marino 	  switches[i].validated = 1;
7162e4b17023SJohn Marino     }
7163e4b17023SJohn Marino 
7164e4b17023SJohn Marino   if (*p) p++;
7165e4b17023SJohn Marino   if (*p && (p[-1] == '|' || p[-1] == '&'))
7166e4b17023SJohn Marino     goto next_member;
7167e4b17023SJohn Marino 
7168e4b17023SJohn Marino   if (*p && p[-1] == ':')
7169e4b17023SJohn Marino     {
7170e4b17023SJohn Marino       while (*p && *p != ';' && *p != '}')
7171e4b17023SJohn Marino 	{
7172e4b17023SJohn Marino 	  if (*p == '%')
7173e4b17023SJohn Marino 	    {
7174e4b17023SJohn Marino 	      p++;
7175e4b17023SJohn Marino 	      if (*p == '{' || *p == '<')
7176e4b17023SJohn Marino 		p = validate_switches (p+1);
7177e4b17023SJohn Marino 	      else if (p[0] == 'W' && p[1] == '{')
7178e4b17023SJohn Marino 		p = validate_switches (p+2);
7179e4b17023SJohn Marino 	    }
7180e4b17023SJohn Marino 	  else
7181e4b17023SJohn Marino 	    p++;
7182e4b17023SJohn Marino 	}
7183e4b17023SJohn Marino 
7184e4b17023SJohn Marino       if (*p) p++;
7185e4b17023SJohn Marino       if (*p && p[-1] == ';')
7186e4b17023SJohn Marino 	goto next_member;
7187e4b17023SJohn Marino     }
7188e4b17023SJohn Marino 
7189e4b17023SJohn Marino   return p;
7190e4b17023SJohn Marino #undef SKIP_WHITE
7191e4b17023SJohn Marino }
7192e4b17023SJohn Marino 
7193e4b17023SJohn Marino struct mdswitchstr
7194e4b17023SJohn Marino {
7195e4b17023SJohn Marino   const char *str;
7196e4b17023SJohn Marino   int len;
7197e4b17023SJohn Marino };
7198e4b17023SJohn Marino 
7199e4b17023SJohn Marino static struct mdswitchstr *mdswitches;
7200e4b17023SJohn Marino static int n_mdswitches;
7201e4b17023SJohn Marino 
7202e4b17023SJohn Marino /* Check whether a particular argument was used.  The first time we
7203e4b17023SJohn Marino    canonicalize the switches to keep only the ones we care about.  */
7204e4b17023SJohn Marino 
7205e4b17023SJohn Marino static int
used_arg(const char * p,int len)7206e4b17023SJohn Marino used_arg (const char *p, int len)
7207e4b17023SJohn Marino {
7208e4b17023SJohn Marino   struct mswitchstr
7209e4b17023SJohn Marino   {
7210e4b17023SJohn Marino     const char *str;
7211e4b17023SJohn Marino     const char *replace;
7212e4b17023SJohn Marino     int len;
7213e4b17023SJohn Marino     int rep_len;
7214e4b17023SJohn Marino   };
7215e4b17023SJohn Marino 
7216e4b17023SJohn Marino   static struct mswitchstr *mswitches;
7217e4b17023SJohn Marino   static int n_mswitches;
7218e4b17023SJohn Marino   int i, j;
7219e4b17023SJohn Marino 
7220e4b17023SJohn Marino   if (!mswitches)
7221e4b17023SJohn Marino     {
7222e4b17023SJohn Marino       struct mswitchstr *matches;
7223e4b17023SJohn Marino       const char *q;
7224e4b17023SJohn Marino       int cnt = 0;
7225e4b17023SJohn Marino 
7226e4b17023SJohn Marino       /* Break multilib_matches into the component strings of string
7227e4b17023SJohn Marino          and replacement string.  */
7228e4b17023SJohn Marino       for (q = multilib_matches; *q != '\0'; q++)
7229e4b17023SJohn Marino 	if (*q == ';')
7230e4b17023SJohn Marino 	  cnt++;
7231e4b17023SJohn Marino 
7232e4b17023SJohn Marino       matches
7233e4b17023SJohn Marino 	= (struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt);
7234e4b17023SJohn Marino       i = 0;
7235e4b17023SJohn Marino       q = multilib_matches;
7236e4b17023SJohn Marino       while (*q != '\0')
7237e4b17023SJohn Marino 	{
7238e4b17023SJohn Marino 	  matches[i].str = q;
7239e4b17023SJohn Marino 	  while (*q != ' ')
7240e4b17023SJohn Marino 	    {
7241e4b17023SJohn Marino 	      if (*q == '\0')
7242e4b17023SJohn Marino 		{
7243e4b17023SJohn Marino 		invalid_matches:
7244e4b17023SJohn Marino 		  fatal_error ("multilib spec %qs is invalid",
7245e4b17023SJohn Marino 			       multilib_matches);
7246e4b17023SJohn Marino 		}
7247e4b17023SJohn Marino 	      q++;
7248e4b17023SJohn Marino 	    }
7249e4b17023SJohn Marino 	  matches[i].len = q - matches[i].str;
7250e4b17023SJohn Marino 
7251e4b17023SJohn Marino 	  matches[i].replace = ++q;
7252e4b17023SJohn Marino 	  while (*q != ';' && *q != '\0')
7253e4b17023SJohn Marino 	    {
7254e4b17023SJohn Marino 	      if (*q == ' ')
7255e4b17023SJohn Marino 		goto invalid_matches;
7256e4b17023SJohn Marino 	      q++;
7257e4b17023SJohn Marino 	    }
7258e4b17023SJohn Marino 	  matches[i].rep_len = q - matches[i].replace;
7259e4b17023SJohn Marino 	  i++;
7260e4b17023SJohn Marino 	  if (*q == ';')
7261e4b17023SJohn Marino 	    q++;
7262e4b17023SJohn Marino 	}
7263e4b17023SJohn Marino 
7264e4b17023SJohn Marino       /* Now build a list of the replacement string for switches that we care
7265e4b17023SJohn Marino 	 about.  Make sure we allocate at least one entry.  This prevents
7266e4b17023SJohn Marino 	 xmalloc from calling fatal, and prevents us from re-executing this
7267e4b17023SJohn Marino 	 block of code.  */
7268e4b17023SJohn Marino       mswitches
7269e4b17023SJohn Marino 	= XNEWVEC (struct mswitchstr, n_mdswitches + (n_switches ? n_switches : 1));
7270e4b17023SJohn Marino       for (i = 0; i < n_switches; i++)
7271e4b17023SJohn Marino 	if ((switches[i].live_cond & SWITCH_IGNORE) == 0)
7272e4b17023SJohn Marino 	  {
7273e4b17023SJohn Marino 	    int xlen = strlen (switches[i].part1);
7274e4b17023SJohn Marino 	    for (j = 0; j < cnt; j++)
7275e4b17023SJohn Marino 	      if (xlen == matches[j].len
7276e4b17023SJohn Marino 		  && ! strncmp (switches[i].part1, matches[j].str, xlen))
7277e4b17023SJohn Marino 		{
7278e4b17023SJohn Marino 		  mswitches[n_mswitches].str = matches[j].replace;
7279e4b17023SJohn Marino 		  mswitches[n_mswitches].len = matches[j].rep_len;
7280e4b17023SJohn Marino 		  mswitches[n_mswitches].replace = (char *) 0;
7281e4b17023SJohn Marino 		  mswitches[n_mswitches].rep_len = 0;
7282e4b17023SJohn Marino 		  n_mswitches++;
7283e4b17023SJohn Marino 		  break;
7284e4b17023SJohn Marino 		}
7285e4b17023SJohn Marino 	  }
7286e4b17023SJohn Marino 
7287e4b17023SJohn Marino       /* Add MULTILIB_DEFAULTS switches too, as long as they were not present
7288e4b17023SJohn Marino 	 on the command line nor any options mutually incompatible with
7289e4b17023SJohn Marino 	 them.  */
7290e4b17023SJohn Marino       for (i = 0; i < n_mdswitches; i++)
7291e4b17023SJohn Marino 	{
7292e4b17023SJohn Marino 	  const char *r;
7293e4b17023SJohn Marino 
7294e4b17023SJohn Marino 	  for (q = multilib_options; *q != '\0'; q++)
7295e4b17023SJohn Marino 	    {
7296e4b17023SJohn Marino 	      while (*q == ' ')
7297e4b17023SJohn Marino 		q++;
7298e4b17023SJohn Marino 
7299e4b17023SJohn Marino 	      r = q;
7300e4b17023SJohn Marino 	      while (strncmp (q, mdswitches[i].str, mdswitches[i].len) != 0
7301e4b17023SJohn Marino 		     || strchr (" /", q[mdswitches[i].len]) == NULL)
7302e4b17023SJohn Marino 		{
7303e4b17023SJohn Marino 		  while (*q != ' ' && *q != '/' && *q != '\0')
7304e4b17023SJohn Marino 		    q++;
7305e4b17023SJohn Marino 		  if (*q != '/')
7306e4b17023SJohn Marino 		    break;
7307e4b17023SJohn Marino 		  q++;
7308e4b17023SJohn Marino 		}
7309e4b17023SJohn Marino 
7310e4b17023SJohn Marino 	      if (*q != ' ' && *q != '\0')
7311e4b17023SJohn Marino 		{
7312e4b17023SJohn Marino 		  while (*r != ' ' && *r != '\0')
7313e4b17023SJohn Marino 		    {
7314e4b17023SJohn Marino 		      q = r;
7315e4b17023SJohn Marino 		      while (*q != ' ' && *q != '/' && *q != '\0')
7316e4b17023SJohn Marino 			q++;
7317e4b17023SJohn Marino 
7318e4b17023SJohn Marino 		      if (used_arg (r, q - r))
7319e4b17023SJohn Marino 			break;
7320e4b17023SJohn Marino 
7321e4b17023SJohn Marino 		      if (*q != '/')
7322e4b17023SJohn Marino 			{
7323e4b17023SJohn Marino 			  mswitches[n_mswitches].str = mdswitches[i].str;
7324e4b17023SJohn Marino 			  mswitches[n_mswitches].len = mdswitches[i].len;
7325e4b17023SJohn Marino 			  mswitches[n_mswitches].replace = (char *) 0;
7326e4b17023SJohn Marino 			  mswitches[n_mswitches].rep_len = 0;
7327e4b17023SJohn Marino 			  n_mswitches++;
7328e4b17023SJohn Marino 			  break;
7329e4b17023SJohn Marino 			}
7330e4b17023SJohn Marino 
7331e4b17023SJohn Marino 		      r = q + 1;
7332e4b17023SJohn Marino 		    }
7333e4b17023SJohn Marino 		  break;
7334e4b17023SJohn Marino 		}
7335e4b17023SJohn Marino 	    }
7336e4b17023SJohn Marino 	}
7337e4b17023SJohn Marino     }
7338e4b17023SJohn Marino 
7339e4b17023SJohn Marino   for (i = 0; i < n_mswitches; i++)
7340e4b17023SJohn Marino     if (len == mswitches[i].len && ! strncmp (p, mswitches[i].str, len))
7341e4b17023SJohn Marino       return 1;
7342e4b17023SJohn Marino 
7343e4b17023SJohn Marino   return 0;
7344e4b17023SJohn Marino }
7345e4b17023SJohn Marino 
7346e4b17023SJohn Marino static int
default_arg(const char * p,int len)7347e4b17023SJohn Marino default_arg (const char *p, int len)
7348e4b17023SJohn Marino {
7349e4b17023SJohn Marino   int i;
7350e4b17023SJohn Marino 
7351e4b17023SJohn Marino   for (i = 0; i < n_mdswitches; i++)
7352e4b17023SJohn Marino     if (len == mdswitches[i].len && ! strncmp (p, mdswitches[i].str, len))
7353e4b17023SJohn Marino       return 1;
7354e4b17023SJohn Marino 
7355e4b17023SJohn Marino   return 0;
7356e4b17023SJohn Marino }
7357e4b17023SJohn Marino 
7358e4b17023SJohn Marino /* Work out the subdirectory to use based on the options. The format of
7359e4b17023SJohn Marino    multilib_select is a list of elements. Each element is a subdirectory
7360e4b17023SJohn Marino    name followed by a list of options followed by a semicolon. The format
7361e4b17023SJohn Marino    of multilib_exclusions is the same, but without the preceding
7362e4b17023SJohn Marino    directory. First gcc will check the exclusions, if none of the options
7363e4b17023SJohn Marino    beginning with an exclamation point are present, and all of the other
7364e4b17023SJohn Marino    options are present, then we will ignore this completely. Passing
7365e4b17023SJohn Marino    that, gcc will consider each multilib_select in turn using the same
7366e4b17023SJohn Marino    rules for matching the options. If a match is found, that subdirectory
73675ce9237cSJohn Marino    will be used.
73685ce9237cSJohn Marino    A subdirectory name is optionally followed by a colon and the corresponding
73695ce9237cSJohn Marino    multiarch name.  */
7370e4b17023SJohn Marino 
7371e4b17023SJohn Marino static void
set_multilib_dir(void)7372e4b17023SJohn Marino set_multilib_dir (void)
7373e4b17023SJohn Marino {
7374e4b17023SJohn Marino   const char *p;
7375e4b17023SJohn Marino   unsigned int this_path_len;
7376e4b17023SJohn Marino   const char *this_path, *this_arg;
7377e4b17023SJohn Marino   const char *start, *end;
7378e4b17023SJohn Marino   int not_arg;
7379e4b17023SJohn Marino   int ok, ndfltok, first;
7380e4b17023SJohn Marino 
7381e4b17023SJohn Marino   n_mdswitches = 0;
7382e4b17023SJohn Marino   start = multilib_defaults;
7383e4b17023SJohn Marino   while (*start == ' ' || *start == '\t')
7384e4b17023SJohn Marino     start++;
7385e4b17023SJohn Marino   while (*start != '\0')
7386e4b17023SJohn Marino     {
7387e4b17023SJohn Marino       n_mdswitches++;
7388e4b17023SJohn Marino       while (*start != ' ' && *start != '\t' && *start != '\0')
7389e4b17023SJohn Marino 	start++;
7390e4b17023SJohn Marino       while (*start == ' ' || *start == '\t')
7391e4b17023SJohn Marino         start++;
7392e4b17023SJohn Marino     }
7393e4b17023SJohn Marino 
7394e4b17023SJohn Marino   if (n_mdswitches)
7395e4b17023SJohn Marino     {
7396e4b17023SJohn Marino       int i = 0;
7397e4b17023SJohn Marino 
7398e4b17023SJohn Marino       mdswitches = XNEWVEC (struct mdswitchstr, n_mdswitches);
7399e4b17023SJohn Marino       for (start = multilib_defaults; *start != '\0'; start = end + 1)
7400e4b17023SJohn Marino 	{
7401e4b17023SJohn Marino 	  while (*start == ' ' || *start == '\t')
7402e4b17023SJohn Marino 	    start++;
7403e4b17023SJohn Marino 
7404e4b17023SJohn Marino 	  if (*start == '\0')
7405e4b17023SJohn Marino 	    break;
7406e4b17023SJohn Marino 
7407e4b17023SJohn Marino 	  for (end = start + 1;
7408e4b17023SJohn Marino 	       *end != ' ' && *end != '\t' && *end != '\0'; end++)
7409e4b17023SJohn Marino 	    ;
7410e4b17023SJohn Marino 
7411e4b17023SJohn Marino 	  obstack_grow (&multilib_obstack, start, end - start);
7412e4b17023SJohn Marino 	  obstack_1grow (&multilib_obstack, 0);
7413e4b17023SJohn Marino 	  mdswitches[i].str = XOBFINISH (&multilib_obstack, const char *);
7414e4b17023SJohn Marino 	  mdswitches[i++].len = end - start;
7415e4b17023SJohn Marino 
7416e4b17023SJohn Marino 	  if (*end == '\0')
7417e4b17023SJohn Marino 	    break;
7418e4b17023SJohn Marino 	}
7419e4b17023SJohn Marino     }
7420e4b17023SJohn Marino 
7421e4b17023SJohn Marino   p = multilib_exclusions;
7422e4b17023SJohn Marino   while (*p != '\0')
7423e4b17023SJohn Marino     {
7424e4b17023SJohn Marino       /* Ignore newlines.  */
7425e4b17023SJohn Marino       if (*p == '\n')
7426e4b17023SJohn Marino 	{
7427e4b17023SJohn Marino 	  ++p;
7428e4b17023SJohn Marino 	  continue;
7429e4b17023SJohn Marino 	}
7430e4b17023SJohn Marino 
7431e4b17023SJohn Marino       /* Check the arguments.  */
7432e4b17023SJohn Marino       ok = 1;
7433e4b17023SJohn Marino       while (*p != ';')
7434e4b17023SJohn Marino 	{
7435e4b17023SJohn Marino 	  if (*p == '\0')
7436e4b17023SJohn Marino 	    {
7437e4b17023SJohn Marino 	    invalid_exclusions:
7438e4b17023SJohn Marino 	      fatal_error ("multilib exclusions %qs is invalid",
7439e4b17023SJohn Marino 			   multilib_exclusions);
7440e4b17023SJohn Marino 	    }
7441e4b17023SJohn Marino 
7442e4b17023SJohn Marino 	  if (! ok)
7443e4b17023SJohn Marino 	    {
7444e4b17023SJohn Marino 	      ++p;
7445e4b17023SJohn Marino 	      continue;
7446e4b17023SJohn Marino 	    }
7447e4b17023SJohn Marino 
7448e4b17023SJohn Marino 	  this_arg = p;
7449e4b17023SJohn Marino 	  while (*p != ' ' && *p != ';')
7450e4b17023SJohn Marino 	    {
7451e4b17023SJohn Marino 	      if (*p == '\0')
7452e4b17023SJohn Marino 		goto invalid_exclusions;
7453e4b17023SJohn Marino 	      ++p;
7454e4b17023SJohn Marino 	    }
7455e4b17023SJohn Marino 
7456e4b17023SJohn Marino 	  if (*this_arg != '!')
7457e4b17023SJohn Marino 	    not_arg = 0;
7458e4b17023SJohn Marino 	  else
7459e4b17023SJohn Marino 	    {
7460e4b17023SJohn Marino 	      not_arg = 1;
7461e4b17023SJohn Marino 	      ++this_arg;
7462e4b17023SJohn Marino 	    }
7463e4b17023SJohn Marino 
7464e4b17023SJohn Marino 	  ok = used_arg (this_arg, p - this_arg);
7465e4b17023SJohn Marino 	  if (not_arg)
7466e4b17023SJohn Marino 	    ok = ! ok;
7467e4b17023SJohn Marino 
7468e4b17023SJohn Marino 	  if (*p == ' ')
7469e4b17023SJohn Marino 	    ++p;
7470e4b17023SJohn Marino 	}
7471e4b17023SJohn Marino 
7472e4b17023SJohn Marino       if (ok)
7473e4b17023SJohn Marino 	return;
7474e4b17023SJohn Marino 
7475e4b17023SJohn Marino       ++p;
7476e4b17023SJohn Marino     }
7477e4b17023SJohn Marino 
7478e4b17023SJohn Marino   first = 1;
7479e4b17023SJohn Marino   p = multilib_select;
7480e4b17023SJohn Marino   while (*p != '\0')
7481e4b17023SJohn Marino     {
7482e4b17023SJohn Marino       /* Ignore newlines.  */
7483e4b17023SJohn Marino       if (*p == '\n')
7484e4b17023SJohn Marino 	{
7485e4b17023SJohn Marino 	  ++p;
7486e4b17023SJohn Marino 	  continue;
7487e4b17023SJohn Marino 	}
7488e4b17023SJohn Marino 
7489e4b17023SJohn Marino       /* Get the initial path.  */
7490e4b17023SJohn Marino       this_path = p;
7491e4b17023SJohn Marino       while (*p != ' ')
7492e4b17023SJohn Marino 	{
7493e4b17023SJohn Marino 	  if (*p == '\0')
7494e4b17023SJohn Marino 	    {
7495e4b17023SJohn Marino 	    invalid_select:
7496e4b17023SJohn Marino 	      fatal_error ("multilib select %qs is invalid",
7497e4b17023SJohn Marino 			   multilib_select);
7498e4b17023SJohn Marino 	    }
7499e4b17023SJohn Marino 	  ++p;
7500e4b17023SJohn Marino 	}
7501e4b17023SJohn Marino       this_path_len = p - this_path;
7502e4b17023SJohn Marino 
7503e4b17023SJohn Marino       /* Check the arguments.  */
7504e4b17023SJohn Marino       ok = 1;
7505e4b17023SJohn Marino       ndfltok = 1;
7506e4b17023SJohn Marino       ++p;
7507e4b17023SJohn Marino       while (*p != ';')
7508e4b17023SJohn Marino 	{
7509e4b17023SJohn Marino 	  if (*p == '\0')
7510e4b17023SJohn Marino 	    goto invalid_select;
7511e4b17023SJohn Marino 
7512e4b17023SJohn Marino 	  if (! ok)
7513e4b17023SJohn Marino 	    {
7514e4b17023SJohn Marino 	      ++p;
7515e4b17023SJohn Marino 	      continue;
7516e4b17023SJohn Marino 	    }
7517e4b17023SJohn Marino 
7518e4b17023SJohn Marino 	  this_arg = p;
7519e4b17023SJohn Marino 	  while (*p != ' ' && *p != ';')
7520e4b17023SJohn Marino 	    {
7521e4b17023SJohn Marino 	      if (*p == '\0')
7522e4b17023SJohn Marino 		goto invalid_select;
7523e4b17023SJohn Marino 	      ++p;
7524e4b17023SJohn Marino 	    }
7525e4b17023SJohn Marino 
7526e4b17023SJohn Marino 	  if (*this_arg != '!')
7527e4b17023SJohn Marino 	    not_arg = 0;
7528e4b17023SJohn Marino 	  else
7529e4b17023SJohn Marino 	    {
7530e4b17023SJohn Marino 	      not_arg = 1;
7531e4b17023SJohn Marino 	      ++this_arg;
7532e4b17023SJohn Marino 	    }
7533e4b17023SJohn Marino 
7534e4b17023SJohn Marino 	  /* If this is a default argument, we can just ignore it.
7535e4b17023SJohn Marino 	     This is true even if this_arg begins with '!'.  Beginning
7536e4b17023SJohn Marino 	     with '!' does not mean that this argument is necessarily
7537e4b17023SJohn Marino 	     inappropriate for this library: it merely means that
7538e4b17023SJohn Marino 	     there is a more specific library which uses this
7539e4b17023SJohn Marino 	     argument.  If this argument is a default, we need not
7540e4b17023SJohn Marino 	     consider that more specific library.  */
7541e4b17023SJohn Marino 	  ok = used_arg (this_arg, p - this_arg);
7542e4b17023SJohn Marino 	  if (not_arg)
7543e4b17023SJohn Marino 	    ok = ! ok;
7544e4b17023SJohn Marino 
7545e4b17023SJohn Marino 	  if (! ok)
7546e4b17023SJohn Marino 	    ndfltok = 0;
7547e4b17023SJohn Marino 
7548e4b17023SJohn Marino 	  if (default_arg (this_arg, p - this_arg))
7549e4b17023SJohn Marino 	    ok = 1;
7550e4b17023SJohn Marino 
7551e4b17023SJohn Marino 	  if (*p == ' ')
7552e4b17023SJohn Marino 	    ++p;
7553e4b17023SJohn Marino 	}
7554e4b17023SJohn Marino 
7555e4b17023SJohn Marino       if (ok && first)
7556e4b17023SJohn Marino 	{
7557e4b17023SJohn Marino 	  if (this_path_len != 1
7558e4b17023SJohn Marino 	      || this_path[0] != '.')
7559e4b17023SJohn Marino 	    {
7560e4b17023SJohn Marino 	      char *new_multilib_dir = XNEWVEC (char, this_path_len + 1);
7561e4b17023SJohn Marino 	      char *q;
7562e4b17023SJohn Marino 
7563e4b17023SJohn Marino 	      strncpy (new_multilib_dir, this_path, this_path_len);
7564e4b17023SJohn Marino 	      new_multilib_dir[this_path_len] = '\0';
7565e4b17023SJohn Marino 	      q = strchr (new_multilib_dir, ':');
7566e4b17023SJohn Marino 	      if (q != NULL)
7567e4b17023SJohn Marino 		*q = '\0';
7568e4b17023SJohn Marino 	      multilib_dir = new_multilib_dir;
7569e4b17023SJohn Marino 	    }
7570e4b17023SJohn Marino 	  first = 0;
7571e4b17023SJohn Marino 	}
7572e4b17023SJohn Marino 
7573e4b17023SJohn Marino       if (ndfltok)
7574e4b17023SJohn Marino 	{
7575e4b17023SJohn Marino 	  const char *q = this_path, *end = this_path + this_path_len;
7576e4b17023SJohn Marino 
7577e4b17023SJohn Marino 	  while (q < end && *q != ':')
7578e4b17023SJohn Marino 	    q++;
7579e4b17023SJohn Marino 	  if (q < end)
7580e4b17023SJohn Marino 	    {
75815ce9237cSJohn Marino 	      const char *q2 = q + 1, *ml_end = end;
75825ce9237cSJohn Marino 	      char *new_multilib_os_dir;
75835ce9237cSJohn Marino 
75845ce9237cSJohn Marino 	      while (q2 < end && *q2 != ':')
75855ce9237cSJohn Marino 		q2++;
75865ce9237cSJohn Marino 	      if (*q2 == ':')
75875ce9237cSJohn Marino 		ml_end = q2;
75885ce9237cSJohn Marino 	      new_multilib_os_dir = XNEWVEC (char, ml_end - q);
75895ce9237cSJohn Marino 	      memcpy (new_multilib_os_dir, q + 1, ml_end - q - 1);
75905ce9237cSJohn Marino 	      new_multilib_os_dir[ml_end - q - 1] = '\0';
75915ce9237cSJohn Marino 	      multilib_os_dir = *new_multilib_os_dir ? new_multilib_os_dir : ".";
75925ce9237cSJohn Marino 
75935ce9237cSJohn Marino 	      if (q2 < end && *q2 == ':')
75945ce9237cSJohn Marino 		{
75955ce9237cSJohn Marino 		  char *new_multiarch_dir = XNEWVEC (char, end - q2);
75965ce9237cSJohn Marino 		  memcpy (new_multiarch_dir, q2 + 1, end - q2 - 1);
75975ce9237cSJohn Marino 		  new_multiarch_dir[end - q2 - 1] = '\0';
75985ce9237cSJohn Marino 		  multiarch_dir = new_multiarch_dir;
75995ce9237cSJohn Marino 		}
7600e4b17023SJohn Marino 	      break;
7601e4b17023SJohn Marino 	    }
7602e4b17023SJohn Marino 	}
7603e4b17023SJohn Marino 
7604e4b17023SJohn Marino       ++p;
7605e4b17023SJohn Marino     }
7606e4b17023SJohn Marino 
7607e4b17023SJohn Marino   if (multilib_dir == NULL && multilib_os_dir != NULL
7608e4b17023SJohn Marino       && strcmp (multilib_os_dir, ".") == 0)
7609e4b17023SJohn Marino     {
7610e4b17023SJohn Marino       free (CONST_CAST (char *, multilib_os_dir));
7611e4b17023SJohn Marino       multilib_os_dir = NULL;
7612e4b17023SJohn Marino     }
7613e4b17023SJohn Marino   else if (multilib_dir != NULL && multilib_os_dir == NULL)
7614e4b17023SJohn Marino     multilib_os_dir = multilib_dir;
7615e4b17023SJohn Marino }
7616e4b17023SJohn Marino 
7617e4b17023SJohn Marino /* Print out the multiple library subdirectory selection
7618e4b17023SJohn Marino    information.  This prints out a series of lines.  Each line looks
7619e4b17023SJohn Marino    like SUBDIRECTORY;@OPTION@OPTION, with as many options as is
7620e4b17023SJohn Marino    required.  Only the desired options are printed out, the negative
7621e4b17023SJohn Marino    matches.  The options are print without a leading dash.  There are
7622e4b17023SJohn Marino    no spaces to make it easy to use the information in the shell.
7623e4b17023SJohn Marino    Each subdirectory is printed only once.  This assumes the ordering
7624e4b17023SJohn Marino    generated by the genmultilib script. Also, we leave out ones that match
7625e4b17023SJohn Marino    the exclusions.  */
7626e4b17023SJohn Marino 
7627e4b17023SJohn Marino static void
print_multilib_info(void)7628e4b17023SJohn Marino print_multilib_info (void)
7629e4b17023SJohn Marino {
7630e4b17023SJohn Marino   const char *p = multilib_select;
7631e4b17023SJohn Marino   const char *last_path = 0, *this_path;
7632e4b17023SJohn Marino   int skip;
7633e4b17023SJohn Marino   unsigned int last_path_len = 0;
7634e4b17023SJohn Marino 
7635e4b17023SJohn Marino   while (*p != '\0')
7636e4b17023SJohn Marino     {
7637e4b17023SJohn Marino       skip = 0;
7638e4b17023SJohn Marino       /* Ignore newlines.  */
7639e4b17023SJohn Marino       if (*p == '\n')
7640e4b17023SJohn Marino 	{
7641e4b17023SJohn Marino 	  ++p;
7642e4b17023SJohn Marino 	  continue;
7643e4b17023SJohn Marino 	}
7644e4b17023SJohn Marino 
7645e4b17023SJohn Marino       /* Get the initial path.  */
7646e4b17023SJohn Marino       this_path = p;
7647e4b17023SJohn Marino       while (*p != ' ')
7648e4b17023SJohn Marino 	{
7649e4b17023SJohn Marino 	  if (*p == '\0')
7650e4b17023SJohn Marino 	    {
7651e4b17023SJohn Marino 	    invalid_select:
7652e4b17023SJohn Marino 	      fatal_error ("multilib select %qs is invalid", multilib_select);
7653e4b17023SJohn Marino 	    }
7654e4b17023SJohn Marino 
7655e4b17023SJohn Marino 	  ++p;
7656e4b17023SJohn Marino 	}
7657e4b17023SJohn Marino 
7658e4b17023SJohn Marino       /* When --disable-multilib was used but target defines
76595ce9237cSJohn Marino 	 MULTILIB_OSDIRNAMES, entries starting with .: (and not starting
76605ce9237cSJohn Marino          with .:: for multiarch configurations) are there just to find
76615ce9237cSJohn Marino          multilib_os_dir, so skip them from output.  */
76625ce9237cSJohn Marino       if (this_path[0] == '.' && this_path[1] == ':' && this_path[2] != ':')
7663e4b17023SJohn Marino 	skip = 1;
7664e4b17023SJohn Marino 
7665e4b17023SJohn Marino       /* Check for matches with the multilib_exclusions. We don't bother
7666e4b17023SJohn Marino          with the '!' in either list. If any of the exclusion rules match
7667e4b17023SJohn Marino          all of its options with the select rule, we skip it.  */
7668e4b17023SJohn Marino       {
7669e4b17023SJohn Marino 	const char *e = multilib_exclusions;
7670e4b17023SJohn Marino 	const char *this_arg;
7671e4b17023SJohn Marino 
7672e4b17023SJohn Marino 	while (*e != '\0')
7673e4b17023SJohn Marino 	  {
7674e4b17023SJohn Marino 	    int m = 1;
7675e4b17023SJohn Marino 	    /* Ignore newlines.  */
7676e4b17023SJohn Marino 	    if (*e == '\n')
7677e4b17023SJohn Marino 	      {
7678e4b17023SJohn Marino 		++e;
7679e4b17023SJohn Marino 		continue;
7680e4b17023SJohn Marino 	      }
7681e4b17023SJohn Marino 
7682e4b17023SJohn Marino 	    /* Check the arguments.  */
7683e4b17023SJohn Marino 	    while (*e != ';')
7684e4b17023SJohn Marino 	      {
7685e4b17023SJohn Marino 		const char *q;
7686e4b17023SJohn Marino 		int mp = 0;
7687e4b17023SJohn Marino 
7688e4b17023SJohn Marino 		if (*e == '\0')
7689e4b17023SJohn Marino 		  {
7690e4b17023SJohn Marino 		  invalid_exclusion:
7691e4b17023SJohn Marino 		    fatal_error ("multilib exclusion %qs is invalid",
7692e4b17023SJohn Marino 				 multilib_exclusions);
7693e4b17023SJohn Marino 		  }
7694e4b17023SJohn Marino 
7695e4b17023SJohn Marino 		if (! m)
7696e4b17023SJohn Marino 		  {
7697e4b17023SJohn Marino 		    ++e;
7698e4b17023SJohn Marino 		    continue;
7699e4b17023SJohn Marino 		  }
7700e4b17023SJohn Marino 
7701e4b17023SJohn Marino 		this_arg = e;
7702e4b17023SJohn Marino 
7703e4b17023SJohn Marino 		while (*e != ' ' && *e != ';')
7704e4b17023SJohn Marino 		  {
7705e4b17023SJohn Marino 		    if (*e == '\0')
7706e4b17023SJohn Marino 		      goto invalid_exclusion;
7707e4b17023SJohn Marino 		    ++e;
7708e4b17023SJohn Marino 		  }
7709e4b17023SJohn Marino 
7710e4b17023SJohn Marino 		q = p + 1;
7711e4b17023SJohn Marino 		while (*q != ';')
7712e4b17023SJohn Marino 		  {
7713e4b17023SJohn Marino 		    const char *arg;
7714e4b17023SJohn Marino 		    int len = e - this_arg;
7715e4b17023SJohn Marino 
7716e4b17023SJohn Marino 		    if (*q == '\0')
7717e4b17023SJohn Marino 		      goto invalid_select;
7718e4b17023SJohn Marino 
7719e4b17023SJohn Marino 		    arg = q;
7720e4b17023SJohn Marino 
7721e4b17023SJohn Marino 		    while (*q != ' ' && *q != ';')
7722e4b17023SJohn Marino 		      {
7723e4b17023SJohn Marino 			if (*q == '\0')
7724e4b17023SJohn Marino 			  goto invalid_select;
7725e4b17023SJohn Marino 			++q;
7726e4b17023SJohn Marino 		      }
7727e4b17023SJohn Marino 
7728e4b17023SJohn Marino 		    if (! strncmp (arg, this_arg,
7729e4b17023SJohn Marino 				   (len < q - arg) ? q - arg : len)
7730e4b17023SJohn Marino 			|| default_arg (this_arg, e - this_arg))
7731e4b17023SJohn Marino 		      {
7732e4b17023SJohn Marino 			mp = 1;
7733e4b17023SJohn Marino 			break;
7734e4b17023SJohn Marino 		      }
7735e4b17023SJohn Marino 
7736e4b17023SJohn Marino 		    if (*q == ' ')
7737e4b17023SJohn Marino 		      ++q;
7738e4b17023SJohn Marino 		  }
7739e4b17023SJohn Marino 
7740e4b17023SJohn Marino 		if (! mp)
7741e4b17023SJohn Marino 		  m = 0;
7742e4b17023SJohn Marino 
7743e4b17023SJohn Marino 		if (*e == ' ')
7744e4b17023SJohn Marino 		  ++e;
7745e4b17023SJohn Marino 	      }
7746e4b17023SJohn Marino 
7747e4b17023SJohn Marino 	    if (m)
7748e4b17023SJohn Marino 	      {
7749e4b17023SJohn Marino 		skip = 1;
7750e4b17023SJohn Marino 		break;
7751e4b17023SJohn Marino 	      }
7752e4b17023SJohn Marino 
7753e4b17023SJohn Marino 	    if (*e != '\0')
7754e4b17023SJohn Marino 	      ++e;
7755e4b17023SJohn Marino 	  }
7756e4b17023SJohn Marino       }
7757e4b17023SJohn Marino 
7758e4b17023SJohn Marino       if (! skip)
7759e4b17023SJohn Marino 	{
7760e4b17023SJohn Marino 	  /* If this is a duplicate, skip it.  */
7761e4b17023SJohn Marino 	  skip = (last_path != 0
7762e4b17023SJohn Marino 		  && (unsigned int) (p - this_path) == last_path_len
7763e4b17023SJohn Marino 		  && ! filename_ncmp (last_path, this_path, last_path_len));
7764e4b17023SJohn Marino 
7765e4b17023SJohn Marino 	  last_path = this_path;
7766e4b17023SJohn Marino 	  last_path_len = p - this_path;
7767e4b17023SJohn Marino 	}
7768e4b17023SJohn Marino 
7769e4b17023SJohn Marino       /* If this directory requires any default arguments, we can skip
7770e4b17023SJohn Marino 	 it.  We will already have printed a directory identical to
7771e4b17023SJohn Marino 	 this one which does not require that default argument.  */
7772e4b17023SJohn Marino       if (! skip)
7773e4b17023SJohn Marino 	{
7774e4b17023SJohn Marino 	  const char *q;
7775e4b17023SJohn Marino 
7776e4b17023SJohn Marino 	  q = p + 1;
7777e4b17023SJohn Marino 	  while (*q != ';')
7778e4b17023SJohn Marino 	    {
7779e4b17023SJohn Marino 	      const char *arg;
7780e4b17023SJohn Marino 
7781e4b17023SJohn Marino 	      if (*q == '\0')
7782e4b17023SJohn Marino 		goto invalid_select;
7783e4b17023SJohn Marino 
7784e4b17023SJohn Marino 	      if (*q == '!')
7785e4b17023SJohn Marino 		arg = NULL;
7786e4b17023SJohn Marino 	      else
7787e4b17023SJohn Marino 		arg = q;
7788e4b17023SJohn Marino 
7789e4b17023SJohn Marino 	      while (*q != ' ' && *q != ';')
7790e4b17023SJohn Marino 		{
7791e4b17023SJohn Marino 		  if (*q == '\0')
7792e4b17023SJohn Marino 		    goto invalid_select;
7793e4b17023SJohn Marino 		  ++q;
7794e4b17023SJohn Marino 		}
7795e4b17023SJohn Marino 
7796e4b17023SJohn Marino 	      if (arg != NULL
7797e4b17023SJohn Marino 		  && default_arg (arg, q - arg))
7798e4b17023SJohn Marino 		{
7799e4b17023SJohn Marino 		  skip = 1;
7800e4b17023SJohn Marino 		  break;
7801e4b17023SJohn Marino 		}
7802e4b17023SJohn Marino 
7803e4b17023SJohn Marino 	      if (*q == ' ')
7804e4b17023SJohn Marino 		++q;
7805e4b17023SJohn Marino 	    }
7806e4b17023SJohn Marino 	}
7807e4b17023SJohn Marino 
7808e4b17023SJohn Marino       if (! skip)
7809e4b17023SJohn Marino 	{
7810e4b17023SJohn Marino 	  const char *p1;
7811e4b17023SJohn Marino 
7812e4b17023SJohn Marino 	  for (p1 = last_path; p1 < p && *p1 != ':'; p1++)
7813e4b17023SJohn Marino 	    putchar (*p1);
7814e4b17023SJohn Marino 	  putchar (';');
7815e4b17023SJohn Marino 	}
7816e4b17023SJohn Marino 
7817e4b17023SJohn Marino       ++p;
7818e4b17023SJohn Marino       while (*p != ';')
7819e4b17023SJohn Marino 	{
7820e4b17023SJohn Marino 	  int use_arg;
7821e4b17023SJohn Marino 
7822e4b17023SJohn Marino 	  if (*p == '\0')
7823e4b17023SJohn Marino 	    goto invalid_select;
7824e4b17023SJohn Marino 
7825e4b17023SJohn Marino 	  if (skip)
7826e4b17023SJohn Marino 	    {
7827e4b17023SJohn Marino 	      ++p;
7828e4b17023SJohn Marino 	      continue;
7829e4b17023SJohn Marino 	    }
7830e4b17023SJohn Marino 
7831e4b17023SJohn Marino 	  use_arg = *p != '!';
7832e4b17023SJohn Marino 
7833e4b17023SJohn Marino 	  if (use_arg)
7834e4b17023SJohn Marino 	    putchar ('@');
7835e4b17023SJohn Marino 
7836e4b17023SJohn Marino 	  while (*p != ' ' && *p != ';')
7837e4b17023SJohn Marino 	    {
7838e4b17023SJohn Marino 	      if (*p == '\0')
7839e4b17023SJohn Marino 		goto invalid_select;
7840e4b17023SJohn Marino 	      if (use_arg)
7841e4b17023SJohn Marino 		putchar (*p);
7842e4b17023SJohn Marino 	      ++p;
7843e4b17023SJohn Marino 	    }
7844e4b17023SJohn Marino 
7845e4b17023SJohn Marino 	  if (*p == ' ')
7846e4b17023SJohn Marino 	    ++p;
7847e4b17023SJohn Marino 	}
7848e4b17023SJohn Marino 
7849e4b17023SJohn Marino       if (! skip)
7850e4b17023SJohn Marino 	{
7851e4b17023SJohn Marino 	  /* If there are extra options, print them now.  */
7852e4b17023SJohn Marino 	  if (multilib_extra && *multilib_extra)
7853e4b17023SJohn Marino 	    {
7854e4b17023SJohn Marino 	      int print_at = TRUE;
7855e4b17023SJohn Marino 	      const char *q;
7856e4b17023SJohn Marino 
7857e4b17023SJohn Marino 	      for (q = multilib_extra; *q != '\0'; q++)
7858e4b17023SJohn Marino 		{
7859e4b17023SJohn Marino 		  if (*q == ' ')
7860e4b17023SJohn Marino 		    print_at = TRUE;
7861e4b17023SJohn Marino 		  else
7862e4b17023SJohn Marino 		    {
7863e4b17023SJohn Marino 		      if (print_at)
7864e4b17023SJohn Marino 			putchar ('@');
7865e4b17023SJohn Marino 		      putchar (*q);
7866e4b17023SJohn Marino 		      print_at = FALSE;
7867e4b17023SJohn Marino 		    }
7868e4b17023SJohn Marino 		}
7869e4b17023SJohn Marino 	    }
7870e4b17023SJohn Marino 
7871e4b17023SJohn Marino 	  putchar ('\n');
7872e4b17023SJohn Marino 	}
7873e4b17023SJohn Marino 
7874e4b17023SJohn Marino       ++p;
7875e4b17023SJohn Marino     }
7876e4b17023SJohn Marino }
7877e4b17023SJohn Marino 
7878e4b17023SJohn Marino /* getenv built-in spec function.
7879e4b17023SJohn Marino 
7880e4b17023SJohn Marino    Returns the value of the environment variable given by its first
7881e4b17023SJohn Marino    argument, concatenated with the second argument.  If the
7882e4b17023SJohn Marino    environment variable is not defined, a fatal error is issued.  */
7883e4b17023SJohn Marino 
7884e4b17023SJohn Marino static const char *
getenv_spec_function(int argc,const char ** argv)7885e4b17023SJohn Marino getenv_spec_function (int argc, const char **argv)
7886e4b17023SJohn Marino {
7887e4b17023SJohn Marino   char *value;
7888e4b17023SJohn Marino   char *result;
7889e4b17023SJohn Marino   char *ptr;
7890e4b17023SJohn Marino   size_t len;
7891e4b17023SJohn Marino 
7892e4b17023SJohn Marino   if (argc != 2)
7893e4b17023SJohn Marino     return NULL;
7894e4b17023SJohn Marino 
7895e4b17023SJohn Marino   value = getenv (argv[0]);
7896e4b17023SJohn Marino   if (!value)
7897e4b17023SJohn Marino     fatal_error ("environment variable %qs not defined", argv[0]);
7898e4b17023SJohn Marino 
7899e4b17023SJohn Marino   /* We have to escape every character of the environment variable so
7900e4b17023SJohn Marino      they are not interpreted as active spec characters.  A
7901e4b17023SJohn Marino      particularly painful case is when we are reading a variable
7902e4b17023SJohn Marino      holding a windows path complete with \ separators.  */
7903e4b17023SJohn Marino   len = strlen (value) * 2 + strlen (argv[1]) + 1;
7904e4b17023SJohn Marino   result = XNEWVAR (char, len);
7905e4b17023SJohn Marino   for (ptr = result; *value; ptr += 2)
7906e4b17023SJohn Marino     {
7907e4b17023SJohn Marino       ptr[0] = '\\';
7908e4b17023SJohn Marino       ptr[1] = *value++;
7909e4b17023SJohn Marino     }
7910e4b17023SJohn Marino 
7911e4b17023SJohn Marino   strcpy (ptr, argv[1]);
7912e4b17023SJohn Marino 
7913e4b17023SJohn Marino   return result;
7914e4b17023SJohn Marino }
7915e4b17023SJohn Marino 
7916e4b17023SJohn Marino /* if-exists built-in spec function.
7917e4b17023SJohn Marino 
7918e4b17023SJohn Marino    Checks to see if the file specified by the absolute pathname in
7919e4b17023SJohn Marino    ARGS exists.  Returns that pathname if found.
7920e4b17023SJohn Marino 
7921e4b17023SJohn Marino    The usual use for this function is to check for a library file
7922e4b17023SJohn Marino    (whose name has been expanded with %s).  */
7923e4b17023SJohn Marino 
7924e4b17023SJohn Marino static const char *
if_exists_spec_function(int argc,const char ** argv)7925e4b17023SJohn Marino if_exists_spec_function (int argc, const char **argv)
7926e4b17023SJohn Marino {
7927e4b17023SJohn Marino   /* Must have only one argument.  */
7928e4b17023SJohn Marino   if (argc == 1 && IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
7929e4b17023SJohn Marino     return argv[0];
7930e4b17023SJohn Marino 
7931e4b17023SJohn Marino   return NULL;
7932e4b17023SJohn Marino }
7933e4b17023SJohn Marino 
7934e4b17023SJohn Marino /* if-exists-else built-in spec function.
7935e4b17023SJohn Marino 
7936e4b17023SJohn Marino    This is like if-exists, but takes an additional argument which
7937e4b17023SJohn Marino    is returned if the first argument does not exist.  */
7938e4b17023SJohn Marino 
7939e4b17023SJohn Marino static const char *
if_exists_else_spec_function(int argc,const char ** argv)7940e4b17023SJohn Marino if_exists_else_spec_function (int argc, const char **argv)
7941e4b17023SJohn Marino {
7942e4b17023SJohn Marino   /* Must have exactly two arguments.  */
7943e4b17023SJohn Marino   if (argc != 2)
7944e4b17023SJohn Marino     return NULL;
7945e4b17023SJohn Marino 
7946e4b17023SJohn Marino   if (IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
7947e4b17023SJohn Marino     return argv[0];
7948e4b17023SJohn Marino 
7949e4b17023SJohn Marino   return argv[1];
7950e4b17023SJohn Marino }
7951e4b17023SJohn Marino 
7952e4b17023SJohn Marino /* replace-outfile built-in spec function.
7953e4b17023SJohn Marino 
7954e4b17023SJohn Marino    This looks for the first argument in the outfiles array's name and
7955e4b17023SJohn Marino    replaces it with the second argument.  */
7956e4b17023SJohn Marino 
7957e4b17023SJohn Marino static const char *
replace_outfile_spec_function(int argc,const char ** argv)7958e4b17023SJohn Marino replace_outfile_spec_function (int argc, const char **argv)
7959e4b17023SJohn Marino {
7960e4b17023SJohn Marino   int i;
7961e4b17023SJohn Marino   /* Must have exactly two arguments.  */
7962e4b17023SJohn Marino   if (argc != 2)
7963e4b17023SJohn Marino     abort ();
7964e4b17023SJohn Marino 
7965e4b17023SJohn Marino   for (i = 0; i < n_infiles; i++)
7966e4b17023SJohn Marino     {
7967e4b17023SJohn Marino       if (outfiles[i] && !filename_cmp (outfiles[i], argv[0]))
7968e4b17023SJohn Marino 	outfiles[i] = xstrdup (argv[1]);
7969e4b17023SJohn Marino     }
7970e4b17023SJohn Marino   return NULL;
7971e4b17023SJohn Marino }
7972e4b17023SJohn Marino 
7973e4b17023SJohn Marino /* remove-outfile built-in spec function.
7974e4b17023SJohn Marino  *
7975e4b17023SJohn Marino  *    This looks for the first argument in the outfiles array's name and
7976e4b17023SJohn Marino  *       removes it.  */
7977e4b17023SJohn Marino 
7978e4b17023SJohn Marino static const char *
remove_outfile_spec_function(int argc,const char ** argv)7979e4b17023SJohn Marino remove_outfile_spec_function (int argc, const char **argv)
7980e4b17023SJohn Marino {
7981e4b17023SJohn Marino   int i;
7982e4b17023SJohn Marino   /* Must have exactly one argument.  */
7983e4b17023SJohn Marino   if (argc != 1)
7984e4b17023SJohn Marino     abort ();
7985e4b17023SJohn Marino 
7986e4b17023SJohn Marino   for (i = 0; i < n_infiles; i++)
7987e4b17023SJohn Marino     {
7988e4b17023SJohn Marino       if (outfiles[i] && !filename_cmp (outfiles[i], argv[0]))
7989e4b17023SJohn Marino         outfiles[i] = NULL;
7990e4b17023SJohn Marino     }
7991e4b17023SJohn Marino   return NULL;
7992e4b17023SJohn Marino }
7993e4b17023SJohn Marino 
7994e4b17023SJohn Marino /* Given two version numbers, compares the two numbers.
7995e4b17023SJohn Marino    A version number must match the regular expression
7996e4b17023SJohn Marino    ([1-9][0-9]*|0)(\.([1-9][0-9]*|0))*
7997e4b17023SJohn Marino */
7998e4b17023SJohn Marino static int
compare_version_strings(const char * v1,const char * v2)7999e4b17023SJohn Marino compare_version_strings (const char *v1, const char *v2)
8000e4b17023SJohn Marino {
8001e4b17023SJohn Marino   int rresult;
8002e4b17023SJohn Marino   regex_t r;
8003e4b17023SJohn Marino 
8004e4b17023SJohn Marino   if (regcomp (&r, "^([1-9][0-9]*|0)(\\.([1-9][0-9]*|0))*$",
8005e4b17023SJohn Marino 	       REG_EXTENDED | REG_NOSUB) != 0)
8006e4b17023SJohn Marino     abort ();
8007e4b17023SJohn Marino   rresult = regexec (&r, v1, 0, NULL, 0);
8008e4b17023SJohn Marino   if (rresult == REG_NOMATCH)
8009e4b17023SJohn Marino     fatal_error ("invalid version number %qs", v1);
8010e4b17023SJohn Marino   else if (rresult != 0)
8011e4b17023SJohn Marino     abort ();
8012e4b17023SJohn Marino   rresult = regexec (&r, v2, 0, NULL, 0);
8013e4b17023SJohn Marino   if (rresult == REG_NOMATCH)
8014e4b17023SJohn Marino     fatal_error ("invalid version number %qs", v2);
8015e4b17023SJohn Marino   else if (rresult != 0)
8016e4b17023SJohn Marino     abort ();
8017e4b17023SJohn Marino 
8018e4b17023SJohn Marino   return strverscmp (v1, v2);
8019e4b17023SJohn Marino }
8020e4b17023SJohn Marino 
8021e4b17023SJohn Marino 
8022e4b17023SJohn Marino /* version_compare built-in spec function.
8023e4b17023SJohn Marino 
8024e4b17023SJohn Marino    This takes an argument of the following form:
8025e4b17023SJohn Marino 
8026e4b17023SJohn Marino    <comparison-op> <arg1> [<arg2>] <switch> <result>
8027e4b17023SJohn Marino 
8028e4b17023SJohn Marino    and produces "result" if the comparison evaluates to true,
8029e4b17023SJohn Marino    and nothing if it doesn't.
8030e4b17023SJohn Marino 
8031e4b17023SJohn Marino    The supported <comparison-op> values are:
8032e4b17023SJohn Marino 
8033e4b17023SJohn Marino    >=  true if switch is a later (or same) version than arg1
8034e4b17023SJohn Marino    !>  opposite of >=
8035e4b17023SJohn Marino    <   true if switch is an earlier version than arg1
8036e4b17023SJohn Marino    !<  opposite of <
8037e4b17023SJohn Marino    ><  true if switch is arg1 or later, and earlier than arg2
8038e4b17023SJohn Marino    <>  true if switch is earlier than arg1 or is arg2 or later
8039e4b17023SJohn Marino 
8040e4b17023SJohn Marino    If the switch is not present, the condition is false unless
8041e4b17023SJohn Marino    the first character of the <comparison-op> is '!'.
8042e4b17023SJohn Marino 
8043e4b17023SJohn Marino    For example,
8044e4b17023SJohn Marino    %:version-compare(>= 10.3 mmacosx-version-min= -lmx)
8045e4b17023SJohn Marino    adds -lmx if -mmacosx-version-min=10.3.9 was passed.  */
8046e4b17023SJohn Marino 
8047e4b17023SJohn Marino static const char *
version_compare_spec_function(int argc,const char ** argv)8048e4b17023SJohn Marino version_compare_spec_function (int argc, const char **argv)
8049e4b17023SJohn Marino {
8050e4b17023SJohn Marino   int comp1, comp2;
8051e4b17023SJohn Marino   size_t switch_len;
8052e4b17023SJohn Marino   const char *switch_value = NULL;
8053e4b17023SJohn Marino   int nargs = 1, i;
8054e4b17023SJohn Marino   bool result;
8055e4b17023SJohn Marino 
8056e4b17023SJohn Marino   if (argc < 3)
8057e4b17023SJohn Marino     fatal_error ("too few arguments to %%:version-compare");
8058e4b17023SJohn Marino   if (argv[0][0] == '\0')
8059e4b17023SJohn Marino     abort ();
8060e4b17023SJohn Marino   if ((argv[0][1] == '<' || argv[0][1] == '>') && argv[0][0] != '!')
8061e4b17023SJohn Marino     nargs = 2;
8062e4b17023SJohn Marino   if (argc != nargs + 3)
8063e4b17023SJohn Marino     fatal_error ("too many arguments to %%:version-compare");
8064e4b17023SJohn Marino 
8065e4b17023SJohn Marino   switch_len = strlen (argv[nargs + 1]);
8066e4b17023SJohn Marino   for (i = 0; i < n_switches; i++)
8067e4b17023SJohn Marino     if (!strncmp (switches[i].part1, argv[nargs + 1], switch_len)
8068e4b17023SJohn Marino 	&& check_live_switch (i, switch_len))
8069e4b17023SJohn Marino       switch_value = switches[i].part1 + switch_len;
8070e4b17023SJohn Marino 
8071e4b17023SJohn Marino   if (switch_value == NULL)
8072e4b17023SJohn Marino     comp1 = comp2 = -1;
8073e4b17023SJohn Marino   else
8074e4b17023SJohn Marino     {
8075e4b17023SJohn Marino       comp1 = compare_version_strings (switch_value, argv[1]);
8076e4b17023SJohn Marino       if (nargs == 2)
8077e4b17023SJohn Marino 	comp2 = compare_version_strings (switch_value, argv[2]);
8078e4b17023SJohn Marino       else
8079e4b17023SJohn Marino 	comp2 = -1;  /* This value unused.  */
8080e4b17023SJohn Marino     }
8081e4b17023SJohn Marino 
8082e4b17023SJohn Marino   switch (argv[0][0] << 8 | argv[0][1])
8083e4b17023SJohn Marino     {
8084e4b17023SJohn Marino     case '>' << 8 | '=':
8085e4b17023SJohn Marino       result = comp1 >= 0;
8086e4b17023SJohn Marino       break;
8087e4b17023SJohn Marino     case '!' << 8 | '<':
8088e4b17023SJohn Marino       result = comp1 >= 0 || switch_value == NULL;
8089e4b17023SJohn Marino       break;
8090e4b17023SJohn Marino     case '<' << 8:
8091e4b17023SJohn Marino       result = comp1 < 0;
8092e4b17023SJohn Marino       break;
8093e4b17023SJohn Marino     case '!' << 8 | '>':
8094e4b17023SJohn Marino       result = comp1 < 0 || switch_value == NULL;
8095e4b17023SJohn Marino       break;
8096e4b17023SJohn Marino     case '>' << 8 | '<':
8097e4b17023SJohn Marino       result = comp1 >= 0 && comp2 < 0;
8098e4b17023SJohn Marino       break;
8099e4b17023SJohn Marino     case '<' << 8 | '>':
8100e4b17023SJohn Marino       result = comp1 < 0 || comp2 >= 0;
8101e4b17023SJohn Marino       break;
8102e4b17023SJohn Marino 
8103e4b17023SJohn Marino     default:
8104e4b17023SJohn Marino       fatal_error ("unknown operator %qs in %%:version-compare", argv[0]);
8105e4b17023SJohn Marino     }
8106e4b17023SJohn Marino   if (! result)
8107e4b17023SJohn Marino     return NULL;
8108e4b17023SJohn Marino 
8109e4b17023SJohn Marino   return argv[nargs + 2];
8110e4b17023SJohn Marino }
8111e4b17023SJohn Marino 
8112e4b17023SJohn Marino /* %:include builtin spec function.  This differs from %include in that it
8113e4b17023SJohn Marino    can be nested inside a spec, and thus be conditionalized.  It takes
8114e4b17023SJohn Marino    one argument, the filename, and looks for it in the startfile path.
8115e4b17023SJohn Marino    The result is always NULL, i.e. an empty expansion.  */
8116e4b17023SJohn Marino 
8117e4b17023SJohn Marino static const char *
include_spec_function(int argc,const char ** argv)8118e4b17023SJohn Marino include_spec_function (int argc, const char **argv)
8119e4b17023SJohn Marino {
8120e4b17023SJohn Marino   char *file;
8121e4b17023SJohn Marino 
8122e4b17023SJohn Marino   if (argc != 1)
8123e4b17023SJohn Marino     abort ();
8124e4b17023SJohn Marino 
8125e4b17023SJohn Marino   file = find_a_file (&startfile_prefixes, argv[0], R_OK, true);
8126e4b17023SJohn Marino   read_specs (file ? file : argv[0], FALSE);
8127e4b17023SJohn Marino 
8128e4b17023SJohn Marino   return NULL;
8129e4b17023SJohn Marino }
8130e4b17023SJohn Marino 
8131e4b17023SJohn Marino /* %:find-file spec function.  This function replaces its argument by
8132e4b17023SJohn Marino     the file found thru find_file, that is the -print-file-name gcc
8133e4b17023SJohn Marino     program option. */
8134e4b17023SJohn Marino static const char *
find_file_spec_function(int argc,const char ** argv)8135e4b17023SJohn Marino find_file_spec_function (int argc, const char **argv)
8136e4b17023SJohn Marino {
8137e4b17023SJohn Marino   const char *file;
8138e4b17023SJohn Marino 
8139e4b17023SJohn Marino   if (argc != 1)
8140e4b17023SJohn Marino     abort ();
8141e4b17023SJohn Marino 
8142e4b17023SJohn Marino   file = find_file (argv[0]);
8143e4b17023SJohn Marino   return file;
8144e4b17023SJohn Marino }
8145e4b17023SJohn Marino 
8146e4b17023SJohn Marino 
8147e4b17023SJohn Marino /* %:find-plugindir spec function.  This function replaces its argument
8148e4b17023SJohn Marino     by the -iplugindir=<dir> option.  `dir' is found thru find_file, that
8149e4b17023SJohn Marino     is the -print-file-name gcc program option. */
8150e4b17023SJohn Marino static const char *
find_plugindir_spec_function(int argc,const char ** argv ATTRIBUTE_UNUSED)8151e4b17023SJohn Marino find_plugindir_spec_function (int argc, const char **argv ATTRIBUTE_UNUSED)
8152e4b17023SJohn Marino {
8153e4b17023SJohn Marino   const char *option;
8154e4b17023SJohn Marino 
8155e4b17023SJohn Marino   if (argc != 0)
8156e4b17023SJohn Marino     abort ();
8157e4b17023SJohn Marino 
8158e4b17023SJohn Marino   option = concat ("-iplugindir=", find_file ("plugin"), NULL);
8159e4b17023SJohn Marino   return option;
8160e4b17023SJohn Marino }
8161e4b17023SJohn Marino 
8162e4b17023SJohn Marino 
8163e4b17023SJohn Marino /* %:print-asm-header spec function.  Print a banner to say that the
8164e4b17023SJohn Marino    following output is from the assembler.  */
8165e4b17023SJohn Marino 
8166e4b17023SJohn Marino static const char *
print_asm_header_spec_function(int arg ATTRIBUTE_UNUSED,const char ** argv ATTRIBUTE_UNUSED)8167e4b17023SJohn Marino print_asm_header_spec_function (int arg ATTRIBUTE_UNUSED,
8168e4b17023SJohn Marino 				const char **argv ATTRIBUTE_UNUSED)
8169e4b17023SJohn Marino {
8170e4b17023SJohn Marino   printf (_("Assembler options\n=================\n\n"));
8171e4b17023SJohn Marino   printf (_("Use \"-Wa,OPTION\" to pass \"OPTION\" to the assembler.\n\n"));
8172e4b17023SJohn Marino   fflush (stdout);
8173e4b17023SJohn Marino   return NULL;
8174e4b17023SJohn Marino }
8175e4b17023SJohn Marino 
8176e4b17023SJohn Marino /* Get a random number for -frandom-seed */
8177e4b17023SJohn Marino 
8178e4b17023SJohn Marino static unsigned HOST_WIDE_INT
get_random_number(void)8179e4b17023SJohn Marino get_random_number (void)
8180e4b17023SJohn Marino {
8181e4b17023SJohn Marino   unsigned HOST_WIDE_INT ret = 0;
8182e4b17023SJohn Marino   int fd;
8183e4b17023SJohn Marino 
8184e4b17023SJohn Marino   fd = open ("/dev/urandom", O_RDONLY);
8185e4b17023SJohn Marino   if (fd >= 0)
8186e4b17023SJohn Marino     {
8187e4b17023SJohn Marino       read (fd, &ret, sizeof (HOST_WIDE_INT));
8188e4b17023SJohn Marino       close (fd);
8189e4b17023SJohn Marino       if (ret)
8190e4b17023SJohn Marino         return ret;
8191e4b17023SJohn Marino     }
8192e4b17023SJohn Marino 
8193e4b17023SJohn Marino   /* Get some more or less random data.  */
8194e4b17023SJohn Marino #ifdef HAVE_GETTIMEOFDAY
8195e4b17023SJohn Marino   {
8196e4b17023SJohn Marino     struct timeval tv;
8197e4b17023SJohn Marino 
8198e4b17023SJohn Marino     gettimeofday (&tv, NULL);
8199e4b17023SJohn Marino     ret = tv.tv_sec * 1000 + tv.tv_usec / 1000;
8200e4b17023SJohn Marino   }
8201e4b17023SJohn Marino #else
8202e4b17023SJohn Marino   {
8203e4b17023SJohn Marino     time_t now = time (NULL);
8204e4b17023SJohn Marino 
8205e4b17023SJohn Marino     if (now != (time_t)-1)
8206e4b17023SJohn Marino       ret = (unsigned) now;
8207e4b17023SJohn Marino   }
8208e4b17023SJohn Marino #endif
8209e4b17023SJohn Marino 
8210e4b17023SJohn Marino   return ret ^ getpid();
8211e4b17023SJohn Marino }
8212e4b17023SJohn Marino 
8213e4b17023SJohn Marino /* %:compare-debug-dump-opt spec function.  Save the last argument,
8214e4b17023SJohn Marino    expected to be the last -fdump-final-insns option, or generate a
8215e4b17023SJohn Marino    temporary.  */
8216e4b17023SJohn Marino 
8217e4b17023SJohn Marino static const char *
compare_debug_dump_opt_spec_function(int arg,const char ** argv ATTRIBUTE_UNUSED)8218e4b17023SJohn Marino compare_debug_dump_opt_spec_function (int arg,
8219e4b17023SJohn Marino 				      const char **argv ATTRIBUTE_UNUSED)
8220e4b17023SJohn Marino {
8221e4b17023SJohn Marino   const char *ret;
8222e4b17023SJohn Marino   char *name;
8223e4b17023SJohn Marino   int which;
8224e4b17023SJohn Marino   static char random_seed[HOST_BITS_PER_WIDE_INT / 4 + 3];
8225e4b17023SJohn Marino 
8226e4b17023SJohn Marino   if (arg != 0)
8227e4b17023SJohn Marino     fatal_error ("too many arguments to %%:compare-debug-dump-opt");
8228e4b17023SJohn Marino 
8229e4b17023SJohn Marino   do_spec_2 ("%{fdump-final-insns=*:%*}");
8230e4b17023SJohn Marino   do_spec_1 (" ", 0, NULL);
8231e4b17023SJohn Marino 
8232e4b17023SJohn Marino   if (VEC_length (const_char_p, argbuf) > 0
8233e4b17023SJohn Marino       && strcmp (argv[VEC_length (const_char_p, argbuf) - 1], "."))
8234e4b17023SJohn Marino     {
8235e4b17023SJohn Marino       if (!compare_debug)
8236e4b17023SJohn Marino 	return NULL;
8237e4b17023SJohn Marino 
8238e4b17023SJohn Marino       name = xstrdup (argv[VEC_length (const_char_p, argbuf) - 1]);
8239e4b17023SJohn Marino       ret = NULL;
8240e4b17023SJohn Marino     }
8241e4b17023SJohn Marino   else
8242e4b17023SJohn Marino     {
8243e4b17023SJohn Marino       const char *ext = NULL;
8244e4b17023SJohn Marino 
8245e4b17023SJohn Marino       if (VEC_length (const_char_p, argbuf) > 0)
8246e4b17023SJohn Marino 	{
8247e4b17023SJohn Marino 	  do_spec_2 ("%{o*:%*}%{!o:%{!S:%b%O}%{S:%b.s}}");
8248e4b17023SJohn Marino 	  ext = ".gkd";
8249e4b17023SJohn Marino 	}
8250e4b17023SJohn Marino       else if (!compare_debug)
8251e4b17023SJohn Marino 	return NULL;
8252e4b17023SJohn Marino       else
8253e4b17023SJohn Marino 	do_spec_2 ("%g.gkd");
8254e4b17023SJohn Marino 
8255e4b17023SJohn Marino       do_spec_1 (" ", 0, NULL);
8256e4b17023SJohn Marino 
8257e4b17023SJohn Marino       gcc_assert (VEC_length (const_char_p, argbuf) > 0);
8258e4b17023SJohn Marino 
8259e4b17023SJohn Marino       name = concat (VEC_last (const_char_p, argbuf), ext, NULL);
8260e4b17023SJohn Marino 
8261e4b17023SJohn Marino       ret = concat ("-fdump-final-insns=", name, NULL);
8262e4b17023SJohn Marino     }
8263e4b17023SJohn Marino 
8264e4b17023SJohn Marino   which = compare_debug < 0;
8265e4b17023SJohn Marino   debug_check_temp_file[which] = name;
8266e4b17023SJohn Marino 
8267e4b17023SJohn Marino   if (!which)
8268e4b17023SJohn Marino     {
8269e4b17023SJohn Marino       unsigned HOST_WIDE_INT value = get_random_number ();
8270e4b17023SJohn Marino 
8271e4b17023SJohn Marino       sprintf (random_seed, HOST_WIDE_INT_PRINT_HEX, value);
8272e4b17023SJohn Marino     }
8273e4b17023SJohn Marino 
8274e4b17023SJohn Marino   if (*random_seed)
8275e4b17023SJohn Marino     ret = concat ("%{!frandom-seed=*:-frandom-seed=", random_seed, "} ",
8276e4b17023SJohn Marino 		  ret, NULL);
8277e4b17023SJohn Marino 
8278e4b17023SJohn Marino   if (which)
8279e4b17023SJohn Marino     *random_seed = 0;
8280e4b17023SJohn Marino 
8281e4b17023SJohn Marino   return ret;
8282e4b17023SJohn Marino }
8283e4b17023SJohn Marino 
8284e4b17023SJohn Marino static const char *debug_auxbase_opt;
8285e4b17023SJohn Marino 
8286e4b17023SJohn Marino /* %:compare-debug-self-opt spec function.  Expands to the options
8287e4b17023SJohn Marino     that are to be passed in the second compilation of
8288e4b17023SJohn Marino     compare-debug.  */
8289e4b17023SJohn Marino 
8290e4b17023SJohn Marino static const char *
compare_debug_self_opt_spec_function(int arg,const char ** argv ATTRIBUTE_UNUSED)8291e4b17023SJohn Marino compare_debug_self_opt_spec_function (int arg,
8292e4b17023SJohn Marino 				      const char **argv ATTRIBUTE_UNUSED)
8293e4b17023SJohn Marino {
8294e4b17023SJohn Marino   if (arg != 0)
8295e4b17023SJohn Marino     fatal_error ("too many arguments to %%:compare-debug-self-opt");
8296e4b17023SJohn Marino 
8297e4b17023SJohn Marino   if (compare_debug >= 0)
8298e4b17023SJohn Marino     return NULL;
8299e4b17023SJohn Marino 
8300e4b17023SJohn Marino   do_spec_2 ("%{c|S:%{o*:%*}}");
8301e4b17023SJohn Marino   do_spec_1 (" ", 0, NULL);
8302e4b17023SJohn Marino 
8303e4b17023SJohn Marino   if (VEC_length (const_char_p, argbuf) > 0)
8304e4b17023SJohn Marino     debug_auxbase_opt = concat ("-auxbase-strip ",
8305e4b17023SJohn Marino 				VEC_last (const_char_p, argbuf),
8306e4b17023SJohn Marino 				NULL);
8307e4b17023SJohn Marino   else
8308e4b17023SJohn Marino     debug_auxbase_opt = NULL;
8309e4b17023SJohn Marino 
8310e4b17023SJohn Marino   return concat ("\
8311e4b17023SJohn Marino %<o %<MD %<MMD %<MF* %<MG %<MP %<MQ* %<MT* \
8312e4b17023SJohn Marino %<fdump-final-insns=* -w -S -o %j \
8313e4b17023SJohn Marino %{!fcompare-debug-second:-fcompare-debug-second} \
8314e4b17023SJohn Marino ", compare_debug_opt, NULL);
8315e4b17023SJohn Marino }
8316e4b17023SJohn Marino 
8317e4b17023SJohn Marino /* %:compare-debug-auxbase-opt spec function.  Expands to the auxbase
8318e4b17023SJohn Marino     options that are to be passed in the second compilation of
8319e4b17023SJohn Marino     compare-debug.  It expects, as an argument, the basename of the
8320e4b17023SJohn Marino     current input file name, with the .gk suffix appended to it.  */
8321e4b17023SJohn Marino 
8322e4b17023SJohn Marino static const char *
compare_debug_auxbase_opt_spec_function(int arg,const char ** argv)8323e4b17023SJohn Marino compare_debug_auxbase_opt_spec_function (int arg,
8324e4b17023SJohn Marino 					 const char **argv)
8325e4b17023SJohn Marino {
8326e4b17023SJohn Marino   char *name;
8327e4b17023SJohn Marino   int len;
8328e4b17023SJohn Marino 
8329e4b17023SJohn Marino   if (arg == 0)
8330e4b17023SJohn Marino     fatal_error ("too few arguments to %%:compare-debug-auxbase-opt");
8331e4b17023SJohn Marino 
8332e4b17023SJohn Marino   if (arg != 1)
8333e4b17023SJohn Marino     fatal_error ("too many arguments to %%:compare-debug-auxbase-opt");
8334e4b17023SJohn Marino 
8335e4b17023SJohn Marino   if (compare_debug >= 0)
8336e4b17023SJohn Marino     return NULL;
8337e4b17023SJohn Marino 
8338e4b17023SJohn Marino   len = strlen (argv[0]);
8339e4b17023SJohn Marino   if (len < 3 || strcmp (argv[0] + len - 3, ".gk") != 0)
8340e4b17023SJohn Marino     fatal_error ("argument to %%:compare-debug-auxbase-opt "
8341e4b17023SJohn Marino 		 "does not end in .gk");
8342e4b17023SJohn Marino 
8343e4b17023SJohn Marino   if (debug_auxbase_opt)
8344e4b17023SJohn Marino     return debug_auxbase_opt;
8345e4b17023SJohn Marino 
8346e4b17023SJohn Marino #define OPT "-auxbase "
8347e4b17023SJohn Marino 
8348e4b17023SJohn Marino   len -= 3;
8349e4b17023SJohn Marino   name = (char*) xmalloc (sizeof (OPT) + len);
8350e4b17023SJohn Marino   memcpy (name, OPT, sizeof (OPT) - 1);
8351e4b17023SJohn Marino   memcpy (name + sizeof (OPT) - 1, argv[0], len);
8352e4b17023SJohn Marino   name[sizeof (OPT) - 1 + len] = '\0';
8353e4b17023SJohn Marino 
8354e4b17023SJohn Marino #undef OPT
8355e4b17023SJohn Marino 
8356e4b17023SJohn Marino   return name;
8357e4b17023SJohn Marino }
8358e4b17023SJohn Marino 
8359e4b17023SJohn Marino /* %:pass-through-libs spec function.  Finds all -l options and input
8360e4b17023SJohn Marino    file names in the lib spec passed to it, and makes a list of them
8361e4b17023SJohn Marino    prepended with the plugin option to cause them to be passed through
8362e4b17023SJohn Marino    to the final link after all the new object files have been added.  */
8363e4b17023SJohn Marino 
8364e4b17023SJohn Marino const char *
pass_through_libs_spec_func(int argc,const char ** argv)8365e4b17023SJohn Marino pass_through_libs_spec_func (int argc, const char **argv)
8366e4b17023SJohn Marino {
8367e4b17023SJohn Marino   char *prepended = xstrdup (" ");
8368e4b17023SJohn Marino   int n;
8369e4b17023SJohn Marino   /* Shlemiel the painter's algorithm.  Innately horrible, but at least
8370e4b17023SJohn Marino      we know that there will never be more than a handful of strings to
8371e4b17023SJohn Marino      concat, and it's only once per run, so it's not worth optimising.  */
8372e4b17023SJohn Marino   for (n = 0; n < argc; n++)
8373e4b17023SJohn Marino     {
8374e4b17023SJohn Marino       char *old = prepended;
8375e4b17023SJohn Marino       /* Anything that isn't an option is a full path to an output
8376e4b17023SJohn Marino          file; pass it through if it ends in '.a'.  Among options,
8377e4b17023SJohn Marino 	 pass only -l.  */
8378e4b17023SJohn Marino       if (argv[n][0] == '-' && argv[n][1] == 'l')
8379e4b17023SJohn Marino 	{
8380e4b17023SJohn Marino 	  const char *lopt = argv[n] + 2;
8381e4b17023SJohn Marino 	  /* Handle both joined and non-joined -l options.  If for any
8382e4b17023SJohn Marino 	     reason there's a trailing -l with no joined or following
8383e4b17023SJohn Marino 	     arg just discard it.  */
8384e4b17023SJohn Marino 	  if (!*lopt && ++n >= argc)
8385e4b17023SJohn Marino 	    break;
8386e4b17023SJohn Marino 	  else if (!*lopt)
8387e4b17023SJohn Marino 	    lopt = argv[n];
8388e4b17023SJohn Marino 	  prepended = concat (prepended, "-plugin-opt=-pass-through=-l",
8389e4b17023SJohn Marino 		lopt, " ", NULL);
8390e4b17023SJohn Marino 	}
8391e4b17023SJohn Marino       else if (!strcmp (".a", argv[n] + strlen (argv[n]) - 2))
8392e4b17023SJohn Marino 	{
8393e4b17023SJohn Marino 	  prepended = concat (prepended, "-plugin-opt=-pass-through=",
8394e4b17023SJohn Marino 		argv[n], " ", NULL);
8395e4b17023SJohn Marino 	}
8396e4b17023SJohn Marino       if (prepended != old)
8397e4b17023SJohn Marino 	free (old);
8398e4b17023SJohn Marino     }
8399e4b17023SJohn Marino   return prepended;
8400e4b17023SJohn Marino }
84015ce9237cSJohn Marino 
84025ce9237cSJohn Marino /* Insert backslash before spaces in ORIG (usually a file path), to
84035ce9237cSJohn Marino    avoid being broken by spec parser.
84045ce9237cSJohn Marino 
84055ce9237cSJohn Marino    This function is needed as do_spec_1 treats white space (' ' and '\t')
84065ce9237cSJohn Marino    as the end of an argument. But in case of -plugin /usr/gcc install/xxx.so,
84075ce9237cSJohn Marino    the file name should be treated as a single argument rather than being
84085ce9237cSJohn Marino    broken into multiple. Solution is to insert '\\' before the space in a
84095ce9237cSJohn Marino    file name.
84105ce9237cSJohn Marino 
84115ce9237cSJohn Marino    This function converts and only converts all occurrence of ' '
84125ce9237cSJohn Marino    to '\\' + ' ' and '\t' to '\\' + '\t'.  For example:
84135ce9237cSJohn Marino    "a b"  -> "a\\ b"
84145ce9237cSJohn Marino    "a  b" -> "a\\ \\ b"
84155ce9237cSJohn Marino    "a\tb" -> "a\\\tb"
84165ce9237cSJohn Marino    "a\\ b" -> "a\\\\ b"
84175ce9237cSJohn Marino 
84185ce9237cSJohn Marino    orig: input null-terminating string that was allocated by xalloc. The
84195ce9237cSJohn Marino    memory it points to might be freed in this function. Behavior undefined
84205ce9237cSJohn Marino    if ORIG wasn't xalloced or was freed already at entry.
84215ce9237cSJohn Marino 
84225ce9237cSJohn Marino    Return: ORIG if no conversion needed. Otherwise a newly allocated string
84235ce9237cSJohn Marino    that was converted from ORIG.  */
84245ce9237cSJohn Marino 
84255ce9237cSJohn Marino static char *
convert_white_space(char * orig)84265ce9237cSJohn Marino convert_white_space (char *orig)
84275ce9237cSJohn Marino {
84285ce9237cSJohn Marino   int len, number_of_space = 0;
84295ce9237cSJohn Marino 
84305ce9237cSJohn Marino   for (len = 0; orig[len]; len++)
84315ce9237cSJohn Marino     if (orig[len] == ' ' || orig[len] == '\t') number_of_space++;
84325ce9237cSJohn Marino 
84335ce9237cSJohn Marino   if (number_of_space)
84345ce9237cSJohn Marino     {
84355ce9237cSJohn Marino       char *new_spec = (char *) xmalloc (len + number_of_space + 1);
84365ce9237cSJohn Marino       int j, k;
84375ce9237cSJohn Marino       for (j = 0, k = 0; j <= len; j++, k++)
84385ce9237cSJohn Marino 	{
84395ce9237cSJohn Marino 	  if (orig[j] == ' ' || orig[j] == '\t')
84405ce9237cSJohn Marino 	    new_spec[k++] = '\\';
84415ce9237cSJohn Marino 	  new_spec[k] = orig[j];
84425ce9237cSJohn Marino 	}
84435ce9237cSJohn Marino       free (orig);
84445ce9237cSJohn Marino       return new_spec;
84455ce9237cSJohn Marino   }
84465ce9237cSJohn Marino   else
84475ce9237cSJohn Marino     return orig;
84485ce9237cSJohn Marino }
8449