138fd1498Szrj /* Compiler driver program that can handle many languages.
238fd1498Szrj Copyright (C) 1987-2018 Free Software Foundation, Inc.
338fd1498Szrj
438fd1498Szrj This file is part of GCC.
538fd1498Szrj
638fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
738fd1498Szrj the terms of the GNU General Public License as published by the Free
838fd1498Szrj Software Foundation; either version 3, or (at your option) any later
938fd1498Szrj version.
1038fd1498Szrj
1138fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1238fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1338fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1438fd1498Szrj for more details.
1538fd1498Szrj
1638fd1498Szrj You should have received a copy of the GNU General Public License
1738fd1498Szrj along with GCC; see the file COPYING3. If not see
1838fd1498Szrj <http://www.gnu.org/licenses/>. */
1938fd1498Szrj
2038fd1498Szrj /* This program is the user interface to the C compiler and possibly to
2138fd1498Szrj other compilers. It is used because compilation is a complicated procedure
2238fd1498Szrj which involves running several programs and passing temporary files between
2338fd1498Szrj them, forwarding the users switches to those programs selectively,
2438fd1498Szrj and deleting the temporary files at the end.
2538fd1498Szrj
2638fd1498Szrj CC recognizes how to compile each input file by suffixes in the file names.
2738fd1498Szrj Once it knows which kind of compilation to perform, the procedure for
2838fd1498Szrj compilation is specified by a string called a "spec". */
2938fd1498Szrj
3038fd1498Szrj #include "config.h"
3138fd1498Szrj #include "system.h"
3238fd1498Szrj #include "coretypes.h"
3338fd1498Szrj #include "multilib.h" /* before tm.h */
3438fd1498Szrj #include "tm.h"
3538fd1498Szrj #include "xregex.h"
3638fd1498Szrj #include "obstack.h"
3738fd1498Szrj #include "intl.h"
3838fd1498Szrj #include "prefix.h"
3938fd1498Szrj #include "gcc.h"
4038fd1498Szrj #include "diagnostic.h"
4138fd1498Szrj #include "flags.h"
4238fd1498Szrj #include "opts.h"
4338fd1498Szrj #include "params.h"
4438fd1498Szrj #include "filenames.h"
4538fd1498Szrj #include "spellcheck.h"
4638fd1498Szrj
4738fd1498Szrj
4838fd1498Szrj
4938fd1498Szrj /* Manage the manipulation of env vars.
5038fd1498Szrj
5138fd1498Szrj We poison "getenv" and "putenv", so that all enviroment-handling is
5238fd1498Szrj done through this class. Note that poisoning happens in the
5338fd1498Szrj preprocessor at the identifier level, and doesn't distinguish between
5438fd1498Szrj env.getenv ();
5538fd1498Szrj and
5638fd1498Szrj getenv ();
5738fd1498Szrj Hence we need to use "get" for the accessor method, not "getenv". */
5838fd1498Szrj
5938fd1498Szrj class env_manager
6038fd1498Szrj {
6138fd1498Szrj public:
6238fd1498Szrj void init (bool can_restore, bool debug);
6338fd1498Szrj const char *get (const char *name);
6438fd1498Szrj void xput (const char *string);
6538fd1498Szrj void restore ();
6638fd1498Szrj
6738fd1498Szrj private:
6838fd1498Szrj bool m_can_restore;
6938fd1498Szrj bool m_debug;
7038fd1498Szrj struct kv
7138fd1498Szrj {
7238fd1498Szrj char *m_key;
7338fd1498Szrj char *m_value;
7438fd1498Szrj };
7538fd1498Szrj vec<kv> m_keys;
7638fd1498Szrj
7738fd1498Szrj };
7838fd1498Szrj
7938fd1498Szrj /* The singleton instance of class env_manager. */
8038fd1498Szrj
8138fd1498Szrj static env_manager env;
8238fd1498Szrj
8338fd1498Szrj /* Initializer for class env_manager.
8438fd1498Szrj
8538fd1498Szrj We can't do this as a constructor since we have a statically
8638fd1498Szrj allocated instance ("env" above). */
8738fd1498Szrj
8838fd1498Szrj void
init(bool can_restore,bool debug)8938fd1498Szrj env_manager::init (bool can_restore, bool debug)
9038fd1498Szrj {
9138fd1498Szrj m_can_restore = can_restore;
9238fd1498Szrj m_debug = debug;
9338fd1498Szrj }
9438fd1498Szrj
9538fd1498Szrj /* Get the value of NAME within the environment. Essentially
9638fd1498Szrj a wrapper for ::getenv, but adding logging, and the possibility
9738fd1498Szrj of caching results. */
9838fd1498Szrj
9938fd1498Szrj const char *
get(const char * name)10038fd1498Szrj env_manager::get (const char *name)
10138fd1498Szrj {
10238fd1498Szrj const char *result = ::getenv (name);
10338fd1498Szrj if (m_debug)
10438fd1498Szrj fprintf (stderr, "env_manager::getenv (%s) -> %s\n", name, result);
10538fd1498Szrj return result;
10638fd1498Szrj }
10738fd1498Szrj
10838fd1498Szrj /* Put the given KEY=VALUE entry STRING into the environment.
10938fd1498Szrj If the env_manager was initialized with CAN_RESTORE set, then
11038fd1498Szrj also record the old value of KEY within the environment, so that it
11138fd1498Szrj can be later restored. */
11238fd1498Szrj
11338fd1498Szrj void
xput(const char * string)11438fd1498Szrj env_manager::xput (const char *string)
11538fd1498Szrj {
11638fd1498Szrj if (m_debug)
11738fd1498Szrj fprintf (stderr, "env_manager::xput (%s)\n", string);
11838fd1498Szrj if (verbose_flag)
11938fd1498Szrj fnotice (stderr, "%s\n", string);
12038fd1498Szrj
12138fd1498Szrj if (m_can_restore)
12238fd1498Szrj {
12338fd1498Szrj char *equals = strchr (const_cast <char *> (string), '=');
12438fd1498Szrj gcc_assert (equals);
12538fd1498Szrj
12638fd1498Szrj struct kv kv;
12738fd1498Szrj kv.m_key = xstrndup (string, equals - string);
12838fd1498Szrj const char *cur_value = ::getenv (kv.m_key);
12938fd1498Szrj if (m_debug)
13038fd1498Szrj fprintf (stderr, "saving old value: %s\n",cur_value);
13138fd1498Szrj kv.m_value = cur_value ? xstrdup (cur_value) : NULL;
13238fd1498Szrj m_keys.safe_push (kv);
13338fd1498Szrj }
13438fd1498Szrj
13538fd1498Szrj ::putenv (CONST_CAST (char *, string));
13638fd1498Szrj }
13738fd1498Szrj
13838fd1498Szrj /* Undo any xputenv changes made since last restore.
13938fd1498Szrj Can only be called if the env_manager was initialized with
14038fd1498Szrj CAN_RESTORE enabled. */
14138fd1498Szrj
14238fd1498Szrj void
restore()14338fd1498Szrj env_manager::restore ()
14438fd1498Szrj {
14538fd1498Szrj unsigned int i;
14638fd1498Szrj struct kv *item;
14738fd1498Szrj
14838fd1498Szrj gcc_assert (m_can_restore);
14938fd1498Szrj
15038fd1498Szrj FOR_EACH_VEC_ELT_REVERSE (m_keys, i, item)
15138fd1498Szrj {
15238fd1498Szrj if (m_debug)
15338fd1498Szrj printf ("restoring saved key: %s value: %s\n", item->m_key, item->m_value);
15438fd1498Szrj if (item->m_value)
15538fd1498Szrj ::setenv (item->m_key, item->m_value, 1);
15638fd1498Szrj else
15738fd1498Szrj ::unsetenv (item->m_key);
15838fd1498Szrj free (item->m_key);
15938fd1498Szrj free (item->m_value);
16038fd1498Szrj }
16138fd1498Szrj
16238fd1498Szrj m_keys.truncate (0);
16338fd1498Szrj }
16438fd1498Szrj
16538fd1498Szrj /* Forbid other uses of getenv and putenv. */
16638fd1498Szrj #if (GCC_VERSION >= 3000)
16738fd1498Szrj #pragma GCC poison getenv putenv
16838fd1498Szrj #endif
16938fd1498Szrj
17038fd1498Szrj
17138fd1498Szrj
17238fd1498Szrj /* By default there is no special suffix for target executables. */
17338fd1498Szrj #ifdef TARGET_EXECUTABLE_SUFFIX
17438fd1498Szrj #define HAVE_TARGET_EXECUTABLE_SUFFIX
17538fd1498Szrj #else
17638fd1498Szrj #define TARGET_EXECUTABLE_SUFFIX ""
17738fd1498Szrj #endif
17838fd1498Szrj
17938fd1498Szrj /* By default there is no special suffix for host executables. */
18038fd1498Szrj #ifdef HOST_EXECUTABLE_SUFFIX
18138fd1498Szrj #define HAVE_HOST_EXECUTABLE_SUFFIX
18238fd1498Szrj #else
18338fd1498Szrj #define HOST_EXECUTABLE_SUFFIX ""
18438fd1498Szrj #endif
18538fd1498Szrj
18638fd1498Szrj /* By default, the suffix for target object files is ".o". */
18738fd1498Szrj #ifdef TARGET_OBJECT_SUFFIX
18838fd1498Szrj #define HAVE_TARGET_OBJECT_SUFFIX
18938fd1498Szrj #else
19038fd1498Szrj #define TARGET_OBJECT_SUFFIX ".o"
19138fd1498Szrj #endif
19238fd1498Szrj
19338fd1498Szrj static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
19438fd1498Szrj
19538fd1498Szrj /* Most every one is fine with LIBRARY_PATH. For some, it conflicts. */
19638fd1498Szrj #ifndef LIBRARY_PATH_ENV
19738fd1498Szrj #define LIBRARY_PATH_ENV "LIBRARY_PATH"
19838fd1498Szrj #endif
19938fd1498Szrj
20038fd1498Szrj /* If a stage of compilation returns an exit status >= 1,
20138fd1498Szrj compilation of that file ceases. */
20238fd1498Szrj
20338fd1498Szrj #define MIN_FATAL_STATUS 1
20438fd1498Szrj
20538fd1498Szrj /* Flag set by cppspec.c to 1. */
20638fd1498Szrj int is_cpp_driver;
20738fd1498Szrj
20838fd1498Szrj /* Flag set to nonzero if an @file argument has been supplied to gcc. */
20938fd1498Szrj static bool at_file_supplied;
21038fd1498Szrj
21138fd1498Szrj /* Definition of string containing the arguments given to configure. */
21238fd1498Szrj #include "configargs.h"
21338fd1498Szrj
21438fd1498Szrj /* Flag saying to print the command line options understood by gcc and its
21538fd1498Szrj sub-processes. */
21638fd1498Szrj
21738fd1498Szrj static int print_help_list;
21838fd1498Szrj
21938fd1498Szrj /* Flag saying to print the version of gcc and its sub-processes. */
22038fd1498Szrj
22138fd1498Szrj static int print_version;
22238fd1498Szrj
22338fd1498Szrj /* Flag indicating whether we should ONLY print the command and
22438fd1498Szrj arguments (like verbose_flag) without executing the command.
22538fd1498Szrj Displayed arguments are quoted so that the generated command
22638fd1498Szrj line is suitable for execution. This is intended for use in
22738fd1498Szrj shell scripts to capture the driver-generated command line. */
22838fd1498Szrj static int verbose_only_flag;
22938fd1498Szrj
23038fd1498Szrj /* Flag indicating how to print command line options of sub-processes. */
23138fd1498Szrj
23238fd1498Szrj static int print_subprocess_help;
23338fd1498Szrj
23438fd1498Szrj /* Linker suffix passed to -fuse-ld=... */
23538fd1498Szrj static const char *use_ld;
23638fd1498Szrj
23738fd1498Szrj /* Whether we should report subprocess execution times to a file. */
23838fd1498Szrj
23938fd1498Szrj FILE *report_times_to_file = NULL;
24038fd1498Szrj
24138fd1498Szrj /* Nonzero means place this string before uses of /, so that include
24238fd1498Szrj and library files can be found in an alternate location. */
24338fd1498Szrj
24438fd1498Szrj #ifdef TARGET_SYSTEM_ROOT
24538fd1498Szrj #define DEFAULT_TARGET_SYSTEM_ROOT (TARGET_SYSTEM_ROOT)
24638fd1498Szrj #else
24738fd1498Szrj #define DEFAULT_TARGET_SYSTEM_ROOT (0)
24838fd1498Szrj #endif
24938fd1498Szrj static const char *target_system_root = DEFAULT_TARGET_SYSTEM_ROOT;
25038fd1498Szrj
25138fd1498Szrj /* Nonzero means pass the updated target_system_root to the compiler. */
25238fd1498Szrj
25338fd1498Szrj static int target_system_root_changed;
25438fd1498Szrj
25538fd1498Szrj /* Nonzero means append this string to target_system_root. */
25638fd1498Szrj
25738fd1498Szrj static const char *target_sysroot_suffix = 0;
25838fd1498Szrj
25938fd1498Szrj /* Nonzero means append this string to target_system_root for headers. */
26038fd1498Szrj
26138fd1498Szrj static const char *target_sysroot_hdrs_suffix = 0;
26238fd1498Szrj
26338fd1498Szrj /* Nonzero means write "temp" files in source directory
26438fd1498Szrj and use the source file's name in them, and don't delete them. */
26538fd1498Szrj
26638fd1498Szrj static enum save_temps {
26738fd1498Szrj SAVE_TEMPS_NONE, /* no -save-temps */
26838fd1498Szrj SAVE_TEMPS_CWD, /* -save-temps in current directory */
269*df642abcSzrj SAVE_TEMPS_OBJ, /* -save-temps in object directory */
270*df642abcSzrj SAVE_TEMPS_OBJZ /* -save-temps in object directory with mangling */
27138fd1498Szrj } save_temps_flag;
27238fd1498Szrj
27338fd1498Szrj /* Output file to use to get the object directory for -save-temps=obj */
27438fd1498Szrj static char *save_temps_prefix = 0;
27538fd1498Szrj static size_t save_temps_length = 0;
27638fd1498Szrj
27738fd1498Szrj /* The compiler version. */
27838fd1498Szrj
27938fd1498Szrj static const char *compiler_version;
28038fd1498Szrj
28138fd1498Szrj /* The target version. */
28238fd1498Szrj
28338fd1498Szrj static const char *const spec_version = DEFAULT_TARGET_VERSION;
28438fd1498Szrj
28538fd1498Szrj /* The target machine. */
28638fd1498Szrj
28738fd1498Szrj static const char *spec_machine = DEFAULT_TARGET_MACHINE;
28838fd1498Szrj static const char *spec_host_machine = DEFAULT_REAL_TARGET_MACHINE;
28938fd1498Szrj
29038fd1498Szrj /* List of offload targets. Separated by colon. Empty string for
29138fd1498Szrj -foffload=disable. */
29238fd1498Szrj
29338fd1498Szrj static char *offload_targets = NULL;
29438fd1498Szrj
29538fd1498Szrj /* Nonzero if cross-compiling.
29638fd1498Szrj When -b is used, the value comes from the `specs' file. */
29738fd1498Szrj
29838fd1498Szrj #ifdef CROSS_DIRECTORY_STRUCTURE
29938fd1498Szrj static const char *cross_compile = "1";
30038fd1498Szrj #else
30138fd1498Szrj static const char *cross_compile = "0";
30238fd1498Szrj #endif
30338fd1498Szrj
30438fd1498Szrj /* Greatest exit code of sub-processes that has been encountered up to
30538fd1498Szrj now. */
30638fd1498Szrj static int greatest_status = 1;
30738fd1498Szrj
30838fd1498Szrj /* This is the obstack which we use to allocate many strings. */
30938fd1498Szrj
31038fd1498Szrj static struct obstack obstack;
31138fd1498Szrj
31238fd1498Szrj /* This is the obstack to build an environment variable to pass to
31338fd1498Szrj collect2 that describes all of the relevant switches of what to
31438fd1498Szrj pass the compiler in building the list of pointers to constructors
31538fd1498Szrj and destructors. */
31638fd1498Szrj
31738fd1498Szrj static struct obstack collect_obstack;
31838fd1498Szrj
31938fd1498Szrj /* Forward declaration for prototypes. */
32038fd1498Szrj struct path_prefix;
32138fd1498Szrj struct prefix_list;
32238fd1498Szrj
32338fd1498Szrj static void init_spec (void);
32438fd1498Szrj static void store_arg (const char *, int, int);
32538fd1498Szrj static void insert_wrapper (const char *);
32638fd1498Szrj static char *load_specs (const char *);
32738fd1498Szrj static void read_specs (const char *, bool, bool);
32838fd1498Szrj static void set_spec (const char *, const char *, bool);
32938fd1498Szrj static struct compiler *lookup_compiler (const char *, size_t, const char *);
33038fd1498Szrj static char *build_search_list (const struct path_prefix *, const char *,
33138fd1498Szrj bool, bool);
33238fd1498Szrj static void xputenv (const char *);
33338fd1498Szrj static void putenv_from_prefixes (const struct path_prefix *, const char *,
33438fd1498Szrj bool);
33538fd1498Szrj static int access_check (const char *, int);
33638fd1498Szrj static char *find_a_file (const struct path_prefix *, const char *, int, bool);
33738fd1498Szrj static void add_prefix (struct path_prefix *, const char *, const char *,
33838fd1498Szrj int, int, int);
33938fd1498Szrj static void add_sysrooted_prefix (struct path_prefix *, const char *,
34038fd1498Szrj const char *, int, int, int);
34138fd1498Szrj static char *skip_whitespace (char *);
34238fd1498Szrj static void delete_if_ordinary (const char *);
34338fd1498Szrj static void delete_temp_files (void);
34438fd1498Szrj static void delete_failure_queue (void);
34538fd1498Szrj static void clear_failure_queue (void);
34638fd1498Szrj static int check_live_switch (int, int);
34738fd1498Szrj static const char *handle_braces (const char *);
34838fd1498Szrj static inline bool input_suffix_matches (const char *, const char *);
34938fd1498Szrj static inline bool switch_matches (const char *, const char *, int);
35038fd1498Szrj static inline void mark_matching_switches (const char *, const char *, int);
35138fd1498Szrj static inline void process_marked_switches (void);
35238fd1498Szrj static const char *process_brace_body (const char *, const char *, const char *, int, int);
35338fd1498Szrj static const struct spec_function *lookup_spec_function (const char *);
35438fd1498Szrj static const char *eval_spec_function (const char *, const char *);
35538fd1498Szrj static const char *handle_spec_function (const char *, bool *);
35638fd1498Szrj static char *save_string (const char *, int);
35738fd1498Szrj static void set_collect_gcc_options (void);
35838fd1498Szrj static int do_spec_1 (const char *, int, const char *);
35938fd1498Szrj static int do_spec_2 (const char *);
36038fd1498Szrj static void do_option_spec (const char *, const char *);
36138fd1498Szrj static void do_self_spec (const char *);
36238fd1498Szrj static const char *find_file (const char *);
36338fd1498Szrj static int is_directory (const char *, bool);
36438fd1498Szrj static const char *validate_switches (const char *, bool);
36538fd1498Szrj static void validate_all_switches (void);
36638fd1498Szrj static inline void validate_switches_from_spec (const char *, bool);
36738fd1498Szrj static void give_switch (int, int);
36838fd1498Szrj static int default_arg (const char *, int);
36938fd1498Szrj static void set_multilib_dir (void);
37038fd1498Szrj static void print_multilib_info (void);
37138fd1498Szrj static void perror_with_name (const char *);
37238fd1498Szrj static void display_help (void);
37338fd1498Szrj static void add_preprocessor_option (const char *, int);
37438fd1498Szrj static void add_assembler_option (const char *, int);
37538fd1498Szrj static void add_linker_option (const char *, int);
37638fd1498Szrj static void process_command (unsigned int, struct cl_decoded_option *);
37738fd1498Szrj static int execute (void);
37838fd1498Szrj static void alloc_args (void);
37938fd1498Szrj static void clear_args (void);
38038fd1498Szrj static void fatal_signal (int);
38138fd1498Szrj #if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC)
38238fd1498Szrj static void init_gcc_specs (struct obstack *, const char *, const char *,
38338fd1498Szrj const char *);
38438fd1498Szrj #endif
38538fd1498Szrj #if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
38638fd1498Szrj static const char *convert_filename (const char *, int, int);
38738fd1498Szrj #endif
38838fd1498Szrj
38938fd1498Szrj static void try_generate_repro (const char **argv);
39038fd1498Szrj static const char *getenv_spec_function (int, const char **);
39138fd1498Szrj static const char *if_exists_spec_function (int, const char **);
39238fd1498Szrj static const char *if_exists_else_spec_function (int, const char **);
39338fd1498Szrj static const char *sanitize_spec_function (int, const char **);
39438fd1498Szrj static const char *replace_outfile_spec_function (int, const char **);
39538fd1498Szrj static const char *remove_outfile_spec_function (int, const char **);
39638fd1498Szrj static const char *version_compare_spec_function (int, const char **);
39738fd1498Szrj static const char *include_spec_function (int, const char **);
39838fd1498Szrj static const char *find_file_spec_function (int, const char **);
39938fd1498Szrj static const char *find_plugindir_spec_function (int, const char **);
40038fd1498Szrj static const char *print_asm_header_spec_function (int, const char **);
40138fd1498Szrj static const char *compare_debug_dump_opt_spec_function (int, const char **);
40238fd1498Szrj static const char *compare_debug_self_opt_spec_function (int, const char **);
40338fd1498Szrj static const char *compare_debug_auxbase_opt_spec_function (int, const char **);
40438fd1498Szrj static const char *pass_through_libs_spec_func (int, const char **);
40538fd1498Szrj static const char *replace_extension_spec_func (int, const char **);
40638fd1498Szrj static const char *greater_than_spec_func (int, const char **);
40738fd1498Szrj static const char *debug_level_greater_than_spec_func (int, const char **);
40838fd1498Szrj static char *convert_white_space (char *);
40938fd1498Szrj
41038fd1498Szrj /* The Specs Language
41138fd1498Szrj
41238fd1498Szrj Specs are strings containing lines, each of which (if not blank)
41338fd1498Szrj is made up of a program name, and arguments separated by spaces.
41438fd1498Szrj The program name must be exact and start from root, since no path
41538fd1498Szrj is searched and it is unreliable to depend on the current working directory.
41638fd1498Szrj Redirection of input or output is not supported; the subprograms must
41738fd1498Szrj accept filenames saying what files to read and write.
41838fd1498Szrj
41938fd1498Szrj In addition, the specs can contain %-sequences to substitute variable text
42038fd1498Szrj or for conditional text. Here is a table of all defined %-sequences.
42138fd1498Szrj Note that spaces are not generated automatically around the results of
42238fd1498Szrj expanding these sequences; therefore, you can concatenate them together
42338fd1498Szrj or with constant text in a single argument.
42438fd1498Szrj
42538fd1498Szrj %% substitute one % into the program name or argument.
42638fd1498Szrj %i substitute the name of the input file being processed.
42738fd1498Szrj %b substitute the basename of the input file being processed.
42838fd1498Szrj This is the substring up to (and not including) the last period
42938fd1498Szrj and not including the directory unless -save-temps was specified
43038fd1498Szrj to put temporaries in a different location.
43138fd1498Szrj %B same as %b, but include the file suffix (text after the last period).
43238fd1498Szrj %gSUFFIX
43338fd1498Szrj substitute a file name that has suffix SUFFIX and is chosen
43438fd1498Szrj once per compilation, and mark the argument a la %d. To reduce
43538fd1498Szrj exposure to denial-of-service attacks, the file name is now
43638fd1498Szrj chosen in a way that is hard to predict even when previously
43738fd1498Szrj chosen file names are known. For example, `%g.s ... %g.o ... %g.s'
43838fd1498Szrj might turn into `ccUVUUAU.s ccXYAXZ12.o ccUVUUAU.s'. SUFFIX matches
43938fd1498Szrj the regexp "[.0-9A-Za-z]*%O"; "%O" is treated exactly as if it
44038fd1498Szrj had been pre-processed. Previously, %g was simply substituted
44138fd1498Szrj with a file name chosen once per compilation, without regard
44238fd1498Szrj to any appended suffix (which was therefore treated just like
44338fd1498Szrj ordinary text), making such attacks more likely to succeed.
44438fd1498Szrj %|SUFFIX
44538fd1498Szrj like %g, but if -pipe is in effect, expands simply to "-".
44638fd1498Szrj %mSUFFIX
44738fd1498Szrj like %g, but if -pipe is in effect, expands to nothing. (We have both
44838fd1498Szrj %| and %m to accommodate differences between system assemblers; see
44938fd1498Szrj the AS_NEEDS_DASH_FOR_PIPED_INPUT target macro.)
45038fd1498Szrj %uSUFFIX
45138fd1498Szrj like %g, but generates a new temporary file name even if %uSUFFIX
45238fd1498Szrj was already seen.
45338fd1498Szrj %USUFFIX
45438fd1498Szrj substitutes the last file name generated with %uSUFFIX, generating a
45538fd1498Szrj new one if there is no such last file name. In the absence of any
45638fd1498Szrj %uSUFFIX, this is just like %gSUFFIX, except they don't share
45738fd1498Szrj the same suffix "space", so `%g.s ... %U.s ... %g.s ... %U.s'
45838fd1498Szrj would involve the generation of two distinct file names, one
45938fd1498Szrj for each `%g.s' and another for each `%U.s'. Previously, %U was
46038fd1498Szrj simply substituted with a file name chosen for the previous %u,
46138fd1498Szrj without regard to any appended suffix.
46238fd1498Szrj %jSUFFIX
46338fd1498Szrj substitutes the name of the HOST_BIT_BUCKET, if any, and if it is
46438fd1498Szrj writable, and if save-temps is off; otherwise, substitute the name
46538fd1498Szrj of a temporary file, just like %u. This temporary file is not
46638fd1498Szrj meant for communication between processes, but rather as a junk
46738fd1498Szrj disposal mechanism.
46838fd1498Szrj %.SUFFIX
46938fd1498Szrj substitutes .SUFFIX for the suffixes of a matched switch's args when
47038fd1498Szrj it is subsequently output with %*. SUFFIX is terminated by the next
47138fd1498Szrj space or %.
47238fd1498Szrj %d marks the argument containing or following the %d as a
47338fd1498Szrj temporary file name, so that file will be deleted if GCC exits
47438fd1498Szrj successfully. Unlike %g, this contributes no text to the argument.
47538fd1498Szrj %w marks the argument containing or following the %w as the
47638fd1498Szrj "output file" of this compilation. This puts the argument
47738fd1498Szrj into the sequence of arguments that %o will substitute later.
47838fd1498Szrj %V indicates that this compilation produces no "output file".
47938fd1498Szrj %W{...}
48038fd1498Szrj like %{...} but mark last argument supplied within
48138fd1498Szrj as a file to be deleted on failure.
48238fd1498Szrj %o substitutes the names of all the output files, with spaces
48338fd1498Szrj automatically placed around them. You should write spaces
48438fd1498Szrj around the %o as well or the results are undefined.
48538fd1498Szrj %o is for use in the specs for running the linker.
48638fd1498Szrj Input files whose names have no recognized suffix are not compiled
48738fd1498Szrj at all, but they are included among the output files, so they will
48838fd1498Szrj be linked.
48938fd1498Szrj %O substitutes the suffix for object files. Note that this is
49038fd1498Szrj handled specially when it immediately follows %g, %u, or %U
49138fd1498Szrj (with or without a suffix argument) because of the need for
49238fd1498Szrj those to form complete file names. The handling is such that
49338fd1498Szrj %O is treated exactly as if it had already been substituted,
49438fd1498Szrj except that %g, %u, and %U do not currently support additional
49538fd1498Szrj SUFFIX characters following %O as they would following, for
49638fd1498Szrj example, `.o'.
49738fd1498Szrj %I Substitute any of -iprefix (made from GCC_EXEC_PREFIX), -isysroot
49838fd1498Szrj (made from TARGET_SYSTEM_ROOT), -isystem (made from COMPILER_PATH
49938fd1498Szrj and -B options) and -imultilib as necessary.
50038fd1498Szrj %s current argument is the name of a library or startup file of some sort.
50138fd1498Szrj Search for that file in a standard list of directories
50238fd1498Szrj and substitute the full name found.
50338fd1498Szrj %eSTR Print STR as an error message. STR is terminated by a newline.
50438fd1498Szrj Use this when inconsistent options are detected.
50538fd1498Szrj %nSTR Print STR as a notice. STR is terminated by a newline.
50638fd1498Szrj %x{OPTION} Accumulate an option for %X.
50738fd1498Szrj %X Output the accumulated linker options specified by compilations.
50838fd1498Szrj %Y Output the accumulated assembler options specified by compilations.
50938fd1498Szrj %Z Output the accumulated preprocessor options specified by compilations.
51038fd1498Szrj %a process ASM_SPEC as a spec.
51138fd1498Szrj This allows config.h to specify part of the spec for running as.
51238fd1498Szrj %A process ASM_FINAL_SPEC as a spec. A capital A is actually
51338fd1498Szrj used here. This can be used to run a post-processor after the
51438fd1498Szrj assembler has done its job.
51538fd1498Szrj %D Dump out a -L option for each directory in startfile_prefixes.
51638fd1498Szrj If multilib_dir is set, extra entries are generated with it affixed.
51738fd1498Szrj %l process LINK_SPEC as a spec.
51838fd1498Szrj %L process LIB_SPEC as a spec.
51938fd1498Szrj %M Output multilib_os_dir.
52038fd1498Szrj %G process LIBGCC_SPEC as a spec.
52138fd1498Szrj %R Output the concatenation of target_system_root and
52238fd1498Szrj target_sysroot_suffix.
52338fd1498Szrj %S process STARTFILE_SPEC as a spec. A capital S is actually used here.
52438fd1498Szrj %E process ENDFILE_SPEC as a spec. A capital E is actually used here.
52538fd1498Szrj %C process CPP_SPEC as a spec.
52638fd1498Szrj %1 process CC1_SPEC as a spec.
52738fd1498Szrj %2 process CC1PLUS_SPEC as a spec.
52838fd1498Szrj %* substitute the variable part of a matched option. (See below.)
52938fd1498Szrj Note that each comma in the substituted string is replaced by
53038fd1498Szrj a single space. A space is appended after the last substition
53138fd1498Szrj unless there is more text in current sequence.
53238fd1498Szrj %<S remove all occurrences of -S from the command line.
53338fd1498Szrj Note - this command is position dependent. % commands in the
53438fd1498Szrj spec string before this one will see -S, % commands in the
53538fd1498Szrj spec string after this one will not.
53638fd1498Szrj %>S Similar to "%<S", but keep it in the GCC command line.
53738fd1498Szrj %<S* remove all occurrences of all switches beginning with -S from the
53838fd1498Szrj command line.
53938fd1498Szrj %:function(args)
54038fd1498Szrj Call the named function FUNCTION, passing it ARGS. ARGS is
54138fd1498Szrj first processed as a nested spec string, then split into an
54238fd1498Szrj argument vector in the usual fashion. The function returns
54338fd1498Szrj a string which is processed as if it had appeared literally
54438fd1498Szrj as part of the current spec.
54538fd1498Szrj %{S} substitutes the -S switch, if that switch was given to GCC.
54638fd1498Szrj If that switch was not specified, this substitutes nothing.
54738fd1498Szrj Here S is a metasyntactic variable.
54838fd1498Szrj %{S*} substitutes all the switches specified to GCC whose names start
54938fd1498Szrj with -S. This is used for -o, -I, etc; switches that take
55038fd1498Szrj arguments. GCC considers `-o foo' as being one switch whose
55138fd1498Szrj name starts with `o'. %{o*} would substitute this text,
55238fd1498Szrj including the space; thus, two arguments would be generated.
55338fd1498Szrj %{S*&T*} likewise, but preserve order of S and T options (the order
55438fd1498Szrj of S and T in the spec is not significant). Can be any number
55538fd1498Szrj of ampersand-separated variables; for each the wild card is
55638fd1498Szrj optional. Useful for CPP as %{D*&U*&A*}.
55738fd1498Szrj
55838fd1498Szrj %{S:X} substitutes X, if the -S switch was given to GCC.
55938fd1498Szrj %{!S:X} substitutes X, if the -S switch was NOT given to GCC.
56038fd1498Szrj %{S*:X} substitutes X if one or more switches whose names start
56138fd1498Szrj with -S was given to GCC. Normally X is substituted only
56238fd1498Szrj once, no matter how many such switches appeared. However,
56338fd1498Szrj if %* appears somewhere in X, then X will be substituted
56438fd1498Szrj once for each matching switch, with the %* replaced by the
56538fd1498Szrj part of that switch that matched the '*'. A space will be
56638fd1498Szrj appended after the last substition unless there is more
56738fd1498Szrj text in current sequence.
56838fd1498Szrj %{.S:X} substitutes X, if processing a file with suffix S.
56938fd1498Szrj %{!.S:X} substitutes X, if NOT processing a file with suffix S.
57038fd1498Szrj %{,S:X} substitutes X, if processing a file which will use spec S.
57138fd1498Szrj %{!,S:X} substitutes X, if NOT processing a file which will use spec S.
57238fd1498Szrj
57338fd1498Szrj %{S|T:X} substitutes X if either -S or -T was given to GCC. This may be
57438fd1498Szrj combined with '!', '.', ',', and '*' as above binding stronger
57538fd1498Szrj than the OR.
57638fd1498Szrj If %* appears in X, all of the alternatives must be starred, and
57738fd1498Szrj only the first matching alternative is substituted.
57838fd1498Szrj %{%:function(args):X}
57938fd1498Szrj Call function named FUNCTION with args ARGS. If the function
58038fd1498Szrj returns non-NULL, then X is substituted, if it returns
58138fd1498Szrj NULL, it isn't substituted.
58238fd1498Szrj %{S:X; if S was given to GCC, substitutes X;
58338fd1498Szrj T:Y; else if T was given to GCC, substitutes Y;
58438fd1498Szrj :D} else substitutes D. There can be as many clauses as you need.
58538fd1498Szrj This may be combined with '.', '!', ',', '|', and '*' as above.
58638fd1498Szrj
58738fd1498Szrj %(Spec) processes a specification defined in a specs file as *Spec:
58838fd1498Szrj
58938fd1498Szrj The switch matching text S in a %{S}, %{S:X}, or similar construct can use
59038fd1498Szrj a backslash to ignore the special meaning of the character following it,
59138fd1498Szrj thus allowing literal matching of a character that is otherwise specially
59238fd1498Szrj treated. For example, %{std=iso9899\:1999:X} substitutes X if the
59338fd1498Szrj -std=iso9899:1999 option is given.
59438fd1498Szrj
59538fd1498Szrj The conditional text X in a %{S:X} or similar construct may contain
59638fd1498Szrj other nested % constructs or spaces, or even newlines. They are
59738fd1498Szrj processed as usual, as described above. Trailing white space in X is
59838fd1498Szrj ignored. White space may also appear anywhere on the left side of the
59938fd1498Szrj colon in these constructs, except between . or * and the corresponding
60038fd1498Szrj word.
60138fd1498Szrj
60238fd1498Szrj The -O, -f, -g, -m, and -W switches are handled specifically in these
60338fd1498Szrj constructs. If another value of -O or the negated form of a -f, -m, or
60438fd1498Szrj -W switch is found later in the command line, the earlier switch
60538fd1498Szrj value is ignored, except with {S*} where S is just one letter; this
60638fd1498Szrj passes all matching options.
60738fd1498Szrj
60838fd1498Szrj The character | at the beginning of the predicate text is used to indicate
60938fd1498Szrj that a command should be piped to the following command, but only if -pipe
61038fd1498Szrj is specified.
61138fd1498Szrj
61238fd1498Szrj Note that it is built into GCC which switches take arguments and which
61338fd1498Szrj do not. You might think it would be useful to generalize this to
61438fd1498Szrj allow each compiler's spec to say which switches take arguments. But
61538fd1498Szrj this cannot be done in a consistent fashion. GCC cannot even decide
61638fd1498Szrj which input files have been specified without knowing which switches
61738fd1498Szrj take arguments, and it must know which input files to compile in order
61838fd1498Szrj to tell which compilers to run.
61938fd1498Szrj
62038fd1498Szrj GCC also knows implicitly that arguments starting in `-l' are to be
62138fd1498Szrj treated as compiler output files, and passed to the linker in their
62238fd1498Szrj proper position among the other output files. */
62338fd1498Szrj
62438fd1498Szrj /* Define the macros used for specs %a, %l, %L, %S, %C, %1. */
62538fd1498Szrj
62638fd1498Szrj /* config.h can define ASM_SPEC to provide extra args to the assembler
62738fd1498Szrj or extra switch-translations. */
62838fd1498Szrj #ifndef ASM_SPEC
62938fd1498Szrj #define ASM_SPEC ""
63038fd1498Szrj #endif
63138fd1498Szrj
63238fd1498Szrj /* config.h can define ASM_FINAL_SPEC to run a post processor after
63338fd1498Szrj the assembler has run. */
63438fd1498Szrj #ifndef ASM_FINAL_SPEC
63538fd1498Szrj #define ASM_FINAL_SPEC \
63638fd1498Szrj "%{gsplit-dwarf: \n\
63738fd1498Szrj objcopy --extract-dwo \
63838fd1498Szrj %{c:%{o*:%*}%{!o*:%b%O}}%{!c:%U%O} \
63938fd1498Szrj %{c:%{o*:%:replace-extension(%{o*:%*} .dwo)}%{!o*:%b.dwo}}%{!c:%b.dwo} \n\
64038fd1498Szrj objcopy --strip-dwo \
64138fd1498Szrj %{c:%{o*:%*}%{!o*:%b%O}}%{!c:%U%O} \
64238fd1498Szrj }"
64338fd1498Szrj #endif
64438fd1498Szrj
64538fd1498Szrj /* config.h can define CPP_SPEC to provide extra args to the C preprocessor
64638fd1498Szrj or extra switch-translations. */
64738fd1498Szrj #ifndef CPP_SPEC
64838fd1498Szrj #define CPP_SPEC ""
64938fd1498Szrj #endif
65038fd1498Szrj
65138fd1498Szrj /* config.h can define CC1_SPEC to provide extra args to cc1 and cc1plus
65238fd1498Szrj or extra switch-translations. */
65338fd1498Szrj #ifndef CC1_SPEC
65438fd1498Szrj #define CC1_SPEC ""
65538fd1498Szrj #endif
65638fd1498Szrj
65738fd1498Szrj /* config.h can define CC1PLUS_SPEC to provide extra args to cc1plus
65838fd1498Szrj or extra switch-translations. */
65938fd1498Szrj #ifndef CC1PLUS_SPEC
66038fd1498Szrj #define CC1PLUS_SPEC ""
66138fd1498Szrj #endif
66238fd1498Szrj
66338fd1498Szrj /* config.h can define LINK_SPEC to provide extra args to the linker
66438fd1498Szrj or extra switch-translations. */
66538fd1498Szrj #ifndef LINK_SPEC
66638fd1498Szrj #define LINK_SPEC ""
66738fd1498Szrj #endif
66838fd1498Szrj
66938fd1498Szrj /* config.h can define LIB_SPEC to override the default libraries. */
67038fd1498Szrj #ifndef LIB_SPEC
67138fd1498Szrj #define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
67238fd1498Szrj #endif
67338fd1498Szrj
67438fd1498Szrj /* When using -fsplit-stack we need to wrap pthread_create, in order
67538fd1498Szrj to initialize the stack guard. We always use wrapping, rather than
67638fd1498Szrj shared library ordering, and we keep the wrapper function in
67738fd1498Szrj libgcc. This is not yet a real spec, though it could become one;
67838fd1498Szrj it is currently just stuffed into LINK_SPEC. FIXME: This wrapping
67938fd1498Szrj only works with GNU ld and gold. */
68038fd1498Szrj #ifdef HAVE_GOLD_NON_DEFAULT_SPLIT_STACK
68138fd1498Szrj #define STACK_SPLIT_SPEC " %{fsplit-stack: -fuse-ld=gold --wrap=pthread_create}"
68238fd1498Szrj #else
68338fd1498Szrj #define STACK_SPLIT_SPEC " %{fsplit-stack: --wrap=pthread_create}"
68438fd1498Szrj #endif
68538fd1498Szrj
68638fd1498Szrj #ifndef LIBASAN_SPEC
68738fd1498Szrj #define STATIC_LIBASAN_LIBS \
68838fd1498Szrj " %{static-libasan|static:%:include(libsanitizer.spec)%(link_libasan)}"
68938fd1498Szrj #ifdef LIBASAN_EARLY_SPEC
69038fd1498Szrj #define LIBASAN_SPEC STATIC_LIBASAN_LIBS
69138fd1498Szrj #elif defined(HAVE_LD_STATIC_DYNAMIC)
69238fd1498Szrj #define LIBASAN_SPEC "%{static-libasan:" LD_STATIC_OPTION \
69338fd1498Szrj "} -lasan %{static-libasan:" LD_DYNAMIC_OPTION "}" \
69438fd1498Szrj STATIC_LIBASAN_LIBS
69538fd1498Szrj #else
69638fd1498Szrj #define LIBASAN_SPEC "-lasan" STATIC_LIBASAN_LIBS
69738fd1498Szrj #endif
69838fd1498Szrj #endif
69938fd1498Szrj
70038fd1498Szrj #ifndef LIBASAN_EARLY_SPEC
70138fd1498Szrj #define LIBASAN_EARLY_SPEC ""
70238fd1498Szrj #endif
70338fd1498Szrj
70438fd1498Szrj #ifndef LIBTSAN_SPEC
70538fd1498Szrj #define STATIC_LIBTSAN_LIBS \
70638fd1498Szrj " %{static-libtsan|static:%:include(libsanitizer.spec)%(link_libtsan)}"
70738fd1498Szrj #ifdef LIBTSAN_EARLY_SPEC
70838fd1498Szrj #define LIBTSAN_SPEC STATIC_LIBTSAN_LIBS
70938fd1498Szrj #elif defined(HAVE_LD_STATIC_DYNAMIC)
71038fd1498Szrj #define LIBTSAN_SPEC "%{static-libtsan:" LD_STATIC_OPTION \
71138fd1498Szrj "} -ltsan %{static-libtsan:" LD_DYNAMIC_OPTION "}" \
71238fd1498Szrj STATIC_LIBTSAN_LIBS
71338fd1498Szrj #else
71438fd1498Szrj #define LIBTSAN_SPEC "-ltsan" STATIC_LIBTSAN_LIBS
71538fd1498Szrj #endif
71638fd1498Szrj #endif
71738fd1498Szrj
71838fd1498Szrj #ifndef LIBTSAN_EARLY_SPEC
71938fd1498Szrj #define LIBTSAN_EARLY_SPEC ""
72038fd1498Szrj #endif
72138fd1498Szrj
72238fd1498Szrj #ifndef LIBLSAN_SPEC
72338fd1498Szrj #define STATIC_LIBLSAN_LIBS \
72438fd1498Szrj " %{static-liblsan|static:%:include(libsanitizer.spec)%(link_liblsan)}"
72538fd1498Szrj #ifdef LIBLSAN_EARLY_SPEC
72638fd1498Szrj #define LIBLSAN_SPEC STATIC_LIBLSAN_LIBS
72738fd1498Szrj #elif defined(HAVE_LD_STATIC_DYNAMIC)
72838fd1498Szrj #define LIBLSAN_SPEC "%{static-liblsan:" LD_STATIC_OPTION \
72938fd1498Szrj "} -llsan %{static-liblsan:" LD_DYNAMIC_OPTION "}" \
73038fd1498Szrj STATIC_LIBLSAN_LIBS
73138fd1498Szrj #else
73238fd1498Szrj #define LIBLSAN_SPEC "-llsan" STATIC_LIBLSAN_LIBS
73338fd1498Szrj #endif
73438fd1498Szrj #endif
73538fd1498Szrj
73638fd1498Szrj #ifndef LIBLSAN_EARLY_SPEC
73738fd1498Szrj #define LIBLSAN_EARLY_SPEC ""
73838fd1498Szrj #endif
73938fd1498Szrj
74038fd1498Szrj #ifndef LIBUBSAN_SPEC
74138fd1498Szrj #define STATIC_LIBUBSAN_LIBS \
74238fd1498Szrj " %{static-libubsan|static:%:include(libsanitizer.spec)%(link_libubsan)}"
74338fd1498Szrj #ifdef HAVE_LD_STATIC_DYNAMIC
74438fd1498Szrj #define LIBUBSAN_SPEC "%{static-libubsan:" LD_STATIC_OPTION \
74538fd1498Szrj "} -lubsan %{static-libubsan:" LD_DYNAMIC_OPTION "}" \
74638fd1498Szrj STATIC_LIBUBSAN_LIBS
74738fd1498Szrj #else
74838fd1498Szrj #define LIBUBSAN_SPEC "-lubsan" STATIC_LIBUBSAN_LIBS
74938fd1498Szrj #endif
75038fd1498Szrj #endif
75138fd1498Szrj
75238fd1498Szrj /* Linker options for compressed debug sections. */
75338fd1498Szrj #if HAVE_LD_COMPRESS_DEBUG == 0
75438fd1498Szrj /* No linker support. */
75538fd1498Szrj #define LINK_COMPRESS_DEBUG_SPEC \
75638fd1498Szrj " %{gz*:%e-gz is not supported in this configuration} "
75738fd1498Szrj #elif HAVE_LD_COMPRESS_DEBUG == 1
75838fd1498Szrj /* GNU style on input, GNU ld options. Reject, not useful. */
75938fd1498Szrj #define LINK_COMPRESS_DEBUG_SPEC \
76038fd1498Szrj " %{gz*:%e-gz is not supported in this configuration} "
76138fd1498Szrj #elif HAVE_LD_COMPRESS_DEBUG == 2
76238fd1498Szrj /* GNU style, GNU gold options. */
76338fd1498Szrj #define LINK_COMPRESS_DEBUG_SPEC \
76438fd1498Szrj " %{gz|gz=zlib-gnu:" LD_COMPRESS_DEBUG_OPTION "=zlib}" \
76538fd1498Szrj " %{gz=none:" LD_COMPRESS_DEBUG_OPTION "=none}" \
76638fd1498Szrj " %{gz=zlib:%e-gz=zlib is not supported in this configuration} "
76738fd1498Szrj #elif HAVE_LD_COMPRESS_DEBUG == 3
76838fd1498Szrj /* ELF gABI style. */
76938fd1498Szrj #define LINK_COMPRESS_DEBUG_SPEC \
77038fd1498Szrj " %{gz|gz=zlib:" LD_COMPRESS_DEBUG_OPTION "=zlib}" \
77138fd1498Szrj " %{gz=none:" LD_COMPRESS_DEBUG_OPTION "=none}" \
77238fd1498Szrj " %{gz=zlib-gnu:" LD_COMPRESS_DEBUG_OPTION "=zlib-gnu} "
77338fd1498Szrj #else
77438fd1498Szrj #error Unknown value for HAVE_LD_COMPRESS_DEBUG.
77538fd1498Szrj #endif
77638fd1498Szrj
77738fd1498Szrj /* config.h can define LIBGCC_SPEC to override how and when libgcc.a is
77838fd1498Szrj included. */
77938fd1498Szrj #ifndef LIBGCC_SPEC
78038fd1498Szrj #if defined(REAL_LIBGCC_SPEC)
78138fd1498Szrj #define LIBGCC_SPEC REAL_LIBGCC_SPEC
78238fd1498Szrj #elif defined(LINK_LIBGCC_SPECIAL_1)
78338fd1498Szrj /* Have gcc do the search for libgcc.a. */
78438fd1498Szrj #define LIBGCC_SPEC "libgcc.a%s"
78538fd1498Szrj #else
78638fd1498Szrj #define LIBGCC_SPEC "-lgcc"
78738fd1498Szrj #endif
78838fd1498Szrj #endif
78938fd1498Szrj
79038fd1498Szrj /* config.h can define STARTFILE_SPEC to override the default crt0 files. */
79138fd1498Szrj #ifndef STARTFILE_SPEC
79238fd1498Szrj #define STARTFILE_SPEC \
79338fd1498Szrj "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}"
79438fd1498Szrj #endif
79538fd1498Szrj
79638fd1498Szrj /* config.h can define ENDFILE_SPEC to override the default crtn files. */
79738fd1498Szrj #ifndef ENDFILE_SPEC
79838fd1498Szrj #define ENDFILE_SPEC ""
79938fd1498Szrj #endif
80038fd1498Szrj
80138fd1498Szrj #ifndef LINKER_NAME
80238fd1498Szrj #define LINKER_NAME "collect2"
80338fd1498Szrj #endif
80438fd1498Szrj
80538fd1498Szrj #ifdef HAVE_AS_DEBUG_PREFIX_MAP
80638fd1498Szrj #define ASM_MAP " %{fdebug-prefix-map=*:--debug-prefix-map %*}"
80738fd1498Szrj #else
80838fd1498Szrj #define ASM_MAP ""
80938fd1498Szrj #endif
81038fd1498Szrj
81138fd1498Szrj /* Assembler options for compressed debug sections. */
81238fd1498Szrj #if HAVE_LD_COMPRESS_DEBUG < 2
81338fd1498Szrj /* Reject if the linker cannot write compressed debug sections. */
81438fd1498Szrj #define ASM_COMPRESS_DEBUG_SPEC \
81538fd1498Szrj " %{gz*:%e-gz is not supported in this configuration} "
81638fd1498Szrj #else /* HAVE_LD_COMPRESS_DEBUG >= 2 */
81738fd1498Szrj #if HAVE_AS_COMPRESS_DEBUG == 0
81838fd1498Szrj /* No assembler support. Ignore silently. */
81938fd1498Szrj #define ASM_COMPRESS_DEBUG_SPEC \
82038fd1498Szrj " %{gz*:} "
82138fd1498Szrj #elif HAVE_AS_COMPRESS_DEBUG == 1
82238fd1498Szrj /* GNU style, GNU as options. */
82338fd1498Szrj #define ASM_COMPRESS_DEBUG_SPEC \
82438fd1498Szrj " %{gz|gz=zlib-gnu:" AS_COMPRESS_DEBUG_OPTION "}" \
82538fd1498Szrj " %{gz=none:" AS_NO_COMPRESS_DEBUG_OPTION "}" \
82638fd1498Szrj " %{gz=zlib:%e-gz=zlib is not supported in this configuration} "
82738fd1498Szrj #elif HAVE_AS_COMPRESS_DEBUG == 2
82838fd1498Szrj /* ELF gABI style. */
82938fd1498Szrj #define ASM_COMPRESS_DEBUG_SPEC \
83038fd1498Szrj " %{gz|gz=zlib:" AS_COMPRESS_DEBUG_OPTION "=zlib}" \
83138fd1498Szrj " %{gz=none:" AS_COMPRESS_DEBUG_OPTION "=none}" \
83238fd1498Szrj " %{gz=zlib-gnu:" AS_COMPRESS_DEBUG_OPTION "=zlib-gnu} "
83338fd1498Szrj #else
83438fd1498Szrj #error Unknown value for HAVE_AS_COMPRESS_DEBUG.
83538fd1498Szrj #endif
83638fd1498Szrj #endif /* HAVE_LD_COMPRESS_DEBUG >= 2 */
83738fd1498Szrj
83838fd1498Szrj /* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g'
83938fd1498Szrj to the assembler. */
84038fd1498Szrj #ifndef ASM_DEBUG_SPEC
84138fd1498Szrj # if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \
84238fd1498Szrj && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
84338fd1498Szrj # define ASM_DEBUG_SPEC \
84438fd1498Szrj (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG \
84538fd1498Szrj ? "%{%:debug-level-gt(0):" \
84638fd1498Szrj "%{gdwarf*:--gdwarf2}%{!gdwarf*:%{g*:--gstabs}}}" ASM_MAP \
84738fd1498Szrj : "%{%:debug-level-gt(0):" \
84838fd1498Szrj "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}}" ASM_MAP)
84938fd1498Szrj # else
85038fd1498Szrj # if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
85138fd1498Szrj # define ASM_DEBUG_SPEC "%{g*:%{%:debug-level-gt(0):--gstabs}}" ASM_MAP
85238fd1498Szrj # endif
85338fd1498Szrj # if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG)
85438fd1498Szrj # define ASM_DEBUG_SPEC "%{g*:%{%:debug-level-gt(0):--gdwarf2}}" ASM_MAP
85538fd1498Szrj # endif
85638fd1498Szrj # endif
85738fd1498Szrj #endif
85838fd1498Szrj #ifndef ASM_DEBUG_SPEC
85938fd1498Szrj # define ASM_DEBUG_SPEC ""
86038fd1498Szrj #endif
86138fd1498Szrj
86238fd1498Szrj /* Here is the spec for running the linker, after compiling all files. */
86338fd1498Szrj
86438fd1498Szrj /* This is overridable by the target in case they need to specify the
86538fd1498Szrj -lgcc and -lc order specially, yet not require them to override all
86638fd1498Szrj of LINK_COMMAND_SPEC. */
86738fd1498Szrj #ifndef LINK_GCC_C_SEQUENCE_SPEC
86838fd1498Szrj #define LINK_GCC_C_SEQUENCE_SPEC "%G %L %G"
86938fd1498Szrj #endif
87038fd1498Szrj
87138fd1498Szrj #ifndef LINK_SSP_SPEC
87238fd1498Szrj #ifdef TARGET_LIBC_PROVIDES_SSP
87338fd1498Szrj #define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \
87438fd1498Szrj "|fstack-protector-strong|fstack-protector-explicit:}"
87538fd1498Szrj #else
87638fd1498Szrj #define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \
87738fd1498Szrj "|fstack-protector-strong|fstack-protector-explicit" \
87838fd1498Szrj ":-lssp_nonshared -lssp}"
87938fd1498Szrj #endif
88038fd1498Szrj #endif
88138fd1498Szrj
88238fd1498Szrj #ifdef ENABLE_DEFAULT_PIE
88338fd1498Szrj #define PIE_SPEC "!no-pie"
88438fd1498Szrj #define NO_FPIE1_SPEC "fno-pie"
88538fd1498Szrj #define FPIE1_SPEC NO_FPIE1_SPEC ":;"
88638fd1498Szrj #define NO_FPIE2_SPEC "fno-PIE"
88738fd1498Szrj #define FPIE2_SPEC NO_FPIE2_SPEC ":;"
88838fd1498Szrj #define NO_FPIE_SPEC NO_FPIE1_SPEC "|" NO_FPIE2_SPEC
88938fd1498Szrj #define FPIE_SPEC NO_FPIE_SPEC ":;"
89038fd1498Szrj #define NO_FPIC1_SPEC "fno-pic"
89138fd1498Szrj #define FPIC1_SPEC NO_FPIC1_SPEC ":;"
89238fd1498Szrj #define NO_FPIC2_SPEC "fno-PIC"
89338fd1498Szrj #define FPIC2_SPEC NO_FPIC2_SPEC ":;"
89438fd1498Szrj #define NO_FPIC_SPEC NO_FPIC1_SPEC "|" NO_FPIC2_SPEC
89538fd1498Szrj #define FPIC_SPEC NO_FPIC_SPEC ":;"
89638fd1498Szrj #define NO_FPIE1_AND_FPIC1_SPEC NO_FPIE1_SPEC "|" NO_FPIC1_SPEC
89738fd1498Szrj #define FPIE1_OR_FPIC1_SPEC NO_FPIE1_AND_FPIC1_SPEC ":;"
89838fd1498Szrj #define NO_FPIE2_AND_FPIC2_SPEC NO_FPIE2_SPEC "|" NO_FPIC2_SPEC
89938fd1498Szrj #define FPIE2_OR_FPIC2_SPEC NO_FPIE2_AND_FPIC2_SPEC ":;"
90038fd1498Szrj #define NO_FPIE_AND_FPIC_SPEC NO_FPIE_SPEC "|" NO_FPIC_SPEC
90138fd1498Szrj #define FPIE_OR_FPIC_SPEC NO_FPIE_AND_FPIC_SPEC ":;"
90238fd1498Szrj #else
90338fd1498Szrj #define PIE_SPEC "pie"
90438fd1498Szrj #define FPIE1_SPEC "fpie"
90538fd1498Szrj #define NO_FPIE1_SPEC FPIE1_SPEC ":;"
90638fd1498Szrj #define FPIE2_SPEC "fPIE"
90738fd1498Szrj #define NO_FPIE2_SPEC FPIE2_SPEC ":;"
90838fd1498Szrj #define FPIE_SPEC FPIE1_SPEC "|" FPIE2_SPEC
90938fd1498Szrj #define NO_FPIE_SPEC FPIE_SPEC ":;"
91038fd1498Szrj #define FPIC1_SPEC "fpic"
91138fd1498Szrj #define NO_FPIC1_SPEC FPIC1_SPEC ":;"
91238fd1498Szrj #define FPIC2_SPEC "fPIC"
91338fd1498Szrj #define NO_FPIC2_SPEC FPIC2_SPEC ":;"
91438fd1498Szrj #define FPIC_SPEC FPIC1_SPEC "|" FPIC2_SPEC
91538fd1498Szrj #define NO_FPIC_SPEC FPIC_SPEC ":;"
91638fd1498Szrj #define FPIE1_OR_FPIC1_SPEC FPIE1_SPEC "|" FPIC1_SPEC
91738fd1498Szrj #define NO_FPIE1_AND_FPIC1_SPEC FPIE1_OR_FPIC1_SPEC ":;"
91838fd1498Szrj #define FPIE2_OR_FPIC2_SPEC FPIE2_SPEC "|" FPIC2_SPEC
91938fd1498Szrj #define NO_FPIE2_AND_FPIC2_SPEC FPIE1_OR_FPIC2_SPEC ":;"
92038fd1498Szrj #define FPIE_OR_FPIC_SPEC FPIE_SPEC "|" FPIC_SPEC
92138fd1498Szrj #define NO_FPIE_AND_FPIC_SPEC FPIE_OR_FPIC_SPEC ":;"
92238fd1498Szrj #endif
92338fd1498Szrj
92438fd1498Szrj #ifndef LINK_PIE_SPEC
92538fd1498Szrj #ifdef HAVE_LD_PIE
92638fd1498Szrj #ifndef LD_PIE_SPEC
92738fd1498Szrj #define LD_PIE_SPEC "-pie"
92838fd1498Szrj #endif
92938fd1498Szrj #else
93038fd1498Szrj #define LD_PIE_SPEC ""
93138fd1498Szrj #endif
93238fd1498Szrj #define LINK_PIE_SPEC "%{static|shared|r:;" PIE_SPEC ":" LD_PIE_SPEC "} "
93338fd1498Szrj #endif
93438fd1498Szrj
93538fd1498Szrj #ifndef LINK_BUILDID_SPEC
93638fd1498Szrj # if defined(HAVE_LD_BUILDID) && defined(ENABLE_LD_BUILDID)
93738fd1498Szrj # define LINK_BUILDID_SPEC "%{!r:--build-id} "
93838fd1498Szrj # endif
93938fd1498Szrj #endif
94038fd1498Szrj
94138fd1498Szrj /* Conditional to test whether the LTO plugin is used or not.
94238fd1498Szrj FIXME: For slim LTO we will need to enable plugin unconditionally. This
94338fd1498Szrj still cause problems with PLUGIN_LD != LD and when plugin is built but
94438fd1498Szrj not useable. For GCC 4.6 we don't support slim LTO and thus we can enable
94538fd1498Szrj plugin only when LTO is enabled. We still honor explicit
94638fd1498Szrj -fuse-linker-plugin if the linker used understands -plugin. */
94738fd1498Szrj
94838fd1498Szrj /* The linker has some plugin support. */
94938fd1498Szrj #if HAVE_LTO_PLUGIN > 0
95038fd1498Szrj /* The linker used has full plugin support, use LTO plugin by default. */
95138fd1498Szrj #if HAVE_LTO_PLUGIN == 2
95238fd1498Szrj #define PLUGIN_COND "!fno-use-linker-plugin:%{!fno-lto"
95338fd1498Szrj #define PLUGIN_COND_CLOSE "}"
95438fd1498Szrj #else
95538fd1498Szrj /* The linker used has limited plugin support, use LTO plugin with explicit
95638fd1498Szrj -fuse-linker-plugin. */
95738fd1498Szrj #define PLUGIN_COND "fuse-linker-plugin"
95838fd1498Szrj #define PLUGIN_COND_CLOSE ""
95938fd1498Szrj #endif
96038fd1498Szrj #define LINK_PLUGIN_SPEC \
96138fd1498Szrj "%{" PLUGIN_COND": \
96238fd1498Szrj -plugin %(linker_plugin_file) \
96338fd1498Szrj -plugin-opt=%(lto_wrapper) \
96438fd1498Szrj -plugin-opt=-fresolution=%u.res \
96538fd1498Szrj %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} \
96638fd1498Szrj }" PLUGIN_COND_CLOSE
96738fd1498Szrj #else
96838fd1498Szrj /* The linker used doesn't support -plugin, reject -fuse-linker-plugin. */
96938fd1498Szrj #define LINK_PLUGIN_SPEC "%{fuse-linker-plugin:\
97038fd1498Szrj %e-fuse-linker-plugin is not supported in this configuration}"
97138fd1498Szrj #endif
97238fd1498Szrj
97338fd1498Szrj /* Linker command line options for -fsanitize= early on the command line. */
97438fd1498Szrj #ifndef SANITIZER_EARLY_SPEC
97538fd1498Szrj #define SANITIZER_EARLY_SPEC "\
97638fd1498Szrj %{!nostdlib:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_EARLY_SPEC "} \
97738fd1498Szrj %{%:sanitize(thread):" LIBTSAN_EARLY_SPEC "} \
97838fd1498Szrj %{%:sanitize(leak):" LIBLSAN_EARLY_SPEC "}}}"
97938fd1498Szrj #endif
98038fd1498Szrj
98138fd1498Szrj /* Linker command line options for -fsanitize= late on the command line. */
98238fd1498Szrj #ifndef SANITIZER_SPEC
98338fd1498Szrj #define SANITIZER_SPEC "\
98438fd1498Szrj %{!nostdlib:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_SPEC "\
98538fd1498Szrj %{static:%ecannot specify -static with -fsanitize=address}}\
98638fd1498Szrj %{%:sanitize(thread):" LIBTSAN_SPEC "\
98738fd1498Szrj %{static:%ecannot specify -static with -fsanitize=thread}}\
98838fd1498Szrj %{%:sanitize(undefined):" LIBUBSAN_SPEC "}\
98938fd1498Szrj %{%:sanitize(leak):" LIBLSAN_SPEC "}}}"
99038fd1498Szrj #endif
99138fd1498Szrj
99238fd1498Szrj #ifndef POST_LINK_SPEC
99338fd1498Szrj #define POST_LINK_SPEC ""
99438fd1498Szrj #endif
99538fd1498Szrj
99638fd1498Szrj /* This is the spec to use, once the code for creating the vtable
99738fd1498Szrj verification runtime library, libvtv.so, has been created. Currently
99838fd1498Szrj the vtable verification runtime functions are in libstdc++, so we use
99938fd1498Szrj the spec just below this one. */
100038fd1498Szrj #ifndef VTABLE_VERIFICATION_SPEC
100138fd1498Szrj #if ENABLE_VTABLE_VERIFY
100238fd1498Szrj #define VTABLE_VERIFICATION_SPEC "\
100338fd1498Szrj %{!nostdlib:%{fvtable-verify=std: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end}\
100438fd1498Szrj %{fvtable-verify=preinit: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end}}"
100538fd1498Szrj #else
100638fd1498Szrj #define VTABLE_VERIFICATION_SPEC "\
100738fd1498Szrj %{fvtable-verify=none:} \
100838fd1498Szrj %{fvtable-verify=std: \
100938fd1498Szrj %e-fvtable-verify=std is not supported in this configuration} \
101038fd1498Szrj %{fvtable-verify=preinit: \
101138fd1498Szrj %e-fvtable-verify=preinit is not supported in this configuration}"
101238fd1498Szrj #endif
101338fd1498Szrj #endif
101438fd1498Szrj
101538fd1498Szrj #ifndef CHKP_SPEC
101638fd1498Szrj #define CHKP_SPEC ""
101738fd1498Szrj #endif
101838fd1498Szrj
101938fd1498Szrj /* -u* was put back because both BSD and SysV seem to support it. */
102038fd1498Szrj /* %{static|no-pie|static-pie:} simply prevents an error message:
102138fd1498Szrj 1. If the target machine doesn't handle -static.
102238fd1498Szrj 2. If PIE isn't enabled by default.
102338fd1498Szrj 3. If the target machine doesn't handle -static-pie.
102438fd1498Szrj */
102538fd1498Szrj /* We want %{T*} after %{L*} and %D so that it can be used to specify linker
102638fd1498Szrj scripts which exist in user specified directories, or in standard
102738fd1498Szrj directories. */
102838fd1498Szrj /* We pass any -flto flags on to the linker, which is expected
102938fd1498Szrj to understand them. In practice, this means it had better be collect2. */
103038fd1498Szrj /* %{e*} includes -export-dynamic; see comment in common.opt. */
103138fd1498Szrj #ifndef LINK_COMMAND_SPEC
103238fd1498Szrj #define LINK_COMMAND_SPEC "\
103338fd1498Szrj %{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
103438fd1498Szrj %(linker) " \
103538fd1498Szrj LINK_PLUGIN_SPEC \
103638fd1498Szrj "%{flto|flto=*:%<fcompare-debug*} \
103738fd1498Szrj %{flto} %{fno-lto} %{flto=*} %l " LINK_PIE_SPEC \
103838fd1498Szrj "%{fuse-ld=*:-fuse-ld=%*} " LINK_COMPRESS_DEBUG_SPEC \
103938fd1498Szrj "%X %{o*} %{e*} %{N} %{n} %{r}\
104038fd1498Szrj %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}} \
104138fd1498Szrj %{static|no-pie|static-pie:} %{L*} %(mfwrap) %(link_libgcc) " \
104238fd1498Szrj VTABLE_VERIFICATION_SPEC " " SANITIZER_EARLY_SPEC " %o " CHKP_SPEC " \
104338fd1498Szrj %{fopenacc|fopenmp|%:gt(%{ftree-parallelize-loops=*:%*} 1):\
104438fd1498Szrj %:include(libgomp.spec)%(link_gomp)}\
104538fd1498Szrj %{fgnu-tm:%:include(libitm.spec)%(link_itm)}\
104638fd1498Szrj %(mflib) " STACK_SPLIT_SPEC "\
104738fd1498Szrj %{fprofile-arcs|fprofile-generate*|coverage:-lgcov} " SANITIZER_SPEC " \
104838fd1498Szrj %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
104938fd1498Szrj %{!nostdlib:%{!nostartfiles:%E}} %{T*} \n%(post_link) }}}}}}"
105038fd1498Szrj #endif
105138fd1498Szrj
105238fd1498Szrj #ifndef LINK_LIBGCC_SPEC
105338fd1498Szrj /* Generate -L options for startfile prefix list. */
105438fd1498Szrj # define LINK_LIBGCC_SPEC "%D"
105538fd1498Szrj #endif
105638fd1498Szrj
105738fd1498Szrj #ifndef STARTFILE_PREFIX_SPEC
105838fd1498Szrj # define STARTFILE_PREFIX_SPEC ""
105938fd1498Szrj #endif
106038fd1498Szrj
106138fd1498Szrj #ifndef SYSROOT_SPEC
106238fd1498Szrj # define SYSROOT_SPEC "--sysroot=%R"
106338fd1498Szrj #endif
106438fd1498Szrj
106538fd1498Szrj #ifndef SYSROOT_SUFFIX_SPEC
106638fd1498Szrj # define SYSROOT_SUFFIX_SPEC ""
106738fd1498Szrj #endif
106838fd1498Szrj
106938fd1498Szrj #ifndef SYSROOT_HEADERS_SUFFIX_SPEC
107038fd1498Szrj # define SYSROOT_HEADERS_SUFFIX_SPEC ""
107138fd1498Szrj #endif
107238fd1498Szrj
107338fd1498Szrj static const char *asm_debug = ASM_DEBUG_SPEC;
107438fd1498Szrj static const char *cpp_spec = CPP_SPEC;
107538fd1498Szrj static const char *cc1_spec = CC1_SPEC;
107638fd1498Szrj static const char *cc1plus_spec = CC1PLUS_SPEC;
107738fd1498Szrj static const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC;
107838fd1498Szrj static const char *link_ssp_spec = LINK_SSP_SPEC;
107938fd1498Szrj static const char *asm_spec = ASM_SPEC;
108038fd1498Szrj static const char *asm_final_spec = ASM_FINAL_SPEC;
108138fd1498Szrj static const char *link_spec = LINK_SPEC;
108238fd1498Szrj static const char *lib_spec = LIB_SPEC;
108338fd1498Szrj static const char *link_gomp_spec = "";
108438fd1498Szrj static const char *libgcc_spec = LIBGCC_SPEC;
108538fd1498Szrj static const char *endfile_spec = ENDFILE_SPEC;
108638fd1498Szrj static const char *startfile_spec = STARTFILE_SPEC;
108738fd1498Szrj static const char *linker_name_spec = LINKER_NAME;
108838fd1498Szrj static const char *linker_plugin_file_spec = "";
108938fd1498Szrj static const char *lto_wrapper_spec = "";
109038fd1498Szrj static const char *lto_gcc_spec = "";
109138fd1498Szrj static const char *post_link_spec = POST_LINK_SPEC;
109238fd1498Szrj static const char *link_command_spec = LINK_COMMAND_SPEC;
109338fd1498Szrj static const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
109438fd1498Szrj static const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC;
109538fd1498Szrj static const char *sysroot_spec = SYSROOT_SPEC;
109638fd1498Szrj static const char *sysroot_suffix_spec = SYSROOT_SUFFIX_SPEC;
109738fd1498Szrj static const char *sysroot_hdrs_suffix_spec = SYSROOT_HEADERS_SUFFIX_SPEC;
109838fd1498Szrj static const char *self_spec = "";
109938fd1498Szrj
110038fd1498Szrj /* Standard options to cpp, cc1, and as, to reduce duplication in specs.
110138fd1498Szrj There should be no need to override these in target dependent files,
110238fd1498Szrj but we need to copy them to the specs file so that newer versions
110338fd1498Szrj of the GCC driver can correctly drive older tool chains with the
110438fd1498Szrj appropriate -B options. */
110538fd1498Szrj
110638fd1498Szrj /* When cpplib handles traditional preprocessing, get rid of this, and
110738fd1498Szrj call cc1 (or cc1obj in objc/lang-specs.h) from the main specs so
110838fd1498Szrj that we default the front end language better. */
110938fd1498Szrj static const char *trad_capable_cpp =
111038fd1498Szrj "cc1 -E %{traditional|traditional-cpp:-traditional-cpp}";
111138fd1498Szrj
111238fd1498Szrj /* We don't wrap .d files in %W{} since a missing .d file, and
111338fd1498Szrj therefore no dependency entry, confuses make into thinking a .o
111438fd1498Szrj file that happens to exist is up-to-date. */
111538fd1498Szrj static const char *cpp_unique_options =
111638fd1498Szrj "%{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*&F*} %{P} %I\
111738fd1498Szrj %{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\
111838fd1498Szrj %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\
111938fd1498Szrj %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\
112038fd1498Szrj %{!E:%{!M:%{!MM:%{!MT:%{!MQ:%{MD|MMD:%{o*:-MQ %*}}}}}}}\
112138fd1498Szrj %{remap} %{g3|ggdb3|gstabs3|gxcoff3|gvms3:-dD}\
112238fd1498Szrj %{!iplugindir*:%{fplugin*:%:find-plugindir()}}\
112338fd1498Szrj %{H} %C %{D*&U*&A*} %{i*} %Z %i\
112438fd1498Szrj %{E|M|MM:%W{o*}}";
112538fd1498Szrj
112638fd1498Szrj /* This contains cpp options which are common with cc1_options and are passed
112738fd1498Szrj only when preprocessing only to avoid duplication. We pass the cc1 spec
112838fd1498Szrj options to the preprocessor so that it the cc1 spec may manipulate
112938fd1498Szrj options used to set target flags. Those special target flags settings may
113038fd1498Szrj in turn cause preprocessor symbols to be defined specially. */
113138fd1498Szrj static const char *cpp_options =
113238fd1498Szrj "%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w}\
113338fd1498Szrj %{f*} %{g*:%{%:debug-level-gt(0):%{g*}\
113438fd1498Szrj %{!fno-working-directory:-fworking-directory}}} %{O*}\
113538fd1498Szrj %{undef} %{save-temps*:-fpch-preprocess}";
113638fd1498Szrj
113738fd1498Szrj /* This contains cpp options which are not passed when the preprocessor
113838fd1498Szrj output will be used by another program. */
113938fd1498Szrj static const char *cpp_debug_options = "%{d*}";
114038fd1498Szrj
114138fd1498Szrj /* NB: This is shared amongst all front-ends, except for Ada. */
114238fd1498Szrj static const char *cc1_options =
114338fd1498Szrj "%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
114438fd1498Szrj %{!iplugindir*:%{fplugin*:%:find-plugindir()}}\
114538fd1498Szrj %1 %{!Q:-quiet} %{!dumpbase:-dumpbase %B} %{d*} %{m*} %{aux-info*}\
114638fd1498Szrj %{fcompare-debug-second:%:compare-debug-auxbase-opt(%b)} \
114738fd1498Szrj %{!fcompare-debug-second:%{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}}%{!c:%{!S:-auxbase %b}} \
114838fd1498Szrj %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs}\
114938fd1498Szrj %{v:-version} %{pg:-p} %{p} %{f*} %{undef}\
115038fd1498Szrj %{Qn:-fno-ident} %{Qy:} %{-help:--help}\
115138fd1498Szrj %{-target-help:--target-help}\
115238fd1498Szrj %{-version:--version}\
115338fd1498Szrj %{-help=*:--help=%*}\
115438fd1498Szrj %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\
115538fd1498Szrj %{fsyntax-only:-o %j} %{-param*}\
115638fd1498Szrj %{coverage:-fprofile-arcs -ftest-coverage}\
115738fd1498Szrj %{fprofile-arcs|fprofile-generate*|coverage:\
115838fd1498Szrj %{!fprofile-update=single:\
115938fd1498Szrj %{pthread:-fprofile-update=prefer-atomic}}}";
116038fd1498Szrj
116138fd1498Szrj static const char *asm_options =
116238fd1498Szrj "%{-target-help:%:print-asm-header()} "
116338fd1498Szrj #if HAVE_GNU_AS
116438fd1498Szrj /* If GNU AS is used, then convert -w (no warnings), -I, and -v
116538fd1498Szrj to the assembler equivalents. */
116638fd1498Szrj "%{v} %{w:-W} %{I*} "
116738fd1498Szrj #endif
116838fd1498Szrj ASM_COMPRESS_DEBUG_SPEC
116938fd1498Szrj "%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
117038fd1498Szrj
117138fd1498Szrj static const char *invoke_as =
117238fd1498Szrj #ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
117338fd1498Szrj "%{!fwpa*:\
117438fd1498Szrj %{fcompare-debug=*|fdump-final-insns=*:%:compare-debug-dump-opt()}\
117538fd1498Szrj %{!S:-o %|.s |\n as %(asm_options) %|.s %A }\
117638fd1498Szrj }";
117738fd1498Szrj #else
117838fd1498Szrj "%{!fwpa*:\
117938fd1498Szrj %{fcompare-debug=*|fdump-final-insns=*:%:compare-debug-dump-opt()}\
118038fd1498Szrj %{!S:-o %|.s |\n as %(asm_options) %m.s %A }\
118138fd1498Szrj }";
118238fd1498Szrj #endif
118338fd1498Szrj
118438fd1498Szrj /* Some compilers have limits on line lengths, and the multilib_select
118538fd1498Szrj and/or multilib_matches strings can be very long, so we build them at
118638fd1498Szrj run time. */
118738fd1498Szrj static struct obstack multilib_obstack;
118838fd1498Szrj static const char *multilib_select;
118938fd1498Szrj static const char *multilib_matches;
119038fd1498Szrj static const char *multilib_defaults;
119138fd1498Szrj static const char *multilib_exclusions;
119238fd1498Szrj static const char *multilib_reuse;
119338fd1498Szrj
119438fd1498Szrj /* Check whether a particular argument is a default argument. */
119538fd1498Szrj
119638fd1498Szrj #ifndef MULTILIB_DEFAULTS
119738fd1498Szrj #define MULTILIB_DEFAULTS { "" }
119838fd1498Szrj #endif
119938fd1498Szrj
120038fd1498Szrj static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
120138fd1498Szrj
120238fd1498Szrj #ifndef DRIVER_SELF_SPECS
120338fd1498Szrj #define DRIVER_SELF_SPECS ""
120438fd1498Szrj #endif
120538fd1498Szrj
120638fd1498Szrj /* Linking to libgomp implies pthreads. This is particularly important
120738fd1498Szrj for targets that use different start files and suchlike. */
120838fd1498Szrj #ifndef GOMP_SELF_SPECS
120938fd1498Szrj #define GOMP_SELF_SPECS \
121038fd1498Szrj "%{fopenacc|fopenmp|%:gt(%{ftree-parallelize-loops=*:%*} 1): " \
121138fd1498Szrj "-pthread}"
121238fd1498Szrj #endif
121338fd1498Szrj
121438fd1498Szrj /* Likewise for -fgnu-tm. */
121538fd1498Szrj #ifndef GTM_SELF_SPECS
121638fd1498Szrj #define GTM_SELF_SPECS "%{fgnu-tm: -pthread}"
121738fd1498Szrj #endif
121838fd1498Szrj
121938fd1498Szrj static const char *const driver_self_specs[] = {
122038fd1498Szrj "%{fdump-final-insns:-fdump-final-insns=.} %<fdump-final-insns",
122138fd1498Szrj DRIVER_SELF_SPECS, CONFIGURE_SPECS, GOMP_SELF_SPECS, GTM_SELF_SPECS
122238fd1498Szrj };
122338fd1498Szrj
122438fd1498Szrj #ifndef OPTION_DEFAULT_SPECS
122538fd1498Szrj #define OPTION_DEFAULT_SPECS { "", "" }
122638fd1498Szrj #endif
122738fd1498Szrj
122838fd1498Szrj struct default_spec
122938fd1498Szrj {
123038fd1498Szrj const char *name;
123138fd1498Szrj const char *spec;
123238fd1498Szrj };
123338fd1498Szrj
123438fd1498Szrj static const struct default_spec
123538fd1498Szrj option_default_specs[] = { OPTION_DEFAULT_SPECS };
123638fd1498Szrj
123738fd1498Szrj struct user_specs
123838fd1498Szrj {
123938fd1498Szrj struct user_specs *next;
124038fd1498Szrj const char *filename;
124138fd1498Szrj };
124238fd1498Szrj
124338fd1498Szrj static struct user_specs *user_specs_head, *user_specs_tail;
124438fd1498Szrj
124538fd1498Szrj
124638fd1498Szrj /* Record the mapping from file suffixes for compilation specs. */
124738fd1498Szrj
124838fd1498Szrj struct compiler
124938fd1498Szrj {
125038fd1498Szrj const char *suffix; /* Use this compiler for input files
125138fd1498Szrj whose names end in this suffix. */
125238fd1498Szrj
125338fd1498Szrj const char *spec; /* To use this compiler, run this spec. */
125438fd1498Szrj
125538fd1498Szrj const char *cpp_spec; /* If non-NULL, substitute this spec
125638fd1498Szrj for `%C', rather than the usual
125738fd1498Szrj cpp_spec. */
125838fd1498Szrj int combinable; /* If nonzero, compiler can deal with
125938fd1498Szrj multiple source files at once (IMA). */
126038fd1498Szrj int needs_preprocessing; /* If nonzero, source files need to
126138fd1498Szrj be run through a preprocessor. */
126238fd1498Szrj };
126338fd1498Szrj
126438fd1498Szrj /* Pointer to a vector of `struct compiler' that gives the spec for
126538fd1498Szrj compiling a file, based on its suffix.
126638fd1498Szrj A file that does not end in any of these suffixes will be passed
126738fd1498Szrj unchanged to the loader and nothing else will be done to it.
126838fd1498Szrj
126938fd1498Szrj An entry containing two 0s is used to terminate the vector.
127038fd1498Szrj
127138fd1498Szrj If multiple entries match a file, the last matching one is used. */
127238fd1498Szrj
127338fd1498Szrj static struct compiler *compilers;
127438fd1498Szrj
127538fd1498Szrj /* Number of entries in `compilers', not counting the null terminator. */
127638fd1498Szrj
127738fd1498Szrj static int n_compilers;
127838fd1498Szrj
127938fd1498Szrj /* The default list of file name suffixes and their compilation specs. */
128038fd1498Szrj
128138fd1498Szrj static const struct compiler default_compilers[] =
128238fd1498Szrj {
128338fd1498Szrj /* Add lists of suffixes of known languages here. If those languages
128438fd1498Szrj were not present when we built the driver, we will hit these copies
128538fd1498Szrj and be given a more meaningful error than "file not used since
128638fd1498Szrj linking is not done". */
128738fd1498Szrj {".m", "#Objective-C", 0, 0, 0}, {".mi", "#Objective-C", 0, 0, 0},
128838fd1498Szrj {".mm", "#Objective-C++", 0, 0, 0}, {".M", "#Objective-C++", 0, 0, 0},
128938fd1498Szrj {".mii", "#Objective-C++", 0, 0, 0},
129038fd1498Szrj {".cc", "#C++", 0, 0, 0}, {".cxx", "#C++", 0, 0, 0},
129138fd1498Szrj {".cpp", "#C++", 0, 0, 0}, {".cp", "#C++", 0, 0, 0},
129238fd1498Szrj {".c++", "#C++", 0, 0, 0}, {".C", "#C++", 0, 0, 0},
129338fd1498Szrj {".CPP", "#C++", 0, 0, 0}, {".ii", "#C++", 0, 0, 0},
129438fd1498Szrj {".ads", "#Ada", 0, 0, 0}, {".adb", "#Ada", 0, 0, 0},
129538fd1498Szrj {".f", "#Fortran", 0, 0, 0}, {".F", "#Fortran", 0, 0, 0},
129638fd1498Szrj {".for", "#Fortran", 0, 0, 0}, {".FOR", "#Fortran", 0, 0, 0},
129738fd1498Szrj {".ftn", "#Fortran", 0, 0, 0}, {".FTN", "#Fortran", 0, 0, 0},
129838fd1498Szrj {".fpp", "#Fortran", 0, 0, 0}, {".FPP", "#Fortran", 0, 0, 0},
129938fd1498Szrj {".f90", "#Fortran", 0, 0, 0}, {".F90", "#Fortran", 0, 0, 0},
130038fd1498Szrj {".f95", "#Fortran", 0, 0, 0}, {".F95", "#Fortran", 0, 0, 0},
130138fd1498Szrj {".f03", "#Fortran", 0, 0, 0}, {".F03", "#Fortran", 0, 0, 0},
130238fd1498Szrj {".f08", "#Fortran", 0, 0, 0}, {".F08", "#Fortran", 0, 0, 0},
130338fd1498Szrj {".r", "#Ratfor", 0, 0, 0},
130438fd1498Szrj {".go", "#Go", 0, 1, 0},
130538fd1498Szrj /* Next come the entries for C. */
130638fd1498Szrj {".c", "@c", 0, 0, 1},
130738fd1498Szrj {"@c",
130838fd1498Szrj /* cc1 has an integrated ISO C preprocessor. We should invoke the
130938fd1498Szrj external preprocessor if -save-temps is given. */
131038fd1498Szrj "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
131138fd1498Szrj %{!E:%{!M:%{!MM:\
131238fd1498Szrj %{traditional:\
131338fd1498Szrj %eGNU C no longer supports -traditional without -E}\
131438fd1498Szrj %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
131538fd1498Szrj %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\
131638fd1498Szrj cc1 -fpreprocessed %{save-temps*:%b.i} %{!save-temps*:%g.i} \
131738fd1498Szrj %(cc1_options)}\
131838fd1498Szrj %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\
131938fd1498Szrj cc1 %(cpp_unique_options) %(cc1_options)}}}\
132038fd1498Szrj %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 1},
132138fd1498Szrj {"-",
132238fd1498Szrj "%{!E:%e-E or -x required when input is from standard input}\
132338fd1498Szrj %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 0, 0, 0},
132438fd1498Szrj {".h", "@c-header", 0, 0, 0},
132538fd1498Szrj {"@c-header",
132638fd1498Szrj /* cc1 has an integrated ISO C preprocessor. We should invoke the
132738fd1498Szrj external preprocessor if -save-temps is given. */
132838fd1498Szrj "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
132938fd1498Szrj %{!E:%{!M:%{!MM:\
133038fd1498Szrj %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
133138fd1498Szrj %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\
133238fd1498Szrj cc1 -fpreprocessed %{save-temps*:%b.i} %{!save-temps*:%g.i} \
133338fd1498Szrj %(cc1_options)\
133438fd1498Szrj %{!fsyntax-only:%{!S:-o %g.s} \
133538fd1498Szrj %{!fdump-ada-spec*:%{!o*:--output-pch=%i.gch}\
133638fd1498Szrj %W{o*:--output-pch=%*}}%V}}\
133738fd1498Szrj %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\
133838fd1498Szrj cc1 %(cpp_unique_options) %(cc1_options)\
133938fd1498Szrj %{!fsyntax-only:%{!S:-o %g.s} \
134038fd1498Szrj %{!fdump-ada-spec*:%{!o*:--output-pch=%i.gch}\
134138fd1498Szrj %W{o*:--output-pch=%*}}%V}}}}}}}", 0, 0, 0},
134238fd1498Szrj {".i", "@cpp-output", 0, 0, 0},
134338fd1498Szrj {"@cpp-output",
134438fd1498Szrj "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
134538fd1498Szrj {".s", "@assembler", 0, 0, 0},
134638fd1498Szrj {"@assembler",
134738fd1498Szrj "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0, 0, 0},
134838fd1498Szrj {".sx", "@assembler-with-cpp", 0, 0, 0},
134938fd1498Szrj {".S", "@assembler-with-cpp", 0, 0, 0},
135038fd1498Szrj {"@assembler-with-cpp",
135138fd1498Szrj #ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
135238fd1498Szrj "%(trad_capable_cpp) -lang-asm %(cpp_options) -fno-directives-only\
135338fd1498Szrj %{E|M|MM:%(cpp_debug_options)}\
135438fd1498Szrj %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
135538fd1498Szrj as %(asm_debug) %(asm_options) %|.s %A }}}}"
135638fd1498Szrj #else
135738fd1498Szrj "%(trad_capable_cpp) -lang-asm %(cpp_options) -fno-directives-only\
135838fd1498Szrj %{E|M|MM:%(cpp_debug_options)}\
135938fd1498Szrj %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
136038fd1498Szrj as %(asm_debug) %(asm_options) %m.s %A }}}}"
136138fd1498Szrj #endif
136238fd1498Szrj , 0, 0, 0},
136338fd1498Szrj
136438fd1498Szrj #include "specs.h"
136538fd1498Szrj /* Mark end of table. */
136638fd1498Szrj {0, 0, 0, 0, 0}
136738fd1498Szrj };
136838fd1498Szrj
136938fd1498Szrj /* Number of elements in default_compilers, not counting the terminator. */
137038fd1498Szrj
137138fd1498Szrj static const int n_default_compilers = ARRAY_SIZE (default_compilers) - 1;
137238fd1498Szrj
137338fd1498Szrj typedef char *char_p; /* For DEF_VEC_P. */
137438fd1498Szrj
137538fd1498Szrj /* A vector of options to give to the linker.
137638fd1498Szrj These options are accumulated by %x,
137738fd1498Szrj and substituted into the linker command with %X. */
137838fd1498Szrj static vec<char_p> linker_options;
137938fd1498Szrj
138038fd1498Szrj /* A vector of options to give to the assembler.
138138fd1498Szrj These options are accumulated by -Wa,
138238fd1498Szrj and substituted into the assembler command with %Y. */
138338fd1498Szrj static vec<char_p> assembler_options;
138438fd1498Szrj
138538fd1498Szrj /* A vector of options to give to the preprocessor.
138638fd1498Szrj These options are accumulated by -Wp,
138738fd1498Szrj and substituted into the preprocessor command with %Z. */
138838fd1498Szrj static vec<char_p> preprocessor_options;
138938fd1498Szrj
139038fd1498Szrj static char *
skip_whitespace(char * p)139138fd1498Szrj skip_whitespace (char *p)
139238fd1498Szrj {
139338fd1498Szrj while (1)
139438fd1498Szrj {
139538fd1498Szrj /* A fully-blank line is a delimiter in the SPEC file and shouldn't
139638fd1498Szrj be considered whitespace. */
139738fd1498Szrj if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n')
139838fd1498Szrj return p + 1;
139938fd1498Szrj else if (*p == '\n' || *p == ' ' || *p == '\t')
140038fd1498Szrj p++;
140138fd1498Szrj else if (*p == '#')
140238fd1498Szrj {
140338fd1498Szrj while (*p != '\n')
140438fd1498Szrj p++;
140538fd1498Szrj p++;
140638fd1498Szrj }
140738fd1498Szrj else
140838fd1498Szrj break;
140938fd1498Szrj }
141038fd1498Szrj
141138fd1498Szrj return p;
141238fd1498Szrj }
141338fd1498Szrj /* Structures to keep track of prefixes to try when looking for files. */
141438fd1498Szrj
141538fd1498Szrj struct prefix_list
141638fd1498Szrj {
141738fd1498Szrj const char *prefix; /* String to prepend to the path. */
141838fd1498Szrj struct prefix_list *next; /* Next in linked list. */
141938fd1498Szrj int require_machine_suffix; /* Don't use without machine_suffix. */
142038fd1498Szrj /* 2 means try both machine_suffix and just_machine_suffix. */
142138fd1498Szrj int priority; /* Sort key - priority within list. */
142238fd1498Szrj int os_multilib; /* 1 if OS multilib scheme should be used,
142338fd1498Szrj 0 for GCC multilib scheme. */
142438fd1498Szrj };
142538fd1498Szrj
142638fd1498Szrj struct path_prefix
142738fd1498Szrj {
142838fd1498Szrj struct prefix_list *plist; /* List of prefixes to try */
142938fd1498Szrj int max_len; /* Max length of a prefix in PLIST */
143038fd1498Szrj const char *name; /* Name of this list (used in config stuff) */
143138fd1498Szrj };
143238fd1498Szrj
143338fd1498Szrj /* List of prefixes to try when looking for executables. */
143438fd1498Szrj
143538fd1498Szrj static struct path_prefix exec_prefixes = { 0, 0, "exec" };
143638fd1498Szrj
143738fd1498Szrj /* List of prefixes to try when looking for startup (crt0) files. */
143838fd1498Szrj
143938fd1498Szrj static struct path_prefix startfile_prefixes = { 0, 0, "startfile" };
144038fd1498Szrj
144138fd1498Szrj /* List of prefixes to try when looking for include files. */
144238fd1498Szrj
144338fd1498Szrj static struct path_prefix include_prefixes = { 0, 0, "include" };
144438fd1498Szrj
144538fd1498Szrj /* Suffix to attach to directories searched for commands.
144638fd1498Szrj This looks like `MACHINE/VERSION/'. */
144738fd1498Szrj
144838fd1498Szrj static const char *machine_suffix = 0;
144938fd1498Szrj
145038fd1498Szrj /* Suffix to attach to directories searched for commands.
145138fd1498Szrj This is just `MACHINE/'. */
145238fd1498Szrj
145338fd1498Szrj static const char *just_machine_suffix = 0;
145438fd1498Szrj
145538fd1498Szrj /* Adjusted value of GCC_EXEC_PREFIX envvar. */
145638fd1498Szrj
145738fd1498Szrj static const char *gcc_exec_prefix;
145838fd1498Szrj
145938fd1498Szrj /* Adjusted value of standard_libexec_prefix. */
146038fd1498Szrj
146138fd1498Szrj static const char *gcc_libexec_prefix;
146238fd1498Szrj
146338fd1498Szrj /* Default prefixes to attach to command names. */
146438fd1498Szrj
146538fd1498Szrj #ifndef STANDARD_STARTFILE_PREFIX_1
146638fd1498Szrj #define STANDARD_STARTFILE_PREFIX_1 "/lib/"
146738fd1498Szrj #endif
146838fd1498Szrj #ifndef STANDARD_STARTFILE_PREFIX_2
146938fd1498Szrj #define STANDARD_STARTFILE_PREFIX_2 "/usr/lib/"
147038fd1498Szrj #endif
147138fd1498Szrj
147238fd1498Szrj #ifdef CROSS_DIRECTORY_STRUCTURE /* Don't use these prefixes for a cross compiler. */
147338fd1498Szrj #undef MD_EXEC_PREFIX
147438fd1498Szrj #undef MD_STARTFILE_PREFIX
147538fd1498Szrj #undef MD_STARTFILE_PREFIX_1
147638fd1498Szrj #endif
147738fd1498Szrj
147838fd1498Szrj /* If no prefixes defined, use the null string, which will disable them. */
147938fd1498Szrj #ifndef MD_EXEC_PREFIX
148038fd1498Szrj #define MD_EXEC_PREFIX ""
148138fd1498Szrj #endif
148238fd1498Szrj #ifndef MD_STARTFILE_PREFIX
148338fd1498Szrj #define MD_STARTFILE_PREFIX ""
148438fd1498Szrj #endif
148538fd1498Szrj #ifndef MD_STARTFILE_PREFIX_1
148638fd1498Szrj #define MD_STARTFILE_PREFIX_1 ""
148738fd1498Szrj #endif
148838fd1498Szrj
148938fd1498Szrj /* These directories are locations set at configure-time based on the
149038fd1498Szrj --prefix option provided to configure. Their initializers are
149138fd1498Szrj defined in Makefile.in. These paths are not *directly* used when
149238fd1498Szrj gcc_exec_prefix is set because, in that case, we know where the
149338fd1498Szrj compiler has been installed, and use paths relative to that
149438fd1498Szrj location instead. */
149538fd1498Szrj static const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX;
149638fd1498Szrj static const char *const standard_libexec_prefix = STANDARD_LIBEXEC_PREFIX;
149738fd1498Szrj static const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
149838fd1498Szrj static const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
149938fd1498Szrj
150038fd1498Szrj /* For native compilers, these are well-known paths containing
150138fd1498Szrj components that may be provided by the system. For cross
150238fd1498Szrj compilers, these paths are not used. */
150338fd1498Szrj static const char *md_exec_prefix = MD_EXEC_PREFIX;
150438fd1498Szrj static const char *md_startfile_prefix = MD_STARTFILE_PREFIX;
150538fd1498Szrj static const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
150638fd1498Szrj static const char *const standard_startfile_prefix_1
150738fd1498Szrj = STANDARD_STARTFILE_PREFIX_1;
150838fd1498Szrj static const char *const standard_startfile_prefix_2
150938fd1498Szrj = STANDARD_STARTFILE_PREFIX_2;
151038fd1498Szrj
151138fd1498Szrj /* A relative path to be used in finding the location of tools
151238fd1498Szrj relative to the driver. */
151338fd1498Szrj static const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
151438fd1498Szrj
151538fd1498Szrj /* A prefix to be used when this is an accelerator compiler. */
151638fd1498Szrj static const char *const accel_dir_suffix = ACCEL_DIR_SUFFIX;
151738fd1498Szrj
151838fd1498Szrj /* Subdirectory to use for locating libraries. Set by
151938fd1498Szrj set_multilib_dir based on the compilation options. */
152038fd1498Szrj
152138fd1498Szrj static const char *multilib_dir;
152238fd1498Szrj
152338fd1498Szrj /* Subdirectory to use for locating libraries in OS conventions. Set by
152438fd1498Szrj set_multilib_dir based on the compilation options. */
152538fd1498Szrj
152638fd1498Szrj static const char *multilib_os_dir;
152738fd1498Szrj
152838fd1498Szrj /* Subdirectory to use for locating libraries in multiarch conventions. Set by
152938fd1498Szrj set_multilib_dir based on the compilation options. */
153038fd1498Szrj
153138fd1498Szrj static const char *multiarch_dir;
153238fd1498Szrj
153338fd1498Szrj /* Structure to keep track of the specs that have been defined so far.
153438fd1498Szrj These are accessed using %(specname) in a compiler or link
153538fd1498Szrj spec. */
153638fd1498Szrj
153738fd1498Szrj struct spec_list
153838fd1498Szrj {
153938fd1498Szrj /* The following 2 fields must be first */
154038fd1498Szrj /* to allow EXTRA_SPECS to be initialized */
154138fd1498Szrj const char *name; /* name of the spec. */
154238fd1498Szrj const char *ptr; /* available ptr if no static pointer */
154338fd1498Szrj
154438fd1498Szrj /* The following fields are not initialized */
154538fd1498Szrj /* by EXTRA_SPECS */
154638fd1498Szrj const char **ptr_spec; /* pointer to the spec itself. */
154738fd1498Szrj struct spec_list *next; /* Next spec in linked list. */
154838fd1498Szrj int name_len; /* length of the name */
154938fd1498Szrj bool user_p; /* whether string come from file spec. */
155038fd1498Szrj bool alloc_p; /* whether string was allocated */
155138fd1498Szrj const char *default_ptr; /* The default value of *ptr_spec. */
155238fd1498Szrj };
155338fd1498Szrj
155438fd1498Szrj #define INIT_STATIC_SPEC(NAME,PTR) \
155538fd1498Szrj { NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, false, false, \
155638fd1498Szrj *PTR }
155738fd1498Szrj
155838fd1498Szrj /* List of statically defined specs. */
155938fd1498Szrj static struct spec_list static_specs[] =
156038fd1498Szrj {
156138fd1498Szrj INIT_STATIC_SPEC ("asm", &asm_spec),
156238fd1498Szrj INIT_STATIC_SPEC ("asm_debug", &asm_debug),
156338fd1498Szrj INIT_STATIC_SPEC ("asm_final", &asm_final_spec),
156438fd1498Szrj INIT_STATIC_SPEC ("asm_options", &asm_options),
156538fd1498Szrj INIT_STATIC_SPEC ("invoke_as", &invoke_as),
156638fd1498Szrj INIT_STATIC_SPEC ("cpp", &cpp_spec),
156738fd1498Szrj INIT_STATIC_SPEC ("cpp_options", &cpp_options),
156838fd1498Szrj INIT_STATIC_SPEC ("cpp_debug_options", &cpp_debug_options),
156938fd1498Szrj INIT_STATIC_SPEC ("cpp_unique_options", &cpp_unique_options),
157038fd1498Szrj INIT_STATIC_SPEC ("trad_capable_cpp", &trad_capable_cpp),
157138fd1498Szrj INIT_STATIC_SPEC ("cc1", &cc1_spec),
157238fd1498Szrj INIT_STATIC_SPEC ("cc1_options", &cc1_options),
157338fd1498Szrj INIT_STATIC_SPEC ("cc1plus", &cc1plus_spec),
157438fd1498Szrj INIT_STATIC_SPEC ("link_gcc_c_sequence", &link_gcc_c_sequence_spec),
157538fd1498Szrj INIT_STATIC_SPEC ("link_ssp", &link_ssp_spec),
157638fd1498Szrj INIT_STATIC_SPEC ("endfile", &endfile_spec),
157738fd1498Szrj INIT_STATIC_SPEC ("link", &link_spec),
157838fd1498Szrj INIT_STATIC_SPEC ("lib", &lib_spec),
157938fd1498Szrj INIT_STATIC_SPEC ("link_gomp", &link_gomp_spec),
158038fd1498Szrj INIT_STATIC_SPEC ("libgcc", &libgcc_spec),
158138fd1498Szrj INIT_STATIC_SPEC ("startfile", &startfile_spec),
158238fd1498Szrj INIT_STATIC_SPEC ("cross_compile", &cross_compile),
158338fd1498Szrj INIT_STATIC_SPEC ("version", &compiler_version),
158438fd1498Szrj INIT_STATIC_SPEC ("multilib", &multilib_select),
158538fd1498Szrj INIT_STATIC_SPEC ("multilib_defaults", &multilib_defaults),
158638fd1498Szrj INIT_STATIC_SPEC ("multilib_extra", &multilib_extra),
158738fd1498Szrj INIT_STATIC_SPEC ("multilib_matches", &multilib_matches),
158838fd1498Szrj INIT_STATIC_SPEC ("multilib_exclusions", &multilib_exclusions),
158938fd1498Szrj INIT_STATIC_SPEC ("multilib_options", &multilib_options),
159038fd1498Szrj INIT_STATIC_SPEC ("multilib_reuse", &multilib_reuse),
159138fd1498Szrj INIT_STATIC_SPEC ("linker", &linker_name_spec),
159238fd1498Szrj INIT_STATIC_SPEC ("linker_plugin_file", &linker_plugin_file_spec),
159338fd1498Szrj INIT_STATIC_SPEC ("lto_wrapper", <o_wrapper_spec),
159438fd1498Szrj INIT_STATIC_SPEC ("lto_gcc", <o_gcc_spec),
159538fd1498Szrj INIT_STATIC_SPEC ("post_link", &post_link_spec),
159638fd1498Szrj INIT_STATIC_SPEC ("link_libgcc", &link_libgcc_spec),
159738fd1498Szrj INIT_STATIC_SPEC ("md_exec_prefix", &md_exec_prefix),
159838fd1498Szrj INIT_STATIC_SPEC ("md_startfile_prefix", &md_startfile_prefix),
159938fd1498Szrj INIT_STATIC_SPEC ("md_startfile_prefix_1", &md_startfile_prefix_1),
160038fd1498Szrj INIT_STATIC_SPEC ("startfile_prefix_spec", &startfile_prefix_spec),
160138fd1498Szrj INIT_STATIC_SPEC ("sysroot_spec", &sysroot_spec),
160238fd1498Szrj INIT_STATIC_SPEC ("sysroot_suffix_spec", &sysroot_suffix_spec),
160338fd1498Szrj INIT_STATIC_SPEC ("sysroot_hdrs_suffix_spec", &sysroot_hdrs_suffix_spec),
160438fd1498Szrj INIT_STATIC_SPEC ("self_spec", &self_spec),
160538fd1498Szrj };
160638fd1498Szrj
160738fd1498Szrj #ifdef EXTRA_SPECS /* additional specs needed */
160838fd1498Szrj /* Structure to keep track of just the first two args of a spec_list.
160938fd1498Szrj That is all that the EXTRA_SPECS macro gives us. */
161038fd1498Szrj struct spec_list_1
161138fd1498Szrj {
161238fd1498Szrj const char *const name;
161338fd1498Szrj const char *const ptr;
161438fd1498Szrj };
161538fd1498Szrj
161638fd1498Szrj static const struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
161738fd1498Szrj static struct spec_list *extra_specs = (struct spec_list *) 0;
161838fd1498Szrj #endif
161938fd1498Szrj
162038fd1498Szrj /* List of dynamically allocates specs that have been defined so far. */
162138fd1498Szrj
162238fd1498Szrj static struct spec_list *specs = (struct spec_list *) 0;
162338fd1498Szrj
162438fd1498Szrj /* List of static spec functions. */
162538fd1498Szrj
162638fd1498Szrj static const struct spec_function static_spec_functions[] =
162738fd1498Szrj {
162838fd1498Szrj { "getenv", getenv_spec_function },
162938fd1498Szrj { "if-exists", if_exists_spec_function },
163038fd1498Szrj { "if-exists-else", if_exists_else_spec_function },
163138fd1498Szrj { "sanitize", sanitize_spec_function },
163238fd1498Szrj { "replace-outfile", replace_outfile_spec_function },
163338fd1498Szrj { "remove-outfile", remove_outfile_spec_function },
163438fd1498Szrj { "version-compare", version_compare_spec_function },
163538fd1498Szrj { "include", include_spec_function },
163638fd1498Szrj { "find-file", find_file_spec_function },
163738fd1498Szrj { "find-plugindir", find_plugindir_spec_function },
163838fd1498Szrj { "print-asm-header", print_asm_header_spec_function },
163938fd1498Szrj { "compare-debug-dump-opt", compare_debug_dump_opt_spec_function },
164038fd1498Szrj { "compare-debug-self-opt", compare_debug_self_opt_spec_function },
164138fd1498Szrj { "compare-debug-auxbase-opt", compare_debug_auxbase_opt_spec_function },
164238fd1498Szrj { "pass-through-libs", pass_through_libs_spec_func },
164338fd1498Szrj { "replace-extension", replace_extension_spec_func },
164438fd1498Szrj { "gt", greater_than_spec_func },
164538fd1498Szrj { "debug-level-gt", debug_level_greater_than_spec_func },
164638fd1498Szrj #ifdef EXTRA_SPEC_FUNCTIONS
164738fd1498Szrj EXTRA_SPEC_FUNCTIONS
164838fd1498Szrj #endif
164938fd1498Szrj { 0, 0 }
165038fd1498Szrj };
165138fd1498Szrj
165238fd1498Szrj static int processing_spec_function;
165338fd1498Szrj
165438fd1498Szrj /* Add appropriate libgcc specs to OBSTACK, taking into account
165538fd1498Szrj various permutations of -shared-libgcc, -shared, and such. */
165638fd1498Szrj
165738fd1498Szrj #if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC)
165838fd1498Szrj
165938fd1498Szrj #ifndef USE_LD_AS_NEEDED
166038fd1498Szrj #define USE_LD_AS_NEEDED 0
166138fd1498Szrj #endif
166238fd1498Szrj
166338fd1498Szrj static void
init_gcc_specs(struct obstack * obstack,const char * shared_name,const char * static_name,const char * eh_name)166438fd1498Szrj init_gcc_specs (struct obstack *obstack, const char *shared_name,
166538fd1498Szrj const char *static_name, const char *eh_name)
166638fd1498Szrj {
166738fd1498Szrj char *buf;
166838fd1498Szrj
166938fd1498Szrj #if USE_LD_AS_NEEDED
167038fd1498Szrj buf = concat ("%{static|static-libgcc|static-pie:", static_name, " ", eh_name, "}"
167138fd1498Szrj "%{!static:%{!static-libgcc:%{!static-pie:"
167238fd1498Szrj "%{!shared-libgcc:",
167338fd1498Szrj static_name, " " LD_AS_NEEDED_OPTION " ",
167438fd1498Szrj shared_name, " " LD_NO_AS_NEEDED_OPTION
167538fd1498Szrj "}"
167638fd1498Szrj "%{shared-libgcc:",
167738fd1498Szrj shared_name, "%{!shared: ", static_name, "}"
167838fd1498Szrj "}}"
167938fd1498Szrj #else
168038fd1498Szrj buf = concat ("%{static|static-libgcc:", static_name, " ", eh_name, "}"
168138fd1498Szrj "%{!static:%{!static-libgcc:"
168238fd1498Szrj "%{!shared:"
168338fd1498Szrj "%{!shared-libgcc:", static_name, " ", eh_name, "}"
168438fd1498Szrj "%{shared-libgcc:", shared_name, " ", static_name, "}"
168538fd1498Szrj "}"
168638fd1498Szrj #ifdef LINK_EH_SPEC
168738fd1498Szrj "%{shared:"
168838fd1498Szrj "%{shared-libgcc:", shared_name, "}"
168938fd1498Szrj "%{!shared-libgcc:", static_name, "}"
169038fd1498Szrj "}"
169138fd1498Szrj #else
169238fd1498Szrj "%{shared:", shared_name, "}"
169338fd1498Szrj #endif
169438fd1498Szrj #endif
169538fd1498Szrj "}}", NULL);
169638fd1498Szrj
169738fd1498Szrj obstack_grow (obstack, buf, strlen (buf));
169838fd1498Szrj free (buf);
169938fd1498Szrj }
170038fd1498Szrj #endif /* ENABLE_SHARED_LIBGCC */
170138fd1498Szrj
170238fd1498Szrj /* Initialize the specs lookup routines. */
170338fd1498Szrj
170438fd1498Szrj static void
init_spec(void)170538fd1498Szrj init_spec (void)
170638fd1498Szrj {
170738fd1498Szrj struct spec_list *next = (struct spec_list *) 0;
170838fd1498Szrj struct spec_list *sl = (struct spec_list *) 0;
170938fd1498Szrj int i;
171038fd1498Szrj
171138fd1498Szrj if (specs)
171238fd1498Szrj return; /* Already initialized. */
171338fd1498Szrj
171438fd1498Szrj if (verbose_flag)
171538fd1498Szrj fnotice (stderr, "Using built-in specs.\n");
171638fd1498Szrj
171738fd1498Szrj #ifdef EXTRA_SPECS
171838fd1498Szrj extra_specs = XCNEWVEC (struct spec_list, ARRAY_SIZE (extra_specs_1));
171938fd1498Szrj
172038fd1498Szrj for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--)
172138fd1498Szrj {
172238fd1498Szrj sl = &extra_specs[i];
172338fd1498Szrj sl->name = extra_specs_1[i].name;
172438fd1498Szrj sl->ptr = extra_specs_1[i].ptr;
172538fd1498Szrj sl->next = next;
172638fd1498Szrj sl->name_len = strlen (sl->name);
172738fd1498Szrj sl->ptr_spec = &sl->ptr;
172838fd1498Szrj gcc_assert (sl->ptr_spec != NULL);
172938fd1498Szrj sl->default_ptr = sl->ptr;
173038fd1498Szrj next = sl;
173138fd1498Szrj }
173238fd1498Szrj #endif
173338fd1498Szrj
173438fd1498Szrj for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
173538fd1498Szrj {
173638fd1498Szrj sl = &static_specs[i];
173738fd1498Szrj sl->next = next;
173838fd1498Szrj next = sl;
173938fd1498Szrj }
174038fd1498Szrj
174138fd1498Szrj #if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC)
174238fd1498Szrj /* ??? If neither -shared-libgcc nor --static-libgcc was
174338fd1498Szrj seen, then we should be making an educated guess. Some proposed
174438fd1498Szrj heuristics for ELF include:
174538fd1498Szrj
174638fd1498Szrj (1) If "-Wl,--export-dynamic", then it's a fair bet that the
174738fd1498Szrj program will be doing dynamic loading, which will likely
174838fd1498Szrj need the shared libgcc.
174938fd1498Szrj
175038fd1498Szrj (2) If "-ldl", then it's also a fair bet that we're doing
175138fd1498Szrj dynamic loading.
175238fd1498Szrj
175338fd1498Szrj (3) For each ET_DYN we're linking against (either through -lfoo
175438fd1498Szrj or /some/path/foo.so), check to see whether it or one of
175538fd1498Szrj its dependencies depends on a shared libgcc.
175638fd1498Szrj
175738fd1498Szrj (4) If "-shared"
175838fd1498Szrj
175938fd1498Szrj If the runtime is fixed to look for program headers instead
176038fd1498Szrj of calling __register_frame_info at all, for each object,
176138fd1498Szrj use the shared libgcc if any EH symbol referenced.
176238fd1498Szrj
176338fd1498Szrj If crtstuff is fixed to not invoke __register_frame_info
176438fd1498Szrj automatically, for each object, use the shared libgcc if
176538fd1498Szrj any non-empty unwind section found.
176638fd1498Szrj
176738fd1498Szrj Doing any of this probably requires invoking an external program to
176838fd1498Szrj do the actual object file scanning. */
176938fd1498Szrj {
177038fd1498Szrj const char *p = libgcc_spec;
177138fd1498Szrj int in_sep = 1;
177238fd1498Szrj
177338fd1498Szrj /* Transform the extant libgcc_spec into one that uses the shared libgcc
177438fd1498Szrj when given the proper command line arguments. */
177538fd1498Szrj while (*p)
177638fd1498Szrj {
177738fd1498Szrj if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0)
177838fd1498Szrj {
177938fd1498Szrj init_gcc_specs (&obstack,
178038fd1498Szrj "-lgcc_s"
178138fd1498Szrj #ifdef USE_LIBUNWIND_EXCEPTIONS
178238fd1498Szrj " -lunwind"
178338fd1498Szrj #endif
178438fd1498Szrj ,
178538fd1498Szrj "-lgcc",
178638fd1498Szrj "-lgcc_eh"
178738fd1498Szrj #ifdef USE_LIBUNWIND_EXCEPTIONS
178838fd1498Szrj # ifdef HAVE_LD_STATIC_DYNAMIC
178938fd1498Szrj " %{!static:%{!static-pie:" LD_STATIC_OPTION "}} -lunwind"
179038fd1498Szrj " %{!static:%{!static-pie:" LD_DYNAMIC_OPTION "}}"
179138fd1498Szrj # else
179238fd1498Szrj " -lunwind"
179338fd1498Szrj # endif
179438fd1498Szrj #endif
179538fd1498Szrj );
179638fd1498Szrj
179738fd1498Szrj p += 5;
179838fd1498Szrj in_sep = 0;
179938fd1498Szrj }
180038fd1498Szrj else if (in_sep && *p == 'l' && strncmp (p, "libgcc.a%s", 10) == 0)
180138fd1498Szrj {
180238fd1498Szrj /* Ug. We don't know shared library extensions. Hope that
180338fd1498Szrj systems that use this form don't do shared libraries. */
180438fd1498Szrj init_gcc_specs (&obstack,
180538fd1498Szrj "-lgcc_s",
180638fd1498Szrj "libgcc.a%s",
180738fd1498Szrj "libgcc_eh.a%s"
180838fd1498Szrj #ifdef USE_LIBUNWIND_EXCEPTIONS
180938fd1498Szrj " -lunwind"
181038fd1498Szrj #endif
181138fd1498Szrj );
181238fd1498Szrj p += 10;
181338fd1498Szrj in_sep = 0;
181438fd1498Szrj }
181538fd1498Szrj else
181638fd1498Szrj {
181738fd1498Szrj obstack_1grow (&obstack, *p);
181838fd1498Szrj in_sep = (*p == ' ');
181938fd1498Szrj p += 1;
182038fd1498Szrj }
182138fd1498Szrj }
182238fd1498Szrj
182338fd1498Szrj obstack_1grow (&obstack, '\0');
182438fd1498Szrj libgcc_spec = XOBFINISH (&obstack, const char *);
182538fd1498Szrj }
182638fd1498Szrj #endif
182738fd1498Szrj #ifdef USE_AS_TRADITIONAL_FORMAT
182838fd1498Szrj /* Prepend "--traditional-format" to whatever asm_spec we had before. */
182938fd1498Szrj {
183038fd1498Szrj static const char tf[] = "--traditional-format ";
183138fd1498Szrj obstack_grow (&obstack, tf, sizeof (tf) - 1);
183238fd1498Szrj obstack_grow0 (&obstack, asm_spec, strlen (asm_spec));
183338fd1498Szrj asm_spec = XOBFINISH (&obstack, const char *);
183438fd1498Szrj }
183538fd1498Szrj #endif
183638fd1498Szrj
183738fd1498Szrj #if defined LINK_EH_SPEC || defined LINK_BUILDID_SPEC || \
183838fd1498Szrj defined LINKER_HASH_STYLE
183938fd1498Szrj # ifdef LINK_BUILDID_SPEC
184038fd1498Szrj /* Prepend LINK_BUILDID_SPEC to whatever link_spec we had before. */
184138fd1498Szrj obstack_grow (&obstack, LINK_BUILDID_SPEC, sizeof (LINK_BUILDID_SPEC) - 1);
184238fd1498Szrj # endif
184338fd1498Szrj # ifdef LINK_EH_SPEC
184438fd1498Szrj /* Prepend LINK_EH_SPEC to whatever link_spec we had before. */
184538fd1498Szrj obstack_grow (&obstack, LINK_EH_SPEC, sizeof (LINK_EH_SPEC) - 1);
184638fd1498Szrj # endif
184738fd1498Szrj # ifdef LINKER_HASH_STYLE
184838fd1498Szrj /* Prepend --hash-style=LINKER_HASH_STYLE to whatever link_spec we had
184938fd1498Szrj before. */
185038fd1498Szrj {
185138fd1498Szrj static const char hash_style[] = "--hash-style=";
185238fd1498Szrj obstack_grow (&obstack, hash_style, sizeof (hash_style) - 1);
185338fd1498Szrj obstack_grow (&obstack, LINKER_HASH_STYLE, sizeof (LINKER_HASH_STYLE) - 1);
185438fd1498Szrj obstack_1grow (&obstack, ' ');
185538fd1498Szrj }
185638fd1498Szrj # endif
185738fd1498Szrj obstack_grow0 (&obstack, link_spec, strlen (link_spec));
185838fd1498Szrj link_spec = XOBFINISH (&obstack, const char *);
185938fd1498Szrj #endif
186038fd1498Szrj
186138fd1498Szrj specs = sl;
186238fd1498Szrj }
186338fd1498Szrj
186438fd1498Szrj /* Change the value of spec NAME to SPEC. If SPEC is empty, then the spec is
186538fd1498Szrj removed; If the spec starts with a + then SPEC is added to the end of the
186638fd1498Szrj current spec. */
186738fd1498Szrj
186838fd1498Szrj static void
set_spec(const char * name,const char * spec,bool user_p)186938fd1498Szrj set_spec (const char *name, const char *spec, bool user_p)
187038fd1498Szrj {
187138fd1498Szrj struct spec_list *sl;
187238fd1498Szrj const char *old_spec;
187338fd1498Szrj int name_len = strlen (name);
187438fd1498Szrj int i;
187538fd1498Szrj
187638fd1498Szrj /* If this is the first call, initialize the statically allocated specs. */
187738fd1498Szrj if (!specs)
187838fd1498Szrj {
187938fd1498Szrj struct spec_list *next = (struct spec_list *) 0;
188038fd1498Szrj for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
188138fd1498Szrj {
188238fd1498Szrj sl = &static_specs[i];
188338fd1498Szrj sl->next = next;
188438fd1498Szrj next = sl;
188538fd1498Szrj }
188638fd1498Szrj specs = sl;
188738fd1498Szrj }
188838fd1498Szrj
188938fd1498Szrj /* See if the spec already exists. */
189038fd1498Szrj for (sl = specs; sl; sl = sl->next)
189138fd1498Szrj if (name_len == sl->name_len && !strcmp (sl->name, name))
189238fd1498Szrj break;
189338fd1498Szrj
189438fd1498Szrj if (!sl)
189538fd1498Szrj {
189638fd1498Szrj /* Not found - make it. */
189738fd1498Szrj sl = XNEW (struct spec_list);
189838fd1498Szrj sl->name = xstrdup (name);
189938fd1498Szrj sl->name_len = name_len;
190038fd1498Szrj sl->ptr_spec = &sl->ptr;
190138fd1498Szrj sl->alloc_p = 0;
190238fd1498Szrj *(sl->ptr_spec) = "";
190338fd1498Szrj sl->next = specs;
190438fd1498Szrj sl->default_ptr = NULL;
190538fd1498Szrj specs = sl;
190638fd1498Szrj }
190738fd1498Szrj
190838fd1498Szrj old_spec = *(sl->ptr_spec);
190938fd1498Szrj *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1]))
191038fd1498Szrj ? concat (old_spec, spec + 1, NULL)
191138fd1498Szrj : xstrdup (spec));
191238fd1498Szrj
191338fd1498Szrj #ifdef DEBUG_SPECS
191438fd1498Szrj if (verbose_flag)
191538fd1498Szrj fnotice (stderr, "Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
191638fd1498Szrj #endif
191738fd1498Szrj
191838fd1498Szrj /* Free the old spec. */
191938fd1498Szrj if (old_spec && sl->alloc_p)
192038fd1498Szrj free (CONST_CAST (char *, old_spec));
192138fd1498Szrj
192238fd1498Szrj sl->user_p = user_p;
192338fd1498Szrj sl->alloc_p = true;
192438fd1498Szrj }
192538fd1498Szrj
192638fd1498Szrj /* Accumulate a command (program name and args), and run it. */
192738fd1498Szrj
192838fd1498Szrj typedef const char *const_char_p; /* For DEF_VEC_P. */
192938fd1498Szrj
193038fd1498Szrj /* Vector of pointers to arguments in the current line of specifications. */
193138fd1498Szrj
193238fd1498Szrj static vec<const_char_p> argbuf;
193338fd1498Szrj
193438fd1498Szrj /* Were the options -c, -S or -E passed. */
193538fd1498Szrj static int have_c = 0;
193638fd1498Szrj
193738fd1498Szrj /* Was the option -o passed. */
193838fd1498Szrj static int have_o = 0;
193938fd1498Szrj
194038fd1498Szrj /* Was the option -E passed. */
194138fd1498Szrj static int have_E = 0;
194238fd1498Szrj
194338fd1498Szrj /* Pointer to output file name passed in with -o. */
194438fd1498Szrj static const char *output_file = 0;
194538fd1498Szrj
194638fd1498Szrj /* This is the list of suffixes and codes (%g/%u/%U/%j) and the associated
194738fd1498Szrj temp file. If the HOST_BIT_BUCKET is used for %j, no entry is made for
194838fd1498Szrj it here. */
194938fd1498Szrj
195038fd1498Szrj static struct temp_name {
195138fd1498Szrj const char *suffix; /* suffix associated with the code. */
195238fd1498Szrj int length; /* strlen (suffix). */
195338fd1498Szrj int unique; /* Indicates whether %g or %u/%U was used. */
195438fd1498Szrj const char *filename; /* associated filename. */
195538fd1498Szrj int filename_length; /* strlen (filename). */
195638fd1498Szrj struct temp_name *next;
195738fd1498Szrj } *temp_names;
195838fd1498Szrj
195938fd1498Szrj /* Number of commands executed so far. */
196038fd1498Szrj
196138fd1498Szrj static int execution_count;
196238fd1498Szrj
196338fd1498Szrj /* Number of commands that exited with a signal. */
196438fd1498Szrj
196538fd1498Szrj static int signal_count;
196638fd1498Szrj
196738fd1498Szrj /* Allocate the argument vector. */
196838fd1498Szrj
196938fd1498Szrj static void
alloc_args(void)197038fd1498Szrj alloc_args (void)
197138fd1498Szrj {
197238fd1498Szrj argbuf.create (10);
197338fd1498Szrj }
197438fd1498Szrj
197538fd1498Szrj /* Clear out the vector of arguments (after a command is executed). */
197638fd1498Szrj
197738fd1498Szrj static void
clear_args(void)197838fd1498Szrj clear_args (void)
197938fd1498Szrj {
198038fd1498Szrj argbuf.truncate (0);
198138fd1498Szrj }
198238fd1498Szrj
198338fd1498Szrj /* Add one argument to the vector at the end.
198438fd1498Szrj This is done when a space is seen or at the end of the line.
198538fd1498Szrj If DELETE_ALWAYS is nonzero, the arg is a filename
198638fd1498Szrj and the file should be deleted eventually.
198738fd1498Szrj If DELETE_FAILURE is nonzero, the arg is a filename
198838fd1498Szrj and the file should be deleted if this compilation fails. */
198938fd1498Szrj
199038fd1498Szrj static void
store_arg(const char * arg,int delete_always,int delete_failure)199138fd1498Szrj store_arg (const char *arg, int delete_always, int delete_failure)
199238fd1498Szrj {
199338fd1498Szrj argbuf.safe_push (arg);
199438fd1498Szrj
199538fd1498Szrj if (delete_always || delete_failure)
199638fd1498Szrj {
199738fd1498Szrj const char *p;
199838fd1498Szrj /* If the temporary file we should delete is specified as
199938fd1498Szrj part of a joined argument extract the filename. */
200038fd1498Szrj if (arg[0] == '-'
200138fd1498Szrj && (p = strrchr (arg, '=')))
200238fd1498Szrj arg = p + 1;
200338fd1498Szrj record_temp_file (arg, delete_always, delete_failure);
200438fd1498Szrj }
200538fd1498Szrj }
200638fd1498Szrj
200738fd1498Szrj /* Load specs from a file name named FILENAME, replacing occurrences of
200838fd1498Szrj various different types of line-endings, \r\n, \n\r and just \r, with
200938fd1498Szrj a single \n. */
201038fd1498Szrj
201138fd1498Szrj static char *
load_specs(const char * filename)201238fd1498Szrj load_specs (const char *filename)
201338fd1498Szrj {
201438fd1498Szrj int desc;
201538fd1498Szrj int readlen;
201638fd1498Szrj struct stat statbuf;
201738fd1498Szrj char *buffer;
201838fd1498Szrj char *buffer_p;
201938fd1498Szrj char *specs;
202038fd1498Szrj char *specs_p;
202138fd1498Szrj
202238fd1498Szrj if (verbose_flag)
202338fd1498Szrj fnotice (stderr, "Reading specs from %s\n", filename);
202438fd1498Szrj
202538fd1498Szrj /* Open and stat the file. */
202638fd1498Szrj desc = open (filename, O_RDONLY, 0);
202738fd1498Szrj if (desc < 0)
202838fd1498Szrj pfatal_with_name (filename);
202938fd1498Szrj if (stat (filename, &statbuf) < 0)
203038fd1498Szrj pfatal_with_name (filename);
203138fd1498Szrj
203238fd1498Szrj /* Read contents of file into BUFFER. */
203338fd1498Szrj buffer = XNEWVEC (char, statbuf.st_size + 1);
203438fd1498Szrj readlen = read (desc, buffer, (unsigned) statbuf.st_size);
203538fd1498Szrj if (readlen < 0)
203638fd1498Szrj pfatal_with_name (filename);
203738fd1498Szrj buffer[readlen] = 0;
203838fd1498Szrj close (desc);
203938fd1498Szrj
204038fd1498Szrj specs = XNEWVEC (char, readlen + 1);
204138fd1498Szrj specs_p = specs;
204238fd1498Szrj for (buffer_p = buffer; buffer_p && *buffer_p; buffer_p++)
204338fd1498Szrj {
204438fd1498Szrj int skip = 0;
204538fd1498Szrj char c = *buffer_p;
204638fd1498Szrj if (c == '\r')
204738fd1498Szrj {
204838fd1498Szrj if (buffer_p > buffer && *(buffer_p - 1) == '\n') /* \n\r */
204938fd1498Szrj skip = 1;
205038fd1498Szrj else if (*(buffer_p + 1) == '\n') /* \r\n */
205138fd1498Szrj skip = 1;
205238fd1498Szrj else /* \r */
205338fd1498Szrj c = '\n';
205438fd1498Szrj }
205538fd1498Szrj if (! skip)
205638fd1498Szrj *specs_p++ = c;
205738fd1498Szrj }
205838fd1498Szrj *specs_p = '\0';
205938fd1498Szrj
206038fd1498Szrj free (buffer);
206138fd1498Szrj return (specs);
206238fd1498Szrj }
206338fd1498Szrj
206438fd1498Szrj /* Read compilation specs from a file named FILENAME,
206538fd1498Szrj replacing the default ones.
206638fd1498Szrj
206738fd1498Szrj A suffix which starts with `*' is a definition for
206838fd1498Szrj one of the machine-specific sub-specs. The "suffix" should be
206938fd1498Szrj *asm, *cc1, *cpp, *link, *startfile, etc.
207038fd1498Szrj The corresponding spec is stored in asm_spec, etc.,
207138fd1498Szrj rather than in the `compilers' vector.
207238fd1498Szrj
207338fd1498Szrj Anything invalid in the file is a fatal error. */
207438fd1498Szrj
207538fd1498Szrj static void
read_specs(const char * filename,bool main_p,bool user_p)207638fd1498Szrj read_specs (const char *filename, bool main_p, bool user_p)
207738fd1498Szrj {
207838fd1498Szrj char *buffer;
207938fd1498Szrj char *p;
208038fd1498Szrj
208138fd1498Szrj buffer = load_specs (filename);
208238fd1498Szrj
208338fd1498Szrj /* Scan BUFFER for specs, putting them in the vector. */
208438fd1498Szrj p = buffer;
208538fd1498Szrj while (1)
208638fd1498Szrj {
208738fd1498Szrj char *suffix;
208838fd1498Szrj char *spec;
208938fd1498Szrj char *in, *out, *p1, *p2, *p3;
209038fd1498Szrj
209138fd1498Szrj /* Advance P in BUFFER to the next nonblank nocomment line. */
209238fd1498Szrj p = skip_whitespace (p);
209338fd1498Szrj if (*p == 0)
209438fd1498Szrj break;
209538fd1498Szrj
209638fd1498Szrj /* Is this a special command that starts with '%'? */
209738fd1498Szrj /* Don't allow this for the main specs file, since it would
209838fd1498Szrj encourage people to overwrite it. */
209938fd1498Szrj if (*p == '%' && !main_p)
210038fd1498Szrj {
210138fd1498Szrj p1 = p;
210238fd1498Szrj while (*p && *p != '\n')
210338fd1498Szrj p++;
210438fd1498Szrj
210538fd1498Szrj /* Skip '\n'. */
210638fd1498Szrj p++;
210738fd1498Szrj
210838fd1498Szrj if (!strncmp (p1, "%include", sizeof ("%include") - 1)
210938fd1498Szrj && (p1[sizeof "%include" - 1] == ' '
211038fd1498Szrj || p1[sizeof "%include" - 1] == '\t'))
211138fd1498Szrj {
211238fd1498Szrj char *new_filename;
211338fd1498Szrj
211438fd1498Szrj p1 += sizeof ("%include");
211538fd1498Szrj while (*p1 == ' ' || *p1 == '\t')
211638fd1498Szrj p1++;
211738fd1498Szrj
211838fd1498Szrj if (*p1++ != '<' || p[-2] != '>')
211938fd1498Szrj fatal_error (input_location,
212038fd1498Szrj "specs %%include syntax malformed after "
212138fd1498Szrj "%ld characters",
212238fd1498Szrj (long) (p1 - buffer + 1));
212338fd1498Szrj
212438fd1498Szrj p[-2] = '\0';
212538fd1498Szrj new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
212638fd1498Szrj read_specs (new_filename ? new_filename : p1, false, user_p);
212738fd1498Szrj continue;
212838fd1498Szrj }
212938fd1498Szrj else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1)
213038fd1498Szrj && (p1[sizeof "%include_noerr" - 1] == ' '
213138fd1498Szrj || p1[sizeof "%include_noerr" - 1] == '\t'))
213238fd1498Szrj {
213338fd1498Szrj char *new_filename;
213438fd1498Szrj
213538fd1498Szrj p1 += sizeof "%include_noerr";
213638fd1498Szrj while (*p1 == ' ' || *p1 == '\t')
213738fd1498Szrj p1++;
213838fd1498Szrj
213938fd1498Szrj if (*p1++ != '<' || p[-2] != '>')
214038fd1498Szrj fatal_error (input_location,
214138fd1498Szrj "specs %%include syntax malformed after "
214238fd1498Szrj "%ld characters",
214338fd1498Szrj (long) (p1 - buffer + 1));
214438fd1498Szrj
214538fd1498Szrj p[-2] = '\0';
214638fd1498Szrj new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
214738fd1498Szrj if (new_filename)
214838fd1498Szrj read_specs (new_filename, false, user_p);
214938fd1498Szrj else if (verbose_flag)
215038fd1498Szrj fnotice (stderr, "could not find specs file %s\n", p1);
215138fd1498Szrj continue;
215238fd1498Szrj }
215338fd1498Szrj else if (!strncmp (p1, "%rename", sizeof "%rename" - 1)
215438fd1498Szrj && (p1[sizeof "%rename" - 1] == ' '
215538fd1498Szrj || p1[sizeof "%rename" - 1] == '\t'))
215638fd1498Szrj {
215738fd1498Szrj int name_len;
215838fd1498Szrj struct spec_list *sl;
215938fd1498Szrj struct spec_list *newsl;
216038fd1498Szrj
216138fd1498Szrj /* Get original name. */
216238fd1498Szrj p1 += sizeof "%rename";
216338fd1498Szrj while (*p1 == ' ' || *p1 == '\t')
216438fd1498Szrj p1++;
216538fd1498Szrj
216638fd1498Szrj if (! ISALPHA ((unsigned char) *p1))
216738fd1498Szrj fatal_error (input_location,
216838fd1498Szrj "specs %%rename syntax malformed after "
216938fd1498Szrj "%ld characters",
217038fd1498Szrj (long) (p1 - buffer));
217138fd1498Szrj
217238fd1498Szrj p2 = p1;
217338fd1498Szrj while (*p2 && !ISSPACE ((unsigned char) *p2))
217438fd1498Szrj p2++;
217538fd1498Szrj
217638fd1498Szrj if (*p2 != ' ' && *p2 != '\t')
217738fd1498Szrj fatal_error (input_location,
217838fd1498Szrj "specs %%rename syntax malformed after "
217938fd1498Szrj "%ld characters",
218038fd1498Szrj (long) (p2 - buffer));
218138fd1498Szrj
218238fd1498Szrj name_len = p2 - p1;
218338fd1498Szrj *p2++ = '\0';
218438fd1498Szrj while (*p2 == ' ' || *p2 == '\t')
218538fd1498Szrj p2++;
218638fd1498Szrj
218738fd1498Szrj if (! ISALPHA ((unsigned char) *p2))
218838fd1498Szrj fatal_error (input_location,
218938fd1498Szrj "specs %%rename syntax malformed after "
219038fd1498Szrj "%ld characters",
219138fd1498Szrj (long) (p2 - buffer));
219238fd1498Szrj
219338fd1498Szrj /* Get new spec name. */
219438fd1498Szrj p3 = p2;
219538fd1498Szrj while (*p3 && !ISSPACE ((unsigned char) *p3))
219638fd1498Szrj p3++;
219738fd1498Szrj
219838fd1498Szrj if (p3 != p - 1)
219938fd1498Szrj fatal_error (input_location,
220038fd1498Szrj "specs %%rename syntax malformed after "
220138fd1498Szrj "%ld characters",
220238fd1498Szrj (long) (p3 - buffer));
220338fd1498Szrj *p3 = '\0';
220438fd1498Szrj
220538fd1498Szrj for (sl = specs; sl; sl = sl->next)
220638fd1498Szrj if (name_len == sl->name_len && !strcmp (sl->name, p1))
220738fd1498Szrj break;
220838fd1498Szrj
220938fd1498Szrj if (!sl)
221038fd1498Szrj fatal_error (input_location,
221138fd1498Szrj "specs %s spec was not found to be renamed", p1);
221238fd1498Szrj
221338fd1498Szrj if (strcmp (p1, p2) == 0)
221438fd1498Szrj continue;
221538fd1498Szrj
221638fd1498Szrj for (newsl = specs; newsl; newsl = newsl->next)
221738fd1498Szrj if (strcmp (newsl->name, p2) == 0)
221838fd1498Szrj fatal_error (input_location,
221938fd1498Szrj "%s: attempt to rename spec %qs to "
222038fd1498Szrj "already defined spec %qs",
222138fd1498Szrj filename, p1, p2);
222238fd1498Szrj
222338fd1498Szrj if (verbose_flag)
222438fd1498Szrj {
222538fd1498Szrj fnotice (stderr, "rename spec %s to %s\n", p1, p2);
222638fd1498Szrj #ifdef DEBUG_SPECS
222738fd1498Szrj fnotice (stderr, "spec is '%s'\n\n", *(sl->ptr_spec));
222838fd1498Szrj #endif
222938fd1498Szrj }
223038fd1498Szrj
223138fd1498Szrj set_spec (p2, *(sl->ptr_spec), user_p);
223238fd1498Szrj if (sl->alloc_p)
223338fd1498Szrj free (CONST_CAST (char *, *(sl->ptr_spec)));
223438fd1498Szrj
223538fd1498Szrj *(sl->ptr_spec) = "";
223638fd1498Szrj sl->alloc_p = 0;
223738fd1498Szrj continue;
223838fd1498Szrj }
223938fd1498Szrj else
224038fd1498Szrj fatal_error (input_location,
224138fd1498Szrj "specs unknown %% command after %ld characters",
224238fd1498Szrj (long) (p1 - buffer));
224338fd1498Szrj }
224438fd1498Szrj
224538fd1498Szrj /* Find the colon that should end the suffix. */
224638fd1498Szrj p1 = p;
224738fd1498Szrj while (*p1 && *p1 != ':' && *p1 != '\n')
224838fd1498Szrj p1++;
224938fd1498Szrj
225038fd1498Szrj /* The colon shouldn't be missing. */
225138fd1498Szrj if (*p1 != ':')
225238fd1498Szrj fatal_error (input_location,
225338fd1498Szrj "specs file malformed after %ld characters",
225438fd1498Szrj (long) (p1 - buffer));
225538fd1498Szrj
225638fd1498Szrj /* Skip back over trailing whitespace. */
225738fd1498Szrj p2 = p1;
225838fd1498Szrj while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t'))
225938fd1498Szrj p2--;
226038fd1498Szrj
226138fd1498Szrj /* Copy the suffix to a string. */
226238fd1498Szrj suffix = save_string (p, p2 - p);
226338fd1498Szrj /* Find the next line. */
226438fd1498Szrj p = skip_whitespace (p1 + 1);
226538fd1498Szrj if (p[1] == 0)
226638fd1498Szrj fatal_error (input_location,
226738fd1498Szrj "specs file malformed after %ld characters",
226838fd1498Szrj (long) (p - buffer));
226938fd1498Szrj
227038fd1498Szrj p1 = p;
227138fd1498Szrj /* Find next blank line or end of string. */
227238fd1498Szrj while (*p1 && !(*p1 == '\n' && (p1[1] == '\n' || p1[1] == '\0')))
227338fd1498Szrj p1++;
227438fd1498Szrj
227538fd1498Szrj /* Specs end at the blank line and do not include the newline. */
227638fd1498Szrj spec = save_string (p, p1 - p);
227738fd1498Szrj p = p1;
227838fd1498Szrj
227938fd1498Szrj /* Delete backslash-newline sequences from the spec. */
228038fd1498Szrj in = spec;
228138fd1498Szrj out = spec;
228238fd1498Szrj while (*in != 0)
228338fd1498Szrj {
228438fd1498Szrj if (in[0] == '\\' && in[1] == '\n')
228538fd1498Szrj in += 2;
228638fd1498Szrj else if (in[0] == '#')
228738fd1498Szrj while (*in && *in != '\n')
228838fd1498Szrj in++;
228938fd1498Szrj
229038fd1498Szrj else
229138fd1498Szrj *out++ = *in++;
229238fd1498Szrj }
229338fd1498Szrj *out = 0;
229438fd1498Szrj
229538fd1498Szrj if (suffix[0] == '*')
229638fd1498Szrj {
229738fd1498Szrj if (! strcmp (suffix, "*link_command"))
229838fd1498Szrj link_command_spec = spec;
229938fd1498Szrj else
230038fd1498Szrj {
230138fd1498Szrj set_spec (suffix + 1, spec, user_p);
230238fd1498Szrj free (spec);
230338fd1498Szrj }
230438fd1498Szrj }
230538fd1498Szrj else
230638fd1498Szrj {
230738fd1498Szrj /* Add this pair to the vector. */
230838fd1498Szrj compilers
230938fd1498Szrj = XRESIZEVEC (struct compiler, compilers, n_compilers + 2);
231038fd1498Szrj
231138fd1498Szrj compilers[n_compilers].suffix = suffix;
231238fd1498Szrj compilers[n_compilers].spec = spec;
231338fd1498Szrj n_compilers++;
231438fd1498Szrj memset (&compilers[n_compilers], 0, sizeof compilers[n_compilers]);
231538fd1498Szrj }
231638fd1498Szrj
231738fd1498Szrj if (*suffix == 0)
231838fd1498Szrj link_command_spec = spec;
231938fd1498Szrj }
232038fd1498Szrj
232138fd1498Szrj if (link_command_spec == 0)
232238fd1498Szrj fatal_error (input_location, "spec file has no spec for linking");
232338fd1498Szrj
232438fd1498Szrj XDELETEVEC (buffer);
232538fd1498Szrj }
232638fd1498Szrj
232738fd1498Szrj /* Record the names of temporary files we tell compilers to write,
232838fd1498Szrj and delete them at the end of the run. */
232938fd1498Szrj
233038fd1498Szrj /* This is the common prefix we use to make temp file names.
233138fd1498Szrj It is chosen once for each run of this program.
233238fd1498Szrj It is substituted into a spec by %g or %j.
233338fd1498Szrj Thus, all temp file names contain this prefix.
233438fd1498Szrj In practice, all temp file names start with this prefix.
233538fd1498Szrj
233638fd1498Szrj This prefix comes from the envvar TMPDIR if it is defined;
233738fd1498Szrj otherwise, from the P_tmpdir macro if that is defined;
233838fd1498Szrj otherwise, in /usr/tmp or /tmp;
233938fd1498Szrj or finally the current directory if all else fails. */
234038fd1498Szrj
234138fd1498Szrj static const char *temp_filename;
234238fd1498Szrj
234338fd1498Szrj /* Length of the prefix. */
234438fd1498Szrj
234538fd1498Szrj static int temp_filename_length;
234638fd1498Szrj
234738fd1498Szrj /* Define the list of temporary files to delete. */
234838fd1498Szrj
234938fd1498Szrj struct temp_file
235038fd1498Szrj {
235138fd1498Szrj const char *name;
235238fd1498Szrj struct temp_file *next;
235338fd1498Szrj };
235438fd1498Szrj
235538fd1498Szrj /* Queue of files to delete on success or failure of compilation. */
235638fd1498Szrj static struct temp_file *always_delete_queue;
235738fd1498Szrj /* Queue of files to delete on failure of compilation. */
235838fd1498Szrj static struct temp_file *failure_delete_queue;
235938fd1498Szrj
236038fd1498Szrj /* Record FILENAME as a file to be deleted automatically.
236138fd1498Szrj ALWAYS_DELETE nonzero means delete it if all compilation succeeds;
236238fd1498Szrj otherwise delete it in any case.
236338fd1498Szrj FAIL_DELETE nonzero means delete it if a compilation step fails;
236438fd1498Szrj otherwise delete it in any case. */
236538fd1498Szrj
236638fd1498Szrj void
record_temp_file(const char * filename,int always_delete,int fail_delete)236738fd1498Szrj record_temp_file (const char *filename, int always_delete, int fail_delete)
236838fd1498Szrj {
236938fd1498Szrj char *const name = xstrdup (filename);
237038fd1498Szrj
237138fd1498Szrj if (always_delete)
237238fd1498Szrj {
237338fd1498Szrj struct temp_file *temp;
237438fd1498Szrj for (temp = always_delete_queue; temp; temp = temp->next)
237538fd1498Szrj if (! filename_cmp (name, temp->name))
237638fd1498Szrj {
237738fd1498Szrj free (name);
237838fd1498Szrj goto already1;
237938fd1498Szrj }
238038fd1498Szrj
238138fd1498Szrj temp = XNEW (struct temp_file);
238238fd1498Szrj temp->next = always_delete_queue;
238338fd1498Szrj temp->name = name;
238438fd1498Szrj always_delete_queue = temp;
238538fd1498Szrj
238638fd1498Szrj already1:;
238738fd1498Szrj }
238838fd1498Szrj
238938fd1498Szrj if (fail_delete)
239038fd1498Szrj {
239138fd1498Szrj struct temp_file *temp;
239238fd1498Szrj for (temp = failure_delete_queue; temp; temp = temp->next)
239338fd1498Szrj if (! filename_cmp (name, temp->name))
239438fd1498Szrj {
239538fd1498Szrj free (name);
239638fd1498Szrj goto already2;
239738fd1498Szrj }
239838fd1498Szrj
239938fd1498Szrj temp = XNEW (struct temp_file);
240038fd1498Szrj temp->next = failure_delete_queue;
240138fd1498Szrj temp->name = name;
240238fd1498Szrj failure_delete_queue = temp;
240338fd1498Szrj
240438fd1498Szrj already2:;
240538fd1498Szrj }
240638fd1498Szrj }
240738fd1498Szrj
240838fd1498Szrj /* Delete all the temporary files whose names we previously recorded. */
240938fd1498Szrj
241038fd1498Szrj #ifndef DELETE_IF_ORDINARY
241138fd1498Szrj #define DELETE_IF_ORDINARY(NAME,ST,VERBOSE_FLAG) \
241238fd1498Szrj do \
241338fd1498Szrj { \
241438fd1498Szrj if (stat (NAME, &ST) >= 0 && S_ISREG (ST.st_mode)) \
241538fd1498Szrj if (unlink (NAME) < 0) \
241638fd1498Szrj if (VERBOSE_FLAG) \
241738fd1498Szrj perror_with_name (NAME); \
241838fd1498Szrj } while (0)
241938fd1498Szrj #endif
242038fd1498Szrj
242138fd1498Szrj static void
delete_if_ordinary(const char * name)242238fd1498Szrj delete_if_ordinary (const char *name)
242338fd1498Szrj {
242438fd1498Szrj struct stat st;
242538fd1498Szrj #ifdef DEBUG
242638fd1498Szrj int i, c;
242738fd1498Szrj
242838fd1498Szrj printf ("Delete %s? (y or n) ", name);
242938fd1498Szrj fflush (stdout);
243038fd1498Szrj i = getchar ();
243138fd1498Szrj if (i != '\n')
243238fd1498Szrj while ((c = getchar ()) != '\n' && c != EOF)
243338fd1498Szrj ;
243438fd1498Szrj
243538fd1498Szrj if (i == 'y' || i == 'Y')
243638fd1498Szrj #endif /* DEBUG */
243738fd1498Szrj DELETE_IF_ORDINARY (name, st, verbose_flag);
243838fd1498Szrj }
243938fd1498Szrj
244038fd1498Szrj static void
delete_temp_files(void)244138fd1498Szrj delete_temp_files (void)
244238fd1498Szrj {
244338fd1498Szrj struct temp_file *temp;
244438fd1498Szrj
244538fd1498Szrj for (temp = always_delete_queue; temp; temp = temp->next)
244638fd1498Szrj delete_if_ordinary (temp->name);
244738fd1498Szrj always_delete_queue = 0;
244838fd1498Szrj }
244938fd1498Szrj
245038fd1498Szrj /* Delete all the files to be deleted on error. */
245138fd1498Szrj
245238fd1498Szrj static void
delete_failure_queue(void)245338fd1498Szrj delete_failure_queue (void)
245438fd1498Szrj {
245538fd1498Szrj struct temp_file *temp;
245638fd1498Szrj
245738fd1498Szrj for (temp = failure_delete_queue; temp; temp = temp->next)
245838fd1498Szrj delete_if_ordinary (temp->name);
245938fd1498Szrj }
246038fd1498Szrj
246138fd1498Szrj static void
clear_failure_queue(void)246238fd1498Szrj clear_failure_queue (void)
246338fd1498Szrj {
246438fd1498Szrj failure_delete_queue = 0;
246538fd1498Szrj }
246638fd1498Szrj
246738fd1498Szrj /* Call CALLBACK for each path in PATHS, breaking out early if CALLBACK
246838fd1498Szrj returns non-NULL.
246938fd1498Szrj If DO_MULTI is true iterate over the paths twice, first with multilib
247038fd1498Szrj suffix then without, otherwise iterate over the paths once without
247138fd1498Szrj adding a multilib suffix. When DO_MULTI is true, some attempt is made
247238fd1498Szrj to avoid visiting the same path twice, but we could do better. For
247338fd1498Szrj instance, /usr/lib/../lib is considered different from /usr/lib.
247438fd1498Szrj At least EXTRA_SPACE chars past the end of the path passed to
247538fd1498Szrj CALLBACK are available for use by the callback.
247638fd1498Szrj CALLBACK_INFO allows extra parameters to be passed to CALLBACK.
247738fd1498Szrj
247838fd1498Szrj Returns the value returned by CALLBACK. */
247938fd1498Szrj
248038fd1498Szrj static void *
for_each_path(const struct path_prefix * paths,bool do_multi,size_t extra_space,void * (* callback)(char *,void *),void * callback_info)248138fd1498Szrj for_each_path (const struct path_prefix *paths,
248238fd1498Szrj bool do_multi,
248338fd1498Szrj size_t extra_space,
248438fd1498Szrj void *(*callback) (char *, void *),
248538fd1498Szrj void *callback_info)
248638fd1498Szrj {
248738fd1498Szrj struct prefix_list *pl;
248838fd1498Szrj const char *multi_dir = NULL;
248938fd1498Szrj const char *multi_os_dir = NULL;
249038fd1498Szrj const char *multiarch_suffix = NULL;
249138fd1498Szrj const char *multi_suffix;
249238fd1498Szrj const char *just_multi_suffix;
249338fd1498Szrj char *path = NULL;
249438fd1498Szrj void *ret = NULL;
249538fd1498Szrj bool skip_multi_dir = false;
249638fd1498Szrj bool skip_multi_os_dir = false;
249738fd1498Szrj
249838fd1498Szrj multi_suffix = machine_suffix;
249938fd1498Szrj just_multi_suffix = just_machine_suffix;
250038fd1498Szrj if (do_multi && multilib_dir && strcmp (multilib_dir, ".") != 0)
250138fd1498Szrj {
250238fd1498Szrj multi_dir = concat (multilib_dir, dir_separator_str, NULL);
250338fd1498Szrj multi_suffix = concat (multi_suffix, multi_dir, NULL);
250438fd1498Szrj just_multi_suffix = concat (just_multi_suffix, multi_dir, NULL);
250538fd1498Szrj }
250638fd1498Szrj if (do_multi && multilib_os_dir && strcmp (multilib_os_dir, ".") != 0)
250738fd1498Szrj multi_os_dir = concat (multilib_os_dir, dir_separator_str, NULL);
250838fd1498Szrj if (multiarch_dir)
250938fd1498Szrj multiarch_suffix = concat (multiarch_dir, dir_separator_str, NULL);
251038fd1498Szrj
251138fd1498Szrj while (1)
251238fd1498Szrj {
251338fd1498Szrj size_t multi_dir_len = 0;
251438fd1498Szrj size_t multi_os_dir_len = 0;
251538fd1498Szrj size_t multiarch_len = 0;
251638fd1498Szrj size_t suffix_len;
251738fd1498Szrj size_t just_suffix_len;
251838fd1498Szrj size_t len;
251938fd1498Szrj
252038fd1498Szrj if (multi_dir)
252138fd1498Szrj multi_dir_len = strlen (multi_dir);
252238fd1498Szrj if (multi_os_dir)
252338fd1498Szrj multi_os_dir_len = strlen (multi_os_dir);
252438fd1498Szrj if (multiarch_suffix)
252538fd1498Szrj multiarch_len = strlen (multiarch_suffix);
252638fd1498Szrj suffix_len = strlen (multi_suffix);
252738fd1498Szrj just_suffix_len = strlen (just_multi_suffix);
252838fd1498Szrj
252938fd1498Szrj if (path == NULL)
253038fd1498Szrj {
253138fd1498Szrj len = paths->max_len + extra_space + 1;
253238fd1498Szrj len += MAX (MAX (suffix_len, multi_os_dir_len), multiarch_len);
253338fd1498Szrj path = XNEWVEC (char, len);
253438fd1498Szrj }
253538fd1498Szrj
253638fd1498Szrj for (pl = paths->plist; pl != 0; pl = pl->next)
253738fd1498Szrj {
253838fd1498Szrj len = strlen (pl->prefix);
253938fd1498Szrj memcpy (path, pl->prefix, len);
254038fd1498Szrj
2541632577dbSzrj #if 0 /* DragonFly base: MACHINE/VERSION isn't used anywhere */
254238fd1498Szrj /* Look first in MACHINE/VERSION subdirectory. */
254338fd1498Szrj if (!skip_multi_dir)
254438fd1498Szrj {
254538fd1498Szrj memcpy (path + len, multi_suffix, suffix_len + 1);
254638fd1498Szrj ret = callback (path, callback_info);
254738fd1498Szrj if (ret)
254838fd1498Szrj break;
254938fd1498Szrj }
2550632577dbSzrj #endif
255138fd1498Szrj
255238fd1498Szrj /* Some paths are tried with just the machine (ie. target)
255338fd1498Szrj subdir. This is used for finding as, ld, etc. */
255438fd1498Szrj if (!skip_multi_dir
255538fd1498Szrj && pl->require_machine_suffix == 2)
255638fd1498Szrj {
255738fd1498Szrj memcpy (path + len, just_multi_suffix, just_suffix_len + 1);
255838fd1498Szrj ret = callback (path, callback_info);
255938fd1498Szrj if (ret)
256038fd1498Szrj break;
256138fd1498Szrj }
256238fd1498Szrj
256338fd1498Szrj /* Now try the multiarch path. */
256438fd1498Szrj if (!skip_multi_dir
256538fd1498Szrj && !pl->require_machine_suffix && multiarch_dir)
256638fd1498Szrj {
256738fd1498Szrj memcpy (path + len, multiarch_suffix, multiarch_len + 1);
256838fd1498Szrj ret = callback (path, callback_info);
256938fd1498Szrj if (ret)
257038fd1498Szrj break;
257138fd1498Szrj }
257238fd1498Szrj
257338fd1498Szrj /* Now try the base path. */
257438fd1498Szrj if (!pl->require_machine_suffix
257538fd1498Szrj && !(pl->os_multilib ? skip_multi_os_dir : skip_multi_dir))
257638fd1498Szrj {
257738fd1498Szrj const char *this_multi;
257838fd1498Szrj size_t this_multi_len;
257938fd1498Szrj
258038fd1498Szrj if (pl->os_multilib)
258138fd1498Szrj {
258238fd1498Szrj this_multi = multi_os_dir;
258338fd1498Szrj this_multi_len = multi_os_dir_len;
258438fd1498Szrj }
258538fd1498Szrj else
258638fd1498Szrj {
258738fd1498Szrj this_multi = multi_dir;
258838fd1498Szrj this_multi_len = multi_dir_len;
258938fd1498Szrj }
259038fd1498Szrj
259138fd1498Szrj if (this_multi_len)
259238fd1498Szrj memcpy (path + len, this_multi, this_multi_len + 1);
259338fd1498Szrj else
259438fd1498Szrj path[len] = '\0';
259538fd1498Szrj
259638fd1498Szrj ret = callback (path, callback_info);
259738fd1498Szrj if (ret)
259838fd1498Szrj break;
259938fd1498Szrj }
260038fd1498Szrj }
260138fd1498Szrj if (pl)
260238fd1498Szrj break;
260338fd1498Szrj
260438fd1498Szrj if (multi_dir == NULL && multi_os_dir == NULL)
260538fd1498Szrj break;
260638fd1498Szrj
260738fd1498Szrj /* Run through the paths again, this time without multilibs.
260838fd1498Szrj Don't repeat any we have already seen. */
260938fd1498Szrj if (multi_dir)
261038fd1498Szrj {
261138fd1498Szrj free (CONST_CAST (char *, multi_dir));
261238fd1498Szrj multi_dir = NULL;
261338fd1498Szrj free (CONST_CAST (char *, multi_suffix));
261438fd1498Szrj multi_suffix = machine_suffix;
261538fd1498Szrj free (CONST_CAST (char *, just_multi_suffix));
261638fd1498Szrj just_multi_suffix = just_machine_suffix;
261738fd1498Szrj }
261838fd1498Szrj else
261938fd1498Szrj skip_multi_dir = true;
262038fd1498Szrj if (multi_os_dir)
262138fd1498Szrj {
262238fd1498Szrj free (CONST_CAST (char *, multi_os_dir));
262338fd1498Szrj multi_os_dir = NULL;
262438fd1498Szrj }
262538fd1498Szrj else
262638fd1498Szrj skip_multi_os_dir = true;
262738fd1498Szrj }
262838fd1498Szrj
262938fd1498Szrj if (multi_dir)
263038fd1498Szrj {
263138fd1498Szrj free (CONST_CAST (char *, multi_dir));
263238fd1498Szrj free (CONST_CAST (char *, multi_suffix));
263338fd1498Szrj free (CONST_CAST (char *, just_multi_suffix));
263438fd1498Szrj }
263538fd1498Szrj if (multi_os_dir)
263638fd1498Szrj free (CONST_CAST (char *, multi_os_dir));
263738fd1498Szrj if (ret != path)
263838fd1498Szrj free (path);
263938fd1498Szrj return ret;
264038fd1498Szrj }
264138fd1498Szrj
264238fd1498Szrj /* Callback for build_search_list. Adds path to obstack being built. */
264338fd1498Szrj
264438fd1498Szrj struct add_to_obstack_info {
264538fd1498Szrj struct obstack *ob;
264638fd1498Szrj bool check_dir;
264738fd1498Szrj bool first_time;
264838fd1498Szrj };
264938fd1498Szrj
265038fd1498Szrj static void *
add_to_obstack(char * path,void * data)265138fd1498Szrj add_to_obstack (char *path, void *data)
265238fd1498Szrj {
265338fd1498Szrj struct add_to_obstack_info *info = (struct add_to_obstack_info *) data;
265438fd1498Szrj
265538fd1498Szrj if (info->check_dir && !is_directory (path, false))
265638fd1498Szrj return NULL;
265738fd1498Szrj
265838fd1498Szrj if (!info->first_time)
265938fd1498Szrj obstack_1grow (info->ob, PATH_SEPARATOR);
266038fd1498Szrj
266138fd1498Szrj obstack_grow (info->ob, path, strlen (path));
266238fd1498Szrj
266338fd1498Szrj info->first_time = false;
266438fd1498Szrj return NULL;
266538fd1498Szrj }
266638fd1498Szrj
266738fd1498Szrj /* Add or change the value of an environment variable, outputting the
266838fd1498Szrj change to standard error if in verbose mode. */
266938fd1498Szrj static void
xputenv(const char * string)267038fd1498Szrj xputenv (const char *string)
267138fd1498Szrj {
267238fd1498Szrj env.xput (string);
267338fd1498Szrj }
267438fd1498Szrj
267538fd1498Szrj /* Build a list of search directories from PATHS.
267638fd1498Szrj PREFIX is a string to prepend to the list.
267738fd1498Szrj If CHECK_DIR_P is true we ensure the directory exists.
267838fd1498Szrj If DO_MULTI is true, multilib paths are output first, then
267938fd1498Szrj non-multilib paths.
268038fd1498Szrj This is used mostly by putenv_from_prefixes so we use `collect_obstack'.
268138fd1498Szrj It is also used by the --print-search-dirs flag. */
268238fd1498Szrj
268338fd1498Szrj static char *
build_search_list(const struct path_prefix * paths,const char * prefix,bool check_dir,bool do_multi)268438fd1498Szrj build_search_list (const struct path_prefix *paths, const char *prefix,
268538fd1498Szrj bool check_dir, bool do_multi)
268638fd1498Szrj {
268738fd1498Szrj struct add_to_obstack_info info;
268838fd1498Szrj
268938fd1498Szrj info.ob = &collect_obstack;
269038fd1498Szrj info.check_dir = check_dir;
269138fd1498Szrj info.first_time = true;
269238fd1498Szrj
269338fd1498Szrj obstack_grow (&collect_obstack, prefix, strlen (prefix));
269438fd1498Szrj obstack_1grow (&collect_obstack, '=');
269538fd1498Szrj
269638fd1498Szrj for_each_path (paths, do_multi, 0, add_to_obstack, &info);
269738fd1498Szrj
269838fd1498Szrj obstack_1grow (&collect_obstack, '\0');
269938fd1498Szrj return XOBFINISH (&collect_obstack, char *);
270038fd1498Szrj }
270138fd1498Szrj
270238fd1498Szrj /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
270338fd1498Szrj for collect. */
270438fd1498Szrj
270538fd1498Szrj static void
putenv_from_prefixes(const struct path_prefix * paths,const char * env_var,bool do_multi)270638fd1498Szrj putenv_from_prefixes (const struct path_prefix *paths, const char *env_var,
270738fd1498Szrj bool do_multi)
270838fd1498Szrj {
270938fd1498Szrj xputenv (build_search_list (paths, env_var, true, do_multi));
271038fd1498Szrj }
271138fd1498Szrj
271238fd1498Szrj /* Check whether NAME can be accessed in MODE. This is like access,
271338fd1498Szrj except that it never considers directories to be executable. */
271438fd1498Szrj
271538fd1498Szrj static int
access_check(const char * name,int mode)271638fd1498Szrj access_check (const char *name, int mode)
271738fd1498Szrj {
271838fd1498Szrj if (mode == X_OK)
271938fd1498Szrj {
272038fd1498Szrj struct stat st;
272138fd1498Szrj
272238fd1498Szrj if (stat (name, &st) < 0
272338fd1498Szrj || S_ISDIR (st.st_mode))
272438fd1498Szrj return -1;
272538fd1498Szrj }
272638fd1498Szrj
272738fd1498Szrj return access (name, mode);
272838fd1498Szrj }
272938fd1498Szrj
273038fd1498Szrj /* Callback for find_a_file. Appends the file name to the directory
273138fd1498Szrj path. If the resulting file exists in the right mode, return the
273238fd1498Szrj full pathname to the file. */
273338fd1498Szrj
273438fd1498Szrj struct file_at_path_info {
273538fd1498Szrj const char *name;
273638fd1498Szrj const char *suffix;
273738fd1498Szrj int name_len;
273838fd1498Szrj int suffix_len;
273938fd1498Szrj int mode;
274038fd1498Szrj };
274138fd1498Szrj
274238fd1498Szrj static void *
file_at_path(char * path,void * data)274338fd1498Szrj file_at_path (char *path, void *data)
274438fd1498Szrj {
274538fd1498Szrj struct file_at_path_info *info = (struct file_at_path_info *) data;
274638fd1498Szrj size_t len = strlen (path);
274738fd1498Szrj
274838fd1498Szrj memcpy (path + len, info->name, info->name_len);
274938fd1498Szrj len += info->name_len;
275038fd1498Szrj
275138fd1498Szrj /* Some systems have a suffix for executable files.
275238fd1498Szrj So try appending that first. */
275338fd1498Szrj if (info->suffix_len)
275438fd1498Szrj {
275538fd1498Szrj memcpy (path + len, info->suffix, info->suffix_len + 1);
275638fd1498Szrj if (access_check (path, info->mode) == 0)
275738fd1498Szrj return path;
275838fd1498Szrj }
275938fd1498Szrj
276038fd1498Szrj path[len] = '\0';
276138fd1498Szrj if (access_check (path, info->mode) == 0)
276238fd1498Szrj return path;
276338fd1498Szrj
276438fd1498Szrj return NULL;
276538fd1498Szrj }
276638fd1498Szrj
276738fd1498Szrj /* Search for NAME using the prefix list PREFIXES. MODE is passed to
276838fd1498Szrj access to check permissions. If DO_MULTI is true, search multilib
276938fd1498Szrj paths then non-multilib paths, otherwise do not search multilib paths.
277038fd1498Szrj Return 0 if not found, otherwise return its name, allocated with malloc. */
277138fd1498Szrj
277238fd1498Szrj static char *
find_a_file(const struct path_prefix * pprefix,const char * name,int mode,bool do_multi)277338fd1498Szrj find_a_file (const struct path_prefix *pprefix, const char *name, int mode,
277438fd1498Szrj bool do_multi)
277538fd1498Szrj {
277638fd1498Szrj struct file_at_path_info info;
277738fd1498Szrj
277838fd1498Szrj #ifdef DEFAULT_ASSEMBLER
277938fd1498Szrj if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0)
278038fd1498Szrj return xstrdup (DEFAULT_ASSEMBLER);
278138fd1498Szrj #endif
278238fd1498Szrj
278338fd1498Szrj #ifdef DEFAULT_LINKER
278438fd1498Szrj if (! strcmp (name, "ld") && access (DEFAULT_LINKER, mode) == 0)
278538fd1498Szrj return xstrdup (DEFAULT_LINKER);
278638fd1498Szrj #endif
278738fd1498Szrj
278838fd1498Szrj /* Determine the filename to execute (special case for absolute paths). */
278938fd1498Szrj
279038fd1498Szrj if (IS_ABSOLUTE_PATH (name))
279138fd1498Szrj {
279238fd1498Szrj if (access (name, mode) == 0)
279338fd1498Szrj return xstrdup (name);
279438fd1498Szrj
279538fd1498Szrj return NULL;
279638fd1498Szrj }
279738fd1498Szrj
279838fd1498Szrj info.name = name;
279938fd1498Szrj info.suffix = (mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : "";
280038fd1498Szrj info.name_len = strlen (info.name);
280138fd1498Szrj info.suffix_len = strlen (info.suffix);
280238fd1498Szrj info.mode = mode;
280338fd1498Szrj
280438fd1498Szrj return (char*) for_each_path (pprefix, do_multi,
280538fd1498Szrj info.name_len + info.suffix_len,
280638fd1498Szrj file_at_path, &info);
280738fd1498Szrj }
280838fd1498Szrj
280938fd1498Szrj /* Ranking of prefixes in the sort list. -B prefixes are put before
281038fd1498Szrj all others. */
281138fd1498Szrj
281238fd1498Szrj enum path_prefix_priority
281338fd1498Szrj {
281438fd1498Szrj PREFIX_PRIORITY_B_OPT,
281538fd1498Szrj PREFIX_PRIORITY_LAST
281638fd1498Szrj };
281738fd1498Szrj
281838fd1498Szrj /* Add an entry for PREFIX in PLIST. The PLIST is kept in ascending
281938fd1498Szrj order according to PRIORITY. Within each PRIORITY, new entries are
282038fd1498Szrj appended.
282138fd1498Szrj
282238fd1498Szrj If WARN is nonzero, we will warn if no file is found
282338fd1498Szrj through this prefix. WARN should point to an int
282438fd1498Szrj which will be set to 1 if this entry is used.
282538fd1498Szrj
282638fd1498Szrj COMPONENT is the value to be passed to update_path.
282738fd1498Szrj
282838fd1498Szrj REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without
282938fd1498Szrj the complete value of machine_suffix.
283038fd1498Szrj 2 means try both machine_suffix and just_machine_suffix. */
283138fd1498Szrj
283238fd1498Szrj static void
add_prefix(struct path_prefix * pprefix,const char * prefix,const char * component,int priority,int require_machine_suffix,int os_multilib)283338fd1498Szrj add_prefix (struct path_prefix *pprefix, const char *prefix,
283438fd1498Szrj const char *component, /* enum prefix_priority */ int priority,
283538fd1498Szrj int require_machine_suffix, int os_multilib)
283638fd1498Szrj {
283738fd1498Szrj struct prefix_list *pl, **prev;
283838fd1498Szrj int len;
283938fd1498Szrj
284038fd1498Szrj for (prev = &pprefix->plist;
284138fd1498Szrj (*prev) != NULL && (*prev)->priority <= priority;
284238fd1498Szrj prev = &(*prev)->next)
284338fd1498Szrj ;
284438fd1498Szrj
284538fd1498Szrj /* Keep track of the longest prefix. */
284638fd1498Szrj
284738fd1498Szrj prefix = update_path (prefix, component);
284838fd1498Szrj len = strlen (prefix);
284938fd1498Szrj if (len > pprefix->max_len)
285038fd1498Szrj pprefix->max_len = len;
285138fd1498Szrj
285238fd1498Szrj pl = XNEW (struct prefix_list);
285338fd1498Szrj pl->prefix = prefix;
285438fd1498Szrj pl->require_machine_suffix = require_machine_suffix;
285538fd1498Szrj pl->priority = priority;
285638fd1498Szrj pl->os_multilib = os_multilib;
285738fd1498Szrj
285838fd1498Szrj /* Insert after PREV. */
285938fd1498Szrj pl->next = (*prev);
286038fd1498Szrj (*prev) = pl;
286138fd1498Szrj }
286238fd1498Szrj
286338fd1498Szrj /* Same as add_prefix, but prepending target_system_root to prefix. */
286438fd1498Szrj /* The target_system_root prefix has been relocated by gcc_exec_prefix. */
286538fd1498Szrj static void
add_sysrooted_prefix(struct path_prefix * pprefix,const char * prefix,const char * component,int priority,int require_machine_suffix,int os_multilib)286638fd1498Szrj add_sysrooted_prefix (struct path_prefix *pprefix, const char *prefix,
286738fd1498Szrj const char *component,
286838fd1498Szrj /* enum prefix_priority */ int priority,
286938fd1498Szrj int require_machine_suffix, int os_multilib)
287038fd1498Szrj {
287138fd1498Szrj if (!IS_ABSOLUTE_PATH (prefix))
287238fd1498Szrj fatal_error (input_location, "system path %qs is not absolute", prefix);
287338fd1498Szrj
287438fd1498Szrj if (target_system_root)
287538fd1498Szrj {
287638fd1498Szrj char *sysroot_no_trailing_dir_separator = xstrdup (target_system_root);
287738fd1498Szrj size_t sysroot_len = strlen (target_system_root);
287838fd1498Szrj
287938fd1498Szrj if (sysroot_len > 0
288038fd1498Szrj && target_system_root[sysroot_len - 1] == DIR_SEPARATOR)
288138fd1498Szrj sysroot_no_trailing_dir_separator[sysroot_len - 1] = '\0';
288238fd1498Szrj
288338fd1498Szrj if (target_sysroot_suffix)
288438fd1498Szrj prefix = concat (sysroot_no_trailing_dir_separator,
288538fd1498Szrj target_sysroot_suffix, prefix, NULL);
288638fd1498Szrj else
288738fd1498Szrj prefix = concat (sysroot_no_trailing_dir_separator, prefix, NULL);
288838fd1498Szrj
288938fd1498Szrj free (sysroot_no_trailing_dir_separator);
289038fd1498Szrj
289138fd1498Szrj /* We have to override this because GCC's notion of sysroot
289238fd1498Szrj moves along with GCC. */
289338fd1498Szrj component = "GCC";
289438fd1498Szrj }
289538fd1498Szrj
289638fd1498Szrj add_prefix (pprefix, prefix, component, priority,
289738fd1498Szrj require_machine_suffix, os_multilib);
289838fd1498Szrj }
289938fd1498Szrj
290038fd1498Szrj /* Execute the command specified by the arguments on the current line of spec.
290138fd1498Szrj When using pipes, this includes several piped-together commands
290238fd1498Szrj with `|' between them.
290338fd1498Szrj
290438fd1498Szrj Return 0 if successful, -1 if failed. */
290538fd1498Szrj
290638fd1498Szrj static int
execute(void)290738fd1498Szrj execute (void)
290838fd1498Szrj {
290938fd1498Szrj int i;
291038fd1498Szrj int n_commands; /* # of command. */
291138fd1498Szrj char *string;
291238fd1498Szrj struct pex_obj *pex;
291338fd1498Szrj struct command
291438fd1498Szrj {
291538fd1498Szrj const char *prog; /* program name. */
291638fd1498Szrj const char **argv; /* vector of args. */
291738fd1498Szrj };
291838fd1498Szrj const char *arg;
291938fd1498Szrj
292038fd1498Szrj struct command *commands; /* each command buffer with above info. */
292138fd1498Szrj
292238fd1498Szrj gcc_assert (!processing_spec_function);
292338fd1498Szrj
292438fd1498Szrj if (wrapper_string)
292538fd1498Szrj {
292638fd1498Szrj string = find_a_file (&exec_prefixes,
292738fd1498Szrj argbuf[0], X_OK, false);
292838fd1498Szrj if (string)
292938fd1498Szrj argbuf[0] = string;
293038fd1498Szrj insert_wrapper (wrapper_string);
293138fd1498Szrj }
293238fd1498Szrj
293338fd1498Szrj /* Count # of piped commands. */
293438fd1498Szrj for (n_commands = 1, i = 0; argbuf.iterate (i, &arg); i++)
293538fd1498Szrj if (strcmp (arg, "|") == 0)
293638fd1498Szrj n_commands++;
293738fd1498Szrj
293838fd1498Szrj /* Get storage for each command. */
293938fd1498Szrj commands = (struct command *) alloca (n_commands * sizeof (struct command));
294038fd1498Szrj
294138fd1498Szrj /* Split argbuf into its separate piped processes,
294238fd1498Szrj and record info about each one.
294338fd1498Szrj Also search for the programs that are to be run. */
294438fd1498Szrj
294538fd1498Szrj argbuf.safe_push (0);
294638fd1498Szrj
294738fd1498Szrj commands[0].prog = argbuf[0]; /* first command. */
294838fd1498Szrj commands[0].argv = argbuf.address ();
294938fd1498Szrj
295038fd1498Szrj if (!wrapper_string)
295138fd1498Szrj {
295238fd1498Szrj string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
295338fd1498Szrj commands[0].argv[0] = (string) ? string : commands[0].argv[0];
295438fd1498Szrj }
295538fd1498Szrj
295638fd1498Szrj for (n_commands = 1, i = 0; argbuf.iterate (i, &arg); i++)
295738fd1498Szrj if (arg && strcmp (arg, "|") == 0)
295838fd1498Szrj { /* each command. */
295938fd1498Szrj #if defined (__MSDOS__) || defined (OS2) || defined (VMS)
296038fd1498Szrj fatal_error (input_location, "-pipe not supported");
296138fd1498Szrj #endif
296238fd1498Szrj argbuf[i] = 0; /* Termination of
296338fd1498Szrj command args. */
296438fd1498Szrj commands[n_commands].prog = argbuf[i + 1];
296538fd1498Szrj commands[n_commands].argv
296638fd1498Szrj = &(argbuf.address ())[i + 1];
296738fd1498Szrj string = find_a_file (&exec_prefixes, commands[n_commands].prog,
296838fd1498Szrj X_OK, false);
296938fd1498Szrj if (string)
297038fd1498Szrj commands[n_commands].argv[0] = string;
297138fd1498Szrj n_commands++;
297238fd1498Szrj }
297338fd1498Szrj
297438fd1498Szrj /* If -v, print what we are about to do, and maybe query. */
297538fd1498Szrj
297638fd1498Szrj if (verbose_flag)
297738fd1498Szrj {
297838fd1498Szrj /* For help listings, put a blank line between sub-processes. */
297938fd1498Szrj if (print_help_list)
298038fd1498Szrj fputc ('\n', stderr);
298138fd1498Szrj
298238fd1498Szrj /* Print each piped command as a separate line. */
298338fd1498Szrj for (i = 0; i < n_commands; i++)
298438fd1498Szrj {
298538fd1498Szrj const char *const *j;
298638fd1498Szrj
298738fd1498Szrj if (verbose_only_flag)
298838fd1498Szrj {
298938fd1498Szrj for (j = commands[i].argv; *j; j++)
299038fd1498Szrj {
299138fd1498Szrj const char *p;
299238fd1498Szrj for (p = *j; *p; ++p)
299338fd1498Szrj if (!ISALNUM ((unsigned char) *p)
299438fd1498Szrj && *p != '_' && *p != '/' && *p != '-' && *p != '.')
299538fd1498Szrj break;
299638fd1498Szrj if (*p || !*j)
299738fd1498Szrj {
299838fd1498Szrj fprintf (stderr, " \"");
299938fd1498Szrj for (p = *j; *p; ++p)
300038fd1498Szrj {
300138fd1498Szrj if (*p == '"' || *p == '\\' || *p == '$')
300238fd1498Szrj fputc ('\\', stderr);
300338fd1498Szrj fputc (*p, stderr);
300438fd1498Szrj }
300538fd1498Szrj fputc ('"', stderr);
300638fd1498Szrj }
300738fd1498Szrj /* If it's empty, print "". */
300838fd1498Szrj else if (!**j)
300938fd1498Szrj fprintf (stderr, " \"\"");
301038fd1498Szrj else
301138fd1498Szrj fprintf (stderr, " %s", *j);
301238fd1498Szrj }
301338fd1498Szrj }
301438fd1498Szrj else
301538fd1498Szrj for (j = commands[i].argv; *j; j++)
301638fd1498Szrj /* If it's empty, print "". */
301738fd1498Szrj if (!**j)
301838fd1498Szrj fprintf (stderr, " \"\"");
301938fd1498Szrj else
302038fd1498Szrj fprintf (stderr, " %s", *j);
302138fd1498Szrj
302238fd1498Szrj /* Print a pipe symbol after all but the last command. */
302338fd1498Szrj if (i + 1 != n_commands)
302438fd1498Szrj fprintf (stderr, " |");
302538fd1498Szrj fprintf (stderr, "\n");
302638fd1498Szrj }
302738fd1498Szrj fflush (stderr);
302838fd1498Szrj if (verbose_only_flag != 0)
302938fd1498Szrj {
303038fd1498Szrj /* verbose_only_flag should act as if the spec was
303138fd1498Szrj executed, so increment execution_count before
303238fd1498Szrj returning. This prevents spurious warnings about
303338fd1498Szrj unused linker input files, etc. */
303438fd1498Szrj execution_count++;
303538fd1498Szrj return 0;
303638fd1498Szrj }
303738fd1498Szrj #ifdef DEBUG
303838fd1498Szrj fnotice (stderr, "\nGo ahead? (y or n) ");
303938fd1498Szrj fflush (stderr);
304038fd1498Szrj i = getchar ();
304138fd1498Szrj if (i != '\n')
304238fd1498Szrj while (getchar () != '\n')
304338fd1498Szrj ;
304438fd1498Szrj
304538fd1498Szrj if (i != 'y' && i != 'Y')
304638fd1498Szrj return 0;
304738fd1498Szrj #endif /* DEBUG */
304838fd1498Szrj }
304938fd1498Szrj
305038fd1498Szrj #ifdef ENABLE_VALGRIND_CHECKING
305138fd1498Szrj /* Run the each command through valgrind. To simplify prepending the
305238fd1498Szrj path to valgrind and the option "-q" (for quiet operation unless
305338fd1498Szrj something triggers), we allocate a separate argv array. */
305438fd1498Szrj
305538fd1498Szrj for (i = 0; i < n_commands; i++)
305638fd1498Szrj {
305738fd1498Szrj const char **argv;
305838fd1498Szrj int argc;
305938fd1498Szrj int j;
306038fd1498Szrj
306138fd1498Szrj for (argc = 0; commands[i].argv[argc] != NULL; argc++)
306238fd1498Szrj ;
306338fd1498Szrj
306438fd1498Szrj argv = XALLOCAVEC (const char *, argc + 3);
306538fd1498Szrj
306638fd1498Szrj argv[0] = VALGRIND_PATH;
306738fd1498Szrj argv[1] = "-q";
306838fd1498Szrj for (j = 2; j < argc + 2; j++)
306938fd1498Szrj argv[j] = commands[i].argv[j - 2];
307038fd1498Szrj argv[j] = NULL;
307138fd1498Szrj
307238fd1498Szrj commands[i].argv = argv;
307338fd1498Szrj commands[i].prog = argv[0];
307438fd1498Szrj }
307538fd1498Szrj #endif
307638fd1498Szrj
307738fd1498Szrj /* Run each piped subprocess. */
307838fd1498Szrj
307938fd1498Szrj pex = pex_init (PEX_USE_PIPES | ((report_times || report_times_to_file)
308038fd1498Szrj ? PEX_RECORD_TIMES : 0),
308138fd1498Szrj progname, temp_filename);
308238fd1498Szrj if (pex == NULL)
308338fd1498Szrj fatal_error (input_location, "pex_init failed: %m");
308438fd1498Szrj
308538fd1498Szrj for (i = 0; i < n_commands; i++)
308638fd1498Szrj {
308738fd1498Szrj const char *errmsg;
308838fd1498Szrj int err;
308938fd1498Szrj const char *string = commands[i].argv[0];
309038fd1498Szrj
309138fd1498Szrj errmsg = pex_run (pex,
309238fd1498Szrj ((i + 1 == n_commands ? PEX_LAST : 0)
309338fd1498Szrj | (string == commands[i].prog ? PEX_SEARCH : 0)),
309438fd1498Szrj string, CONST_CAST (char **, commands[i].argv),
309538fd1498Szrj NULL, NULL, &err);
309638fd1498Szrj if (errmsg != NULL)
309738fd1498Szrj {
309838fd1498Szrj if (err == 0)
309938fd1498Szrj fatal_error (input_location, errmsg);
310038fd1498Szrj else
310138fd1498Szrj {
310238fd1498Szrj errno = err;
310338fd1498Szrj pfatal_with_name (errmsg);
310438fd1498Szrj }
310538fd1498Szrj }
310638fd1498Szrj
310738fd1498Szrj if (i && string != commands[i].prog)
310838fd1498Szrj free (CONST_CAST (char *, string));
310938fd1498Szrj }
311038fd1498Szrj
311138fd1498Szrj execution_count++;
311238fd1498Szrj
311338fd1498Szrj /* Wait for all the subprocesses to finish. */
311438fd1498Szrj
311538fd1498Szrj {
311638fd1498Szrj int *statuses;
311738fd1498Szrj struct pex_time *times = NULL;
311838fd1498Szrj int ret_code = 0;
311938fd1498Szrj
312038fd1498Szrj statuses = (int *) alloca (n_commands * sizeof (int));
312138fd1498Szrj if (!pex_get_status (pex, n_commands, statuses))
312238fd1498Szrj fatal_error (input_location, "failed to get exit status: %m");
312338fd1498Szrj
312438fd1498Szrj if (report_times || report_times_to_file)
312538fd1498Szrj {
312638fd1498Szrj times = (struct pex_time *) alloca (n_commands * sizeof (struct pex_time));
312738fd1498Szrj if (!pex_get_times (pex, n_commands, times))
312838fd1498Szrj fatal_error (input_location, "failed to get process times: %m");
312938fd1498Szrj }
313038fd1498Szrj
313138fd1498Szrj pex_free (pex);
313238fd1498Szrj
313338fd1498Szrj for (i = 0; i < n_commands; ++i)
313438fd1498Szrj {
313538fd1498Szrj int status = statuses[i];
313638fd1498Szrj
313738fd1498Szrj if (WIFSIGNALED (status))
313838fd1498Szrj switch (WTERMSIG (status))
313938fd1498Szrj {
314038fd1498Szrj case SIGINT:
314138fd1498Szrj case SIGTERM:
314238fd1498Szrj /* SIGQUIT and SIGKILL are not available on MinGW. */
314338fd1498Szrj #ifdef SIGQUIT
314438fd1498Szrj case SIGQUIT:
314538fd1498Szrj #endif
314638fd1498Szrj #ifdef SIGKILL
314738fd1498Szrj case SIGKILL:
314838fd1498Szrj #endif
314938fd1498Szrj /* The user (or environment) did something to the
315038fd1498Szrj inferior. Making this an ICE confuses the user into
315138fd1498Szrj thinking there's a compiler bug. Much more likely is
315238fd1498Szrj the user or OOM killer nuked it. */
315338fd1498Szrj fatal_error (input_location,
315438fd1498Szrj "%s signal terminated program %s",
315538fd1498Szrj strsignal (WTERMSIG (status)),
315638fd1498Szrj commands[i].prog);
315738fd1498Szrj break;
315838fd1498Szrj
315938fd1498Szrj #ifdef SIGPIPE
316038fd1498Szrj case SIGPIPE:
316138fd1498Szrj /* SIGPIPE is a special case. It happens in -pipe mode
316238fd1498Szrj when the compiler dies before the preprocessor is
316338fd1498Szrj done, or the assembler dies before the compiler is
316438fd1498Szrj done. There's generally been an error already, and
316538fd1498Szrj this is just fallout. So don't generate another
316638fd1498Szrj error unless we would otherwise have succeeded. */
316738fd1498Szrj if (signal_count || greatest_status >= MIN_FATAL_STATUS)
316838fd1498Szrj {
316938fd1498Szrj signal_count++;
317038fd1498Szrj ret_code = -1;
317138fd1498Szrj break;
317238fd1498Szrj }
317338fd1498Szrj #endif
317438fd1498Szrj /* FALLTHROUGH */
317538fd1498Szrj
317638fd1498Szrj default:
317738fd1498Szrj /* The inferior failed to catch the signal. */
317838fd1498Szrj internal_error_no_backtrace ("%s signal terminated program %s",
317938fd1498Szrj strsignal (WTERMSIG (status)),
318038fd1498Szrj commands[i].prog);
318138fd1498Szrj }
318238fd1498Szrj else if (WIFEXITED (status)
318338fd1498Szrj && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
318438fd1498Szrj {
318538fd1498Szrj /* For ICEs in cc1, cc1obj, cc1plus see if it is
318638fd1498Szrj reproducible or not. */
318738fd1498Szrj const char *p;
318838fd1498Szrj if (flag_report_bug
318938fd1498Szrj && WEXITSTATUS (status) == ICE_EXIT_CODE
319038fd1498Szrj && i == 0
319138fd1498Szrj && (p = strrchr (commands[0].argv[0], DIR_SEPARATOR))
319238fd1498Szrj && ! strncmp (p + 1, "cc1", 3))
319338fd1498Szrj try_generate_repro (commands[0].argv);
319438fd1498Szrj if (WEXITSTATUS (status) > greatest_status)
319538fd1498Szrj greatest_status = WEXITSTATUS (status);
319638fd1498Szrj ret_code = -1;
319738fd1498Szrj }
319838fd1498Szrj
319938fd1498Szrj if (report_times || report_times_to_file)
320038fd1498Szrj {
320138fd1498Szrj struct pex_time *pt = ×[i];
320238fd1498Szrj double ut, st;
320338fd1498Szrj
320438fd1498Szrj ut = ((double) pt->user_seconds
320538fd1498Szrj + (double) pt->user_microseconds / 1.0e6);
320638fd1498Szrj st = ((double) pt->system_seconds
320738fd1498Szrj + (double) pt->system_microseconds / 1.0e6);
320838fd1498Szrj
320938fd1498Szrj if (ut + st != 0)
321038fd1498Szrj {
321138fd1498Szrj if (report_times)
321238fd1498Szrj fnotice (stderr, "# %s %.2f %.2f\n",
321338fd1498Szrj commands[i].prog, ut, st);
321438fd1498Szrj
321538fd1498Szrj if (report_times_to_file)
321638fd1498Szrj {
321738fd1498Szrj int c = 0;
321838fd1498Szrj const char *const *j;
321938fd1498Szrj
322038fd1498Szrj fprintf (report_times_to_file, "%g %g", ut, st);
322138fd1498Szrj
322238fd1498Szrj for (j = &commands[i].prog; *j; j = &commands[i].argv[++c])
322338fd1498Szrj {
322438fd1498Szrj const char *p;
322538fd1498Szrj for (p = *j; *p; ++p)
322638fd1498Szrj if (*p == '"' || *p == '\\' || *p == '$'
322738fd1498Szrj || ISSPACE (*p))
322838fd1498Szrj break;
322938fd1498Szrj
323038fd1498Szrj if (*p)
323138fd1498Szrj {
323238fd1498Szrj fprintf (report_times_to_file, " \"");
323338fd1498Szrj for (p = *j; *p; ++p)
323438fd1498Szrj {
323538fd1498Szrj if (*p == '"' || *p == '\\' || *p == '$')
323638fd1498Szrj fputc ('\\', report_times_to_file);
323738fd1498Szrj fputc (*p, report_times_to_file);
323838fd1498Szrj }
323938fd1498Szrj fputc ('"', report_times_to_file);
324038fd1498Szrj }
324138fd1498Szrj else
324238fd1498Szrj fprintf (report_times_to_file, " %s", *j);
324338fd1498Szrj }
324438fd1498Szrj
324538fd1498Szrj fputc ('\n', report_times_to_file);
324638fd1498Szrj }
324738fd1498Szrj }
324838fd1498Szrj }
324938fd1498Szrj }
325038fd1498Szrj
325138fd1498Szrj if (commands[0].argv[0] != commands[0].prog)
325238fd1498Szrj free (CONST_CAST (char *, commands[0].argv[0]));
325338fd1498Szrj
325438fd1498Szrj return ret_code;
325538fd1498Szrj }
325638fd1498Szrj }
325738fd1498Szrj
325838fd1498Szrj /* Find all the switches given to us
325938fd1498Szrj and make a vector describing them.
326038fd1498Szrj The elements of the vector are strings, one per switch given.
326138fd1498Szrj If a switch uses following arguments, then the `part1' field
326238fd1498Szrj is the switch itself and the `args' field
326338fd1498Szrj is a null-terminated vector containing the following arguments.
326438fd1498Szrj Bits in the `live_cond' field are:
326538fd1498Szrj SWITCH_LIVE to indicate this switch is true in a conditional spec.
326638fd1498Szrj SWITCH_FALSE to indicate this switch is overridden by a later switch.
326738fd1498Szrj SWITCH_IGNORE to indicate this switch should be ignored (used in %<S).
326838fd1498Szrj SWITCH_IGNORE_PERMANENTLY to indicate this switch should be ignored.
326938fd1498Szrj SWITCH_KEEP_FOR_GCC to indicate that this switch, otherwise ignored,
327038fd1498Szrj should be included in COLLECT_GCC_OPTIONS.
327138fd1498Szrj in all do_spec calls afterwards. Used for %<S from self specs.
327238fd1498Szrj The `known' field describes whether this is an internal switch.
327338fd1498Szrj The `validated' field describes whether any spec has looked at this switch;
327438fd1498Szrj if it remains false at the end of the run, the switch must be meaningless.
327538fd1498Szrj The `ordering' field is used to temporarily mark switches that have to be
327638fd1498Szrj kept in a specific order. */
327738fd1498Szrj
327838fd1498Szrj #define SWITCH_LIVE (1 << 0)
327938fd1498Szrj #define SWITCH_FALSE (1 << 1)
328038fd1498Szrj #define SWITCH_IGNORE (1 << 2)
328138fd1498Szrj #define SWITCH_IGNORE_PERMANENTLY (1 << 3)
328238fd1498Szrj #define SWITCH_KEEP_FOR_GCC (1 << 4)
328338fd1498Szrj
328438fd1498Szrj struct switchstr
328538fd1498Szrj {
328638fd1498Szrj const char *part1;
328738fd1498Szrj const char **args;
328838fd1498Szrj unsigned int live_cond;
328938fd1498Szrj bool known;
329038fd1498Szrj bool validated;
329138fd1498Szrj bool ordering;
329238fd1498Szrj };
329338fd1498Szrj
329438fd1498Szrj static struct switchstr *switches;
329538fd1498Szrj
329638fd1498Szrj static int n_switches;
329738fd1498Szrj
329838fd1498Szrj static int n_switches_alloc;
329938fd1498Szrj
330038fd1498Szrj /* Set to zero if -fcompare-debug is disabled, positive if it's
330138fd1498Szrj enabled and we're running the first compilation, negative if it's
330238fd1498Szrj enabled and we're running the second compilation. For most of the
330338fd1498Szrj time, it's in the range -1..1, but it can be temporarily set to 2
330438fd1498Szrj or 3 to indicate that the -fcompare-debug flags didn't come from
330538fd1498Szrj the command-line, but rather from the GCC_COMPARE_DEBUG environment
330638fd1498Szrj variable, until a synthesized -fcompare-debug flag is added to the
330738fd1498Szrj command line. */
330838fd1498Szrj int compare_debug;
330938fd1498Szrj
331038fd1498Szrj /* Set to nonzero if we've seen the -fcompare-debug-second flag. */
331138fd1498Szrj int compare_debug_second;
331238fd1498Szrj
331338fd1498Szrj /* Set to the flags that should be passed to the second compilation in
331438fd1498Szrj a -fcompare-debug compilation. */
331538fd1498Szrj const char *compare_debug_opt;
331638fd1498Szrj
331738fd1498Szrj static struct switchstr *switches_debug_check[2];
331838fd1498Szrj
331938fd1498Szrj static int n_switches_debug_check[2];
332038fd1498Szrj
332138fd1498Szrj static int n_switches_alloc_debug_check[2];
332238fd1498Szrj
332338fd1498Szrj static char *debug_check_temp_file[2];
332438fd1498Szrj
332538fd1498Szrj /* Language is one of three things:
332638fd1498Szrj
332738fd1498Szrj 1) The name of a real programming language.
332838fd1498Szrj 2) NULL, indicating that no one has figured out
332938fd1498Szrj what it is yet.
333038fd1498Szrj 3) '*', indicating that the file should be passed
333138fd1498Szrj to the linker. */
333238fd1498Szrj struct infile
333338fd1498Szrj {
333438fd1498Szrj const char *name;
333538fd1498Szrj const char *language;
333638fd1498Szrj struct compiler *incompiler;
333738fd1498Szrj bool compiled;
333838fd1498Szrj bool preprocessed;
333938fd1498Szrj };
334038fd1498Szrj
334138fd1498Szrj /* Also a vector of input files specified. */
334238fd1498Szrj
334338fd1498Szrj static struct infile *infiles;
334438fd1498Szrj
334538fd1498Szrj int n_infiles;
334638fd1498Szrj
334738fd1498Szrj static int n_infiles_alloc;
334838fd1498Szrj
334938fd1498Szrj /* True if undefined environment variables encountered during spec processing
335038fd1498Szrj are ok to ignore, typically when we're running for --help or --version. */
335138fd1498Szrj
335238fd1498Szrj static bool spec_undefvar_allowed;
335338fd1498Szrj
335438fd1498Szrj /* True if multiple input files are being compiled to a single
335538fd1498Szrj assembly file. */
335638fd1498Szrj
335738fd1498Szrj static bool combine_inputs;
335838fd1498Szrj
335938fd1498Szrj /* This counts the number of libraries added by lang_specific_driver, so that
336038fd1498Szrj we can tell if there were any user supplied any files or libraries. */
336138fd1498Szrj
336238fd1498Szrj static int added_libraries;
336338fd1498Szrj
336438fd1498Szrj /* And a vector of corresponding output files is made up later. */
336538fd1498Szrj
336638fd1498Szrj const char **outfiles;
336738fd1498Szrj
336838fd1498Szrj #if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
336938fd1498Szrj
337038fd1498Szrj /* Convert NAME to a new name if it is the standard suffix. DO_EXE
337138fd1498Szrj is true if we should look for an executable suffix. DO_OBJ
337238fd1498Szrj is true if we should look for an object suffix. */
337338fd1498Szrj
337438fd1498Szrj static const char *
convert_filename(const char * name,int do_exe ATTRIBUTE_UNUSED,int do_obj ATTRIBUTE_UNUSED)337538fd1498Szrj convert_filename (const char *name, int do_exe ATTRIBUTE_UNUSED,
337638fd1498Szrj int do_obj ATTRIBUTE_UNUSED)
337738fd1498Szrj {
337838fd1498Szrj #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
337938fd1498Szrj int i;
338038fd1498Szrj #endif
338138fd1498Szrj int len;
338238fd1498Szrj
338338fd1498Szrj if (name == NULL)
338438fd1498Szrj return NULL;
338538fd1498Szrj
338638fd1498Szrj len = strlen (name);
338738fd1498Szrj
338838fd1498Szrj #ifdef HAVE_TARGET_OBJECT_SUFFIX
338938fd1498Szrj /* Convert x.o to x.obj if TARGET_OBJECT_SUFFIX is ".obj". */
339038fd1498Szrj if (do_obj && len > 2
339138fd1498Szrj && name[len - 2] == '.'
339238fd1498Szrj && name[len - 1] == 'o')
339338fd1498Szrj {
339438fd1498Szrj obstack_grow (&obstack, name, len - 2);
339538fd1498Szrj obstack_grow0 (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
339638fd1498Szrj name = XOBFINISH (&obstack, const char *);
339738fd1498Szrj }
339838fd1498Szrj #endif
339938fd1498Szrj
340038fd1498Szrj #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
340138fd1498Szrj /* If there is no filetype, make it the executable suffix (which includes
340238fd1498Szrj the "."). But don't get confused if we have just "-o". */
340338fd1498Szrj if (! do_exe || TARGET_EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-'))
340438fd1498Szrj return name;
340538fd1498Szrj
340638fd1498Szrj for (i = len - 1; i >= 0; i--)
340738fd1498Szrj if (IS_DIR_SEPARATOR (name[i]))
340838fd1498Szrj break;
340938fd1498Szrj
341038fd1498Szrj for (i++; i < len; i++)
341138fd1498Szrj if (name[i] == '.')
341238fd1498Szrj return name;
341338fd1498Szrj
341438fd1498Szrj obstack_grow (&obstack, name, len);
341538fd1498Szrj obstack_grow0 (&obstack, TARGET_EXECUTABLE_SUFFIX,
341638fd1498Szrj strlen (TARGET_EXECUTABLE_SUFFIX));
341738fd1498Szrj name = XOBFINISH (&obstack, const char *);
341838fd1498Szrj #endif
341938fd1498Szrj
342038fd1498Szrj return name;
342138fd1498Szrj }
342238fd1498Szrj #endif
342338fd1498Szrj
342438fd1498Szrj /* Display the command line switches accepted by gcc. */
342538fd1498Szrj static void
display_help(void)342638fd1498Szrj display_help (void)
342738fd1498Szrj {
342838fd1498Szrj printf (_("Usage: %s [options] file...\n"), progname);
342938fd1498Szrj fputs (_("Options:\n"), stdout);
343038fd1498Szrj
343138fd1498Szrj fputs (_(" -pass-exit-codes Exit with highest error code from a phase.\n"), stdout);
343238fd1498Szrj fputs (_(" --help Display this information.\n"), stdout);
343338fd1498Szrj fputs (_(" --target-help Display target specific command line options.\n"), stdout);
343438fd1498Szrj fputs (_(" --help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...].\n"), stdout);
343538fd1498Szrj fputs (_(" Display specific types of command line options.\n"), stdout);
343638fd1498Szrj if (! verbose_flag)
343738fd1498Szrj fputs (_(" (Use '-v --help' to display command line options of sub-processes).\n"), stdout);
343838fd1498Szrj fputs (_(" --version Display compiler version information.\n"), stdout);
343938fd1498Szrj fputs (_(" -dumpspecs Display all of the built in spec strings.\n"), stdout);
344038fd1498Szrj fputs (_(" -dumpversion Display the version of the compiler.\n"), stdout);
344138fd1498Szrj fputs (_(" -dumpmachine Display the compiler's target processor.\n"), stdout);
344238fd1498Szrj fputs (_(" -print-search-dirs Display the directories in the compiler's search path.\n"), stdout);
344338fd1498Szrj fputs (_(" -print-libgcc-file-name Display the name of the compiler's companion library.\n"), stdout);
344438fd1498Szrj fputs (_(" -print-file-name=<lib> Display the full path to library <lib>.\n"), stdout);
344538fd1498Szrj fputs (_(" -print-prog-name=<prog> Display the full path to compiler component <prog>.\n"), stdout);
344638fd1498Szrj fputs (_("\
344738fd1498Szrj -print-multiarch Display the target's normalized GNU triplet, used as\n\
344838fd1498Szrj a component in the library path.\n"), stdout);
344938fd1498Szrj fputs (_(" -print-multi-directory Display the root directory for versions of libgcc.\n"), stdout);
345038fd1498Szrj fputs (_("\
345138fd1498Szrj -print-multi-lib Display the mapping between command line options and\n\
345238fd1498Szrj multiple library search directories.\n"), stdout);
345338fd1498Szrj fputs (_(" -print-multi-os-directory Display the relative path to OS libraries.\n"), stdout);
345438fd1498Szrj fputs (_(" -print-sysroot Display the target libraries directory.\n"), stdout);
345538fd1498Szrj fputs (_(" -print-sysroot-headers-suffix Display the sysroot suffix used to find headers.\n"), stdout);
345638fd1498Szrj fputs (_(" -Wa,<options> Pass comma-separated <options> on to the assembler.\n"), stdout);
345738fd1498Szrj fputs (_(" -Wp,<options> Pass comma-separated <options> on to the preprocessor.\n"), stdout);
345838fd1498Szrj fputs (_(" -Wl,<options> Pass comma-separated <options> on to the linker.\n"), stdout);
345938fd1498Szrj fputs (_(" -Xassembler <arg> Pass <arg> on to the assembler.\n"), stdout);
346038fd1498Szrj fputs (_(" -Xpreprocessor <arg> Pass <arg> on to the preprocessor.\n"), stdout);
346138fd1498Szrj fputs (_(" -Xlinker <arg> Pass <arg> on to the linker.\n"), stdout);
346238fd1498Szrj fputs (_(" -save-temps Do not delete intermediate files.\n"), stdout);
346338fd1498Szrj fputs (_(" -save-temps=<arg> Do not delete intermediate files.\n"), stdout);
346438fd1498Szrj fputs (_("\
346538fd1498Szrj -no-canonical-prefixes Do not canonicalize paths when building relative\n\
346638fd1498Szrj prefixes to other gcc components.\n"), stdout);
346738fd1498Szrj fputs (_(" -pipe Use pipes rather than intermediate files.\n"), stdout);
346838fd1498Szrj fputs (_(" -time Time the execution of each subprocess.\n"), stdout);
346938fd1498Szrj fputs (_(" -specs=<file> Override built-in specs with the contents of <file>.\n"), stdout);
347038fd1498Szrj fputs (_(" -std=<standard> Assume that the input sources are for <standard>.\n"), stdout);
347138fd1498Szrj fputs (_("\
347238fd1498Szrj --sysroot=<directory> Use <directory> as the root directory for headers\n\
347338fd1498Szrj and libraries.\n"), stdout);
347438fd1498Szrj fputs (_(" -B <directory> Add <directory> to the compiler's search paths.\n"), stdout);
347538fd1498Szrj fputs (_(" -v Display the programs invoked by the compiler.\n"), stdout);
347638fd1498Szrj fputs (_(" -### Like -v but options quoted and commands not executed.\n"), stdout);
347738fd1498Szrj fputs (_(" -E Preprocess only; do not compile, assemble or link.\n"), stdout);
347838fd1498Szrj fputs (_(" -S Compile only; do not assemble or link.\n"), stdout);
347938fd1498Szrj fputs (_(" -c Compile and assemble, but do not link.\n"), stdout);
348038fd1498Szrj fputs (_(" -o <file> Place the output into <file>.\n"), stdout);
348138fd1498Szrj fputs (_(" -pie Create a dynamically linked position independent\n\
348238fd1498Szrj executable.\n"), stdout);
348338fd1498Szrj fputs (_(" -shared Create a shared library.\n"), stdout);
348438fd1498Szrj fputs (_("\
348538fd1498Szrj -x <language> Specify the language of the following input files.\n\
348638fd1498Szrj Permissible languages include: c c++ assembler none\n\
348738fd1498Szrj 'none' means revert to the default behavior of\n\
348838fd1498Szrj guessing the language based on the file's extension.\n\
348938fd1498Szrj "), stdout);
349038fd1498Szrj
349138fd1498Szrj printf (_("\
349238fd1498Szrj \nOptions starting with -g, -f, -m, -O, -W, or --param are automatically\n\
349338fd1498Szrj passed on to the various sub-processes invoked by %s. In order to pass\n\
349438fd1498Szrj other options on to these processes the -W<letter> options must be used.\n\
349538fd1498Szrj "), progname);
349638fd1498Szrj
349738fd1498Szrj /* The rest of the options are displayed by invocations of the various
349838fd1498Szrj sub-processes. */
349938fd1498Szrj }
350038fd1498Szrj
350138fd1498Szrj static void
add_preprocessor_option(const char * option,int len)350238fd1498Szrj add_preprocessor_option (const char *option, int len)
350338fd1498Szrj {
350438fd1498Szrj preprocessor_options.safe_push (save_string (option, len));
350538fd1498Szrj }
350638fd1498Szrj
350738fd1498Szrj static void
add_assembler_option(const char * option,int len)350838fd1498Szrj add_assembler_option (const char *option, int len)
350938fd1498Szrj {
351038fd1498Szrj assembler_options.safe_push (save_string (option, len));
351138fd1498Szrj }
351238fd1498Szrj
351338fd1498Szrj static void
add_linker_option(const char * option,int len)351438fd1498Szrj add_linker_option (const char *option, int len)
351538fd1498Szrj {
351638fd1498Szrj linker_options.safe_push (save_string (option, len));
351738fd1498Szrj }
351838fd1498Szrj
351938fd1498Szrj /* Allocate space for an input file in infiles. */
352038fd1498Szrj
352138fd1498Szrj static void
alloc_infile(void)352238fd1498Szrj alloc_infile (void)
352338fd1498Szrj {
352438fd1498Szrj if (n_infiles_alloc == 0)
352538fd1498Szrj {
352638fd1498Szrj n_infiles_alloc = 16;
352738fd1498Szrj infiles = XNEWVEC (struct infile, n_infiles_alloc);
352838fd1498Szrj }
352938fd1498Szrj else if (n_infiles_alloc == n_infiles)
353038fd1498Szrj {
353138fd1498Szrj n_infiles_alloc *= 2;
353238fd1498Szrj infiles = XRESIZEVEC (struct infile, infiles, n_infiles_alloc);
353338fd1498Szrj }
353438fd1498Szrj }
353538fd1498Szrj
353638fd1498Szrj /* Store an input file with the given NAME and LANGUAGE in
353738fd1498Szrj infiles. */
353838fd1498Szrj
353938fd1498Szrj static void
add_infile(const char * name,const char * language)354038fd1498Szrj add_infile (const char *name, const char *language)
354138fd1498Szrj {
354238fd1498Szrj alloc_infile ();
354338fd1498Szrj infiles[n_infiles].name = name;
354438fd1498Szrj infiles[n_infiles++].language = language;
354538fd1498Szrj }
354638fd1498Szrj
354738fd1498Szrj /* Allocate space for a switch in switches. */
354838fd1498Szrj
354938fd1498Szrj static void
alloc_switch(void)355038fd1498Szrj alloc_switch (void)
355138fd1498Szrj {
355238fd1498Szrj if (n_switches_alloc == 0)
355338fd1498Szrj {
355438fd1498Szrj n_switches_alloc = 16;
355538fd1498Szrj switches = XNEWVEC (struct switchstr, n_switches_alloc);
355638fd1498Szrj }
355738fd1498Szrj else if (n_switches_alloc == n_switches)
355838fd1498Szrj {
355938fd1498Szrj n_switches_alloc *= 2;
356038fd1498Szrj switches = XRESIZEVEC (struct switchstr, switches, n_switches_alloc);
356138fd1498Szrj }
356238fd1498Szrj }
356338fd1498Szrj
356438fd1498Szrj /* Save an option OPT with N_ARGS arguments in array ARGS, marking it
356538fd1498Szrj as validated if VALIDATED and KNOWN if it is an internal switch. */
356638fd1498Szrj
356738fd1498Szrj static void
save_switch(const char * opt,size_t n_args,const char * const * args,bool validated,bool known)356838fd1498Szrj save_switch (const char *opt, size_t n_args, const char *const *args,
356938fd1498Szrj bool validated, bool known)
357038fd1498Szrj {
357138fd1498Szrj alloc_switch ();
357238fd1498Szrj switches[n_switches].part1 = opt + 1;
357338fd1498Szrj if (n_args == 0)
357438fd1498Szrj switches[n_switches].args = 0;
357538fd1498Szrj else
357638fd1498Szrj {
357738fd1498Szrj switches[n_switches].args = XNEWVEC (const char *, n_args + 1);
357838fd1498Szrj memcpy (switches[n_switches].args, args, n_args * sizeof (const char *));
357938fd1498Szrj switches[n_switches].args[n_args] = NULL;
358038fd1498Szrj }
358138fd1498Szrj
358238fd1498Szrj switches[n_switches].live_cond = 0;
358338fd1498Szrj switches[n_switches].validated = validated;
358438fd1498Szrj switches[n_switches].known = known;
358538fd1498Szrj switches[n_switches].ordering = 0;
358638fd1498Szrj n_switches++;
358738fd1498Szrj }
358838fd1498Szrj
358938fd1498Szrj /* Set the SOURCE_DATE_EPOCH environment variable to the current time if it is
359038fd1498Szrj not set already. */
359138fd1498Szrj
359238fd1498Szrj static void
set_source_date_epoch_envvar()359338fd1498Szrj set_source_date_epoch_envvar ()
359438fd1498Szrj {
359538fd1498Szrj /* Array size is 21 = ceil(log_10(2^64)) + 1 to hold string representations
359638fd1498Szrj of 64 bit integers. */
359738fd1498Szrj char source_date_epoch[21];
359838fd1498Szrj time_t tt;
359938fd1498Szrj
360038fd1498Szrj errno = 0;
360138fd1498Szrj tt = time (NULL);
360238fd1498Szrj if (tt < (time_t) 0 || errno != 0)
360338fd1498Szrj tt = (time_t) 0;
360438fd1498Szrj
360538fd1498Szrj snprintf (source_date_epoch, 21, "%llu", (unsigned long long) tt);
360638fd1498Szrj /* Using setenv instead of xputenv because we want the variable to remain
360738fd1498Szrj after finalizing so that it's still set in the second run when using
360838fd1498Szrj -fcompare-debug. */
360938fd1498Szrj setenv ("SOURCE_DATE_EPOCH", source_date_epoch, 0);
361038fd1498Szrj }
361138fd1498Szrj
361238fd1498Szrj /* Handle an option DECODED that is unknown to the option-processing
361338fd1498Szrj machinery. */
361438fd1498Szrj
361538fd1498Szrj static bool
driver_unknown_option_callback(const struct cl_decoded_option * decoded)361638fd1498Szrj driver_unknown_option_callback (const struct cl_decoded_option *decoded)
361738fd1498Szrj {
361838fd1498Szrj const char *opt = decoded->arg;
361938fd1498Szrj if (opt[1] == 'W' && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-'
362038fd1498Szrj && !(decoded->errors & CL_ERR_NEGATIVE))
362138fd1498Szrj {
362238fd1498Szrj /* Leave unknown -Wno-* options for the compiler proper, to be
362338fd1498Szrj diagnosed only if there are warnings. */
362438fd1498Szrj save_switch (decoded->canonical_option[0],
362538fd1498Szrj decoded->canonical_option_num_elements - 1,
362638fd1498Szrj &decoded->canonical_option[1], false, true);
362738fd1498Szrj return false;
362838fd1498Szrj }
362938fd1498Szrj if (decoded->opt_index == OPT_SPECIAL_unknown)
363038fd1498Szrj {
363138fd1498Szrj /* Give it a chance to define it a spec file. */
363238fd1498Szrj save_switch (decoded->canonical_option[0],
363338fd1498Szrj decoded->canonical_option_num_elements - 1,
363438fd1498Szrj &decoded->canonical_option[1], false, false);
363538fd1498Szrj return false;
363638fd1498Szrj }
363738fd1498Szrj else
363838fd1498Szrj return true;
363938fd1498Szrj }
364038fd1498Szrj
364138fd1498Szrj /* Handle an option DECODED that is not marked as CL_DRIVER.
364238fd1498Szrj LANG_MASK will always be CL_DRIVER. */
364338fd1498Szrj
364438fd1498Szrj static void
driver_wrong_lang_callback(const struct cl_decoded_option * decoded,unsigned int lang_mask ATTRIBUTE_UNUSED)364538fd1498Szrj driver_wrong_lang_callback (const struct cl_decoded_option *decoded,
364638fd1498Szrj unsigned int lang_mask ATTRIBUTE_UNUSED)
364738fd1498Szrj {
364838fd1498Szrj /* At this point, non-driver options are accepted (and expected to
364938fd1498Szrj be passed down by specs) unless marked to be rejected by the
365038fd1498Szrj driver. Options to be rejected by the driver but accepted by the
365138fd1498Szrj compilers proper are treated just like completely unknown
365238fd1498Szrj options. */
365338fd1498Szrj const struct cl_option *option = &cl_options[decoded->opt_index];
365438fd1498Szrj
365538fd1498Szrj if (option->cl_reject_driver)
365638fd1498Szrj error ("unrecognized command line option %qs",
365738fd1498Szrj decoded->orig_option_with_args_text);
365838fd1498Szrj else
365938fd1498Szrj save_switch (decoded->canonical_option[0],
366038fd1498Szrj decoded->canonical_option_num_elements - 1,
366138fd1498Szrj &decoded->canonical_option[1], false, true);
366238fd1498Szrj }
366338fd1498Szrj
366438fd1498Szrj static const char *spec_lang = 0;
366538fd1498Szrj static int last_language_n_infiles;
366638fd1498Szrj
366738fd1498Szrj /* Parse -foffload option argument. */
366838fd1498Szrj
366938fd1498Szrj static void
handle_foffload_option(const char * arg)367038fd1498Szrj handle_foffload_option (const char *arg)
367138fd1498Szrj {
367238fd1498Szrj const char *c, *cur, *n, *next, *end;
367338fd1498Szrj char *target;
367438fd1498Szrj
367538fd1498Szrj /* If option argument starts with '-' then no target is specified and we
367638fd1498Szrj do not need to parse it. */
367738fd1498Szrj if (arg[0] == '-')
367838fd1498Szrj return;
367938fd1498Szrj
368038fd1498Szrj end = strchr (arg, '=');
368138fd1498Szrj if (end == NULL)
368238fd1498Szrj end = strchr (arg, '\0');
368338fd1498Szrj cur = arg;
368438fd1498Szrj
368538fd1498Szrj while (cur < end)
368638fd1498Szrj {
368738fd1498Szrj next = strchr (cur, ',');
368838fd1498Szrj if (next == NULL)
368938fd1498Szrj next = end;
369038fd1498Szrj next = (next > end) ? end : next;
369138fd1498Szrj
369238fd1498Szrj target = XNEWVEC (char, next - cur + 1);
369338fd1498Szrj memcpy (target, cur, next - cur);
369438fd1498Szrj target[next - cur] = '\0';
369538fd1498Szrj
369638fd1498Szrj /* If 'disable' is passed to the option, stop parsing the option and clean
369738fd1498Szrj the list of offload targets. */
369838fd1498Szrj if (strcmp (target, "disable") == 0)
369938fd1498Szrj {
370038fd1498Szrj free (offload_targets);
370138fd1498Szrj offload_targets = xstrdup ("");
370238fd1498Szrj break;
370338fd1498Szrj }
370438fd1498Szrj
370538fd1498Szrj /* Check that GCC is configured to support the offload target. */
370638fd1498Szrj c = OFFLOAD_TARGETS;
370738fd1498Szrj while (c)
370838fd1498Szrj {
370938fd1498Szrj n = strchr (c, ',');
371038fd1498Szrj if (n == NULL)
371138fd1498Szrj n = strchr (c, '\0');
371238fd1498Szrj
371338fd1498Szrj if (next - cur == n - c && strncmp (target, c, n - c) == 0)
371438fd1498Szrj break;
371538fd1498Szrj
371638fd1498Szrj c = *n ? n + 1 : NULL;
371738fd1498Szrj }
371838fd1498Szrj
371938fd1498Szrj if (!c)
372038fd1498Szrj fatal_error (input_location,
372138fd1498Szrj "GCC is not configured to support %s as offload target",
372238fd1498Szrj target);
372338fd1498Szrj
372438fd1498Szrj if (!offload_targets)
372538fd1498Szrj {
372638fd1498Szrj offload_targets = target;
372738fd1498Szrj target = NULL;
372838fd1498Szrj }
372938fd1498Szrj else
373038fd1498Szrj {
373138fd1498Szrj /* Check that the target hasn't already presented in the list. */
373238fd1498Szrj c = offload_targets;
373338fd1498Szrj do
373438fd1498Szrj {
373538fd1498Szrj n = strchr (c, ':');
373638fd1498Szrj if (n == NULL)
373738fd1498Szrj n = strchr (c, '\0');
373838fd1498Szrj
373938fd1498Szrj if (next - cur == n - c && strncmp (c, target, n - c) == 0)
374038fd1498Szrj break;
374138fd1498Szrj
374238fd1498Szrj c = n + 1;
374338fd1498Szrj }
374438fd1498Szrj while (*n);
374538fd1498Szrj
374638fd1498Szrj /* If duplicate is not found, append the target to the list. */
374738fd1498Szrj if (c > n)
374838fd1498Szrj {
374938fd1498Szrj size_t offload_targets_len = strlen (offload_targets);
375038fd1498Szrj offload_targets
375138fd1498Szrj = XRESIZEVEC (char, offload_targets,
375238fd1498Szrj offload_targets_len + 1 + next - cur + 1);
375338fd1498Szrj offload_targets[offload_targets_len++] = ':';
375438fd1498Szrj memcpy (offload_targets + offload_targets_len, target, next - cur + 1);
375538fd1498Szrj }
375638fd1498Szrj }
375738fd1498Szrj
375838fd1498Szrj cur = next + 1;
375938fd1498Szrj XDELETEVEC (target);
376038fd1498Szrj }
376138fd1498Szrj }
376238fd1498Szrj
376338fd1498Szrj /* Handle a driver option; arguments and return value as for
376438fd1498Szrj handle_option. */
376538fd1498Szrj
376638fd1498Szrj 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,void (*)(void))376738fd1498Szrj driver_handle_option (struct gcc_options *opts,
376838fd1498Szrj struct gcc_options *opts_set,
376938fd1498Szrj const struct cl_decoded_option *decoded,
377038fd1498Szrj unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
377138fd1498Szrj location_t loc,
377238fd1498Szrj const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED,
377338fd1498Szrj diagnostic_context *dc,
377438fd1498Szrj void (*) (void))
377538fd1498Szrj {
377638fd1498Szrj size_t opt_index = decoded->opt_index;
377738fd1498Szrj const char *arg = decoded->arg;
377838fd1498Szrj const char *compare_debug_replacement_opt;
377938fd1498Szrj int value = decoded->value;
378038fd1498Szrj bool validated = false;
378138fd1498Szrj bool do_save = true;
378238fd1498Szrj
378338fd1498Szrj gcc_assert (opts == &global_options);
378438fd1498Szrj gcc_assert (opts_set == &global_options_set);
378538fd1498Szrj gcc_assert (kind == DK_UNSPECIFIED);
378638fd1498Szrj gcc_assert (loc == UNKNOWN_LOCATION);
378738fd1498Szrj gcc_assert (dc == global_dc);
378838fd1498Szrj
378938fd1498Szrj switch (opt_index)
379038fd1498Szrj {
379138fd1498Szrj case OPT_dumpspecs:
379238fd1498Szrj {
379338fd1498Szrj struct spec_list *sl;
379438fd1498Szrj init_spec ();
379538fd1498Szrj for (sl = specs; sl; sl = sl->next)
379638fd1498Szrj printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec));
379738fd1498Szrj if (link_command_spec)
379838fd1498Szrj printf ("*link_command:\n%s\n\n", link_command_spec);
379938fd1498Szrj exit (0);
380038fd1498Szrj }
380138fd1498Szrj
380238fd1498Szrj case OPT_dumpversion:
380338fd1498Szrj printf ("%s\n", spec_version);
380438fd1498Szrj exit (0);
380538fd1498Szrj
380638fd1498Szrj case OPT_dumpmachine:
380738fd1498Szrj printf ("%s\n", spec_machine);
380838fd1498Szrj exit (0);
380938fd1498Szrj
381038fd1498Szrj case OPT_dumpfullversion:
381138fd1498Szrj printf ("%s\n", BASEVER);
381238fd1498Szrj exit (0);
381338fd1498Szrj
381438fd1498Szrj case OPT__version:
381538fd1498Szrj print_version = 1;
381638fd1498Szrj
381738fd1498Szrj /* CPP driver cannot obtain switch from cc1_options. */
381838fd1498Szrj if (is_cpp_driver)
381938fd1498Szrj add_preprocessor_option ("--version", strlen ("--version"));
382038fd1498Szrj add_assembler_option ("--version", strlen ("--version"));
382138fd1498Szrj add_linker_option ("--version", strlen ("--version"));
382238fd1498Szrj break;
382338fd1498Szrj
382438fd1498Szrj case OPT__help:
382538fd1498Szrj print_help_list = 1;
382638fd1498Szrj
382738fd1498Szrj /* CPP driver cannot obtain switch from cc1_options. */
382838fd1498Szrj if (is_cpp_driver)
382938fd1498Szrj add_preprocessor_option ("--help", 6);
383038fd1498Szrj add_assembler_option ("--help", 6);
383138fd1498Szrj add_linker_option ("--help", 6);
383238fd1498Szrj break;
383338fd1498Szrj
383438fd1498Szrj case OPT__help_:
383538fd1498Szrj print_subprocess_help = 2;
383638fd1498Szrj break;
383738fd1498Szrj
383838fd1498Szrj case OPT__target_help:
383938fd1498Szrj print_subprocess_help = 1;
384038fd1498Szrj
384138fd1498Szrj /* CPP driver cannot obtain switch from cc1_options. */
384238fd1498Szrj if (is_cpp_driver)
384338fd1498Szrj add_preprocessor_option ("--target-help", 13);
384438fd1498Szrj add_assembler_option ("--target-help", 13);
384538fd1498Szrj add_linker_option ("--target-help", 13);
384638fd1498Szrj break;
384738fd1498Szrj
384838fd1498Szrj case OPT__no_sysroot_suffix:
384938fd1498Szrj case OPT_pass_exit_codes:
385038fd1498Szrj case OPT_print_search_dirs:
385138fd1498Szrj case OPT_print_file_name_:
385238fd1498Szrj case OPT_print_prog_name_:
385338fd1498Szrj case OPT_print_multi_lib:
385438fd1498Szrj case OPT_print_multi_directory:
385538fd1498Szrj case OPT_print_sysroot:
385638fd1498Szrj case OPT_print_multi_os_directory:
385738fd1498Szrj case OPT_print_multiarch:
385838fd1498Szrj case OPT_print_sysroot_headers_suffix:
385938fd1498Szrj case OPT_time:
386038fd1498Szrj case OPT_wrapper:
386138fd1498Szrj /* These options set the variables specified in common.opt
386238fd1498Szrj automatically, and do not need to be saved for spec
386338fd1498Szrj processing. */
386438fd1498Szrj do_save = false;
386538fd1498Szrj break;
386638fd1498Szrj
386738fd1498Szrj case OPT_print_libgcc_file_name:
386838fd1498Szrj print_file_name = "libgcc.a";
386938fd1498Szrj do_save = false;
387038fd1498Szrj break;
387138fd1498Szrj
387238fd1498Szrj case OPT_fuse_ld_bfd:
387338fd1498Szrj use_ld = ".bfd";
387438fd1498Szrj break;
387538fd1498Szrj
387638fd1498Szrj case OPT_fuse_ld_gold:
387738fd1498Szrj use_ld = ".gold";
387838fd1498Szrj break;
387938fd1498Szrj
388038fd1498Szrj case OPT_fcompare_debug_second:
388138fd1498Szrj compare_debug_second = 1;
388238fd1498Szrj break;
388338fd1498Szrj
388438fd1498Szrj case OPT_fcompare_debug:
388538fd1498Szrj switch (value)
388638fd1498Szrj {
388738fd1498Szrj case 0:
388838fd1498Szrj compare_debug_replacement_opt = "-fcompare-debug=";
388938fd1498Szrj arg = "";
389038fd1498Szrj goto compare_debug_with_arg;
389138fd1498Szrj
389238fd1498Szrj case 1:
389338fd1498Szrj compare_debug_replacement_opt = "-fcompare-debug=-gtoggle";
389438fd1498Szrj arg = "-gtoggle";
389538fd1498Szrj goto compare_debug_with_arg;
389638fd1498Szrj
389738fd1498Szrj default:
389838fd1498Szrj gcc_unreachable ();
389938fd1498Szrj }
390038fd1498Szrj break;
390138fd1498Szrj
390238fd1498Szrj case OPT_fcompare_debug_:
390338fd1498Szrj compare_debug_replacement_opt = decoded->canonical_option[0];
390438fd1498Szrj compare_debug_with_arg:
390538fd1498Szrj gcc_assert (decoded->canonical_option_num_elements == 1);
390638fd1498Szrj gcc_assert (arg != NULL);
390738fd1498Szrj if (*arg)
390838fd1498Szrj compare_debug = 1;
390938fd1498Szrj else
391038fd1498Szrj compare_debug = -1;
391138fd1498Szrj if (compare_debug < 0)
391238fd1498Szrj compare_debug_opt = NULL;
391338fd1498Szrj else
391438fd1498Szrj compare_debug_opt = arg;
391538fd1498Szrj save_switch (compare_debug_replacement_opt, 0, NULL, validated, true);
391638fd1498Szrj set_source_date_epoch_envvar ();
391738fd1498Szrj return true;
391838fd1498Szrj
391938fd1498Szrj case OPT_fdiagnostics_color_:
392038fd1498Szrj diagnostic_color_init (dc, value);
392138fd1498Szrj break;
392238fd1498Szrj
392338fd1498Szrj case OPT_Wa_:
392438fd1498Szrj {
392538fd1498Szrj int prev, j;
392638fd1498Szrj /* Pass the rest of this option to the assembler. */
392738fd1498Szrj
392838fd1498Szrj /* Split the argument at commas. */
392938fd1498Szrj prev = 0;
393038fd1498Szrj for (j = 0; arg[j]; j++)
393138fd1498Szrj if (arg[j] == ',')
393238fd1498Szrj {
393338fd1498Szrj add_assembler_option (arg + prev, j - prev);
393438fd1498Szrj prev = j + 1;
393538fd1498Szrj }
393638fd1498Szrj
393738fd1498Szrj /* Record the part after the last comma. */
393838fd1498Szrj add_assembler_option (arg + prev, j - prev);
393938fd1498Szrj }
394038fd1498Szrj do_save = false;
394138fd1498Szrj break;
394238fd1498Szrj
394338fd1498Szrj case OPT_Wp_:
394438fd1498Szrj {
394538fd1498Szrj int prev, j;
394638fd1498Szrj /* Pass the rest of this option to the preprocessor. */
394738fd1498Szrj
394838fd1498Szrj /* Split the argument at commas. */
394938fd1498Szrj prev = 0;
395038fd1498Szrj for (j = 0; arg[j]; j++)
395138fd1498Szrj if (arg[j] == ',')
395238fd1498Szrj {
395338fd1498Szrj add_preprocessor_option (arg + prev, j - prev);
395438fd1498Szrj prev = j + 1;
395538fd1498Szrj }
395638fd1498Szrj
395738fd1498Szrj /* Record the part after the last comma. */
395838fd1498Szrj add_preprocessor_option (arg + prev, j - prev);
395938fd1498Szrj }
396038fd1498Szrj do_save = false;
396138fd1498Szrj break;
396238fd1498Szrj
396338fd1498Szrj case OPT_Wl_:
396438fd1498Szrj {
396538fd1498Szrj int prev, j;
396638fd1498Szrj /* Split the argument at commas. */
396738fd1498Szrj prev = 0;
396838fd1498Szrj for (j = 0; arg[j]; j++)
396938fd1498Szrj if (arg[j] == ',')
397038fd1498Szrj {
397138fd1498Szrj add_infile (save_string (arg + prev, j - prev), "*");
397238fd1498Szrj prev = j + 1;
397338fd1498Szrj }
397438fd1498Szrj /* Record the part after the last comma. */
397538fd1498Szrj add_infile (arg + prev, "*");
397638fd1498Szrj }
397738fd1498Szrj do_save = false;
397838fd1498Szrj break;
397938fd1498Szrj
398038fd1498Szrj case OPT_Xlinker:
398138fd1498Szrj add_infile (arg, "*");
398238fd1498Szrj do_save = false;
398338fd1498Szrj break;
398438fd1498Szrj
398538fd1498Szrj case OPT_Xpreprocessor:
398638fd1498Szrj add_preprocessor_option (arg, strlen (arg));
398738fd1498Szrj do_save = false;
398838fd1498Szrj break;
398938fd1498Szrj
399038fd1498Szrj case OPT_Xassembler:
399138fd1498Szrj add_assembler_option (arg, strlen (arg));
399238fd1498Szrj do_save = false;
399338fd1498Szrj break;
399438fd1498Szrj
399538fd1498Szrj case OPT_l:
399638fd1498Szrj /* POSIX allows separation of -l and the lib arg; canonicalize
399738fd1498Szrj by concatenating -l with its arg */
399838fd1498Szrj add_infile (concat ("-l", arg, NULL), "*");
399938fd1498Szrj do_save = false;
400038fd1498Szrj break;
400138fd1498Szrj
400238fd1498Szrj case OPT_L:
400338fd1498Szrj /* Similarly, canonicalize -L for linkers that may not accept
400438fd1498Szrj separate arguments. */
400538fd1498Szrj save_switch (concat ("-L", arg, NULL), 0, NULL, validated, true);
400638fd1498Szrj return true;
400738fd1498Szrj
400838fd1498Szrj case OPT_F:
400938fd1498Szrj /* Likewise -F. */
401038fd1498Szrj save_switch (concat ("-F", arg, NULL), 0, NULL, validated, true);
401138fd1498Szrj return true;
401238fd1498Szrj
401338fd1498Szrj case OPT_save_temps:
401438fd1498Szrj save_temps_flag = SAVE_TEMPS_CWD;
401538fd1498Szrj validated = true;
401638fd1498Szrj break;
401738fd1498Szrj
401838fd1498Szrj case OPT_save_temps_:
401938fd1498Szrj if (strcmp (arg, "cwd") == 0)
402038fd1498Szrj save_temps_flag = SAVE_TEMPS_CWD;
402138fd1498Szrj else if (strcmp (arg, "obj") == 0
402238fd1498Szrj || strcmp (arg, "object") == 0)
402338fd1498Szrj save_temps_flag = SAVE_TEMPS_OBJ;
4024*df642abcSzrj else if (strcmp (arg, "objects") == 0)
4025*df642abcSzrj save_temps_flag = SAVE_TEMPS_OBJZ;
402638fd1498Szrj else
402738fd1498Szrj fatal_error (input_location, "%qs is an unknown -save-temps option",
402838fd1498Szrj decoded->orig_option_with_args_text);
402938fd1498Szrj break;
403038fd1498Szrj
403138fd1498Szrj case OPT_no_canonical_prefixes:
403238fd1498Szrj /* Already handled as a special case, so ignored here. */
403338fd1498Szrj do_save = false;
403438fd1498Szrj break;
403538fd1498Szrj
403638fd1498Szrj case OPT_pipe:
403738fd1498Szrj validated = true;
403838fd1498Szrj /* These options set the variables specified in common.opt
403938fd1498Szrj automatically, but do need to be saved for spec
404038fd1498Szrj processing. */
404138fd1498Szrj break;
404238fd1498Szrj
404338fd1498Szrj case OPT_specs_:
404438fd1498Szrj {
404538fd1498Szrj struct user_specs *user = XNEW (struct user_specs);
404638fd1498Szrj
404738fd1498Szrj user->next = (struct user_specs *) 0;
404838fd1498Szrj user->filename = arg;
404938fd1498Szrj if (user_specs_tail)
405038fd1498Szrj user_specs_tail->next = user;
405138fd1498Szrj else
405238fd1498Szrj user_specs_head = user;
405338fd1498Szrj user_specs_tail = user;
405438fd1498Szrj }
405538fd1498Szrj validated = true;
405638fd1498Szrj break;
405738fd1498Szrj
405838fd1498Szrj case OPT__sysroot_:
405938fd1498Szrj target_system_root = arg;
406038fd1498Szrj target_system_root_changed = 1;
406138fd1498Szrj do_save = false;
406238fd1498Szrj break;
406338fd1498Szrj
406438fd1498Szrj case OPT_time_:
406538fd1498Szrj if (report_times_to_file)
406638fd1498Szrj fclose (report_times_to_file);
406738fd1498Szrj report_times_to_file = fopen (arg, "a");
406838fd1498Szrj do_save = false;
406938fd1498Szrj break;
407038fd1498Szrj
407138fd1498Szrj case OPT____:
407238fd1498Szrj /* "-###"
407338fd1498Szrj This is similar to -v except that there is no execution
407438fd1498Szrj of the commands and the echoed arguments are quoted. It
407538fd1498Szrj is intended for use in shell scripts to capture the
407638fd1498Szrj driver-generated command line. */
407738fd1498Szrj verbose_only_flag++;
407838fd1498Szrj verbose_flag = 1;
407938fd1498Szrj do_save = false;
408038fd1498Szrj break;
408138fd1498Szrj
408238fd1498Szrj case OPT_B:
408338fd1498Szrj {
408438fd1498Szrj size_t len = strlen (arg);
408538fd1498Szrj
408638fd1498Szrj /* Catch the case where the user has forgotten to append a
408738fd1498Szrj directory separator to the path. Note, they may be using
408838fd1498Szrj -B to add an executable name prefix, eg "i386-elf-", in
408938fd1498Szrj order to distinguish between multiple installations of
409038fd1498Szrj GCC in the same directory. Hence we must check to see
409138fd1498Szrj if appending a directory separator actually makes a
409238fd1498Szrj valid directory name. */
409338fd1498Szrj if (!IS_DIR_SEPARATOR (arg[len - 1])
409438fd1498Szrj && is_directory (arg, false))
409538fd1498Szrj {
409638fd1498Szrj char *tmp = XNEWVEC (char, len + 2);
409738fd1498Szrj strcpy (tmp, arg);
409838fd1498Szrj tmp[len] = DIR_SEPARATOR;
409938fd1498Szrj tmp[++len] = 0;
410038fd1498Szrj arg = tmp;
410138fd1498Szrj }
410238fd1498Szrj
410338fd1498Szrj add_prefix (&exec_prefixes, arg, NULL,
410438fd1498Szrj PREFIX_PRIORITY_B_OPT, 0, 0);
410538fd1498Szrj add_prefix (&startfile_prefixes, arg, NULL,
410638fd1498Szrj PREFIX_PRIORITY_B_OPT, 0, 0);
410738fd1498Szrj add_prefix (&include_prefixes, arg, NULL,
410838fd1498Szrj PREFIX_PRIORITY_B_OPT, 0, 0);
410938fd1498Szrj }
411038fd1498Szrj validated = true;
411138fd1498Szrj break;
411238fd1498Szrj
411338fd1498Szrj case OPT_E:
411438fd1498Szrj have_E = true;
411538fd1498Szrj break;
411638fd1498Szrj
411738fd1498Szrj case OPT_x:
411838fd1498Szrj spec_lang = arg;
411938fd1498Szrj if (!strcmp (spec_lang, "none"))
412038fd1498Szrj /* Suppress the warning if -xnone comes after the last input
412138fd1498Szrj file, because alternate command interfaces like g++ might
412238fd1498Szrj find it useful to place -xnone after each input file. */
412338fd1498Szrj spec_lang = 0;
412438fd1498Szrj else
412538fd1498Szrj last_language_n_infiles = n_infiles;
412638fd1498Szrj do_save = false;
412738fd1498Szrj break;
412838fd1498Szrj
412938fd1498Szrj case OPT_o:
413038fd1498Szrj have_o = 1;
413138fd1498Szrj #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX)
413238fd1498Szrj arg = convert_filename (arg, ! have_c, 0);
413338fd1498Szrj #endif
413438fd1498Szrj output_file = arg;
413538fd1498Szrj /* Save the output name in case -save-temps=obj was used. */
413638fd1498Szrj save_temps_prefix = xstrdup (arg);
413738fd1498Szrj /* On some systems, ld cannot handle "-o" without a space. So
413838fd1498Szrj split the option from its argument. */
413938fd1498Szrj save_switch ("-o", 1, &arg, validated, true);
414038fd1498Szrj return true;
414138fd1498Szrj
414238fd1498Szrj #ifdef ENABLE_DEFAULT_PIE
414338fd1498Szrj case OPT_pie:
414438fd1498Szrj /* -pie is turned on by default. */
414538fd1498Szrj #endif
414638fd1498Szrj
414738fd1498Szrj case OPT_static_libgcc:
414838fd1498Szrj case OPT_shared_libgcc:
414938fd1498Szrj case OPT_static_libgfortran:
415038fd1498Szrj case OPT_static_libstdc__:
415138fd1498Szrj /* These are always valid, since gcc.c itself understands the
415238fd1498Szrj first two, gfortranspec.c understands -static-libgfortran and
415338fd1498Szrj g++spec.c understands -static-libstdc++ */
415438fd1498Szrj validated = true;
415538fd1498Szrj break;
415638fd1498Szrj
415738fd1498Szrj case OPT_fwpa:
415838fd1498Szrj flag_wpa = "";
415938fd1498Szrj break;
416038fd1498Szrj
416138fd1498Szrj case OPT_foffload_:
416238fd1498Szrj handle_foffload_option (arg);
416338fd1498Szrj break;
416438fd1498Szrj
416538fd1498Szrj default:
416638fd1498Szrj /* Various driver options need no special processing at this
416738fd1498Szrj point, having been handled in a prescan above or being
416838fd1498Szrj handled by specs. */
416938fd1498Szrj break;
417038fd1498Szrj }
417138fd1498Szrj
417238fd1498Szrj if (do_save)
417338fd1498Szrj save_switch (decoded->canonical_option[0],
417438fd1498Szrj decoded->canonical_option_num_elements - 1,
417538fd1498Szrj &decoded->canonical_option[1], validated, true);
417638fd1498Szrj return true;
417738fd1498Szrj }
417838fd1498Szrj
417938fd1498Szrj /* Put the driver's standard set of option handlers in *HANDLERS. */
418038fd1498Szrj
418138fd1498Szrj static void
set_option_handlers(struct cl_option_handlers * handlers)418238fd1498Szrj set_option_handlers (struct cl_option_handlers *handlers)
418338fd1498Szrj {
418438fd1498Szrj handlers->unknown_option_callback = driver_unknown_option_callback;
418538fd1498Szrj handlers->wrong_lang_callback = driver_wrong_lang_callback;
418638fd1498Szrj handlers->num_handlers = 3;
418738fd1498Szrj handlers->handlers[0].handler = driver_handle_option;
418838fd1498Szrj handlers->handlers[0].mask = CL_DRIVER;
418938fd1498Szrj handlers->handlers[1].handler = common_handle_option;
419038fd1498Szrj handlers->handlers[1].mask = CL_COMMON;
419138fd1498Szrj handlers->handlers[2].handler = target_handle_option;
419238fd1498Szrj handlers->handlers[2].mask = CL_TARGET;
419338fd1498Szrj }
419438fd1498Szrj
419538fd1498Szrj /* Create the vector `switches' and its contents.
419638fd1498Szrj Store its length in `n_switches'. */
419738fd1498Szrj
419838fd1498Szrj static void
process_command(unsigned int decoded_options_count,struct cl_decoded_option * decoded_options)419938fd1498Szrj process_command (unsigned int decoded_options_count,
420038fd1498Szrj struct cl_decoded_option *decoded_options)
420138fd1498Szrj {
420238fd1498Szrj const char *temp;
420338fd1498Szrj char *temp1;
420438fd1498Szrj char *tooldir_prefix, *tooldir_prefix2;
420538fd1498Szrj char *(*get_relative_prefix) (const char *, const char *,
420638fd1498Szrj const char *) = NULL;
420738fd1498Szrj struct cl_option_handlers handlers;
420838fd1498Szrj unsigned int j;
420938fd1498Szrj
421038fd1498Szrj gcc_exec_prefix = env.get ("GCC_EXEC_PREFIX");
421138fd1498Szrj
421238fd1498Szrj n_switches = 0;
421338fd1498Szrj n_infiles = 0;
421438fd1498Szrj added_libraries = 0;
421538fd1498Szrj
421638fd1498Szrj /* Figure compiler version from version string. */
421738fd1498Szrj
421838fd1498Szrj compiler_version = temp1 = xstrdup (version_string);
421938fd1498Szrj
422038fd1498Szrj for (; *temp1; ++temp1)
422138fd1498Szrj {
422238fd1498Szrj if (*temp1 == ' ')
422338fd1498Szrj {
422438fd1498Szrj *temp1 = '\0';
422538fd1498Szrj break;
422638fd1498Szrj }
422738fd1498Szrj }
422838fd1498Szrj
422938fd1498Szrj /* Handle any -no-canonical-prefixes flag early, to assign the function
423038fd1498Szrj that builds relative prefixes. This function creates default search
423138fd1498Szrj paths that are needed later in normal option handling. */
423238fd1498Szrj
423338fd1498Szrj for (j = 1; j < decoded_options_count; j++)
423438fd1498Szrj {
423538fd1498Szrj if (decoded_options[j].opt_index == OPT_no_canonical_prefixes)
423638fd1498Szrj {
423738fd1498Szrj get_relative_prefix = make_relative_prefix_ignore_links;
423838fd1498Szrj break;
423938fd1498Szrj }
424038fd1498Szrj }
424138fd1498Szrj if (! get_relative_prefix)
424238fd1498Szrj get_relative_prefix = make_relative_prefix;
424338fd1498Szrj
424438fd1498Szrj /* Set up the default search paths. If there is no GCC_EXEC_PREFIX,
424538fd1498Szrj see if we can create it from the pathname specified in
424638fd1498Szrj decoded_options[0].arg. */
424738fd1498Szrj
424838fd1498Szrj gcc_libexec_prefix = standard_libexec_prefix;
424938fd1498Szrj #ifndef VMS
425038fd1498Szrj /* FIXME: make_relative_prefix doesn't yet work for VMS. */
425138fd1498Szrj if (!gcc_exec_prefix)
425238fd1498Szrj {
4253632577dbSzrj #if 0 /* DragonFly base: Never use relative prefix (not bootstrapped) */
425438fd1498Szrj gcc_exec_prefix = get_relative_prefix (decoded_options[0].arg,
425538fd1498Szrj standard_bindir_prefix,
425638fd1498Szrj standard_exec_prefix);
425738fd1498Szrj gcc_libexec_prefix = get_relative_prefix (decoded_options[0].arg,
425838fd1498Szrj standard_bindir_prefix,
425938fd1498Szrj standard_libexec_prefix);
426038fd1498Szrj if (gcc_exec_prefix)
426138fd1498Szrj xputenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL));
4262632577dbSzrj #endif
426338fd1498Szrj }
426438fd1498Szrj else
426538fd1498Szrj {
426638fd1498Szrj /* make_relative_prefix requires a program name, but
426738fd1498Szrj GCC_EXEC_PREFIX is typically a directory name with a trailing
426838fd1498Szrj / (which is ignored by make_relative_prefix), so append a
426938fd1498Szrj program name. */
427038fd1498Szrj char *tmp_prefix = concat (gcc_exec_prefix, "gcc", NULL);
427138fd1498Szrj gcc_libexec_prefix = get_relative_prefix (tmp_prefix,
427238fd1498Szrj standard_exec_prefix,
427338fd1498Szrj standard_libexec_prefix);
427438fd1498Szrj
427538fd1498Szrj /* The path is unrelocated, so fallback to the original setting. */
427638fd1498Szrj if (!gcc_libexec_prefix)
427738fd1498Szrj gcc_libexec_prefix = standard_libexec_prefix;
427838fd1498Szrj
427938fd1498Szrj free (tmp_prefix);
428038fd1498Szrj }
428138fd1498Szrj #else
428238fd1498Szrj #endif
428338fd1498Szrj /* From this point onward, gcc_exec_prefix is non-null if the toolchain
428438fd1498Szrj is relocated. The toolchain was either relocated using GCC_EXEC_PREFIX
428538fd1498Szrj or an automatically created GCC_EXEC_PREFIX from
428638fd1498Szrj decoded_options[0].arg. */
428738fd1498Szrj
428838fd1498Szrj /* Do language-specific adjustment/addition of flags. */
428938fd1498Szrj lang_specific_driver (&decoded_options, &decoded_options_count,
429038fd1498Szrj &added_libraries);
429138fd1498Szrj
429238fd1498Szrj if (gcc_exec_prefix)
429338fd1498Szrj {
429438fd1498Szrj int len = strlen (gcc_exec_prefix);
429538fd1498Szrj
429638fd1498Szrj if (len > (int) sizeof ("/lib/gcc/") - 1
429738fd1498Szrj && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1])))
429838fd1498Szrj {
429938fd1498Szrj temp = gcc_exec_prefix + len - sizeof ("/lib/gcc/") + 1;
430038fd1498Szrj if (IS_DIR_SEPARATOR (*temp)
430138fd1498Szrj && filename_ncmp (temp + 1, "lib", 3) == 0
430238fd1498Szrj && IS_DIR_SEPARATOR (temp[4])
430338fd1498Szrj && filename_ncmp (temp + 5, "gcc", 3) == 0)
430438fd1498Szrj len -= sizeof ("/lib/gcc/") - 1;
430538fd1498Szrj }
430638fd1498Szrj
4307632577dbSzrj #if 0 /* DragonFly base: Bad Paths */
430838fd1498Szrj set_std_prefix (gcc_exec_prefix, len);
430938fd1498Szrj add_prefix (&exec_prefixes, gcc_libexec_prefix, "GCC",
431038fd1498Szrj PREFIX_PRIORITY_LAST, 0, 0);
431138fd1498Szrj add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC",
431238fd1498Szrj PREFIX_PRIORITY_LAST, 0, 0);
4313632577dbSzrj #endif
431438fd1498Szrj }
431538fd1498Szrj
431638fd1498Szrj /* COMPILER_PATH and LIBRARY_PATH have values
431738fd1498Szrj that are lists of directory names with colons. */
431838fd1498Szrj
431938fd1498Szrj temp = env.get ("COMPILER_PATH");
432038fd1498Szrj if (temp)
432138fd1498Szrj {
432238fd1498Szrj const char *startp, *endp;
432338fd1498Szrj char *nstore = (char *) alloca (strlen (temp) + 3);
432438fd1498Szrj
432538fd1498Szrj startp = endp = temp;
432638fd1498Szrj while (1)
432738fd1498Szrj {
432838fd1498Szrj if (*endp == PATH_SEPARATOR || *endp == 0)
432938fd1498Szrj {
433038fd1498Szrj strncpy (nstore, startp, endp - startp);
433138fd1498Szrj if (endp == startp)
433238fd1498Szrj strcpy (nstore, concat (".", dir_separator_str, NULL));
433338fd1498Szrj else if (!IS_DIR_SEPARATOR (endp[-1]))
433438fd1498Szrj {
433538fd1498Szrj nstore[endp - startp] = DIR_SEPARATOR;
433638fd1498Szrj nstore[endp - startp + 1] = 0;
433738fd1498Szrj }
433838fd1498Szrj else
433938fd1498Szrj nstore[endp - startp] = 0;
434038fd1498Szrj add_prefix (&exec_prefixes, nstore, 0,
434138fd1498Szrj PREFIX_PRIORITY_LAST, 0, 0);
434238fd1498Szrj add_prefix (&include_prefixes, nstore, 0,
434338fd1498Szrj PREFIX_PRIORITY_LAST, 0, 0);
434438fd1498Szrj if (*endp == 0)
434538fd1498Szrj break;
434638fd1498Szrj endp = startp = endp + 1;
434738fd1498Szrj }
434838fd1498Szrj else
434938fd1498Szrj endp++;
435038fd1498Szrj }
435138fd1498Szrj }
435238fd1498Szrj
435338fd1498Szrj temp = env.get (LIBRARY_PATH_ENV);
435438fd1498Szrj if (temp && *cross_compile == '0')
435538fd1498Szrj {
435638fd1498Szrj const char *startp, *endp;
435738fd1498Szrj char *nstore = (char *) alloca (strlen (temp) + 3);
435838fd1498Szrj
435938fd1498Szrj startp = endp = temp;
436038fd1498Szrj while (1)
436138fd1498Szrj {
436238fd1498Szrj if (*endp == PATH_SEPARATOR || *endp == 0)
436338fd1498Szrj {
436438fd1498Szrj strncpy (nstore, startp, endp - startp);
436538fd1498Szrj if (endp == startp)
436638fd1498Szrj strcpy (nstore, concat (".", dir_separator_str, NULL));
436738fd1498Szrj else if (!IS_DIR_SEPARATOR (endp[-1]))
436838fd1498Szrj {
436938fd1498Szrj nstore[endp - startp] = DIR_SEPARATOR;
437038fd1498Szrj nstore[endp - startp + 1] = 0;
437138fd1498Szrj }
437238fd1498Szrj else
437338fd1498Szrj nstore[endp - startp] = 0;
437438fd1498Szrj add_prefix (&startfile_prefixes, nstore, NULL,
437538fd1498Szrj PREFIX_PRIORITY_LAST, 0, 1);
437638fd1498Szrj if (*endp == 0)
437738fd1498Szrj break;
437838fd1498Szrj endp = startp = endp + 1;
437938fd1498Szrj }
438038fd1498Szrj else
438138fd1498Szrj endp++;
438238fd1498Szrj }
438338fd1498Szrj }
438438fd1498Szrj
438538fd1498Szrj /* Use LPATH like LIBRARY_PATH (for the CMU build program). */
438638fd1498Szrj temp = env.get ("LPATH");
438738fd1498Szrj if (temp && *cross_compile == '0')
438838fd1498Szrj {
438938fd1498Szrj const char *startp, *endp;
439038fd1498Szrj char *nstore = (char *) alloca (strlen (temp) + 3);
439138fd1498Szrj
439238fd1498Szrj startp = endp = temp;
439338fd1498Szrj while (1)
439438fd1498Szrj {
439538fd1498Szrj if (*endp == PATH_SEPARATOR || *endp == 0)
439638fd1498Szrj {
439738fd1498Szrj strncpy (nstore, startp, endp - startp);
439838fd1498Szrj if (endp == startp)
439938fd1498Szrj strcpy (nstore, concat (".", dir_separator_str, NULL));
440038fd1498Szrj else if (!IS_DIR_SEPARATOR (endp[-1]))
440138fd1498Szrj {
440238fd1498Szrj nstore[endp - startp] = DIR_SEPARATOR;
440338fd1498Szrj nstore[endp - startp + 1] = 0;
440438fd1498Szrj }
440538fd1498Szrj else
440638fd1498Szrj nstore[endp - startp] = 0;
440738fd1498Szrj add_prefix (&startfile_prefixes, nstore, NULL,
440838fd1498Szrj PREFIX_PRIORITY_LAST, 0, 1);
440938fd1498Szrj if (*endp == 0)
441038fd1498Szrj break;
441138fd1498Szrj endp = startp = endp + 1;
441238fd1498Szrj }
441338fd1498Szrj else
441438fd1498Szrj endp++;
441538fd1498Szrj }
441638fd1498Szrj }
441738fd1498Szrj
441838fd1498Szrj /* Process the options and store input files and switches in their
441938fd1498Szrj vectors. */
442038fd1498Szrj
442138fd1498Szrj last_language_n_infiles = -1;
442238fd1498Szrj
442338fd1498Szrj set_option_handlers (&handlers);
442438fd1498Szrj
442538fd1498Szrj for (j = 1; j < decoded_options_count; j++)
442638fd1498Szrj {
442738fd1498Szrj switch (decoded_options[j].opt_index)
442838fd1498Szrj {
442938fd1498Szrj case OPT_S:
443038fd1498Szrj case OPT_c:
443138fd1498Szrj case OPT_E:
443238fd1498Szrj have_c = 1;
443338fd1498Szrj break;
443438fd1498Szrj }
443538fd1498Szrj if (have_c)
443638fd1498Szrj break;
443738fd1498Szrj }
443838fd1498Szrj
443938fd1498Szrj for (j = 1; j < decoded_options_count; j++)
444038fd1498Szrj {
444138fd1498Szrj if (decoded_options[j].opt_index == OPT_SPECIAL_input_file)
444238fd1498Szrj {
444338fd1498Szrj const char *arg = decoded_options[j].arg;
444438fd1498Szrj const char *p = strrchr (arg, '@');
444538fd1498Szrj char *fname;
444638fd1498Szrj long offset;
444738fd1498Szrj int consumed;
444838fd1498Szrj #ifdef HAVE_TARGET_OBJECT_SUFFIX
444938fd1498Szrj arg = convert_filename (arg, 0, access (arg, F_OK));
445038fd1498Szrj #endif
445138fd1498Szrj /* For LTO static archive support we handle input file
445238fd1498Szrj specifications that are composed of a filename and
445338fd1498Szrj an offset like FNAME@OFFSET. */
445438fd1498Szrj if (p
445538fd1498Szrj && p != arg
445638fd1498Szrj && sscanf (p, "@%li%n", &offset, &consumed) >= 1
445738fd1498Szrj && strlen (p) == (unsigned int)consumed)
445838fd1498Szrj {
445938fd1498Szrj fname = (char *)xmalloc (p - arg + 1);
446038fd1498Szrj memcpy (fname, arg, p - arg);
446138fd1498Szrj fname[p - arg] = '\0';
446238fd1498Szrj /* Only accept non-stdin and existing FNAME parts, otherwise
446338fd1498Szrj try with the full name. */
446438fd1498Szrj if (strcmp (fname, "-") == 0 || access (fname, F_OK) < 0)
446538fd1498Szrj {
446638fd1498Szrj free (fname);
446738fd1498Szrj fname = xstrdup (arg);
446838fd1498Szrj }
446938fd1498Szrj }
447038fd1498Szrj else
447138fd1498Szrj fname = xstrdup (arg);
447238fd1498Szrj
447338fd1498Szrj if (strcmp (fname, "-") != 0 && access (fname, F_OK) < 0)
447438fd1498Szrj {
447538fd1498Szrj if (fname[0] == '@' && access (fname + 1, F_OK) < 0)
447638fd1498Szrj perror_with_name (fname + 1);
447738fd1498Szrj else
447838fd1498Szrj perror_with_name (fname);
447938fd1498Szrj }
448038fd1498Szrj else
448138fd1498Szrj add_infile (arg, spec_lang);
448238fd1498Szrj
448338fd1498Szrj free (fname);
448438fd1498Szrj continue;
448538fd1498Szrj }
448638fd1498Szrj
448738fd1498Szrj read_cmdline_option (&global_options, &global_options_set,
448838fd1498Szrj decoded_options + j, UNKNOWN_LOCATION,
448938fd1498Szrj CL_DRIVER, &handlers, global_dc);
449038fd1498Szrj }
449138fd1498Szrj
449238fd1498Szrj /* If the user didn't specify any, default to all configured offload
449338fd1498Szrj targets. */
449438fd1498Szrj if (ENABLE_OFFLOADING && offload_targets == NULL)
449538fd1498Szrj handle_foffload_option (OFFLOAD_TARGETS);
449638fd1498Szrj
449738fd1498Szrj if (output_file
449838fd1498Szrj && strcmp (output_file, "-") != 0
449938fd1498Szrj && strcmp (output_file, HOST_BIT_BUCKET) != 0)
450038fd1498Szrj {
450138fd1498Szrj int i;
450238fd1498Szrj for (i = 0; i < n_infiles; i++)
450338fd1498Szrj if ((!infiles[i].language || infiles[i].language[0] != '*')
450438fd1498Szrj && canonical_filename_eq (infiles[i].name, output_file))
450538fd1498Szrj fatal_error (input_location,
450638fd1498Szrj "input file %qs is the same as output file",
450738fd1498Szrj output_file);
450838fd1498Szrj }
450938fd1498Szrj
451038fd1498Szrj if (output_file != NULL && output_file[0] == '\0')
451138fd1498Szrj fatal_error (input_location, "output filename may not be empty");
451238fd1498Szrj
451338fd1498Szrj /* If -save-temps=obj and -o name, create the prefix to use for %b.
451438fd1498Szrj Otherwise just make -save-temps=obj the same as -save-temps=cwd. */
451538fd1498Szrj if (save_temps_flag == SAVE_TEMPS_OBJ && save_temps_prefix != NULL)
451638fd1498Szrj {
451738fd1498Szrj save_temps_length = strlen (save_temps_prefix);
451838fd1498Szrj temp = strrchr (lbasename (save_temps_prefix), '.');
451938fd1498Szrj if (temp)
452038fd1498Szrj {
452138fd1498Szrj save_temps_length -= strlen (temp);
452238fd1498Szrj save_temps_prefix[save_temps_length] = '\0';
452338fd1498Szrj }
452438fd1498Szrj
452538fd1498Szrj }
4526*df642abcSzrj else if (save_temps_flag == SAVE_TEMPS_OBJZ && save_temps_prefix != NULL)
4527*df642abcSzrj {
4528*df642abcSzrj save_temps_length = strlen (save_temps_prefix);
4529*df642abcSzrj }
453038fd1498Szrj else if (save_temps_prefix != NULL)
453138fd1498Szrj {
453238fd1498Szrj free (save_temps_prefix);
453338fd1498Szrj save_temps_prefix = NULL;
453438fd1498Szrj }
453538fd1498Szrj
453638fd1498Szrj if (save_temps_flag && use_pipes)
453738fd1498Szrj {
453838fd1498Szrj /* -save-temps overrides -pipe, so that temp files are produced */
453938fd1498Szrj if (save_temps_flag)
454038fd1498Szrj warning (0, "-pipe ignored because -save-temps specified");
454138fd1498Szrj use_pipes = 0;
454238fd1498Szrj }
454338fd1498Szrj
454438fd1498Szrj if (!compare_debug)
454538fd1498Szrj {
454638fd1498Szrj const char *gcd = env.get ("GCC_COMPARE_DEBUG");
454738fd1498Szrj
454838fd1498Szrj if (gcd && gcd[0] == '-')
454938fd1498Szrj {
455038fd1498Szrj compare_debug = 2;
455138fd1498Szrj compare_debug_opt = gcd;
455238fd1498Szrj }
455338fd1498Szrj else if (gcd && *gcd && strcmp (gcd, "0"))
455438fd1498Szrj {
455538fd1498Szrj compare_debug = 3;
455638fd1498Szrj compare_debug_opt = "-gtoggle";
455738fd1498Szrj }
455838fd1498Szrj }
455938fd1498Szrj else if (compare_debug < 0)
456038fd1498Szrj {
456138fd1498Szrj compare_debug = 0;
456238fd1498Szrj gcc_assert (!compare_debug_opt);
456338fd1498Szrj }
456438fd1498Szrj
456538fd1498Szrj /* Set up the search paths. We add directories that we expect to
456638fd1498Szrj contain GNU Toolchain components before directories specified by
456738fd1498Szrj the machine description so that we will find GNU components (like
456838fd1498Szrj the GNU assembler) before those of the host system. */
456938fd1498Szrj
457038fd1498Szrj /* If we don't know where the toolchain has been installed, use the
457138fd1498Szrj configured-in locations. */
457238fd1498Szrj if (!gcc_exec_prefix)
457338fd1498Szrj {
457438fd1498Szrj #ifndef OS2
4575632577dbSzrj #if 1 /* DragonFly base: All tools in the same common location */
4576632577dbSzrj add_prefix (&exec_prefixes, standard_libexec_prefix, NULL,
4577632577dbSzrj PREFIX_PRIORITY_LAST, 0, 0);
4578632577dbSzrj #endif
4579632577dbSzrj #if 0 /* DragonFly base: Bad paths */
458038fd1498Szrj add_prefix (&exec_prefixes, standard_libexec_prefix, "GCC",
458138fd1498Szrj PREFIX_PRIORITY_LAST, 1, 0);
458238fd1498Szrj add_prefix (&exec_prefixes, standard_libexec_prefix, "BINUTILS",
458338fd1498Szrj PREFIX_PRIORITY_LAST, 2, 0);
458438fd1498Szrj add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS",
458538fd1498Szrj PREFIX_PRIORITY_LAST, 2, 0);
458638fd1498Szrj #endif
4587632577dbSzrj #endif
4588632577dbSzrj #if 0 /* DragonFly base: Bad paths */
458938fd1498Szrj add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS",
459038fd1498Szrj PREFIX_PRIORITY_LAST, 1, 0);
4591632577dbSzrj #endif
459238fd1498Szrj }
459338fd1498Szrj
459438fd1498Szrj gcc_assert (!IS_ABSOLUTE_PATH (tooldir_base_prefix));
459538fd1498Szrj tooldir_prefix2 = concat (tooldir_base_prefix, spec_machine,
459638fd1498Szrj dir_separator_str, NULL);
459738fd1498Szrj
459838fd1498Szrj /* Look for tools relative to the location from which the driver is
459938fd1498Szrj running, or, if that is not available, the configured prefix. */
460038fd1498Szrj tooldir_prefix
460138fd1498Szrj = concat (gcc_exec_prefix ? gcc_exec_prefix : standard_exec_prefix,
460238fd1498Szrj spec_host_machine, dir_separator_str, spec_version,
460338fd1498Szrj accel_dir_suffix, dir_separator_str, tooldir_prefix2, NULL);
460438fd1498Szrj free (tooldir_prefix2);
460538fd1498Szrj
4606632577dbSzrj #if 0 /* DragonFly base: Bad paths */
460738fd1498Szrj add_prefix (&exec_prefixes,
460838fd1498Szrj concat (tooldir_prefix, "bin", dir_separator_str, NULL),
460938fd1498Szrj "BINUTILS", PREFIX_PRIORITY_LAST, 0, 0);
461038fd1498Szrj add_prefix (&startfile_prefixes,
461138fd1498Szrj concat (tooldir_prefix, "lib", dir_separator_str, NULL),
461238fd1498Szrj "BINUTILS", PREFIX_PRIORITY_LAST, 0, 1);
4613632577dbSzrj #endif
461438fd1498Szrj free (tooldir_prefix);
461538fd1498Szrj
461638fd1498Szrj #if defined(TARGET_SYSTEM_ROOT_RELOCATABLE) && !defined(VMS)
461738fd1498Szrj /* If the normal TARGET_SYSTEM_ROOT is inside of $exec_prefix,
461838fd1498Szrj then consider it to relocate with the rest of the GCC installation
461938fd1498Szrj if GCC_EXEC_PREFIX is set.
462038fd1498Szrj ``make_relative_prefix'' is not compiled for VMS, so don't call it. */
462138fd1498Szrj if (target_system_root && !target_system_root_changed && gcc_exec_prefix)
462238fd1498Szrj {
462338fd1498Szrj char *tmp_prefix = get_relative_prefix (decoded_options[0].arg,
462438fd1498Szrj standard_bindir_prefix,
462538fd1498Szrj target_system_root);
462638fd1498Szrj if (tmp_prefix && access_check (tmp_prefix, F_OK) == 0)
462738fd1498Szrj {
462838fd1498Szrj target_system_root = tmp_prefix;
462938fd1498Szrj target_system_root_changed = 1;
463038fd1498Szrj }
463138fd1498Szrj }
463238fd1498Szrj #endif
463338fd1498Szrj
463438fd1498Szrj /* More prefixes are enabled in main, after we read the specs file
463538fd1498Szrj and determine whether this is cross-compilation or not. */
463638fd1498Szrj
463738fd1498Szrj if (n_infiles == last_language_n_infiles && spec_lang != 0)
463838fd1498Szrj warning (0, "%<-x %s%> after last input file has no effect", spec_lang);
463938fd1498Szrj
464038fd1498Szrj /* Synthesize -fcompare-debug flag from the GCC_COMPARE_DEBUG
464138fd1498Szrj environment variable. */
464238fd1498Szrj if (compare_debug == 2 || compare_debug == 3)
464338fd1498Szrj {
464438fd1498Szrj const char *opt = concat ("-fcompare-debug=", compare_debug_opt, NULL);
464538fd1498Szrj save_switch (opt, 0, NULL, false, true);
464638fd1498Szrj compare_debug = 1;
464738fd1498Szrj }
464838fd1498Szrj
464938fd1498Szrj /* Ensure we only invoke each subprocess once. */
465038fd1498Szrj if (print_subprocess_help || print_help_list || print_version)
465138fd1498Szrj {
465238fd1498Szrj n_infiles = 0;
465338fd1498Szrj
465438fd1498Szrj /* Create a dummy input file, so that we can pass
465538fd1498Szrj the help option on to the various sub-processes. */
465638fd1498Szrj add_infile ("help-dummy", "c");
465738fd1498Szrj }
465838fd1498Szrj
465938fd1498Szrj /* Decide if undefined variable references are allowed in specs. */
466038fd1498Szrj
466138fd1498Szrj /* -v alone is safe. --version and --help alone or together are safe. Note
466238fd1498Szrj that -v would make them unsafe, as they'd then be run for subprocesses as
466338fd1498Szrj well, the location of which might depend on variables possibly coming
466438fd1498Szrj from self-specs. Note also that the command name is counted in
466538fd1498Szrj decoded_options_count. */
466638fd1498Szrj
466738fd1498Szrj unsigned help_version_count = 0;
466838fd1498Szrj
466938fd1498Szrj if (print_version)
467038fd1498Szrj help_version_count++;
467138fd1498Szrj
467238fd1498Szrj if (print_help_list)
467338fd1498Szrj help_version_count++;
467438fd1498Szrj
467538fd1498Szrj spec_undefvar_allowed =
467638fd1498Szrj ((verbose_flag && decoded_options_count == 2)
467738fd1498Szrj || help_version_count == decoded_options_count - 1);
467838fd1498Szrj
467938fd1498Szrj alloc_switch ();
468038fd1498Szrj switches[n_switches].part1 = 0;
468138fd1498Szrj alloc_infile ();
468238fd1498Szrj infiles[n_infiles].name = 0;
468338fd1498Szrj }
468438fd1498Szrj
468538fd1498Szrj /* Store switches not filtered out by %<S in spec in COLLECT_GCC_OPTIONS
468638fd1498Szrj and place that in the environment. */
468738fd1498Szrj
468838fd1498Szrj static void
set_collect_gcc_options(void)468938fd1498Szrj set_collect_gcc_options (void)
469038fd1498Szrj {
469138fd1498Szrj int i;
469238fd1498Szrj int first_time;
469338fd1498Szrj
469438fd1498Szrj /* Build COLLECT_GCC_OPTIONS to have all of the options specified to
469538fd1498Szrj the compiler. */
469638fd1498Szrj obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
469738fd1498Szrj sizeof ("COLLECT_GCC_OPTIONS=") - 1);
469838fd1498Szrj
469938fd1498Szrj first_time = TRUE;
470038fd1498Szrj for (i = 0; (int) i < n_switches; i++)
470138fd1498Szrj {
470238fd1498Szrj const char *const *args;
470338fd1498Szrj const char *p, *q;
470438fd1498Szrj if (!first_time)
470538fd1498Szrj obstack_grow (&collect_obstack, " ", 1);
470638fd1498Szrj
470738fd1498Szrj first_time = FALSE;
470838fd1498Szrj
470938fd1498Szrj /* Ignore elided switches. */
471038fd1498Szrj if ((switches[i].live_cond
471138fd1498Szrj & (SWITCH_IGNORE | SWITCH_KEEP_FOR_GCC))
471238fd1498Szrj == SWITCH_IGNORE)
471338fd1498Szrj continue;
471438fd1498Szrj
471538fd1498Szrj obstack_grow (&collect_obstack, "'-", 2);
471638fd1498Szrj q = switches[i].part1;
471738fd1498Szrj while ((p = strchr (q, '\'')))
471838fd1498Szrj {
471938fd1498Szrj obstack_grow (&collect_obstack, q, p - q);
472038fd1498Szrj obstack_grow (&collect_obstack, "'\\''", 4);
472138fd1498Szrj q = ++p;
472238fd1498Szrj }
472338fd1498Szrj obstack_grow (&collect_obstack, q, strlen (q));
472438fd1498Szrj obstack_grow (&collect_obstack, "'", 1);
472538fd1498Szrj
472638fd1498Szrj for (args = switches[i].args; args && *args; args++)
472738fd1498Szrj {
472838fd1498Szrj obstack_grow (&collect_obstack, " '", 2);
472938fd1498Szrj q = *args;
473038fd1498Szrj while ((p = strchr (q, '\'')))
473138fd1498Szrj {
473238fd1498Szrj obstack_grow (&collect_obstack, q, p - q);
473338fd1498Szrj obstack_grow (&collect_obstack, "'\\''", 4);
473438fd1498Szrj q = ++p;
473538fd1498Szrj }
473638fd1498Szrj obstack_grow (&collect_obstack, q, strlen (q));
473738fd1498Szrj obstack_grow (&collect_obstack, "'", 1);
473838fd1498Szrj }
473938fd1498Szrj }
474038fd1498Szrj obstack_grow (&collect_obstack, "\0", 1);
474138fd1498Szrj xputenv (XOBFINISH (&collect_obstack, char *));
474238fd1498Szrj }
474338fd1498Szrj
474438fd1498Szrj /* Process a spec string, accumulating and running commands. */
474538fd1498Szrj
474638fd1498Szrj /* These variables describe the input file name.
474738fd1498Szrj input_file_number is the index on outfiles of this file,
474838fd1498Szrj so that the output file name can be stored for later use by %o.
474938fd1498Szrj input_basename is the start of the part of the input file
475038fd1498Szrj sans all directory names, and basename_length is the number
475138fd1498Szrj of characters starting there excluding the suffix .c or whatever. */
475238fd1498Szrj
475338fd1498Szrj static const char *gcc_input_filename;
475438fd1498Szrj static int input_file_number;
475538fd1498Szrj size_t input_filename_length;
475638fd1498Szrj static int basename_length;
475738fd1498Szrj static int suffixed_basename_length;
475838fd1498Szrj static const char *input_basename;
475938fd1498Szrj static const char *input_suffix;
476038fd1498Szrj #ifndef HOST_LACKS_INODE_NUMBERS
476138fd1498Szrj static struct stat input_stat;
476238fd1498Szrj #endif
476338fd1498Szrj static int input_stat_set;
476438fd1498Szrj
476538fd1498Szrj /* The compiler used to process the current input file. */
476638fd1498Szrj static struct compiler *input_file_compiler;
476738fd1498Szrj
476838fd1498Szrj /* These are variables used within do_spec and do_spec_1. */
476938fd1498Szrj
477038fd1498Szrj /* Nonzero if an arg has been started and not yet terminated
477138fd1498Szrj (with space, tab or newline). */
477238fd1498Szrj static int arg_going;
477338fd1498Szrj
477438fd1498Szrj /* Nonzero means %d or %g has been seen; the next arg to be terminated
477538fd1498Szrj is a temporary file name. */
477638fd1498Szrj static int delete_this_arg;
477738fd1498Szrj
477838fd1498Szrj /* Nonzero means %w has been seen; the next arg to be terminated
477938fd1498Szrj is the output file name of this compilation. */
478038fd1498Szrj static int this_is_output_file;
478138fd1498Szrj
478238fd1498Szrj /* Nonzero means %s has been seen; the next arg to be terminated
478338fd1498Szrj is the name of a library file and we should try the standard
478438fd1498Szrj search dirs for it. */
478538fd1498Szrj static int this_is_library_file;
478638fd1498Szrj
478738fd1498Szrj /* Nonzero means %T has been seen; the next arg to be terminated
478838fd1498Szrj is the name of a linker script and we should try all of the
478938fd1498Szrj standard search dirs for it. If it is found insert a --script
479038fd1498Szrj command line switch and then substitute the full path in place,
479138fd1498Szrj otherwise generate an error message. */
479238fd1498Szrj static int this_is_linker_script;
479338fd1498Szrj
479438fd1498Szrj /* Nonzero means that the input of this command is coming from a pipe. */
479538fd1498Szrj static int input_from_pipe;
479638fd1498Szrj
479738fd1498Szrj /* Nonnull means substitute this for any suffix when outputting a switches
479838fd1498Szrj arguments. */
479938fd1498Szrj static const char *suffix_subst;
480038fd1498Szrj
480138fd1498Szrj /* If there is an argument being accumulated, terminate it and store it. */
480238fd1498Szrj
480338fd1498Szrj static void
end_going_arg(void)480438fd1498Szrj end_going_arg (void)
480538fd1498Szrj {
480638fd1498Szrj if (arg_going)
480738fd1498Szrj {
480838fd1498Szrj const char *string;
480938fd1498Szrj
481038fd1498Szrj obstack_1grow (&obstack, 0);
481138fd1498Szrj string = XOBFINISH (&obstack, const char *);
481238fd1498Szrj if (this_is_library_file)
481338fd1498Szrj string = find_file (string);
481438fd1498Szrj if (this_is_linker_script)
481538fd1498Szrj {
481638fd1498Szrj char * full_script_path = find_a_file (&startfile_prefixes, string, R_OK, true);
481738fd1498Szrj
481838fd1498Szrj if (full_script_path == NULL)
481938fd1498Szrj {
482038fd1498Szrj error ("unable to locate default linker script %qs in the library search paths", string);
482138fd1498Szrj /* Script was not found on search path. */
482238fd1498Szrj return;
482338fd1498Szrj }
482438fd1498Szrj store_arg ("--script", false, false);
482538fd1498Szrj string = full_script_path;
482638fd1498Szrj }
482738fd1498Szrj store_arg (string, delete_this_arg, this_is_output_file);
482838fd1498Szrj if (this_is_output_file)
482938fd1498Szrj outfiles[input_file_number] = string;
483038fd1498Szrj arg_going = 0;
483138fd1498Szrj }
483238fd1498Szrj }
483338fd1498Szrj
483438fd1498Szrj
483538fd1498Szrj /* Parse the WRAPPER string which is a comma separated list of the command line
483638fd1498Szrj and insert them into the beginning of argbuf. */
483738fd1498Szrj
483838fd1498Szrj static void
insert_wrapper(const char * wrapper)483938fd1498Szrj insert_wrapper (const char *wrapper)
484038fd1498Szrj {
484138fd1498Szrj int n = 0;
484238fd1498Szrj int i;
484338fd1498Szrj char *buf = xstrdup (wrapper);
484438fd1498Szrj char *p = buf;
484538fd1498Szrj unsigned int old_length = argbuf.length ();
484638fd1498Szrj
484738fd1498Szrj do
484838fd1498Szrj {
484938fd1498Szrj n++;
485038fd1498Szrj while (*p == ',')
485138fd1498Szrj p++;
485238fd1498Szrj }
485338fd1498Szrj while ((p = strchr (p, ',')) != NULL);
485438fd1498Szrj
485538fd1498Szrj argbuf.safe_grow (old_length + n);
485638fd1498Szrj memmove (argbuf.address () + n,
485738fd1498Szrj argbuf.address (),
485838fd1498Szrj old_length * sizeof (const_char_p));
485938fd1498Szrj
486038fd1498Szrj i = 0;
486138fd1498Szrj p = buf;
486238fd1498Szrj do
486338fd1498Szrj {
486438fd1498Szrj while (*p == ',')
486538fd1498Szrj {
486638fd1498Szrj *p = 0;
486738fd1498Szrj p++;
486838fd1498Szrj }
486938fd1498Szrj argbuf[i] = p;
487038fd1498Szrj i++;
487138fd1498Szrj }
487238fd1498Szrj while ((p = strchr (p, ',')) != NULL);
487338fd1498Szrj gcc_assert (i == n);
487438fd1498Szrj }
487538fd1498Szrj
487638fd1498Szrj /* Process the spec SPEC and run the commands specified therein.
487738fd1498Szrj Returns 0 if the spec is successfully processed; -1 if failed. */
487838fd1498Szrj
487938fd1498Szrj int
do_spec(const char * spec)488038fd1498Szrj do_spec (const char *spec)
488138fd1498Szrj {
488238fd1498Szrj int value;
488338fd1498Szrj
488438fd1498Szrj value = do_spec_2 (spec);
488538fd1498Szrj
488638fd1498Szrj /* Force out any unfinished command.
488738fd1498Szrj If -pipe, this forces out the last command if it ended in `|'. */
488838fd1498Szrj if (value == 0)
488938fd1498Szrj {
489038fd1498Szrj if (argbuf.length () > 0
489138fd1498Szrj && !strcmp (argbuf.last (), "|"))
489238fd1498Szrj argbuf.pop ();
489338fd1498Szrj
489438fd1498Szrj set_collect_gcc_options ();
489538fd1498Szrj
489638fd1498Szrj if (argbuf.length () > 0)
489738fd1498Szrj value = execute ();
489838fd1498Szrj }
489938fd1498Szrj
490038fd1498Szrj return value;
490138fd1498Szrj }
490238fd1498Szrj
490338fd1498Szrj static int
do_spec_2(const char * spec)490438fd1498Szrj do_spec_2 (const char *spec)
490538fd1498Szrj {
490638fd1498Szrj int result;
490738fd1498Szrj
490838fd1498Szrj clear_args ();
490938fd1498Szrj arg_going = 0;
491038fd1498Szrj delete_this_arg = 0;
491138fd1498Szrj this_is_output_file = 0;
491238fd1498Szrj this_is_library_file = 0;
491338fd1498Szrj this_is_linker_script = 0;
491438fd1498Szrj input_from_pipe = 0;
491538fd1498Szrj suffix_subst = NULL;
491638fd1498Szrj
491738fd1498Szrj result = do_spec_1 (spec, 0, NULL);
491838fd1498Szrj
491938fd1498Szrj end_going_arg ();
492038fd1498Szrj
492138fd1498Szrj return result;
492238fd1498Szrj }
492338fd1498Szrj
492438fd1498Szrj
492538fd1498Szrj /* Process the given spec string and add any new options to the end
492638fd1498Szrj of the switches/n_switches array. */
492738fd1498Szrj
492838fd1498Szrj static void
do_option_spec(const char * name,const char * spec)492938fd1498Szrj do_option_spec (const char *name, const char *spec)
493038fd1498Szrj {
493138fd1498Szrj unsigned int i, value_count, value_len;
493238fd1498Szrj const char *p, *q, *value;
493338fd1498Szrj char *tmp_spec, *tmp_spec_p;
493438fd1498Szrj
493538fd1498Szrj if (configure_default_options[0].name == NULL)
493638fd1498Szrj return;
493738fd1498Szrj
493838fd1498Szrj for (i = 0; i < ARRAY_SIZE (configure_default_options); i++)
493938fd1498Szrj if (strcmp (configure_default_options[i].name, name) == 0)
494038fd1498Szrj break;
494138fd1498Szrj if (i == ARRAY_SIZE (configure_default_options))
494238fd1498Szrj return;
494338fd1498Szrj
494438fd1498Szrj value = configure_default_options[i].value;
494538fd1498Szrj value_len = strlen (value);
494638fd1498Szrj
494738fd1498Szrj /* Compute the size of the final spec. */
494838fd1498Szrj value_count = 0;
494938fd1498Szrj p = spec;
495038fd1498Szrj while ((p = strstr (p, "%(VALUE)")) != NULL)
495138fd1498Szrj {
495238fd1498Szrj p ++;
495338fd1498Szrj value_count ++;
495438fd1498Szrj }
495538fd1498Szrj
495638fd1498Szrj /* Replace each %(VALUE) by the specified value. */
495738fd1498Szrj tmp_spec = (char *) alloca (strlen (spec) + 1
495838fd1498Szrj + value_count * (value_len - strlen ("%(VALUE)")));
495938fd1498Szrj tmp_spec_p = tmp_spec;
496038fd1498Szrj q = spec;
496138fd1498Szrj while ((p = strstr (q, "%(VALUE)")) != NULL)
496238fd1498Szrj {
496338fd1498Szrj memcpy (tmp_spec_p, q, p - q);
496438fd1498Szrj tmp_spec_p = tmp_spec_p + (p - q);
496538fd1498Szrj memcpy (tmp_spec_p, value, value_len);
496638fd1498Szrj tmp_spec_p += value_len;
496738fd1498Szrj q = p + strlen ("%(VALUE)");
496838fd1498Szrj }
496938fd1498Szrj strcpy (tmp_spec_p, q);
497038fd1498Szrj
497138fd1498Szrj do_self_spec (tmp_spec);
497238fd1498Szrj }
497338fd1498Szrj
497438fd1498Szrj /* Process the given spec string and add any new options to the end
497538fd1498Szrj of the switches/n_switches array. */
497638fd1498Szrj
497738fd1498Szrj static void
do_self_spec(const char * spec)497838fd1498Szrj do_self_spec (const char *spec)
497938fd1498Szrj {
498038fd1498Szrj int i;
498138fd1498Szrj
498238fd1498Szrj do_spec_2 (spec);
498338fd1498Szrj do_spec_1 (" ", 0, NULL);
498438fd1498Szrj
498538fd1498Szrj /* Mark %<S switches processed by do_self_spec to be ignored permanently.
498638fd1498Szrj do_self_specs adds the replacements to switches array, so it shouldn't
498738fd1498Szrj be processed afterwards. */
498838fd1498Szrj for (i = 0; i < n_switches; i++)
498938fd1498Szrj if ((switches[i].live_cond & SWITCH_IGNORE))
499038fd1498Szrj switches[i].live_cond |= SWITCH_IGNORE_PERMANENTLY;
499138fd1498Szrj
499238fd1498Szrj if (argbuf.length () > 0)
499338fd1498Szrj {
499438fd1498Szrj const char **argbuf_copy;
499538fd1498Szrj struct cl_decoded_option *decoded_options;
499638fd1498Szrj struct cl_option_handlers handlers;
499738fd1498Szrj unsigned int decoded_options_count;
499838fd1498Szrj unsigned int j;
499938fd1498Szrj
500038fd1498Szrj /* Create a copy of argbuf with a dummy argv[0] entry for
500138fd1498Szrj decode_cmdline_options_to_array. */
500238fd1498Szrj argbuf_copy = XNEWVEC (const char *,
500338fd1498Szrj argbuf.length () + 1);
500438fd1498Szrj argbuf_copy[0] = "";
500538fd1498Szrj memcpy (argbuf_copy + 1, argbuf.address (),
500638fd1498Szrj argbuf.length () * sizeof (const char *));
500738fd1498Szrj
500838fd1498Szrj decode_cmdline_options_to_array (argbuf.length () + 1,
500938fd1498Szrj argbuf_copy,
501038fd1498Szrj CL_DRIVER, &decoded_options,
501138fd1498Szrj &decoded_options_count);
501238fd1498Szrj free (argbuf_copy);
501338fd1498Szrj
501438fd1498Szrj set_option_handlers (&handlers);
501538fd1498Szrj
501638fd1498Szrj for (j = 1; j < decoded_options_count; j++)
501738fd1498Szrj {
501838fd1498Szrj switch (decoded_options[j].opt_index)
501938fd1498Szrj {
502038fd1498Szrj case OPT_SPECIAL_input_file:
502138fd1498Szrj /* Specs should only generate options, not input
502238fd1498Szrj files. */
502338fd1498Szrj if (strcmp (decoded_options[j].arg, "-") != 0)
502438fd1498Szrj fatal_error (input_location,
502538fd1498Szrj "switch %qs does not start with %<-%>",
502638fd1498Szrj decoded_options[j].arg);
502738fd1498Szrj else
502838fd1498Szrj fatal_error (input_location,
502938fd1498Szrj "spec-generated switch is just %<-%>");
503038fd1498Szrj break;
503138fd1498Szrj
503238fd1498Szrj case OPT_fcompare_debug_second:
503338fd1498Szrj case OPT_fcompare_debug:
503438fd1498Szrj case OPT_fcompare_debug_:
503538fd1498Szrj case OPT_o:
503638fd1498Szrj /* Avoid duplicate processing of some options from
503738fd1498Szrj compare-debug specs; just save them here. */
503838fd1498Szrj save_switch (decoded_options[j].canonical_option[0],
503938fd1498Szrj (decoded_options[j].canonical_option_num_elements
504038fd1498Szrj - 1),
504138fd1498Szrj &decoded_options[j].canonical_option[1], false, true);
504238fd1498Szrj break;
504338fd1498Szrj
504438fd1498Szrj default:
504538fd1498Szrj read_cmdline_option (&global_options, &global_options_set,
504638fd1498Szrj decoded_options + j, UNKNOWN_LOCATION,
504738fd1498Szrj CL_DRIVER, &handlers, global_dc);
504838fd1498Szrj break;
504938fd1498Szrj }
505038fd1498Szrj }
505138fd1498Szrj
505238fd1498Szrj free (decoded_options);
505338fd1498Szrj
505438fd1498Szrj alloc_switch ();
505538fd1498Szrj switches[n_switches].part1 = 0;
505638fd1498Szrj }
505738fd1498Szrj }
505838fd1498Szrj
505938fd1498Szrj /* Callback for processing %D and %I specs. */
506038fd1498Szrj
506138fd1498Szrj struct spec_path_info {
506238fd1498Szrj const char *option;
506338fd1498Szrj const char *append;
506438fd1498Szrj size_t append_len;
506538fd1498Szrj bool omit_relative;
506638fd1498Szrj bool separate_options;
506738fd1498Szrj };
506838fd1498Szrj
506938fd1498Szrj static void *
spec_path(char * path,void * data)507038fd1498Szrj spec_path (char *path, void *data)
507138fd1498Szrj {
507238fd1498Szrj struct spec_path_info *info = (struct spec_path_info *) data;
507338fd1498Szrj size_t len = 0;
507438fd1498Szrj char save = 0;
507538fd1498Szrj
507638fd1498Szrj if (info->omit_relative && !IS_ABSOLUTE_PATH (path))
507738fd1498Szrj return NULL;
507838fd1498Szrj
507938fd1498Szrj if (info->append_len != 0)
508038fd1498Szrj {
508138fd1498Szrj len = strlen (path);
508238fd1498Szrj memcpy (path + len, info->append, info->append_len + 1);
508338fd1498Szrj }
508438fd1498Szrj
508538fd1498Szrj if (!is_directory (path, true))
508638fd1498Szrj return NULL;
508738fd1498Szrj
508838fd1498Szrj do_spec_1 (info->option, 1, NULL);
508938fd1498Szrj if (info->separate_options)
509038fd1498Szrj do_spec_1 (" ", 0, NULL);
509138fd1498Szrj
509238fd1498Szrj if (info->append_len == 0)
509338fd1498Szrj {
509438fd1498Szrj len = strlen (path);
509538fd1498Szrj save = path[len - 1];
509638fd1498Szrj if (IS_DIR_SEPARATOR (path[len - 1]))
509738fd1498Szrj path[len - 1] = '\0';
509838fd1498Szrj }
509938fd1498Szrj
510038fd1498Szrj do_spec_1 (path, 1, NULL);
510138fd1498Szrj do_spec_1 (" ", 0, NULL);
510238fd1498Szrj
510338fd1498Szrj /* Must not damage the original path. */
510438fd1498Szrj if (info->append_len == 0)
510538fd1498Szrj path[len - 1] = save;
510638fd1498Szrj
510738fd1498Szrj return NULL;
510838fd1498Szrj }
510938fd1498Szrj
511038fd1498Szrj /* Create a temporary FILE with the contents of ARGV. Add @FILE to the
511138fd1498Szrj argument list. */
511238fd1498Szrj
511338fd1498Szrj static void
create_at_file(char ** argv)511438fd1498Szrj create_at_file (char **argv)
511538fd1498Szrj {
511638fd1498Szrj char *temp_file = make_temp_file ("");
511738fd1498Szrj char *at_argument = concat ("@", temp_file, NULL);
511838fd1498Szrj FILE *f = fopen (temp_file, "w");
511938fd1498Szrj int status;
512038fd1498Szrj
512138fd1498Szrj if (f == NULL)
512238fd1498Szrj fatal_error (input_location, "could not open temporary response file %s",
512338fd1498Szrj temp_file);
512438fd1498Szrj
512538fd1498Szrj status = writeargv (argv, f);
512638fd1498Szrj
512738fd1498Szrj if (status)
512838fd1498Szrj fatal_error (input_location,
512938fd1498Szrj "could not write to temporary response file %s",
513038fd1498Szrj temp_file);
513138fd1498Szrj
513238fd1498Szrj status = fclose (f);
513338fd1498Szrj
513438fd1498Szrj if (EOF == status)
513538fd1498Szrj fatal_error (input_location, "could not close temporary response file %s",
513638fd1498Szrj temp_file);
513738fd1498Szrj
513838fd1498Szrj store_arg (at_argument, 0, 0);
513938fd1498Szrj
514038fd1498Szrj record_temp_file (temp_file, !save_temps_flag, !save_temps_flag);
514138fd1498Szrj }
514238fd1498Szrj
514338fd1498Szrj /* True if we should compile INFILE. */
514438fd1498Szrj
514538fd1498Szrj static bool
compile_input_file_p(struct infile * infile)514638fd1498Szrj compile_input_file_p (struct infile *infile)
514738fd1498Szrj {
514838fd1498Szrj if ((!infile->language) || (infile->language[0] != '*'))
514938fd1498Szrj if (infile->incompiler == input_file_compiler)
515038fd1498Szrj return true;
515138fd1498Szrj return false;
515238fd1498Szrj }
515338fd1498Szrj
515438fd1498Szrj /* Process each member of VEC as a spec. */
515538fd1498Szrj
515638fd1498Szrj static void
do_specs_vec(vec<char_p> vec)515738fd1498Szrj do_specs_vec (vec<char_p> vec)
515838fd1498Szrj {
515938fd1498Szrj unsigned ix;
516038fd1498Szrj char *opt;
516138fd1498Szrj
516238fd1498Szrj FOR_EACH_VEC_ELT (vec, ix, opt)
516338fd1498Szrj {
516438fd1498Szrj do_spec_1 (opt, 1, NULL);
516538fd1498Szrj /* Make each accumulated option a separate argument. */
516638fd1498Szrj do_spec_1 (" ", 0, NULL);
516738fd1498Szrj }
516838fd1498Szrj }
516938fd1498Szrj
517038fd1498Szrj /* Process the sub-spec SPEC as a portion of a larger spec.
517138fd1498Szrj This is like processing a whole spec except that we do
517238fd1498Szrj not initialize at the beginning and we do not supply a
517338fd1498Szrj newline by default at the end.
517438fd1498Szrj INSWITCH nonzero means don't process %-sequences in SPEC;
517538fd1498Szrj in this case, % is treated as an ordinary character.
517638fd1498Szrj This is used while substituting switches.
517738fd1498Szrj INSWITCH nonzero also causes SPC not to terminate an argument.
517838fd1498Szrj
517938fd1498Szrj Value is zero unless a line was finished
518038fd1498Szrj and the command on that line reported an error. */
518138fd1498Szrj
518238fd1498Szrj static int
do_spec_1(const char * spec,int inswitch,const char * soft_matched_part)518338fd1498Szrj do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
518438fd1498Szrj {
518538fd1498Szrj const char *p = spec;
518638fd1498Szrj int c;
518738fd1498Szrj int i;
518838fd1498Szrj int value;
518938fd1498Szrj
519038fd1498Szrj /* If it's an empty string argument to a switch, keep it as is. */
519138fd1498Szrj if (inswitch && !*p)
519238fd1498Szrj arg_going = 1;
519338fd1498Szrj
519438fd1498Szrj while ((c = *p++))
519538fd1498Szrj /* If substituting a switch, treat all chars like letters.
519638fd1498Szrj Otherwise, NL, SPC, TAB and % are special. */
519738fd1498Szrj switch (inswitch ? 'a' : c)
519838fd1498Szrj {
519938fd1498Szrj case '\n':
520038fd1498Szrj end_going_arg ();
520138fd1498Szrj
520238fd1498Szrj if (argbuf.length () > 0
520338fd1498Szrj && !strcmp (argbuf.last (), "|"))
520438fd1498Szrj {
520538fd1498Szrj /* A `|' before the newline means use a pipe here,
520638fd1498Szrj but only if -pipe was specified.
520738fd1498Szrj Otherwise, execute now and don't pass the `|' as an arg. */
520838fd1498Szrj if (use_pipes)
520938fd1498Szrj {
521038fd1498Szrj input_from_pipe = 1;
521138fd1498Szrj break;
521238fd1498Szrj }
521338fd1498Szrj else
521438fd1498Szrj argbuf.pop ();
521538fd1498Szrj }
521638fd1498Szrj
521738fd1498Szrj set_collect_gcc_options ();
521838fd1498Szrj
521938fd1498Szrj if (argbuf.length () > 0)
522038fd1498Szrj {
522138fd1498Szrj value = execute ();
522238fd1498Szrj if (value)
522338fd1498Szrj return value;
522438fd1498Szrj }
522538fd1498Szrj /* Reinitialize for a new command, and for a new argument. */
522638fd1498Szrj clear_args ();
522738fd1498Szrj arg_going = 0;
522838fd1498Szrj delete_this_arg = 0;
522938fd1498Szrj this_is_output_file = 0;
523038fd1498Szrj this_is_library_file = 0;
523138fd1498Szrj this_is_linker_script = 0;
523238fd1498Szrj input_from_pipe = 0;
523338fd1498Szrj break;
523438fd1498Szrj
523538fd1498Szrj case '|':
523638fd1498Szrj end_going_arg ();
523738fd1498Szrj
523838fd1498Szrj /* Use pipe */
523938fd1498Szrj obstack_1grow (&obstack, c);
524038fd1498Szrj arg_going = 1;
524138fd1498Szrj break;
524238fd1498Szrj
524338fd1498Szrj case '\t':
524438fd1498Szrj case ' ':
524538fd1498Szrj end_going_arg ();
524638fd1498Szrj
524738fd1498Szrj /* Reinitialize for a new argument. */
524838fd1498Szrj delete_this_arg = 0;
524938fd1498Szrj this_is_output_file = 0;
525038fd1498Szrj this_is_library_file = 0;
525138fd1498Szrj this_is_linker_script = 0;
525238fd1498Szrj break;
525338fd1498Szrj
525438fd1498Szrj case '%':
525538fd1498Szrj switch (c = *p++)
525638fd1498Szrj {
525738fd1498Szrj case 0:
525838fd1498Szrj fatal_error (input_location, "spec %qs invalid", spec);
525938fd1498Szrj
526038fd1498Szrj case 'b':
526138fd1498Szrj if (save_temps_length)
526238fd1498Szrj obstack_grow (&obstack, save_temps_prefix, save_temps_length);
526338fd1498Szrj else
526438fd1498Szrj obstack_grow (&obstack, input_basename, basename_length);
526538fd1498Szrj if (compare_debug < 0)
526638fd1498Szrj obstack_grow (&obstack, ".gk", 3);
526738fd1498Szrj arg_going = 1;
526838fd1498Szrj break;
526938fd1498Szrj
527038fd1498Szrj case 'B':
527138fd1498Szrj if (save_temps_length)
527238fd1498Szrj obstack_grow (&obstack, save_temps_prefix, save_temps_length);
527338fd1498Szrj else
527438fd1498Szrj obstack_grow (&obstack, input_basename, suffixed_basename_length);
527538fd1498Szrj if (compare_debug < 0)
527638fd1498Szrj obstack_grow (&obstack, ".gk", 3);
527738fd1498Szrj arg_going = 1;
527838fd1498Szrj break;
527938fd1498Szrj
528038fd1498Szrj case 'd':
528138fd1498Szrj delete_this_arg = 2;
528238fd1498Szrj break;
528338fd1498Szrj
528438fd1498Szrj /* Dump out the directories specified with LIBRARY_PATH,
528538fd1498Szrj followed by the absolute directories
528638fd1498Szrj that we search for startfiles. */
528738fd1498Szrj case 'D':
528838fd1498Szrj {
528938fd1498Szrj struct spec_path_info info;
529038fd1498Szrj
529138fd1498Szrj info.option = "-L";
529238fd1498Szrj info.append_len = 0;
529338fd1498Szrj #ifdef RELATIVE_PREFIX_NOT_LINKDIR
529438fd1498Szrj /* Used on systems which record the specified -L dirs
529538fd1498Szrj and use them to search for dynamic linking.
529638fd1498Szrj Relative directories always come from -B,
529738fd1498Szrj and it is better not to use them for searching
529838fd1498Szrj at run time. In particular, stage1 loses. */
529938fd1498Szrj info.omit_relative = true;
530038fd1498Szrj #else
530138fd1498Szrj info.omit_relative = false;
530238fd1498Szrj #endif
530338fd1498Szrj info.separate_options = false;
530438fd1498Szrj
530538fd1498Szrj for_each_path (&startfile_prefixes, true, 0, spec_path, &info);
530638fd1498Szrj }
530738fd1498Szrj break;
530838fd1498Szrj
530938fd1498Szrj case 'e':
531038fd1498Szrj /* %efoo means report an error with `foo' as error message
531138fd1498Szrj and don't execute any more commands for this file. */
531238fd1498Szrj {
531338fd1498Szrj const char *q = p;
531438fd1498Szrj char *buf;
531538fd1498Szrj while (*p != 0 && *p != '\n')
531638fd1498Szrj p++;
531738fd1498Szrj buf = (char *) alloca (p - q + 1);
531838fd1498Szrj strncpy (buf, q, p - q);
531938fd1498Szrj buf[p - q] = 0;
532038fd1498Szrj error ("%s", _(buf));
532138fd1498Szrj return -1;
532238fd1498Szrj }
532338fd1498Szrj break;
532438fd1498Szrj case 'n':
532538fd1498Szrj /* %nfoo means report a notice with `foo' on stderr. */
532638fd1498Szrj {
532738fd1498Szrj const char *q = p;
532838fd1498Szrj char *buf;
532938fd1498Szrj while (*p != 0 && *p != '\n')
533038fd1498Szrj p++;
533138fd1498Szrj buf = (char *) alloca (p - q + 1);
533238fd1498Szrj strncpy (buf, q, p - q);
533338fd1498Szrj buf[p - q] = 0;
533438fd1498Szrj inform (UNKNOWN_LOCATION, "%s", _(buf));
533538fd1498Szrj if (*p)
533638fd1498Szrj p++;
533738fd1498Szrj }
533838fd1498Szrj break;
533938fd1498Szrj
534038fd1498Szrj case 'j':
534138fd1498Szrj {
534238fd1498Szrj struct stat st;
534338fd1498Szrj
534438fd1498Szrj /* If save_temps_flag is off, and the HOST_BIT_BUCKET is
534538fd1498Szrj defined, and it is not a directory, and it is
534638fd1498Szrj writable, use it. Otherwise, treat this like any
534738fd1498Szrj other temporary file. */
534838fd1498Szrj
534938fd1498Szrj if ((!save_temps_flag)
535038fd1498Szrj && (stat (HOST_BIT_BUCKET, &st) == 0) && (!S_ISDIR (st.st_mode))
535138fd1498Szrj && (access (HOST_BIT_BUCKET, W_OK) == 0))
535238fd1498Szrj {
535338fd1498Szrj obstack_grow (&obstack, HOST_BIT_BUCKET,
535438fd1498Szrj strlen (HOST_BIT_BUCKET));
535538fd1498Szrj delete_this_arg = 0;
535638fd1498Szrj arg_going = 1;
535738fd1498Szrj break;
535838fd1498Szrj }
535938fd1498Szrj }
536038fd1498Szrj goto create_temp_file;
536138fd1498Szrj case '|':
536238fd1498Szrj if (use_pipes)
536338fd1498Szrj {
536438fd1498Szrj obstack_1grow (&obstack, '-');
536538fd1498Szrj delete_this_arg = 0;
536638fd1498Szrj arg_going = 1;
536738fd1498Szrj
536838fd1498Szrj /* consume suffix */
536938fd1498Szrj while (*p == '.' || ISALNUM ((unsigned char) *p))
537038fd1498Szrj p++;
537138fd1498Szrj if (p[0] == '%' && p[1] == 'O')
537238fd1498Szrj p += 2;
537338fd1498Szrj
537438fd1498Szrj break;
537538fd1498Szrj }
537638fd1498Szrj goto create_temp_file;
537738fd1498Szrj case 'm':
537838fd1498Szrj if (use_pipes)
537938fd1498Szrj {
538038fd1498Szrj /* consume suffix */
538138fd1498Szrj while (*p == '.' || ISALNUM ((unsigned char) *p))
538238fd1498Szrj p++;
538338fd1498Szrj if (p[0] == '%' && p[1] == 'O')
538438fd1498Szrj p += 2;
538538fd1498Szrj
538638fd1498Szrj break;
538738fd1498Szrj }
538838fd1498Szrj goto create_temp_file;
538938fd1498Szrj case 'g':
539038fd1498Szrj case 'u':
539138fd1498Szrj case 'U':
539238fd1498Szrj create_temp_file:
539338fd1498Szrj {
539438fd1498Szrj struct temp_name *t;
539538fd1498Szrj int suffix_length;
539638fd1498Szrj const char *suffix = p;
539738fd1498Szrj char *saved_suffix = NULL;
539838fd1498Szrj
539938fd1498Szrj while (*p == '.' || ISALNUM ((unsigned char) *p))
540038fd1498Szrj p++;
540138fd1498Szrj suffix_length = p - suffix;
540238fd1498Szrj if (p[0] == '%' && p[1] == 'O')
540338fd1498Szrj {
540438fd1498Szrj p += 2;
540538fd1498Szrj /* We don't support extra suffix characters after %O. */
540638fd1498Szrj if (*p == '.' || ISALNUM ((unsigned char) *p))
540738fd1498Szrj fatal_error (input_location,
540838fd1498Szrj "spec %qs has invalid %<%%0%c%>", spec, *p);
540938fd1498Szrj if (suffix_length == 0)
541038fd1498Szrj suffix = TARGET_OBJECT_SUFFIX;
541138fd1498Szrj else
541238fd1498Szrj {
541338fd1498Szrj saved_suffix
541438fd1498Szrj = XNEWVEC (char, suffix_length
541538fd1498Szrj + strlen (TARGET_OBJECT_SUFFIX) + 1);
541638fd1498Szrj strncpy (saved_suffix, suffix, suffix_length);
541738fd1498Szrj strcpy (saved_suffix + suffix_length,
541838fd1498Szrj TARGET_OBJECT_SUFFIX);
541938fd1498Szrj }
542038fd1498Szrj suffix_length += strlen (TARGET_OBJECT_SUFFIX);
542138fd1498Szrj }
542238fd1498Szrj
542338fd1498Szrj if (compare_debug < 0)
542438fd1498Szrj {
542538fd1498Szrj suffix = concat (".gk", suffix, NULL);
542638fd1498Szrj suffix_length += 3;
542738fd1498Szrj }
542838fd1498Szrj
542938fd1498Szrj /* If -save-temps=obj and -o were specified, use that for the
543038fd1498Szrj temp file. */
543138fd1498Szrj if (save_temps_length)
543238fd1498Szrj {
543338fd1498Szrj char *tmp;
543438fd1498Szrj temp_filename_length
543538fd1498Szrj = save_temps_length + suffix_length + 1;
543638fd1498Szrj tmp = (char *) alloca (temp_filename_length);
543738fd1498Szrj memcpy (tmp, save_temps_prefix, save_temps_length);
543838fd1498Szrj memcpy (tmp + save_temps_length, suffix, suffix_length);
543938fd1498Szrj tmp[save_temps_length + suffix_length] = '\0';
544038fd1498Szrj temp_filename = save_string (tmp, save_temps_length
544138fd1498Szrj + suffix_length);
544238fd1498Szrj obstack_grow (&obstack, temp_filename,
544338fd1498Szrj temp_filename_length);
544438fd1498Szrj arg_going = 1;
544538fd1498Szrj delete_this_arg = 0;
544638fd1498Szrj break;
544738fd1498Szrj }
544838fd1498Szrj
544938fd1498Szrj /* If the gcc_input_filename has the same suffix specified
545038fd1498Szrj for the %g, %u, or %U, and -save-temps is specified,
545138fd1498Szrj we could end up using that file as an intermediate
545238fd1498Szrj thus clobbering the user's source file (.e.g.,
545338fd1498Szrj gcc -save-temps foo.s would clobber foo.s with the
545438fd1498Szrj output of cpp0). So check for this condition and
545538fd1498Szrj generate a temp file as the intermediate. */
545638fd1498Szrj
545738fd1498Szrj if (save_temps_flag)
545838fd1498Szrj {
545938fd1498Szrj char *tmp;
546038fd1498Szrj temp_filename_length = basename_length + suffix_length + 1;
546138fd1498Szrj tmp = (char *) alloca (temp_filename_length);
546238fd1498Szrj memcpy (tmp, input_basename, basename_length);
546338fd1498Szrj memcpy (tmp + basename_length, suffix, suffix_length);
546438fd1498Szrj tmp[basename_length + suffix_length] = '\0';
546538fd1498Szrj temp_filename = tmp;
546638fd1498Szrj
546738fd1498Szrj if (filename_cmp (temp_filename, gcc_input_filename) != 0)
546838fd1498Szrj {
546938fd1498Szrj #ifndef HOST_LACKS_INODE_NUMBERS
547038fd1498Szrj struct stat st_temp;
547138fd1498Szrj
547238fd1498Szrj /* Note, set_input() resets input_stat_set to 0. */
547338fd1498Szrj if (input_stat_set == 0)
547438fd1498Szrj {
547538fd1498Szrj input_stat_set = stat (gcc_input_filename,
547638fd1498Szrj &input_stat);
547738fd1498Szrj if (input_stat_set >= 0)
547838fd1498Szrj input_stat_set = 1;
547938fd1498Szrj }
548038fd1498Szrj
548138fd1498Szrj /* If we have the stat for the gcc_input_filename
548238fd1498Szrj and we can do the stat for the temp_filename
548338fd1498Szrj then the they could still refer to the same
548438fd1498Szrj file if st_dev/st_ino's are the same. */
548538fd1498Szrj if (input_stat_set != 1
548638fd1498Szrj || stat (temp_filename, &st_temp) < 0
548738fd1498Szrj || input_stat.st_dev != st_temp.st_dev
548838fd1498Szrj || input_stat.st_ino != st_temp.st_ino)
548938fd1498Szrj #else
549038fd1498Szrj /* Just compare canonical pathnames. */
549138fd1498Szrj char* input_realname = lrealpath (gcc_input_filename);
549238fd1498Szrj char* temp_realname = lrealpath (temp_filename);
549338fd1498Szrj bool files_differ = filename_cmp (input_realname, temp_realname);
549438fd1498Szrj free (input_realname);
549538fd1498Szrj free (temp_realname);
549638fd1498Szrj if (files_differ)
549738fd1498Szrj #endif
549838fd1498Szrj {
549938fd1498Szrj temp_filename
550038fd1498Szrj = save_string (temp_filename,
550138fd1498Szrj temp_filename_length - 1);
550238fd1498Szrj obstack_grow (&obstack, temp_filename,
550338fd1498Szrj temp_filename_length);
550438fd1498Szrj arg_going = 1;
550538fd1498Szrj delete_this_arg = 0;
550638fd1498Szrj break;
550738fd1498Szrj }
550838fd1498Szrj }
550938fd1498Szrj }
551038fd1498Szrj
551138fd1498Szrj /* See if we already have an association of %g/%u/%U and
551238fd1498Szrj suffix. */
551338fd1498Szrj for (t = temp_names; t; t = t->next)
551438fd1498Szrj if (t->length == suffix_length
551538fd1498Szrj && strncmp (t->suffix, suffix, suffix_length) == 0
551638fd1498Szrj && t->unique == (c == 'u' || c == 'U' || c == 'j'))
551738fd1498Szrj break;
551838fd1498Szrj
551938fd1498Szrj /* Make a new association if needed. %u and %j
552038fd1498Szrj require one. */
552138fd1498Szrj if (t == 0 || c == 'u' || c == 'j')
552238fd1498Szrj {
552338fd1498Szrj if (t == 0)
552438fd1498Szrj {
552538fd1498Szrj t = XNEW (struct temp_name);
552638fd1498Szrj t->next = temp_names;
552738fd1498Szrj temp_names = t;
552838fd1498Szrj }
552938fd1498Szrj t->length = suffix_length;
553038fd1498Szrj if (saved_suffix)
553138fd1498Szrj {
553238fd1498Szrj t->suffix = saved_suffix;
553338fd1498Szrj saved_suffix = NULL;
553438fd1498Szrj }
553538fd1498Szrj else
553638fd1498Szrj t->suffix = save_string (suffix, suffix_length);
553738fd1498Szrj t->unique = (c == 'u' || c == 'U' || c == 'j');
553838fd1498Szrj temp_filename = make_temp_file (t->suffix);
553938fd1498Szrj temp_filename_length = strlen (temp_filename);
554038fd1498Szrj t->filename = temp_filename;
554138fd1498Szrj t->filename_length = temp_filename_length;
554238fd1498Szrj }
554338fd1498Szrj
554438fd1498Szrj free (saved_suffix);
554538fd1498Szrj
554638fd1498Szrj obstack_grow (&obstack, t->filename, t->filename_length);
554738fd1498Szrj delete_this_arg = 1;
554838fd1498Szrj }
554938fd1498Szrj arg_going = 1;
555038fd1498Szrj break;
555138fd1498Szrj
555238fd1498Szrj case 'i':
555338fd1498Szrj if (combine_inputs)
555438fd1498Szrj {
555538fd1498Szrj if (at_file_supplied)
555638fd1498Szrj {
555738fd1498Szrj /* We are going to expand `%i' to `@FILE', where FILE
555838fd1498Szrj is a newly-created temporary filename. The filenames
555938fd1498Szrj that would usually be expanded in place of %o will be
556038fd1498Szrj written to the temporary file. */
556138fd1498Szrj char **argv;
556238fd1498Szrj int n_files = 0;
556338fd1498Szrj int j;
556438fd1498Szrj
556538fd1498Szrj for (i = 0; i < n_infiles; i++)
556638fd1498Szrj if (compile_input_file_p (&infiles[i]))
556738fd1498Szrj n_files++;
556838fd1498Szrj
556938fd1498Szrj argv = (char **) alloca (sizeof (char *) * (n_files + 1));
557038fd1498Szrj
557138fd1498Szrj /* Copy the strings over. */
557238fd1498Szrj for (i = 0, j = 0; i < n_infiles; i++)
557338fd1498Szrj if (compile_input_file_p (&infiles[i]))
557438fd1498Szrj {
557538fd1498Szrj argv[j] = CONST_CAST (char *, infiles[i].name);
557638fd1498Szrj infiles[i].compiled = true;
557738fd1498Szrj j++;
557838fd1498Szrj }
557938fd1498Szrj argv[j] = NULL;
558038fd1498Szrj
558138fd1498Szrj create_at_file (argv);
558238fd1498Szrj }
558338fd1498Szrj else
558438fd1498Szrj for (i = 0; (int) i < n_infiles; i++)
558538fd1498Szrj if (compile_input_file_p (&infiles[i]))
558638fd1498Szrj {
558738fd1498Szrj store_arg (infiles[i].name, 0, 0);
558838fd1498Szrj infiles[i].compiled = true;
558938fd1498Szrj }
559038fd1498Szrj }
559138fd1498Szrj else
559238fd1498Szrj {
559338fd1498Szrj obstack_grow (&obstack, gcc_input_filename,
559438fd1498Szrj input_filename_length);
559538fd1498Szrj arg_going = 1;
559638fd1498Szrj }
559738fd1498Szrj break;
559838fd1498Szrj
559938fd1498Szrj case 'I':
560038fd1498Szrj {
560138fd1498Szrj struct spec_path_info info;
560238fd1498Szrj
560338fd1498Szrj if (multilib_dir)
560438fd1498Szrj {
560538fd1498Szrj do_spec_1 ("-imultilib", 1, NULL);
560638fd1498Szrj /* Make this a separate argument. */
560738fd1498Szrj do_spec_1 (" ", 0, NULL);
560838fd1498Szrj do_spec_1 (multilib_dir, 1, NULL);
560938fd1498Szrj do_spec_1 (" ", 0, NULL);
561038fd1498Szrj }
561138fd1498Szrj
561238fd1498Szrj if (multiarch_dir)
561338fd1498Szrj {
561438fd1498Szrj do_spec_1 ("-imultiarch", 1, NULL);
561538fd1498Szrj /* Make this a separate argument. */
561638fd1498Szrj do_spec_1 (" ", 0, NULL);
561738fd1498Szrj do_spec_1 (multiarch_dir, 1, NULL);
561838fd1498Szrj do_spec_1 (" ", 0, NULL);
561938fd1498Szrj }
562038fd1498Szrj
562138fd1498Szrj if (gcc_exec_prefix)
562238fd1498Szrj {
562338fd1498Szrj do_spec_1 ("-iprefix", 1, NULL);
562438fd1498Szrj /* Make this a separate argument. */
562538fd1498Szrj do_spec_1 (" ", 0, NULL);
562638fd1498Szrj do_spec_1 (gcc_exec_prefix, 1, NULL);
562738fd1498Szrj do_spec_1 (" ", 0, NULL);
562838fd1498Szrj }
562938fd1498Szrj
563038fd1498Szrj if (target_system_root_changed ||
563138fd1498Szrj (target_system_root && target_sysroot_hdrs_suffix))
563238fd1498Szrj {
563338fd1498Szrj do_spec_1 ("-isysroot", 1, NULL);
563438fd1498Szrj /* Make this a separate argument. */
563538fd1498Szrj do_spec_1 (" ", 0, NULL);
563638fd1498Szrj do_spec_1 (target_system_root, 1, NULL);
563738fd1498Szrj if (target_sysroot_hdrs_suffix)
563838fd1498Szrj do_spec_1 (target_sysroot_hdrs_suffix, 1, NULL);
563938fd1498Szrj do_spec_1 (" ", 0, NULL);
564038fd1498Szrj }
564138fd1498Szrj
564238fd1498Szrj info.option = "-isystem";
564338fd1498Szrj info.append = "include";
564438fd1498Szrj info.append_len = strlen (info.append);
564538fd1498Szrj info.omit_relative = false;
564638fd1498Szrj info.separate_options = true;
564738fd1498Szrj
564838fd1498Szrj for_each_path (&include_prefixes, false, info.append_len,
564938fd1498Szrj spec_path, &info);
565038fd1498Szrj
565138fd1498Szrj info.append = "include-fixed";
565238fd1498Szrj if (*sysroot_hdrs_suffix_spec)
565338fd1498Szrj info.append = concat (info.append, dir_separator_str,
565438fd1498Szrj multilib_dir, NULL);
565538fd1498Szrj info.append_len = strlen (info.append);
565638fd1498Szrj for_each_path (&include_prefixes, false, info.append_len,
565738fd1498Szrj spec_path, &info);
565838fd1498Szrj }
565938fd1498Szrj break;
566038fd1498Szrj
566138fd1498Szrj case 'o':
566238fd1498Szrj {
566338fd1498Szrj int max = n_infiles;
566438fd1498Szrj max += lang_specific_extra_outfiles;
566538fd1498Szrj
566638fd1498Szrj if (HAVE_GNU_LD && at_file_supplied)
566738fd1498Szrj {
566838fd1498Szrj /* We are going to expand `%o' to `@FILE', where FILE
566938fd1498Szrj is a newly-created temporary filename. The filenames
567038fd1498Szrj that would usually be expanded in place of %o will be
567138fd1498Szrj written to the temporary file. */
567238fd1498Szrj
567338fd1498Szrj char **argv;
567438fd1498Szrj int n_files, j;
567538fd1498Szrj
567638fd1498Szrj /* Convert OUTFILES into a form suitable for writeargv. */
567738fd1498Szrj
567838fd1498Szrj /* Determine how many are non-NULL. */
567938fd1498Szrj for (n_files = 0, i = 0; i < max; i++)
568038fd1498Szrj n_files += outfiles[i] != NULL;
568138fd1498Szrj
568238fd1498Szrj argv = (char **) alloca (sizeof (char *) * (n_files + 1));
568338fd1498Szrj
568438fd1498Szrj /* Copy the strings over. */
568538fd1498Szrj for (i = 0, j = 0; i < max; i++)
568638fd1498Szrj if (outfiles[i])
568738fd1498Szrj {
568838fd1498Szrj argv[j] = CONST_CAST (char *, outfiles[i]);
568938fd1498Szrj j++;
569038fd1498Szrj }
569138fd1498Szrj argv[j] = NULL;
569238fd1498Szrj
569338fd1498Szrj create_at_file (argv);
569438fd1498Szrj }
569538fd1498Szrj else
569638fd1498Szrj for (i = 0; i < max; i++)
569738fd1498Szrj if (outfiles[i])
569838fd1498Szrj store_arg (outfiles[i], 0, 0);
569938fd1498Szrj break;
570038fd1498Szrj }
570138fd1498Szrj
570238fd1498Szrj case 'O':
570338fd1498Szrj obstack_grow (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
570438fd1498Szrj arg_going = 1;
570538fd1498Szrj break;
570638fd1498Szrj
570738fd1498Szrj case 's':
570838fd1498Szrj this_is_library_file = 1;
570938fd1498Szrj break;
571038fd1498Szrj
571138fd1498Szrj case 'T':
571238fd1498Szrj this_is_linker_script = 1;
571338fd1498Szrj break;
571438fd1498Szrj
571538fd1498Szrj case 'V':
571638fd1498Szrj outfiles[input_file_number] = NULL;
571738fd1498Szrj break;
571838fd1498Szrj
571938fd1498Szrj case 'w':
572038fd1498Szrj this_is_output_file = 1;
572138fd1498Szrj break;
572238fd1498Szrj
572338fd1498Szrj case 'W':
572438fd1498Szrj {
572538fd1498Szrj unsigned int cur_index = argbuf.length ();
572638fd1498Szrj /* Handle the {...} following the %W. */
572738fd1498Szrj if (*p != '{')
572838fd1498Szrj fatal_error (input_location,
572938fd1498Szrj "spec %qs has invalid %<%%W%c%>", spec, *p);
573038fd1498Szrj p = handle_braces (p + 1);
573138fd1498Szrj if (p == 0)
573238fd1498Szrj return -1;
573338fd1498Szrj end_going_arg ();
573438fd1498Szrj /* If any args were output, mark the last one for deletion
573538fd1498Szrj on failure. */
573638fd1498Szrj if (argbuf.length () != cur_index)
573738fd1498Szrj record_temp_file (argbuf.last (), 0, 1);
573838fd1498Szrj break;
573938fd1498Szrj }
574038fd1498Szrj
574138fd1498Szrj /* %x{OPTION} records OPTION for %X to output. */
574238fd1498Szrj case 'x':
574338fd1498Szrj {
574438fd1498Szrj const char *p1 = p;
574538fd1498Szrj char *string;
574638fd1498Szrj char *opt;
574738fd1498Szrj unsigned ix;
574838fd1498Szrj
574938fd1498Szrj /* Skip past the option value and make a copy. */
575038fd1498Szrj if (*p != '{')
575138fd1498Szrj fatal_error (input_location,
575238fd1498Szrj "spec %qs has invalid %<%%x%c%>", spec, *p);
575338fd1498Szrj while (*p++ != '}')
575438fd1498Szrj ;
575538fd1498Szrj string = save_string (p1 + 1, p - p1 - 2);
575638fd1498Szrj
575738fd1498Szrj /* See if we already recorded this option. */
575838fd1498Szrj FOR_EACH_VEC_ELT (linker_options, ix, opt)
575938fd1498Szrj if (! strcmp (string, opt))
576038fd1498Szrj {
576138fd1498Szrj free (string);
576238fd1498Szrj return 0;
576338fd1498Szrj }
576438fd1498Szrj
576538fd1498Szrj /* This option is new; add it. */
576638fd1498Szrj add_linker_option (string, strlen (string));
576738fd1498Szrj free (string);
576838fd1498Szrj }
576938fd1498Szrj break;
577038fd1498Szrj
577138fd1498Szrj /* Dump out the options accumulated previously using %x. */
577238fd1498Szrj case 'X':
577338fd1498Szrj do_specs_vec (linker_options);
577438fd1498Szrj break;
577538fd1498Szrj
577638fd1498Szrj /* Dump out the options accumulated previously using -Wa,. */
577738fd1498Szrj case 'Y':
577838fd1498Szrj do_specs_vec (assembler_options);
577938fd1498Szrj break;
578038fd1498Szrj
578138fd1498Szrj /* Dump out the options accumulated previously using -Wp,. */
578238fd1498Szrj case 'Z':
578338fd1498Szrj do_specs_vec (preprocessor_options);
578438fd1498Szrj break;
578538fd1498Szrj
578638fd1498Szrj /* Here are digits and numbers that just process
578738fd1498Szrj a certain constant string as a spec. */
578838fd1498Szrj
578938fd1498Szrj case '1':
579038fd1498Szrj value = do_spec_1 (cc1_spec, 0, NULL);
579138fd1498Szrj if (value != 0)
579238fd1498Szrj return value;
579338fd1498Szrj break;
579438fd1498Szrj
579538fd1498Szrj case '2':
579638fd1498Szrj value = do_spec_1 (cc1plus_spec, 0, NULL);
579738fd1498Szrj if (value != 0)
579838fd1498Szrj return value;
579938fd1498Szrj break;
580038fd1498Szrj
580138fd1498Szrj case 'a':
580238fd1498Szrj value = do_spec_1 (asm_spec, 0, NULL);
580338fd1498Szrj if (value != 0)
580438fd1498Szrj return value;
580538fd1498Szrj break;
580638fd1498Szrj
580738fd1498Szrj case 'A':
580838fd1498Szrj value = do_spec_1 (asm_final_spec, 0, NULL);
580938fd1498Szrj if (value != 0)
581038fd1498Szrj return value;
581138fd1498Szrj break;
581238fd1498Szrj
581338fd1498Szrj case 'C':
581438fd1498Szrj {
581538fd1498Szrj const char *const spec
581638fd1498Szrj = (input_file_compiler->cpp_spec
581738fd1498Szrj ? input_file_compiler->cpp_spec
581838fd1498Szrj : cpp_spec);
581938fd1498Szrj value = do_spec_1 (spec, 0, NULL);
582038fd1498Szrj if (value != 0)
582138fd1498Szrj return value;
582238fd1498Szrj }
582338fd1498Szrj break;
582438fd1498Szrj
582538fd1498Szrj case 'E':
582638fd1498Szrj value = do_spec_1 (endfile_spec, 0, NULL);
582738fd1498Szrj if (value != 0)
582838fd1498Szrj return value;
582938fd1498Szrj break;
583038fd1498Szrj
583138fd1498Szrj case 'l':
583238fd1498Szrj value = do_spec_1 (link_spec, 0, NULL);
583338fd1498Szrj if (value != 0)
583438fd1498Szrj return value;
583538fd1498Szrj break;
583638fd1498Szrj
583738fd1498Szrj case 'L':
583838fd1498Szrj value = do_spec_1 (lib_spec, 0, NULL);
583938fd1498Szrj if (value != 0)
584038fd1498Szrj return value;
584138fd1498Szrj break;
584238fd1498Szrj
584338fd1498Szrj case 'M':
584438fd1498Szrj if (multilib_os_dir == NULL)
584538fd1498Szrj obstack_1grow (&obstack, '.');
584638fd1498Szrj else
584738fd1498Szrj obstack_grow (&obstack, multilib_os_dir,
584838fd1498Szrj strlen (multilib_os_dir));
584938fd1498Szrj break;
585038fd1498Szrj
585138fd1498Szrj case 'G':
585238fd1498Szrj value = do_spec_1 (libgcc_spec, 0, NULL);
585338fd1498Szrj if (value != 0)
585438fd1498Szrj return value;
585538fd1498Szrj break;
585638fd1498Szrj
585738fd1498Szrj case 'R':
585838fd1498Szrj /* We assume there is a directory
585938fd1498Szrj separator at the end of this string. */
586038fd1498Szrj if (target_system_root)
586138fd1498Szrj {
586238fd1498Szrj obstack_grow (&obstack, target_system_root,
586338fd1498Szrj strlen (target_system_root));
586438fd1498Szrj if (target_sysroot_suffix)
586538fd1498Szrj obstack_grow (&obstack, target_sysroot_suffix,
586638fd1498Szrj strlen (target_sysroot_suffix));
586738fd1498Szrj }
586838fd1498Szrj break;
586938fd1498Szrj
587038fd1498Szrj case 'S':
587138fd1498Szrj value = do_spec_1 (startfile_spec, 0, NULL);
587238fd1498Szrj if (value != 0)
587338fd1498Szrj return value;
587438fd1498Szrj break;
587538fd1498Szrj
587638fd1498Szrj /* Here we define characters other than letters and digits. */
587738fd1498Szrj
587838fd1498Szrj case '{':
587938fd1498Szrj p = handle_braces (p);
588038fd1498Szrj if (p == 0)
588138fd1498Szrj return -1;
588238fd1498Szrj break;
588338fd1498Szrj
588438fd1498Szrj case ':':
588538fd1498Szrj p = handle_spec_function (p, NULL);
588638fd1498Szrj if (p == 0)
588738fd1498Szrj return -1;
588838fd1498Szrj break;
588938fd1498Szrj
589038fd1498Szrj case '%':
589138fd1498Szrj obstack_1grow (&obstack, '%');
589238fd1498Szrj break;
589338fd1498Szrj
589438fd1498Szrj case '.':
589538fd1498Szrj {
589638fd1498Szrj unsigned len = 0;
589738fd1498Szrj
589838fd1498Szrj while (p[len] && p[len] != ' ' && p[len] != '%')
589938fd1498Szrj len++;
590038fd1498Szrj suffix_subst = save_string (p - 1, len + 1);
590138fd1498Szrj p += len;
590238fd1498Szrj }
590338fd1498Szrj break;
590438fd1498Szrj
590538fd1498Szrj /* Henceforth ignore the option(s) matching the pattern
590638fd1498Szrj after the %<. */
590738fd1498Szrj case '<':
590838fd1498Szrj case '>':
590938fd1498Szrj {
591038fd1498Szrj unsigned len = 0;
591138fd1498Szrj int have_wildcard = 0;
591238fd1498Szrj int i;
591338fd1498Szrj int switch_option;
591438fd1498Szrj
591538fd1498Szrj if (c == '>')
591638fd1498Szrj switch_option = SWITCH_IGNORE | SWITCH_KEEP_FOR_GCC;
591738fd1498Szrj else
591838fd1498Szrj switch_option = SWITCH_IGNORE;
591938fd1498Szrj
592038fd1498Szrj while (p[len] && p[len] != ' ' && p[len] != '\t')
592138fd1498Szrj len++;
592238fd1498Szrj
592338fd1498Szrj if (p[len-1] == '*')
592438fd1498Szrj have_wildcard = 1;
592538fd1498Szrj
592638fd1498Szrj for (i = 0; i < n_switches; i++)
592738fd1498Szrj if (!strncmp (switches[i].part1, p, len - have_wildcard)
592838fd1498Szrj && (have_wildcard || switches[i].part1[len] == '\0'))
592938fd1498Szrj {
593038fd1498Szrj switches[i].live_cond |= switch_option;
593138fd1498Szrj /* User switch be validated from validate_all_switches.
593238fd1498Szrj when the definition is seen from the spec file.
593338fd1498Szrj If not defined anywhere, will be rejected. */
593438fd1498Szrj if (switches[i].known)
593538fd1498Szrj switches[i].validated = true;
593638fd1498Szrj }
593738fd1498Szrj
593838fd1498Szrj p += len;
593938fd1498Szrj }
594038fd1498Szrj break;
594138fd1498Szrj
594238fd1498Szrj case '*':
594338fd1498Szrj if (soft_matched_part)
594438fd1498Szrj {
594538fd1498Szrj if (soft_matched_part[0])
594638fd1498Szrj do_spec_1 (soft_matched_part, 1, NULL);
594738fd1498Szrj /* Only insert a space after the substitution if it is at the
594838fd1498Szrj end of the current sequence. So if:
594938fd1498Szrj
595038fd1498Szrj "%{foo=*:bar%*}%{foo=*:one%*two}"
595138fd1498Szrj
595238fd1498Szrj matches -foo=hello then it will produce:
595338fd1498Szrj
595438fd1498Szrj barhello onehellotwo
595538fd1498Szrj */
595638fd1498Szrj if (*p == 0 || *p == '}')
595738fd1498Szrj do_spec_1 (" ", 0, NULL);
595838fd1498Szrj }
595938fd1498Szrj else
596038fd1498Szrj /* Catch the case where a spec string contains something like
596138fd1498Szrj '%{foo:%*}'. i.e. there is no * in the pattern on the left
596238fd1498Szrj hand side of the :. */
596338fd1498Szrj error ("spec failure: %<%%*%> has not been initialized by pattern match");
596438fd1498Szrj break;
596538fd1498Szrj
596638fd1498Szrj /* Process a string found as the value of a spec given by name.
596738fd1498Szrj This feature allows individual machine descriptions
596838fd1498Szrj to add and use their own specs. */
596938fd1498Szrj case '(':
597038fd1498Szrj {
597138fd1498Szrj const char *name = p;
597238fd1498Szrj struct spec_list *sl;
597338fd1498Szrj int len;
597438fd1498Szrj
597538fd1498Szrj /* The string after the S/P is the name of a spec that is to be
597638fd1498Szrj processed. */
597738fd1498Szrj while (*p && *p != ')')
597838fd1498Szrj p++;
597938fd1498Szrj
598038fd1498Szrj /* See if it's in the list. */
598138fd1498Szrj for (len = p - name, sl = specs; sl; sl = sl->next)
598238fd1498Szrj if (sl->name_len == len && !strncmp (sl->name, name, len))
598338fd1498Szrj {
598438fd1498Szrj name = *(sl->ptr_spec);
598538fd1498Szrj #ifdef DEBUG_SPECS
598638fd1498Szrj fnotice (stderr, "Processing spec (%s), which is '%s'\n",
598738fd1498Szrj sl->name, name);
598838fd1498Szrj #endif
598938fd1498Szrj break;
599038fd1498Szrj }
599138fd1498Szrj
599238fd1498Szrj if (sl)
599338fd1498Szrj {
599438fd1498Szrj value = do_spec_1 (name, 0, NULL);
599538fd1498Szrj if (value != 0)
599638fd1498Szrj return value;
599738fd1498Szrj }
599838fd1498Szrj
599938fd1498Szrj /* Discard the closing paren. */
600038fd1498Szrj if (*p)
600138fd1498Szrj p++;
600238fd1498Szrj }
600338fd1498Szrj break;
600438fd1498Szrj
600538fd1498Szrj default:
600638fd1498Szrj error ("spec failure: unrecognized spec option %qc", c);
600738fd1498Szrj break;
600838fd1498Szrj }
600938fd1498Szrj break;
601038fd1498Szrj
601138fd1498Szrj case '\\':
601238fd1498Szrj /* Backslash: treat next character as ordinary. */
601338fd1498Szrj c = *p++;
601438fd1498Szrj
601538fd1498Szrj /* Fall through. */
601638fd1498Szrj default:
601738fd1498Szrj /* Ordinary character: put it into the current argument. */
601838fd1498Szrj obstack_1grow (&obstack, c);
601938fd1498Szrj arg_going = 1;
602038fd1498Szrj }
602138fd1498Szrj
602238fd1498Szrj /* End of string. If we are processing a spec function, we need to
602338fd1498Szrj end any pending argument. */
602438fd1498Szrj if (processing_spec_function)
602538fd1498Szrj end_going_arg ();
602638fd1498Szrj
602738fd1498Szrj return 0;
602838fd1498Szrj }
602938fd1498Szrj
603038fd1498Szrj /* Look up a spec function. */
603138fd1498Szrj
603238fd1498Szrj static const struct spec_function *
lookup_spec_function(const char * name)603338fd1498Szrj lookup_spec_function (const char *name)
603438fd1498Szrj {
603538fd1498Szrj const struct spec_function *sf;
603638fd1498Szrj
603738fd1498Szrj for (sf = static_spec_functions; sf->name != NULL; sf++)
603838fd1498Szrj if (strcmp (sf->name, name) == 0)
603938fd1498Szrj return sf;
604038fd1498Szrj
604138fd1498Szrj return NULL;
604238fd1498Szrj }
604338fd1498Szrj
604438fd1498Szrj /* Evaluate a spec function. */
604538fd1498Szrj
604638fd1498Szrj static const char *
eval_spec_function(const char * func,const char * args)604738fd1498Szrj eval_spec_function (const char *func, const char *args)
604838fd1498Szrj {
604938fd1498Szrj const struct spec_function *sf;
605038fd1498Szrj const char *funcval;
605138fd1498Szrj
605238fd1498Szrj /* Saved spec processing context. */
605338fd1498Szrj vec<const_char_p> save_argbuf;
605438fd1498Szrj
605538fd1498Szrj int save_arg_going;
605638fd1498Szrj int save_delete_this_arg;
605738fd1498Szrj int save_this_is_output_file;
605838fd1498Szrj int save_this_is_library_file;
605938fd1498Szrj int save_input_from_pipe;
606038fd1498Szrj int save_this_is_linker_script;
606138fd1498Szrj const char *save_suffix_subst;
606238fd1498Szrj
606338fd1498Szrj int save_growing_size;
606438fd1498Szrj void *save_growing_value = NULL;
606538fd1498Szrj
606638fd1498Szrj sf = lookup_spec_function (func);
606738fd1498Szrj if (sf == NULL)
606838fd1498Szrj fatal_error (input_location, "unknown spec function %qs", func);
606938fd1498Szrj
607038fd1498Szrj /* Push the spec processing context. */
607138fd1498Szrj save_argbuf = argbuf;
607238fd1498Szrj
607338fd1498Szrj save_arg_going = arg_going;
607438fd1498Szrj save_delete_this_arg = delete_this_arg;
607538fd1498Szrj save_this_is_output_file = this_is_output_file;
607638fd1498Szrj save_this_is_library_file = this_is_library_file;
607738fd1498Szrj save_this_is_linker_script = this_is_linker_script;
607838fd1498Szrj save_input_from_pipe = input_from_pipe;
607938fd1498Szrj save_suffix_subst = suffix_subst;
608038fd1498Szrj
608138fd1498Szrj /* If we have some object growing now, finalize it so the args and function
608238fd1498Szrj eval proceed from a cleared context. This is needed to prevent the first
608338fd1498Szrj constructed arg from mistakenly including the growing value. We'll push
608438fd1498Szrj this value back on the obstack once the function evaluation is done, to
608538fd1498Szrj restore a consistent processing context for our caller. This is fine as
608638fd1498Szrj the address of growing objects isn't guaranteed to remain stable until
608738fd1498Szrj they are finalized, and we expect this situation to be rare enough for
608838fd1498Szrj the extra copy not to be an issue. */
608938fd1498Szrj save_growing_size = obstack_object_size (&obstack);
609038fd1498Szrj if (save_growing_size > 0)
609138fd1498Szrj save_growing_value = obstack_finish (&obstack);
609238fd1498Szrj
609338fd1498Szrj /* Create a new spec processing context, and build the function
609438fd1498Szrj arguments. */
609538fd1498Szrj
609638fd1498Szrj alloc_args ();
609738fd1498Szrj if (do_spec_2 (args) < 0)
609838fd1498Szrj fatal_error (input_location, "error in args to spec function %qs", func);
609938fd1498Szrj
610038fd1498Szrj /* argbuf_index is an index for the next argument to be inserted, and
610138fd1498Szrj so contains the count of the args already inserted. */
610238fd1498Szrj
610338fd1498Szrj funcval = (*sf->func) (argbuf.length (),
610438fd1498Szrj argbuf.address ());
610538fd1498Szrj
610638fd1498Szrj /* Pop the spec processing context. */
610738fd1498Szrj argbuf.release ();
610838fd1498Szrj argbuf = save_argbuf;
610938fd1498Szrj
611038fd1498Szrj arg_going = save_arg_going;
611138fd1498Szrj delete_this_arg = save_delete_this_arg;
611238fd1498Szrj this_is_output_file = save_this_is_output_file;
611338fd1498Szrj this_is_library_file = save_this_is_library_file;
611438fd1498Szrj this_is_linker_script = save_this_is_linker_script;
611538fd1498Szrj input_from_pipe = save_input_from_pipe;
611638fd1498Szrj suffix_subst = save_suffix_subst;
611738fd1498Szrj
611838fd1498Szrj if (save_growing_size > 0)
611938fd1498Szrj obstack_grow (&obstack, save_growing_value, save_growing_size);
612038fd1498Szrj
612138fd1498Szrj return funcval;
612238fd1498Szrj }
612338fd1498Szrj
612438fd1498Szrj /* Handle a spec function call of the form:
612538fd1498Szrj
612638fd1498Szrj %:function(args)
612738fd1498Szrj
612838fd1498Szrj ARGS is processed as a spec in a separate context and split into an
612938fd1498Szrj argument vector in the normal fashion. The function returns a string
613038fd1498Szrj containing a spec which we then process in the caller's context, or
613138fd1498Szrj NULL if no processing is required.
613238fd1498Szrj
613338fd1498Szrj If RETVAL_NONNULL is not NULL, then store a bool whether function
613438fd1498Szrj returned non-NULL. */
613538fd1498Szrj
613638fd1498Szrj static const char *
handle_spec_function(const char * p,bool * retval_nonnull)613738fd1498Szrj handle_spec_function (const char *p, bool *retval_nonnull)
613838fd1498Szrj {
613938fd1498Szrj char *func, *args;
614038fd1498Szrj const char *endp, *funcval;
614138fd1498Szrj int count;
614238fd1498Szrj
614338fd1498Szrj processing_spec_function++;
614438fd1498Szrj
614538fd1498Szrj /* Get the function name. */
614638fd1498Szrj for (endp = p; *endp != '\0'; endp++)
614738fd1498Szrj {
614838fd1498Szrj if (*endp == '(') /* ) */
614938fd1498Szrj break;
615038fd1498Szrj /* Only allow [A-Za-z0-9], -, and _ in function names. */
615138fd1498Szrj if (!ISALNUM (*endp) && !(*endp == '-' || *endp == '_'))
615238fd1498Szrj fatal_error (input_location, "malformed spec function name");
615338fd1498Szrj }
615438fd1498Szrj if (*endp != '(') /* ) */
615538fd1498Szrj fatal_error (input_location, "no arguments for spec function");
615638fd1498Szrj func = save_string (p, endp - p);
615738fd1498Szrj p = ++endp;
615838fd1498Szrj
615938fd1498Szrj /* Get the arguments. */
616038fd1498Szrj for (count = 0; *endp != '\0'; endp++)
616138fd1498Szrj {
616238fd1498Szrj /* ( */
616338fd1498Szrj if (*endp == ')')
616438fd1498Szrj {
616538fd1498Szrj if (count == 0)
616638fd1498Szrj break;
616738fd1498Szrj count--;
616838fd1498Szrj }
616938fd1498Szrj else if (*endp == '(') /* ) */
617038fd1498Szrj count++;
617138fd1498Szrj }
617238fd1498Szrj /* ( */
617338fd1498Szrj if (*endp != ')')
617438fd1498Szrj fatal_error (input_location, "malformed spec function arguments");
617538fd1498Szrj args = save_string (p, endp - p);
617638fd1498Szrj p = ++endp;
617738fd1498Szrj
617838fd1498Szrj /* p now points to just past the end of the spec function expression. */
617938fd1498Szrj
618038fd1498Szrj funcval = eval_spec_function (func, args);
618138fd1498Szrj if (funcval != NULL && do_spec_1 (funcval, 0, NULL) < 0)
618238fd1498Szrj p = NULL;
618338fd1498Szrj if (retval_nonnull)
618438fd1498Szrj *retval_nonnull = funcval != NULL;
618538fd1498Szrj
618638fd1498Szrj free (func);
618738fd1498Szrj free (args);
618838fd1498Szrj
618938fd1498Szrj processing_spec_function--;
619038fd1498Szrj
619138fd1498Szrj return p;
619238fd1498Szrj }
619338fd1498Szrj
619438fd1498Szrj /* Inline subroutine of handle_braces. Returns true if the current
619538fd1498Szrj input suffix matches the atom bracketed by ATOM and END_ATOM. */
619638fd1498Szrj static inline bool
input_suffix_matches(const char * atom,const char * end_atom)619738fd1498Szrj input_suffix_matches (const char *atom, const char *end_atom)
619838fd1498Szrj {
619938fd1498Szrj return (input_suffix
620038fd1498Szrj && !strncmp (input_suffix, atom, end_atom - atom)
620138fd1498Szrj && input_suffix[end_atom - atom] == '\0');
620238fd1498Szrj }
620338fd1498Szrj
620438fd1498Szrj /* Subroutine of handle_braces. Returns true if the current
620538fd1498Szrj input file's spec name matches the atom bracketed by ATOM and END_ATOM. */
620638fd1498Szrj static bool
input_spec_matches(const char * atom,const char * end_atom)620738fd1498Szrj input_spec_matches (const char *atom, const char *end_atom)
620838fd1498Szrj {
620938fd1498Szrj return (input_file_compiler
621038fd1498Szrj && input_file_compiler->suffix
621138fd1498Szrj && input_file_compiler->suffix[0] != '\0'
621238fd1498Szrj && !strncmp (input_file_compiler->suffix + 1, atom,
621338fd1498Szrj end_atom - atom)
621438fd1498Szrj && input_file_compiler->suffix[end_atom - atom + 1] == '\0');
621538fd1498Szrj }
621638fd1498Szrj
621738fd1498Szrj /* Subroutine of handle_braces. Returns true if a switch
621838fd1498Szrj matching the atom bracketed by ATOM and END_ATOM appeared on the
621938fd1498Szrj command line. */
622038fd1498Szrj static bool
switch_matches(const char * atom,const char * end_atom,int starred)622138fd1498Szrj switch_matches (const char *atom, const char *end_atom, int starred)
622238fd1498Szrj {
622338fd1498Szrj int i;
622438fd1498Szrj int len = end_atom - atom;
622538fd1498Szrj int plen = starred ? len : -1;
622638fd1498Szrj
622738fd1498Szrj for (i = 0; i < n_switches; i++)
622838fd1498Szrj if (!strncmp (switches[i].part1, atom, len)
622938fd1498Szrj && (starred || switches[i].part1[len] == '\0')
623038fd1498Szrj && check_live_switch (i, plen))
623138fd1498Szrj return true;
623238fd1498Szrj
623338fd1498Szrj /* Check if a switch with separated form matching the atom.
623438fd1498Szrj We check -D and -U switches. */
623538fd1498Szrj else if (switches[i].args != 0)
623638fd1498Szrj {
623738fd1498Szrj if ((*switches[i].part1 == 'D' || *switches[i].part1 == 'U')
623838fd1498Szrj && *switches[i].part1 == atom[0])
623938fd1498Szrj {
624038fd1498Szrj if (!strncmp (switches[i].args[0], &atom[1], len - 1)
624138fd1498Szrj && (starred || (switches[i].part1[1] == '\0'
624238fd1498Szrj && switches[i].args[0][len - 1] == '\0'))
624338fd1498Szrj && check_live_switch (i, (starred ? 1 : -1)))
624438fd1498Szrj return true;
624538fd1498Szrj }
624638fd1498Szrj }
624738fd1498Szrj
624838fd1498Szrj return false;
624938fd1498Szrj }
625038fd1498Szrj
625138fd1498Szrj /* Inline subroutine of handle_braces. Mark all of the switches which
625238fd1498Szrj match ATOM (extends to END_ATOM; STARRED indicates whether there
625338fd1498Szrj was a star after the atom) for later processing. */
625438fd1498Szrj static inline void
mark_matching_switches(const char * atom,const char * end_atom,int starred)625538fd1498Szrj mark_matching_switches (const char *atom, const char *end_atom, int starred)
625638fd1498Szrj {
625738fd1498Szrj int i;
625838fd1498Szrj int len = end_atom - atom;
625938fd1498Szrj int plen = starred ? len : -1;
626038fd1498Szrj
626138fd1498Szrj for (i = 0; i < n_switches; i++)
626238fd1498Szrj if (!strncmp (switches[i].part1, atom, len)
626338fd1498Szrj && (starred || switches[i].part1[len] == '\0')
626438fd1498Szrj && check_live_switch (i, plen))
626538fd1498Szrj switches[i].ordering = 1;
626638fd1498Szrj }
626738fd1498Szrj
626838fd1498Szrj /* Inline subroutine of handle_braces. Process all the currently
626938fd1498Szrj marked switches through give_switch, and clear the marks. */
627038fd1498Szrj static inline void
process_marked_switches(void)627138fd1498Szrj process_marked_switches (void)
627238fd1498Szrj {
627338fd1498Szrj int i;
627438fd1498Szrj
627538fd1498Szrj for (i = 0; i < n_switches; i++)
627638fd1498Szrj if (switches[i].ordering == 1)
627738fd1498Szrj {
627838fd1498Szrj switches[i].ordering = 0;
627938fd1498Szrj give_switch (i, 0);
628038fd1498Szrj }
628138fd1498Szrj }
628238fd1498Szrj
628338fd1498Szrj /* Handle a %{ ... } construct. P points just inside the leading {.
628438fd1498Szrj Returns a pointer one past the end of the brace block, or 0
628538fd1498Szrj if we call do_spec_1 and that returns -1. */
628638fd1498Szrj
628738fd1498Szrj static const char *
handle_braces(const char * p)628838fd1498Szrj handle_braces (const char *p)
628938fd1498Szrj {
629038fd1498Szrj const char *atom, *end_atom;
629138fd1498Szrj const char *d_atom = NULL, *d_end_atom = NULL;
629238fd1498Szrj char *esc_buf = NULL, *d_esc_buf = NULL;
629338fd1498Szrj int esc;
629438fd1498Szrj const char *orig = p;
629538fd1498Szrj
629638fd1498Szrj bool a_is_suffix;
629738fd1498Szrj bool a_is_spectype;
629838fd1498Szrj bool a_is_starred;
629938fd1498Szrj bool a_is_negated;
630038fd1498Szrj bool a_matched;
630138fd1498Szrj
630238fd1498Szrj bool a_must_be_last = false;
630338fd1498Szrj bool ordered_set = false;
630438fd1498Szrj bool disjunct_set = false;
630538fd1498Szrj bool disj_matched = false;
630638fd1498Szrj bool disj_starred = true;
630738fd1498Szrj bool n_way_choice = false;
630838fd1498Szrj bool n_way_matched = false;
630938fd1498Szrj
631038fd1498Szrj #define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0)
631138fd1498Szrj
631238fd1498Szrj do
631338fd1498Szrj {
631438fd1498Szrj if (a_must_be_last)
631538fd1498Szrj goto invalid;
631638fd1498Szrj
631738fd1498Szrj /* Scan one "atom" (S in the description above of %{}, possibly
631838fd1498Szrj with '!', '.', '@', ',', or '*' modifiers). */
631938fd1498Szrj a_matched = false;
632038fd1498Szrj a_is_suffix = false;
632138fd1498Szrj a_is_starred = false;
632238fd1498Szrj a_is_negated = false;
632338fd1498Szrj a_is_spectype = false;
632438fd1498Szrj
632538fd1498Szrj SKIP_WHITE ();
632638fd1498Szrj if (*p == '!')
632738fd1498Szrj p++, a_is_negated = true;
632838fd1498Szrj
632938fd1498Szrj SKIP_WHITE ();
633038fd1498Szrj if (*p == '%' && p[1] == ':')
633138fd1498Szrj {
633238fd1498Szrj atom = NULL;
633338fd1498Szrj end_atom = NULL;
633438fd1498Szrj p = handle_spec_function (p + 2, &a_matched);
633538fd1498Szrj }
633638fd1498Szrj else
633738fd1498Szrj {
633838fd1498Szrj if (*p == '.')
633938fd1498Szrj p++, a_is_suffix = true;
634038fd1498Szrj else if (*p == ',')
634138fd1498Szrj p++, a_is_spectype = true;
634238fd1498Szrj
634338fd1498Szrj atom = p;
634438fd1498Szrj esc = 0;
634538fd1498Szrj while (ISIDNUM (*p) || *p == '-' || *p == '+' || *p == '='
634638fd1498Szrj || *p == ',' || *p == '.' || *p == '@' || *p == '\\')
634738fd1498Szrj {
634838fd1498Szrj if (*p == '\\')
634938fd1498Szrj {
635038fd1498Szrj p++;
635138fd1498Szrj if (!*p)
635238fd1498Szrj fatal_error (input_location,
635338fd1498Szrj "braced spec %qs ends in escape", orig);
635438fd1498Szrj esc++;
635538fd1498Szrj }
635638fd1498Szrj p++;
635738fd1498Szrj }
635838fd1498Szrj end_atom = p;
635938fd1498Szrj
636038fd1498Szrj if (esc)
636138fd1498Szrj {
636238fd1498Szrj const char *ap;
636338fd1498Szrj char *ep;
636438fd1498Szrj
636538fd1498Szrj if (esc_buf && esc_buf != d_esc_buf)
636638fd1498Szrj free (esc_buf);
636738fd1498Szrj esc_buf = NULL;
636838fd1498Szrj ep = esc_buf = (char *) xmalloc (end_atom - atom - esc + 1);
636938fd1498Szrj for (ap = atom; ap != end_atom; ap++, ep++)
637038fd1498Szrj {
637138fd1498Szrj if (*ap == '\\')
637238fd1498Szrj ap++;
637338fd1498Szrj *ep = *ap;
637438fd1498Szrj }
637538fd1498Szrj *ep = '\0';
637638fd1498Szrj atom = esc_buf;
637738fd1498Szrj end_atom = ep;
637838fd1498Szrj }
637938fd1498Szrj
638038fd1498Szrj if (*p == '*')
638138fd1498Szrj p++, a_is_starred = 1;
638238fd1498Szrj }
638338fd1498Szrj
638438fd1498Szrj SKIP_WHITE ();
638538fd1498Szrj switch (*p)
638638fd1498Szrj {
638738fd1498Szrj case '&': case '}':
638838fd1498Szrj /* Substitute the switch(es) indicated by the current atom. */
638938fd1498Szrj ordered_set = true;
639038fd1498Szrj if (disjunct_set || n_way_choice || a_is_negated || a_is_suffix
639138fd1498Szrj || a_is_spectype || atom == end_atom)
639238fd1498Szrj goto invalid;
639338fd1498Szrj
639438fd1498Szrj mark_matching_switches (atom, end_atom, a_is_starred);
639538fd1498Szrj
639638fd1498Szrj if (*p == '}')
639738fd1498Szrj process_marked_switches ();
639838fd1498Szrj break;
639938fd1498Szrj
640038fd1498Szrj case '|': case ':':
640138fd1498Szrj /* Substitute some text if the current atom appears as a switch
640238fd1498Szrj or suffix. */
640338fd1498Szrj disjunct_set = true;
640438fd1498Szrj if (ordered_set)
640538fd1498Szrj goto invalid;
640638fd1498Szrj
640738fd1498Szrj if (atom && atom == end_atom)
640838fd1498Szrj {
640938fd1498Szrj if (!n_way_choice || disj_matched || *p == '|'
641038fd1498Szrj || a_is_negated || a_is_suffix || a_is_spectype
641138fd1498Szrj || a_is_starred)
641238fd1498Szrj goto invalid;
641338fd1498Szrj
641438fd1498Szrj /* An empty term may appear as the last choice of an
641538fd1498Szrj N-way choice set; it means "otherwise". */
641638fd1498Szrj a_must_be_last = true;
641738fd1498Szrj disj_matched = !n_way_matched;
641838fd1498Szrj disj_starred = false;
641938fd1498Szrj }
642038fd1498Szrj else
642138fd1498Szrj {
642238fd1498Szrj if ((a_is_suffix || a_is_spectype) && a_is_starred)
642338fd1498Szrj goto invalid;
642438fd1498Szrj
642538fd1498Szrj if (!a_is_starred)
642638fd1498Szrj disj_starred = false;
642738fd1498Szrj
642838fd1498Szrj /* Don't bother testing this atom if we already have a
642938fd1498Szrj match. */
643038fd1498Szrj if (!disj_matched && !n_way_matched)
643138fd1498Szrj {
643238fd1498Szrj if (atom == NULL)
643338fd1498Szrj /* a_matched is already set by handle_spec_function. */;
643438fd1498Szrj else if (a_is_suffix)
643538fd1498Szrj a_matched = input_suffix_matches (atom, end_atom);
643638fd1498Szrj else if (a_is_spectype)
643738fd1498Szrj a_matched = input_spec_matches (atom, end_atom);
643838fd1498Szrj else
643938fd1498Szrj a_matched = switch_matches (atom, end_atom, a_is_starred);
644038fd1498Szrj
644138fd1498Szrj if (a_matched != a_is_negated)
644238fd1498Szrj {
644338fd1498Szrj disj_matched = true;
644438fd1498Szrj d_atom = atom;
644538fd1498Szrj d_end_atom = end_atom;
644638fd1498Szrj d_esc_buf = esc_buf;
644738fd1498Szrj }
644838fd1498Szrj }
644938fd1498Szrj }
645038fd1498Szrj
645138fd1498Szrj if (*p == ':')
645238fd1498Szrj {
645338fd1498Szrj /* Found the body, that is, the text to substitute if the
645438fd1498Szrj current disjunction matches. */
645538fd1498Szrj p = process_brace_body (p + 1, d_atom, d_end_atom, disj_starred,
645638fd1498Szrj disj_matched && !n_way_matched);
645738fd1498Szrj if (p == 0)
645838fd1498Szrj goto done;
645938fd1498Szrj
646038fd1498Szrj /* If we have an N-way choice, reset state for the next
646138fd1498Szrj disjunction. */
646238fd1498Szrj if (*p == ';')
646338fd1498Szrj {
646438fd1498Szrj n_way_choice = true;
646538fd1498Szrj n_way_matched |= disj_matched;
646638fd1498Szrj disj_matched = false;
646738fd1498Szrj disj_starred = true;
646838fd1498Szrj d_atom = d_end_atom = NULL;
646938fd1498Szrj }
647038fd1498Szrj }
647138fd1498Szrj break;
647238fd1498Szrj
647338fd1498Szrj default:
647438fd1498Szrj goto invalid;
647538fd1498Szrj }
647638fd1498Szrj }
647738fd1498Szrj while (*p++ != '}');
647838fd1498Szrj
647938fd1498Szrj done:
648038fd1498Szrj if (d_esc_buf && d_esc_buf != esc_buf)
648138fd1498Szrj free (d_esc_buf);
648238fd1498Szrj if (esc_buf)
648338fd1498Szrj free (esc_buf);
648438fd1498Szrj
648538fd1498Szrj return p;
648638fd1498Szrj
648738fd1498Szrj invalid:
648838fd1498Szrj fatal_error (input_location, "braced spec %qs is invalid at %qc", orig, *p);
648938fd1498Szrj
649038fd1498Szrj #undef SKIP_WHITE
649138fd1498Szrj }
649238fd1498Szrj
649338fd1498Szrj /* Subroutine of handle_braces. Scan and process a brace substitution body
649438fd1498Szrj (X in the description of %{} syntax). P points one past the colon;
649538fd1498Szrj ATOM and END_ATOM bracket the first atom which was found to be true
649638fd1498Szrj (present) in the current disjunction; STARRED indicates whether all
649738fd1498Szrj the atoms in the current disjunction were starred (for syntax validation);
649838fd1498Szrj MATCHED indicates whether the disjunction matched or not, and therefore
649938fd1498Szrj whether or not the body is to be processed through do_spec_1 or just
650038fd1498Szrj skipped. Returns a pointer to the closing } or ;, or 0 if do_spec_1
650138fd1498Szrj returns -1. */
650238fd1498Szrj
650338fd1498Szrj static const char *
process_brace_body(const char * p,const char * atom,const char * end_atom,int starred,int matched)650438fd1498Szrj process_brace_body (const char *p, const char *atom, const char *end_atom,
650538fd1498Szrj int starred, int matched)
650638fd1498Szrj {
650738fd1498Szrj const char *body, *end_body;
650838fd1498Szrj unsigned int nesting_level;
650938fd1498Szrj bool have_subst = false;
651038fd1498Szrj
651138fd1498Szrj /* Locate the closing } or ;, honoring nested braces.
651238fd1498Szrj Trim trailing whitespace. */
651338fd1498Szrj body = p;
651438fd1498Szrj nesting_level = 1;
651538fd1498Szrj for (;;)
651638fd1498Szrj {
651738fd1498Szrj if (*p == '{')
651838fd1498Szrj nesting_level++;
651938fd1498Szrj else if (*p == '}')
652038fd1498Szrj {
652138fd1498Szrj if (!--nesting_level)
652238fd1498Szrj break;
652338fd1498Szrj }
652438fd1498Szrj else if (*p == ';' && nesting_level == 1)
652538fd1498Szrj break;
652638fd1498Szrj else if (*p == '%' && p[1] == '*' && nesting_level == 1)
652738fd1498Szrj have_subst = true;
652838fd1498Szrj else if (*p == '\0')
652938fd1498Szrj goto invalid;
653038fd1498Szrj p++;
653138fd1498Szrj }
653238fd1498Szrj
653338fd1498Szrj end_body = p;
653438fd1498Szrj while (end_body[-1] == ' ' || end_body[-1] == '\t')
653538fd1498Szrj end_body--;
653638fd1498Szrj
653738fd1498Szrj if (have_subst && !starred)
653838fd1498Szrj goto invalid;
653938fd1498Szrj
654038fd1498Szrj if (matched)
654138fd1498Szrj {
654238fd1498Szrj /* Copy the substitution body to permanent storage and execute it.
654338fd1498Szrj If have_subst is false, this is a simple matter of running the
654438fd1498Szrj body through do_spec_1... */
654538fd1498Szrj char *string = save_string (body, end_body - body);
654638fd1498Szrj if (!have_subst)
654738fd1498Szrj {
654838fd1498Szrj if (do_spec_1 (string, 0, NULL) < 0)
654938fd1498Szrj {
655038fd1498Szrj free (string);
655138fd1498Szrj return 0;
655238fd1498Szrj }
655338fd1498Szrj }
655438fd1498Szrj else
655538fd1498Szrj {
655638fd1498Szrj /* ... but if have_subst is true, we have to process the
655738fd1498Szrj body once for each matching switch, with %* set to the
655838fd1498Szrj variant part of the switch. */
655938fd1498Szrj unsigned int hard_match_len = end_atom - atom;
656038fd1498Szrj int i;
656138fd1498Szrj
656238fd1498Szrj for (i = 0; i < n_switches; i++)
656338fd1498Szrj if (!strncmp (switches[i].part1, atom, hard_match_len)
656438fd1498Szrj && check_live_switch (i, hard_match_len))
656538fd1498Szrj {
656638fd1498Szrj if (do_spec_1 (string, 0,
656738fd1498Szrj &switches[i].part1[hard_match_len]) < 0)
656838fd1498Szrj {
656938fd1498Szrj free (string);
657038fd1498Szrj return 0;
657138fd1498Szrj }
657238fd1498Szrj /* Pass any arguments this switch has. */
657338fd1498Szrj give_switch (i, 1);
657438fd1498Szrj suffix_subst = NULL;
657538fd1498Szrj }
657638fd1498Szrj }
657738fd1498Szrj free (string);
657838fd1498Szrj }
657938fd1498Szrj
658038fd1498Szrj return p;
658138fd1498Szrj
658238fd1498Szrj invalid:
658338fd1498Szrj fatal_error (input_location, "braced spec body %qs is invalid", body);
658438fd1498Szrj }
658538fd1498Szrj
658638fd1498Szrj /* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch
658738fd1498Szrj on the command line. PREFIX_LENGTH is the length of XXX in an {XXX*}
658838fd1498Szrj spec, or -1 if either exact match or %* is used.
658938fd1498Szrj
659038fd1498Szrj A -O switch is obsoleted by a later -O switch. A -f, -g, -m, or -W switch
659138fd1498Szrj whose value does not begin with "no-" is obsoleted by the same value
659238fd1498Szrj with the "no-", similarly for a switch with the "no-" prefix. */
659338fd1498Szrj
659438fd1498Szrj static int
check_live_switch(int switchnum,int prefix_length)659538fd1498Szrj check_live_switch (int switchnum, int prefix_length)
659638fd1498Szrj {
659738fd1498Szrj const char *name = switches[switchnum].part1;
659838fd1498Szrj int i;
659938fd1498Szrj
660038fd1498Szrj /* If we already processed this switch and determined if it was
660138fd1498Szrj live or not, return our past determination. */
660238fd1498Szrj if (switches[switchnum].live_cond != 0)
660338fd1498Szrj return ((switches[switchnum].live_cond & SWITCH_LIVE) != 0
660438fd1498Szrj && (switches[switchnum].live_cond & SWITCH_FALSE) == 0
660538fd1498Szrj && (switches[switchnum].live_cond & SWITCH_IGNORE_PERMANENTLY)
660638fd1498Szrj == 0);
660738fd1498Szrj
660838fd1498Szrj /* In the common case of {<at-most-one-letter>*}, a negating
660938fd1498Szrj switch would always match, so ignore that case. We will just
661038fd1498Szrj send the conflicting switches to the compiler phase. */
661138fd1498Szrj if (prefix_length >= 0 && prefix_length <= 1)
661238fd1498Szrj return 1;
661338fd1498Szrj
661438fd1498Szrj /* Now search for duplicate in a manner that depends on the name. */
661538fd1498Szrj switch (*name)
661638fd1498Szrj {
661738fd1498Szrj case 'O':
661838fd1498Szrj for (i = switchnum + 1; i < n_switches; i++)
661938fd1498Szrj if (switches[i].part1[0] == 'O')
662038fd1498Szrj {
662138fd1498Szrj switches[switchnum].validated = true;
662238fd1498Szrj switches[switchnum].live_cond = SWITCH_FALSE;
662338fd1498Szrj return 0;
662438fd1498Szrj }
662538fd1498Szrj break;
662638fd1498Szrj
662738fd1498Szrj case 'W': case 'f': case 'm': case 'g':
662838fd1498Szrj if (! strncmp (name + 1, "no-", 3))
662938fd1498Szrj {
663038fd1498Szrj /* We have Xno-YYY, search for XYYY. */
663138fd1498Szrj for (i = switchnum + 1; i < n_switches; i++)
663238fd1498Szrj if (switches[i].part1[0] == name[0]
663338fd1498Szrj && ! strcmp (&switches[i].part1[1], &name[4]))
663438fd1498Szrj {
663538fd1498Szrj /* --specs are validated with the validate_switches mechanism. */
663638fd1498Szrj if (switches[switchnum].known)
663738fd1498Szrj switches[switchnum].validated = true;
663838fd1498Szrj switches[switchnum].live_cond = SWITCH_FALSE;
663938fd1498Szrj return 0;
664038fd1498Szrj }
664138fd1498Szrj }
664238fd1498Szrj else
664338fd1498Szrj {
664438fd1498Szrj /* We have XYYY, search for Xno-YYY. */
664538fd1498Szrj for (i = switchnum + 1; i < n_switches; i++)
664638fd1498Szrj if (switches[i].part1[0] == name[0]
664738fd1498Szrj && switches[i].part1[1] == 'n'
664838fd1498Szrj && switches[i].part1[2] == 'o'
664938fd1498Szrj && switches[i].part1[3] == '-'
665038fd1498Szrj && !strcmp (&switches[i].part1[4], &name[1]))
665138fd1498Szrj {
665238fd1498Szrj /* --specs are validated with the validate_switches mechanism. */
665338fd1498Szrj if (switches[switchnum].known)
665438fd1498Szrj switches[switchnum].validated = true;
665538fd1498Szrj switches[switchnum].live_cond = SWITCH_FALSE;
665638fd1498Szrj return 0;
665738fd1498Szrj }
665838fd1498Szrj }
665938fd1498Szrj break;
666038fd1498Szrj }
666138fd1498Szrj
666238fd1498Szrj /* Otherwise the switch is live. */
666338fd1498Szrj switches[switchnum].live_cond |= SWITCH_LIVE;
666438fd1498Szrj return 1;
666538fd1498Szrj }
666638fd1498Szrj
666738fd1498Szrj /* Pass a switch to the current accumulating command
666838fd1498Szrj in the same form that we received it.
666938fd1498Szrj SWITCHNUM identifies the switch; it is an index into
667038fd1498Szrj the vector of switches gcc received, which is `switches'.
667138fd1498Szrj This cannot fail since it never finishes a command line.
667238fd1498Szrj
667338fd1498Szrj If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument. */
667438fd1498Szrj
667538fd1498Szrj static void
give_switch(int switchnum,int omit_first_word)667638fd1498Szrj give_switch (int switchnum, int omit_first_word)
667738fd1498Szrj {
667838fd1498Szrj if ((switches[switchnum].live_cond & SWITCH_IGNORE) != 0)
667938fd1498Szrj return;
668038fd1498Szrj
668138fd1498Szrj if (!omit_first_word)
668238fd1498Szrj {
668338fd1498Szrj do_spec_1 ("-", 0, NULL);
668438fd1498Szrj do_spec_1 (switches[switchnum].part1, 1, NULL);
668538fd1498Szrj }
668638fd1498Szrj
668738fd1498Szrj if (switches[switchnum].args != 0)
668838fd1498Szrj {
668938fd1498Szrj const char **p;
669038fd1498Szrj for (p = switches[switchnum].args; *p; p++)
669138fd1498Szrj {
669238fd1498Szrj const char *arg = *p;
669338fd1498Szrj
669438fd1498Szrj do_spec_1 (" ", 0, NULL);
669538fd1498Szrj if (suffix_subst)
669638fd1498Szrj {
669738fd1498Szrj unsigned length = strlen (arg);
669838fd1498Szrj int dot = 0;
669938fd1498Szrj
670038fd1498Szrj while (length-- && !IS_DIR_SEPARATOR (arg[length]))
670138fd1498Szrj if (arg[length] == '.')
670238fd1498Szrj {
670338fd1498Szrj (CONST_CAST (char *, arg))[length] = 0;
670438fd1498Szrj dot = 1;
670538fd1498Szrj break;
670638fd1498Szrj }
670738fd1498Szrj do_spec_1 (arg, 1, NULL);
670838fd1498Szrj if (dot)
670938fd1498Szrj (CONST_CAST (char *, arg))[length] = '.';
671038fd1498Szrj do_spec_1 (suffix_subst, 1, NULL);
671138fd1498Szrj }
671238fd1498Szrj else
671338fd1498Szrj do_spec_1 (arg, 1, NULL);
671438fd1498Szrj }
671538fd1498Szrj }
671638fd1498Szrj
671738fd1498Szrj do_spec_1 (" ", 0, NULL);
671838fd1498Szrj switches[switchnum].validated = true;
671938fd1498Szrj }
672038fd1498Szrj
672138fd1498Szrj /* Print GCC configuration (e.g. version, thread model, target,
672238fd1498Szrj configuration_arguments) to a given FILE. */
672338fd1498Szrj
672438fd1498Szrj static void
print_configuration(FILE * file)672538fd1498Szrj print_configuration (FILE *file)
672638fd1498Szrj {
672738fd1498Szrj int n;
672838fd1498Szrj const char *thrmod;
672938fd1498Szrj
673038fd1498Szrj fnotice (file, "Target: %s\n", spec_machine);
673138fd1498Szrj fnotice (file, "Configured with: %s\n", configuration_arguments);
673238fd1498Szrj
673338fd1498Szrj #ifdef THREAD_MODEL_SPEC
673438fd1498Szrj /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
673538fd1498Szrj but there's no point in doing all this processing just to get
673638fd1498Szrj thread_model back. */
673738fd1498Szrj obstack_init (&obstack);
673838fd1498Szrj do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
673938fd1498Szrj obstack_1grow (&obstack, '\0');
674038fd1498Szrj thrmod = XOBFINISH (&obstack, const char *);
674138fd1498Szrj #else
674238fd1498Szrj thrmod = thread_model;
674338fd1498Szrj #endif
674438fd1498Szrj
674538fd1498Szrj fnotice (file, "Thread model: %s\n", thrmod);
674638fd1498Szrj
674738fd1498Szrj /* compiler_version is truncated at the first space when initialized
674838fd1498Szrj from version string, so truncate version_string at the first space
674938fd1498Szrj before comparing. */
675038fd1498Szrj for (n = 0; version_string[n]; n++)
675138fd1498Szrj if (version_string[n] == ' ')
675238fd1498Szrj break;
675338fd1498Szrj
675438fd1498Szrj if (! strncmp (version_string, compiler_version, n)
675538fd1498Szrj && compiler_version[n] == 0)
675638fd1498Szrj fnotice (file, "gcc version %s %s\n", version_string,
675738fd1498Szrj pkgversion_string);
675838fd1498Szrj else
675938fd1498Szrj fnotice (file, "gcc driver version %s %sexecuting gcc version %s\n",
676038fd1498Szrj version_string, pkgversion_string, compiler_version);
676138fd1498Szrj
676238fd1498Szrj }
676338fd1498Szrj
676438fd1498Szrj #define RETRY_ICE_ATTEMPTS 3
676538fd1498Szrj
676638fd1498Szrj /* Returns true if FILE1 and FILE2 contain equivalent data, 0 otherwise. */
676738fd1498Szrj
676838fd1498Szrj static bool
files_equal_p(char * file1,char * file2)676938fd1498Szrj files_equal_p (char *file1, char *file2)
677038fd1498Szrj {
677138fd1498Szrj struct stat st1, st2;
677238fd1498Szrj off_t n, len;
677338fd1498Szrj int fd1, fd2;
677438fd1498Szrj const int bufsize = 8192;
677538fd1498Szrj char *buf = XNEWVEC (char, bufsize);
677638fd1498Szrj
677738fd1498Szrj fd1 = open (file1, O_RDONLY);
677838fd1498Szrj fd2 = open (file2, O_RDONLY);
677938fd1498Szrj
678038fd1498Szrj if (fd1 < 0 || fd2 < 0)
678138fd1498Szrj goto error;
678238fd1498Szrj
678338fd1498Szrj if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0)
678438fd1498Szrj goto error;
678538fd1498Szrj
678638fd1498Szrj if (st1.st_size != st2.st_size)
678738fd1498Szrj goto error;
678838fd1498Szrj
678938fd1498Szrj for (n = st1.st_size; n; n -= len)
679038fd1498Szrj {
679138fd1498Szrj len = n;
679238fd1498Szrj if ((int) len > bufsize / 2)
679338fd1498Szrj len = bufsize / 2;
679438fd1498Szrj
679538fd1498Szrj if (read (fd1, buf, len) != (int) len
679638fd1498Szrj || read (fd2, buf + bufsize / 2, len) != (int) len)
679738fd1498Szrj {
679838fd1498Szrj goto error;
679938fd1498Szrj }
680038fd1498Szrj
680138fd1498Szrj if (memcmp (buf, buf + bufsize / 2, len) != 0)
680238fd1498Szrj goto error;
680338fd1498Szrj }
680438fd1498Szrj
680538fd1498Szrj free (buf);
680638fd1498Szrj close (fd1);
680738fd1498Szrj close (fd2);
680838fd1498Szrj
680938fd1498Szrj return 1;
681038fd1498Szrj
681138fd1498Szrj error:
681238fd1498Szrj free (buf);
681338fd1498Szrj close (fd1);
681438fd1498Szrj close (fd2);
681538fd1498Szrj return 0;
681638fd1498Szrj }
681738fd1498Szrj
681838fd1498Szrj /* Check that compiler's output doesn't differ across runs.
681938fd1498Szrj TEMP_STDOUT_FILES and TEMP_STDERR_FILES are arrays of files, containing
682038fd1498Szrj stdout and stderr for each compiler run. Return true if all of
682138fd1498Szrj TEMP_STDOUT_FILES and TEMP_STDERR_FILES are equivalent. */
682238fd1498Szrj
682338fd1498Szrj static bool
check_repro(char ** temp_stdout_files,char ** temp_stderr_files)682438fd1498Szrj check_repro (char **temp_stdout_files, char **temp_stderr_files)
682538fd1498Szrj {
682638fd1498Szrj int i;
682738fd1498Szrj for (i = 0; i < RETRY_ICE_ATTEMPTS - 2; ++i)
682838fd1498Szrj {
682938fd1498Szrj if (!files_equal_p (temp_stdout_files[i], temp_stdout_files[i + 1])
683038fd1498Szrj || !files_equal_p (temp_stderr_files[i], temp_stderr_files[i + 1]))
683138fd1498Szrj {
683238fd1498Szrj fnotice (stderr, "The bug is not reproducible, so it is"
683338fd1498Szrj " likely a hardware or OS problem.\n");
683438fd1498Szrj break;
683538fd1498Szrj }
683638fd1498Szrj }
683738fd1498Szrj return i == RETRY_ICE_ATTEMPTS - 2;
683838fd1498Szrj }
683938fd1498Szrj
684038fd1498Szrj enum attempt_status {
684138fd1498Szrj ATTEMPT_STATUS_FAIL_TO_RUN,
684238fd1498Szrj ATTEMPT_STATUS_SUCCESS,
684338fd1498Szrj ATTEMPT_STATUS_ICE
684438fd1498Szrj };
684538fd1498Szrj
684638fd1498Szrj
684738fd1498Szrj /* Run compiler with arguments NEW_ARGV to reproduce the ICE, storing stdout
684838fd1498Szrj to OUT_TEMP and stderr to ERR_TEMP. If APPEND is TRUE, append to OUT_TEMP
684938fd1498Szrj and ERR_TEMP instead of truncating. If EMIT_SYSTEM_INFO is TRUE, also write
685038fd1498Szrj GCC configuration into to ERR_TEMP. Return ATTEMPT_STATUS_FAIL_TO_RUN if
685138fd1498Szrj compiler failed to run, ATTEMPT_STATUS_ICE if compiled ICE-ed and
685238fd1498Szrj ATTEMPT_STATUS_SUCCESS otherwise. */
685338fd1498Szrj
685438fd1498Szrj static enum attempt_status
run_attempt(const char ** new_argv,const char * out_temp,const char * err_temp,int emit_system_info,int append)685538fd1498Szrj run_attempt (const char **new_argv, const char *out_temp,
685638fd1498Szrj const char *err_temp, int emit_system_info, int append)
685738fd1498Szrj {
685838fd1498Szrj
685938fd1498Szrj if (emit_system_info)
686038fd1498Szrj {
686138fd1498Szrj FILE *file_out = fopen (err_temp, "a");
686238fd1498Szrj print_configuration (file_out);
686338fd1498Szrj fputs ("\n", file_out);
686438fd1498Szrj fclose (file_out);
686538fd1498Szrj }
686638fd1498Szrj
686738fd1498Szrj int exit_status;
686838fd1498Szrj const char *errmsg;
686938fd1498Szrj struct pex_obj *pex;
687038fd1498Szrj int err;
687138fd1498Szrj int pex_flags = PEX_USE_PIPES | PEX_LAST;
687238fd1498Szrj enum attempt_status status = ATTEMPT_STATUS_FAIL_TO_RUN;
687338fd1498Szrj
687438fd1498Szrj if (append)
687538fd1498Szrj pex_flags |= PEX_STDOUT_APPEND | PEX_STDERR_APPEND;
687638fd1498Szrj
687738fd1498Szrj pex = pex_init (PEX_USE_PIPES, new_argv[0], NULL);
687838fd1498Szrj if (!pex)
687938fd1498Szrj fatal_error (input_location, "pex_init failed: %m");
688038fd1498Szrj
688138fd1498Szrj errmsg = pex_run (pex, pex_flags, new_argv[0],
688238fd1498Szrj CONST_CAST2 (char *const *, const char **, &new_argv[1]), out_temp,
688338fd1498Szrj err_temp, &err);
688438fd1498Szrj if (errmsg != NULL)
688538fd1498Szrj {
688638fd1498Szrj if (err == 0)
688738fd1498Szrj fatal_error (input_location, errmsg);
688838fd1498Szrj else
688938fd1498Szrj {
689038fd1498Szrj errno = err;
689138fd1498Szrj pfatal_with_name (errmsg);
689238fd1498Szrj }
689338fd1498Szrj }
689438fd1498Szrj
689538fd1498Szrj if (!pex_get_status (pex, 1, &exit_status))
689638fd1498Szrj goto out;
689738fd1498Szrj
689838fd1498Szrj switch (WEXITSTATUS (exit_status))
689938fd1498Szrj {
690038fd1498Szrj case ICE_EXIT_CODE:
690138fd1498Szrj status = ATTEMPT_STATUS_ICE;
690238fd1498Szrj break;
690338fd1498Szrj
690438fd1498Szrj case SUCCESS_EXIT_CODE:
690538fd1498Szrj status = ATTEMPT_STATUS_SUCCESS;
690638fd1498Szrj break;
690738fd1498Szrj
690838fd1498Szrj default:
690938fd1498Szrj ;
691038fd1498Szrj }
691138fd1498Szrj
691238fd1498Szrj out:
691338fd1498Szrj pex_free (pex);
691438fd1498Szrj return status;
691538fd1498Szrj }
691638fd1498Szrj
691738fd1498Szrj /* This routine reads lines from IN file, adds C++ style comments
691838fd1498Szrj at the begining of each line and writes result into OUT. */
691938fd1498Szrj
692038fd1498Szrj static void
insert_comments(const char * file_in,const char * file_out)692138fd1498Szrj insert_comments (const char *file_in, const char *file_out)
692238fd1498Szrj {
692338fd1498Szrj FILE *in = fopen (file_in, "rb");
692438fd1498Szrj FILE *out = fopen (file_out, "wb");
692538fd1498Szrj char line[256];
692638fd1498Szrj
692738fd1498Szrj bool add_comment = true;
692838fd1498Szrj while (fgets (line, sizeof (line), in))
692938fd1498Szrj {
693038fd1498Szrj if (add_comment)
693138fd1498Szrj fputs ("// ", out);
693238fd1498Szrj fputs (line, out);
693338fd1498Szrj add_comment = strchr (line, '\n') != NULL;
693438fd1498Szrj }
693538fd1498Szrj
693638fd1498Szrj fclose (in);
693738fd1498Szrj fclose (out);
693838fd1498Szrj }
693938fd1498Szrj
694038fd1498Szrj /* This routine adds preprocessed source code into the given ERR_FILE.
694138fd1498Szrj To do this, it adds "-E" to NEW_ARGV and execute RUN_ATTEMPT routine to
694238fd1498Szrj add information in report file. RUN_ATTEMPT should return
694338fd1498Szrj ATTEMPT_STATUS_SUCCESS, in other case we cannot generate the report. */
694438fd1498Szrj
694538fd1498Szrj static void
do_report_bug(const char ** new_argv,const int nargs,char ** out_file,char ** err_file)694638fd1498Szrj do_report_bug (const char **new_argv, const int nargs,
694738fd1498Szrj char **out_file, char **err_file)
694838fd1498Szrj {
694938fd1498Szrj int i, status;
695038fd1498Szrj int fd = open (*out_file, O_RDWR | O_APPEND);
695138fd1498Szrj if (fd < 0)
695238fd1498Szrj return;
695338fd1498Szrj write (fd, "\n//", 3);
695438fd1498Szrj for (i = 0; i < nargs; i++)
695538fd1498Szrj {
695638fd1498Szrj write (fd, " ", 1);
695738fd1498Szrj write (fd, new_argv[i], strlen (new_argv[i]));
695838fd1498Szrj }
695938fd1498Szrj write (fd, "\n\n", 2);
696038fd1498Szrj close (fd);
696138fd1498Szrj new_argv[nargs] = "-E";
696238fd1498Szrj new_argv[nargs + 1] = NULL;
696338fd1498Szrj
696438fd1498Szrj status = run_attempt (new_argv, *out_file, *err_file, 0, 1);
696538fd1498Szrj
696638fd1498Szrj if (status == ATTEMPT_STATUS_SUCCESS)
696738fd1498Szrj {
696838fd1498Szrj fnotice (stderr, "Preprocessed source stored into %s file,"
696938fd1498Szrj " please attach this to your bugreport.\n", *out_file);
697038fd1498Szrj /* Make sure it is not deleted. */
697138fd1498Szrj free (*out_file);
697238fd1498Szrj *out_file = NULL;
697338fd1498Szrj }
697438fd1498Szrj }
697538fd1498Szrj
697638fd1498Szrj /* Try to reproduce ICE. If bug is reproducible, generate report .err file
697738fd1498Szrj containing GCC configuration, backtrace, compiler's command line options
697838fd1498Szrj and preprocessed source code. */
697938fd1498Szrj
698038fd1498Szrj static void
try_generate_repro(const char ** argv)698138fd1498Szrj try_generate_repro (const char **argv)
698238fd1498Szrj {
698338fd1498Szrj int i, nargs, out_arg = -1, quiet = 0, attempt;
698438fd1498Szrj const char **new_argv;
698538fd1498Szrj char *temp_files[RETRY_ICE_ATTEMPTS * 2];
698638fd1498Szrj char **temp_stdout_files = &temp_files[0];
698738fd1498Szrj char **temp_stderr_files = &temp_files[RETRY_ICE_ATTEMPTS];
698838fd1498Szrj
698938fd1498Szrj if (gcc_input_filename == NULL || ! strcmp (gcc_input_filename, "-"))
699038fd1498Szrj return;
699138fd1498Szrj
699238fd1498Szrj for (nargs = 0; argv[nargs] != NULL; ++nargs)
699338fd1498Szrj /* Only retry compiler ICEs, not preprocessor ones. */
699438fd1498Szrj if (! strcmp (argv[nargs], "-E"))
699538fd1498Szrj return;
699638fd1498Szrj else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o')
699738fd1498Szrj {
699838fd1498Szrj if (out_arg == -1)
699938fd1498Szrj out_arg = nargs;
700038fd1498Szrj else
700138fd1498Szrj return;
700238fd1498Szrj }
700338fd1498Szrj /* If the compiler is going to output any time information,
700438fd1498Szrj it might varry between invocations. */
700538fd1498Szrj else if (! strcmp (argv[nargs], "-quiet"))
700638fd1498Szrj quiet = 1;
700738fd1498Szrj else if (! strcmp (argv[nargs], "-ftime-report"))
700838fd1498Szrj return;
700938fd1498Szrj
701038fd1498Szrj if (out_arg == -1 || !quiet)
701138fd1498Szrj return;
701238fd1498Szrj
701338fd1498Szrj memset (temp_files, '\0', sizeof (temp_files));
701438fd1498Szrj new_argv = XALLOCAVEC (const char *, nargs + 4);
701538fd1498Szrj memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *));
701638fd1498Szrj new_argv[nargs++] = "-frandom-seed=0";
701738fd1498Szrj new_argv[nargs++] = "-fdump-noaddr";
701838fd1498Szrj new_argv[nargs] = NULL;
701938fd1498Szrj if (new_argv[out_arg][2] == '\0')
702038fd1498Szrj new_argv[out_arg + 1] = "-";
702138fd1498Szrj else
702238fd1498Szrj new_argv[out_arg] = "-o-";
702338fd1498Szrj
702438fd1498Szrj int status;
702538fd1498Szrj for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS; ++attempt)
702638fd1498Szrj {
702738fd1498Szrj int emit_system_info = 0;
702838fd1498Szrj int append = 0;
702938fd1498Szrj temp_stdout_files[attempt] = make_temp_file (".out");
703038fd1498Szrj temp_stderr_files[attempt] = make_temp_file (".err");
703138fd1498Szrj
703238fd1498Szrj if (attempt == RETRY_ICE_ATTEMPTS - 1)
703338fd1498Szrj {
703438fd1498Szrj append = 1;
703538fd1498Szrj emit_system_info = 1;
703638fd1498Szrj }
703738fd1498Szrj
703838fd1498Szrj status = run_attempt (new_argv, temp_stdout_files[attempt],
703938fd1498Szrj temp_stderr_files[attempt], emit_system_info,
704038fd1498Szrj append);
704138fd1498Szrj
704238fd1498Szrj if (status != ATTEMPT_STATUS_ICE)
704338fd1498Szrj {
704438fd1498Szrj fnotice (stderr, "The bug is not reproducible, so it is"
704538fd1498Szrj " likely a hardware or OS problem.\n");
704638fd1498Szrj goto out;
704738fd1498Szrj }
704838fd1498Szrj }
704938fd1498Szrj
705038fd1498Szrj if (!check_repro (temp_stdout_files, temp_stderr_files))
705138fd1498Szrj goto out;
705238fd1498Szrj
705338fd1498Szrj {
705438fd1498Szrj /* Insert commented out backtrace into report file. */
705538fd1498Szrj char **stderr_commented = &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1];
705638fd1498Szrj insert_comments (temp_stderr_files[RETRY_ICE_ATTEMPTS - 1],
705738fd1498Szrj *stderr_commented);
705838fd1498Szrj
705938fd1498Szrj /* In final attempt we append compiler options and preprocesssed code to last
706038fd1498Szrj generated .out file with configuration and backtrace. */
706138fd1498Szrj char **err = &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1];
706238fd1498Szrj do_report_bug (new_argv, nargs, stderr_commented, err);
706338fd1498Szrj }
706438fd1498Szrj
706538fd1498Szrj out:
706638fd1498Szrj for (i = 0; i < RETRY_ICE_ATTEMPTS * 2; i++)
706738fd1498Szrj if (temp_files[i])
706838fd1498Szrj {
706938fd1498Szrj unlink (temp_stdout_files[i]);
707038fd1498Szrj free (temp_stdout_files[i]);
707138fd1498Szrj }
707238fd1498Szrj }
707338fd1498Szrj
707438fd1498Szrj /* Search for a file named NAME trying various prefixes including the
707538fd1498Szrj user's -B prefix and some standard ones.
707638fd1498Szrj Return the absolute file name found. If nothing is found, return NAME. */
707738fd1498Szrj
707838fd1498Szrj static const char *
find_file(const char * name)707938fd1498Szrj find_file (const char *name)
708038fd1498Szrj {
708138fd1498Szrj char *newname = find_a_file (&startfile_prefixes, name, R_OK, true);
708238fd1498Szrj return newname ? newname : name;
708338fd1498Szrj }
708438fd1498Szrj
708538fd1498Szrj /* Determine whether a directory exists. If LINKER, return 0 for
708638fd1498Szrj certain fixed names not needed by the linker. */
708738fd1498Szrj
708838fd1498Szrj static int
is_directory(const char * path1,bool linker)708938fd1498Szrj is_directory (const char *path1, bool linker)
709038fd1498Szrj {
709138fd1498Szrj int len1;
709238fd1498Szrj char *path;
709338fd1498Szrj char *cp;
709438fd1498Szrj struct stat st;
709538fd1498Szrj
709638fd1498Szrj /* Ensure the string ends with "/.". The resulting path will be a
709738fd1498Szrj directory even if the given path is a symbolic link. */
709838fd1498Szrj len1 = strlen (path1);
709938fd1498Szrj path = (char *) alloca (3 + len1);
710038fd1498Szrj memcpy (path, path1, len1);
710138fd1498Szrj cp = path + len1;
710238fd1498Szrj if (!IS_DIR_SEPARATOR (cp[-1]))
710338fd1498Szrj *cp++ = DIR_SEPARATOR;
710438fd1498Szrj *cp++ = '.';
710538fd1498Szrj *cp = '\0';
710638fd1498Szrj
710738fd1498Szrj /* Exclude directories that the linker is known to search. */
710838fd1498Szrj if (linker
710938fd1498Szrj && IS_DIR_SEPARATOR (path[0])
711038fd1498Szrj && ((cp - path == 6
711138fd1498Szrj && filename_ncmp (path + 1, "lib", 3) == 0)
711238fd1498Szrj || (cp - path == 10
711338fd1498Szrj && filename_ncmp (path + 1, "usr", 3) == 0
711438fd1498Szrj && IS_DIR_SEPARATOR (path[4])
711538fd1498Szrj && filename_ncmp (path + 5, "lib", 3) == 0)))
711638fd1498Szrj return 0;
711738fd1498Szrj
711838fd1498Szrj return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
711938fd1498Szrj }
712038fd1498Szrj
712138fd1498Szrj /* Set up the various global variables to indicate that we're processing
712238fd1498Szrj the input file named FILENAME. */
712338fd1498Szrj
712438fd1498Szrj void
set_input(const char * filename)712538fd1498Szrj set_input (const char *filename)
712638fd1498Szrj {
712738fd1498Szrj const char *p;
712838fd1498Szrj
712938fd1498Szrj gcc_input_filename = filename;
713038fd1498Szrj input_filename_length = strlen (gcc_input_filename);
713138fd1498Szrj input_basename = lbasename (gcc_input_filename);
713238fd1498Szrj
713338fd1498Szrj /* Find a suffix starting with the last period,
713438fd1498Szrj and set basename_length to exclude that suffix. */
713538fd1498Szrj basename_length = strlen (input_basename);
713638fd1498Szrj suffixed_basename_length = basename_length;
713738fd1498Szrj p = input_basename + basename_length;
713838fd1498Szrj while (p != input_basename && *p != '.')
713938fd1498Szrj --p;
714038fd1498Szrj if (*p == '.' && p != input_basename)
714138fd1498Szrj {
714238fd1498Szrj basename_length = p - input_basename;
714338fd1498Szrj input_suffix = p + 1;
714438fd1498Szrj }
714538fd1498Szrj else
714638fd1498Szrj input_suffix = "";
714738fd1498Szrj
714838fd1498Szrj /* If a spec for 'g', 'u', or 'U' is seen with -save-temps then
714938fd1498Szrj we will need to do a stat on the gcc_input_filename. The
715038fd1498Szrj INPUT_STAT_SET signals that the stat is needed. */
715138fd1498Szrj input_stat_set = 0;
715238fd1498Szrj }
715338fd1498Szrj
715438fd1498Szrj /* On fatal signals, delete all the temporary files. */
715538fd1498Szrj
715638fd1498Szrj static void
fatal_signal(int signum)715738fd1498Szrj fatal_signal (int signum)
715838fd1498Szrj {
715938fd1498Szrj signal (signum, SIG_DFL);
716038fd1498Szrj delete_failure_queue ();
716138fd1498Szrj delete_temp_files ();
716238fd1498Szrj /* Get the same signal again, this time not handled,
716338fd1498Szrj so its normal effect occurs. */
716438fd1498Szrj kill (getpid (), signum);
716538fd1498Szrj }
716638fd1498Szrj
716738fd1498Szrj /* Compare the contents of the two files named CMPFILE[0] and
716838fd1498Szrj CMPFILE[1]. Return zero if they're identical, nonzero
716938fd1498Szrj otherwise. */
717038fd1498Szrj
717138fd1498Szrj static int
compare_files(char * cmpfile[])717238fd1498Szrj compare_files (char *cmpfile[])
717338fd1498Szrj {
717438fd1498Szrj int ret = 0;
717538fd1498Szrj FILE *temp[2] = { NULL, NULL };
717638fd1498Szrj int i;
717738fd1498Szrj
717838fd1498Szrj #if HAVE_MMAP_FILE
717938fd1498Szrj {
718038fd1498Szrj size_t length[2];
718138fd1498Szrj void *map[2] = { NULL, NULL };
718238fd1498Szrj
718338fd1498Szrj for (i = 0; i < 2; i++)
718438fd1498Szrj {
718538fd1498Szrj struct stat st;
718638fd1498Szrj
718738fd1498Szrj if (stat (cmpfile[i], &st) < 0 || !S_ISREG (st.st_mode))
718838fd1498Szrj {
718938fd1498Szrj error ("%s: could not determine length of compare-debug file %s",
719038fd1498Szrj gcc_input_filename, cmpfile[i]);
719138fd1498Szrj ret = 1;
719238fd1498Szrj break;
719338fd1498Szrj }
719438fd1498Szrj
719538fd1498Szrj length[i] = st.st_size;
719638fd1498Szrj }
719738fd1498Szrj
719838fd1498Szrj if (!ret && length[0] != length[1])
719938fd1498Szrj {
720038fd1498Szrj error ("%s: -fcompare-debug failure (length)", gcc_input_filename);
720138fd1498Szrj ret = 1;
720238fd1498Szrj }
720338fd1498Szrj
720438fd1498Szrj if (!ret)
720538fd1498Szrj for (i = 0; i < 2; i++)
720638fd1498Szrj {
720738fd1498Szrj int fd = open (cmpfile[i], O_RDONLY);
720838fd1498Szrj if (fd < 0)
720938fd1498Szrj {
721038fd1498Szrj error ("%s: could not open compare-debug file %s",
721138fd1498Szrj gcc_input_filename, cmpfile[i]);
721238fd1498Szrj ret = 1;
721338fd1498Szrj break;
721438fd1498Szrj }
721538fd1498Szrj
721638fd1498Szrj map[i] = mmap (NULL, length[i], PROT_READ, MAP_PRIVATE, fd, 0);
721738fd1498Szrj close (fd);
721838fd1498Szrj
721938fd1498Szrj if (map[i] == (void *) MAP_FAILED)
722038fd1498Szrj {
722138fd1498Szrj ret = -1;
722238fd1498Szrj break;
722338fd1498Szrj }
722438fd1498Szrj }
722538fd1498Szrj
722638fd1498Szrj if (!ret)
722738fd1498Szrj {
722838fd1498Szrj if (memcmp (map[0], map[1], length[0]) != 0)
722938fd1498Szrj {
723038fd1498Szrj error ("%s: -fcompare-debug failure", gcc_input_filename);
723138fd1498Szrj ret = 1;
723238fd1498Szrj }
723338fd1498Szrj }
723438fd1498Szrj
723538fd1498Szrj for (i = 0; i < 2; i++)
723638fd1498Szrj if (map[i])
723738fd1498Szrj munmap ((caddr_t) map[i], length[i]);
723838fd1498Szrj
723938fd1498Szrj if (ret >= 0)
724038fd1498Szrj return ret;
724138fd1498Szrj
724238fd1498Szrj ret = 0;
724338fd1498Szrj }
724438fd1498Szrj #endif
724538fd1498Szrj
724638fd1498Szrj for (i = 0; i < 2; i++)
724738fd1498Szrj {
724838fd1498Szrj temp[i] = fopen (cmpfile[i], "r");
724938fd1498Szrj if (!temp[i])
725038fd1498Szrj {
725138fd1498Szrj error ("%s: could not open compare-debug file %s",
725238fd1498Szrj gcc_input_filename, cmpfile[i]);
725338fd1498Szrj ret = 1;
725438fd1498Szrj break;
725538fd1498Szrj }
725638fd1498Szrj }
725738fd1498Szrj
725838fd1498Szrj if (!ret && temp[0] && temp[1])
725938fd1498Szrj for (;;)
726038fd1498Szrj {
726138fd1498Szrj int c0, c1;
726238fd1498Szrj c0 = fgetc (temp[0]);
726338fd1498Szrj c1 = fgetc (temp[1]);
726438fd1498Szrj
726538fd1498Szrj if (c0 != c1)
726638fd1498Szrj {
726738fd1498Szrj error ("%s: -fcompare-debug failure",
726838fd1498Szrj gcc_input_filename);
726938fd1498Szrj ret = 1;
727038fd1498Szrj break;
727138fd1498Szrj }
727238fd1498Szrj
727338fd1498Szrj if (c0 == EOF)
727438fd1498Szrj break;
727538fd1498Szrj }
727638fd1498Szrj
727738fd1498Szrj for (i = 1; i >= 0; i--)
727838fd1498Szrj {
727938fd1498Szrj if (temp[i])
728038fd1498Szrj fclose (temp[i]);
728138fd1498Szrj }
728238fd1498Szrj
728338fd1498Szrj return ret;
728438fd1498Szrj }
728538fd1498Szrj
driver(bool can_finalize,bool debug)728638fd1498Szrj driver::driver (bool can_finalize, bool debug) :
728738fd1498Szrj explicit_link_files (NULL),
728838fd1498Szrj decoded_options (NULL),
728938fd1498Szrj m_option_suggestions (NULL)
729038fd1498Szrj {
729138fd1498Szrj env.init (can_finalize, debug);
729238fd1498Szrj }
729338fd1498Szrj
~driver()729438fd1498Szrj driver::~driver ()
729538fd1498Szrj {
729638fd1498Szrj XDELETEVEC (explicit_link_files);
729738fd1498Szrj XDELETEVEC (decoded_options);
729838fd1498Szrj if (m_option_suggestions)
729938fd1498Szrj {
730038fd1498Szrj int i;
730138fd1498Szrj char *str;
730238fd1498Szrj FOR_EACH_VEC_ELT (*m_option_suggestions, i, str)
730338fd1498Szrj free (str);
730438fd1498Szrj delete m_option_suggestions;
730538fd1498Szrj }
730638fd1498Szrj }
730738fd1498Szrj
730838fd1498Szrj /* driver::main is implemented as a series of driver:: method calls. */
730938fd1498Szrj
731038fd1498Szrj int
main(int argc,char ** argv)731138fd1498Szrj driver::main (int argc, char **argv)
731238fd1498Szrj {
731338fd1498Szrj bool early_exit;
731438fd1498Szrj
731538fd1498Szrj set_progname (argv[0]);
731638fd1498Szrj expand_at_files (&argc, &argv);
731738fd1498Szrj decode_argv (argc, const_cast <const char **> (argv));
731838fd1498Szrj global_initializations ();
731938fd1498Szrj build_multilib_strings ();
732038fd1498Szrj set_up_specs ();
732138fd1498Szrj putenv_COLLECT_GCC (argv[0]);
732238fd1498Szrj maybe_putenv_COLLECT_LTO_WRAPPER ();
732338fd1498Szrj maybe_putenv_OFFLOAD_TARGETS ();
732438fd1498Szrj handle_unrecognized_options ();
732538fd1498Szrj
732638fd1498Szrj if (!maybe_print_and_exit ())
732738fd1498Szrj return 0;
732838fd1498Szrj
732938fd1498Szrj early_exit = prepare_infiles ();
733038fd1498Szrj if (early_exit)
733138fd1498Szrj return get_exit_code ();
733238fd1498Szrj
733338fd1498Szrj do_spec_on_infiles ();
733438fd1498Szrj maybe_run_linker (argv[0]);
733538fd1498Szrj final_actions ();
733638fd1498Szrj return get_exit_code ();
733738fd1498Szrj }
733838fd1498Szrj
733938fd1498Szrj /* Locate the final component of argv[0] after any leading path, and set
734038fd1498Szrj the program name accordingly. */
734138fd1498Szrj
734238fd1498Szrj void
set_progname(const char * argv0)734338fd1498Szrj driver::set_progname (const char *argv0) const
734438fd1498Szrj {
734538fd1498Szrj const char *p = argv0 + strlen (argv0);
734638fd1498Szrj while (p != argv0 && !IS_DIR_SEPARATOR (p[-1]))
734738fd1498Szrj --p;
734838fd1498Szrj progname = p;
734938fd1498Szrj
735038fd1498Szrj xmalloc_set_program_name (progname);
735138fd1498Szrj }
735238fd1498Szrj
735338fd1498Szrj /* Expand any @ files within the command-line args,
735438fd1498Szrj setting at_file_supplied if any were expanded. */
735538fd1498Szrj
735638fd1498Szrj void
expand_at_files(int * argc,char *** argv)735738fd1498Szrj driver::expand_at_files (int *argc, char ***argv) const
735838fd1498Szrj {
735938fd1498Szrj char **old_argv = *argv;
736038fd1498Szrj
736138fd1498Szrj expandargv (argc, argv);
736238fd1498Szrj
736338fd1498Szrj /* Determine if any expansions were made. */
736438fd1498Szrj if (*argv != old_argv)
736538fd1498Szrj at_file_supplied = true;
736638fd1498Szrj }
736738fd1498Szrj
736838fd1498Szrj /* Decode the command-line arguments from argc/argv into the
736938fd1498Szrj decoded_options array. */
737038fd1498Szrj
737138fd1498Szrj void
decode_argv(int argc,const char ** argv)737238fd1498Szrj driver::decode_argv (int argc, const char **argv)
737338fd1498Szrj {
737438fd1498Szrj /* Register the language-independent parameters. */
737538fd1498Szrj global_init_params ();
737638fd1498Szrj finish_params ();
737738fd1498Szrj
737838fd1498Szrj init_opts_obstack ();
737938fd1498Szrj init_options_struct (&global_options, &global_options_set);
738038fd1498Szrj
738138fd1498Szrj decode_cmdline_options_to_array (argc, argv,
738238fd1498Szrj CL_DRIVER,
738338fd1498Szrj &decoded_options, &decoded_options_count);
738438fd1498Szrj }
738538fd1498Szrj
738638fd1498Szrj /* Perform various initializations and setup. */
738738fd1498Szrj
738838fd1498Szrj void
global_initializations()738938fd1498Szrj driver::global_initializations ()
739038fd1498Szrj {
739138fd1498Szrj /* Unlock the stdio streams. */
739238fd1498Szrj unlock_std_streams ();
739338fd1498Szrj
739438fd1498Szrj gcc_init_libintl ();
739538fd1498Szrj
739638fd1498Szrj diagnostic_initialize (global_dc, 0);
739738fd1498Szrj diagnostic_color_init (global_dc);
739838fd1498Szrj
739938fd1498Szrj #ifdef GCC_DRIVER_HOST_INITIALIZATION
740038fd1498Szrj /* Perform host dependent initialization when needed. */
740138fd1498Szrj GCC_DRIVER_HOST_INITIALIZATION;
740238fd1498Szrj #endif
740338fd1498Szrj
740438fd1498Szrj if (atexit (delete_temp_files) != 0)
740538fd1498Szrj fatal_error (input_location, "atexit failed");
740638fd1498Szrj
740738fd1498Szrj if (signal (SIGINT, SIG_IGN) != SIG_IGN)
740838fd1498Szrj signal (SIGINT, fatal_signal);
740938fd1498Szrj #ifdef SIGHUP
741038fd1498Szrj if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
741138fd1498Szrj signal (SIGHUP, fatal_signal);
741238fd1498Szrj #endif
741338fd1498Szrj if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
741438fd1498Szrj signal (SIGTERM, fatal_signal);
741538fd1498Szrj #ifdef SIGPIPE
741638fd1498Szrj if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
741738fd1498Szrj signal (SIGPIPE, fatal_signal);
741838fd1498Szrj #endif
741938fd1498Szrj #ifdef SIGCHLD
742038fd1498Szrj /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
742138fd1498Szrj receive the signal. A different setting is inheritable */
742238fd1498Szrj signal (SIGCHLD, SIG_DFL);
742338fd1498Szrj #endif
742438fd1498Szrj
742538fd1498Szrj /* Parsing and gimplification sometimes need quite large stack.
742638fd1498Szrj Increase stack size limits if possible. */
742738fd1498Szrj stack_limit_increase (64 * 1024 * 1024);
742838fd1498Szrj
742938fd1498Szrj /* Allocate the argument vector. */
743038fd1498Szrj alloc_args ();
743138fd1498Szrj
743238fd1498Szrj obstack_init (&obstack);
743338fd1498Szrj }
743438fd1498Szrj
743538fd1498Szrj /* Build multilib_select, et. al from the separate lines that make up each
743638fd1498Szrj multilib selection. */
743738fd1498Szrj
743838fd1498Szrj void
build_multilib_strings()743938fd1498Szrj driver::build_multilib_strings () const
744038fd1498Szrj {
744138fd1498Szrj {
744238fd1498Szrj const char *p;
744338fd1498Szrj const char *const *q = multilib_raw;
744438fd1498Szrj int need_space;
744538fd1498Szrj
744638fd1498Szrj obstack_init (&multilib_obstack);
744738fd1498Szrj while ((p = *q++) != (char *) 0)
744838fd1498Szrj obstack_grow (&multilib_obstack, p, strlen (p));
744938fd1498Szrj
745038fd1498Szrj obstack_1grow (&multilib_obstack, 0);
745138fd1498Szrj multilib_select = XOBFINISH (&multilib_obstack, const char *);
745238fd1498Szrj
745338fd1498Szrj q = multilib_matches_raw;
745438fd1498Szrj while ((p = *q++) != (char *) 0)
745538fd1498Szrj obstack_grow (&multilib_obstack, p, strlen (p));
745638fd1498Szrj
745738fd1498Szrj obstack_1grow (&multilib_obstack, 0);
745838fd1498Szrj multilib_matches = XOBFINISH (&multilib_obstack, const char *);
745938fd1498Szrj
746038fd1498Szrj q = multilib_exclusions_raw;
746138fd1498Szrj while ((p = *q++) != (char *) 0)
746238fd1498Szrj obstack_grow (&multilib_obstack, p, strlen (p));
746338fd1498Szrj
746438fd1498Szrj obstack_1grow (&multilib_obstack, 0);
746538fd1498Szrj multilib_exclusions = XOBFINISH (&multilib_obstack, const char *);
746638fd1498Szrj
746738fd1498Szrj q = multilib_reuse_raw;
746838fd1498Szrj while ((p = *q++) != (char *) 0)
746938fd1498Szrj obstack_grow (&multilib_obstack, p, strlen (p));
747038fd1498Szrj
747138fd1498Szrj obstack_1grow (&multilib_obstack, 0);
747238fd1498Szrj multilib_reuse = XOBFINISH (&multilib_obstack, const char *);
747338fd1498Szrj
747438fd1498Szrj need_space = FALSE;
747538fd1498Szrj for (size_t i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++)
747638fd1498Szrj {
747738fd1498Szrj if (need_space)
747838fd1498Szrj obstack_1grow (&multilib_obstack, ' ');
747938fd1498Szrj obstack_grow (&multilib_obstack,
748038fd1498Szrj multilib_defaults_raw[i],
748138fd1498Szrj strlen (multilib_defaults_raw[i]));
748238fd1498Szrj need_space = TRUE;
748338fd1498Szrj }
748438fd1498Szrj
748538fd1498Szrj obstack_1grow (&multilib_obstack, 0);
748638fd1498Szrj multilib_defaults = XOBFINISH (&multilib_obstack, const char *);
748738fd1498Szrj }
748838fd1498Szrj }
748938fd1498Szrj
749038fd1498Szrj /* Set up the spec-handling machinery. */
749138fd1498Szrj
749238fd1498Szrj void
set_up_specs()749338fd1498Szrj driver::set_up_specs () const
749438fd1498Szrj {
749538fd1498Szrj const char *spec_machine_suffix;
749638fd1498Szrj char *specs_file;
749738fd1498Szrj size_t i;
749838fd1498Szrj
749938fd1498Szrj #ifdef INIT_ENVIRONMENT
750038fd1498Szrj /* Set up any other necessary machine specific environment variables. */
750138fd1498Szrj xputenv (INIT_ENVIRONMENT);
750238fd1498Szrj #endif
750338fd1498Szrj
750438fd1498Szrj /* Make a table of what switches there are (switches, n_switches).
750538fd1498Szrj Make a table of specified input files (infiles, n_infiles).
750638fd1498Szrj Decode switches that are handled locally. */
750738fd1498Szrj
750838fd1498Szrj process_command (decoded_options_count, decoded_options);
750938fd1498Szrj
751038fd1498Szrj /* Initialize the vector of specs to just the default.
751138fd1498Szrj This means one element containing 0s, as a terminator. */
751238fd1498Szrj
751338fd1498Szrj compilers = XNEWVAR (struct compiler, sizeof default_compilers);
751438fd1498Szrj memcpy (compilers, default_compilers, sizeof default_compilers);
751538fd1498Szrj n_compilers = n_default_compilers;
751638fd1498Szrj
751738fd1498Szrj /* Read specs from a file if there is one. */
751838fd1498Szrj
751938fd1498Szrj machine_suffix = concat (spec_host_machine, dir_separator_str, spec_version,
752038fd1498Szrj accel_dir_suffix, dir_separator_str, NULL);
752138fd1498Szrj just_machine_suffix = concat (spec_machine, dir_separator_str, NULL);
752238fd1498Szrj
752338fd1498Szrj specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, true);
752438fd1498Szrj /* Read the specs file unless it is a default one. */
752538fd1498Szrj if (specs_file != 0 && strcmp (specs_file, "specs"))
752638fd1498Szrj read_specs (specs_file, true, false);
752738fd1498Szrj else
752838fd1498Szrj init_spec ();
752938fd1498Szrj
753038fd1498Szrj #ifdef ACCEL_COMPILER
753138fd1498Szrj spec_machine_suffix = machine_suffix;
753238fd1498Szrj #else
753338fd1498Szrj spec_machine_suffix = just_machine_suffix;
753438fd1498Szrj #endif
753538fd1498Szrj
753638fd1498Szrj /* We need to check standard_exec_prefix/spec_machine_suffix/specs
753738fd1498Szrj for any override of as, ld and libraries. */
753838fd1498Szrj specs_file = (char *) alloca (strlen (standard_exec_prefix)
753938fd1498Szrj + strlen (spec_machine_suffix) + sizeof ("specs"));
754038fd1498Szrj strcpy (specs_file, standard_exec_prefix);
754138fd1498Szrj strcat (specs_file, spec_machine_suffix);
754238fd1498Szrj strcat (specs_file, "specs");
754338fd1498Szrj if (access (specs_file, R_OK) == 0)
754438fd1498Szrj read_specs (specs_file, true, false);
754538fd1498Szrj
754638fd1498Szrj /* Process any configure-time defaults specified for the command line
754738fd1498Szrj options, via OPTION_DEFAULT_SPECS. */
754838fd1498Szrj for (i = 0; i < ARRAY_SIZE (option_default_specs); i++)
754938fd1498Szrj do_option_spec (option_default_specs[i].name,
755038fd1498Szrj option_default_specs[i].spec);
755138fd1498Szrj
755238fd1498Szrj /* Process DRIVER_SELF_SPECS, adding any new options to the end
755338fd1498Szrj of the command line. */
755438fd1498Szrj
755538fd1498Szrj for (i = 0; i < ARRAY_SIZE (driver_self_specs); i++)
755638fd1498Szrj do_self_spec (driver_self_specs[i]);
755738fd1498Szrj
755838fd1498Szrj /* If not cross-compiling, look for executables in the standard
755938fd1498Szrj places. */
756038fd1498Szrj if (*cross_compile == '0')
756138fd1498Szrj {
756238fd1498Szrj if (*md_exec_prefix)
756338fd1498Szrj {
756438fd1498Szrj add_prefix (&exec_prefixes, md_exec_prefix, "GCC",
756538fd1498Szrj PREFIX_PRIORITY_LAST, 0, 0);
756638fd1498Szrj }
756738fd1498Szrj }
756838fd1498Szrj
756938fd1498Szrj /* Process sysroot_suffix_spec. */
757038fd1498Szrj if (*sysroot_suffix_spec != 0
757138fd1498Szrj && !no_sysroot_suffix
757238fd1498Szrj && do_spec_2 (sysroot_suffix_spec) == 0)
757338fd1498Szrj {
757438fd1498Szrj if (argbuf.length () > 1)
757538fd1498Szrj error ("spec failure: more than one arg to SYSROOT_SUFFIX_SPEC");
757638fd1498Szrj else if (argbuf.length () == 1)
757738fd1498Szrj target_sysroot_suffix = xstrdup (argbuf.last ());
757838fd1498Szrj }
757938fd1498Szrj
758038fd1498Szrj #ifdef HAVE_LD_SYSROOT
758138fd1498Szrj /* Pass the --sysroot option to the linker, if it supports that. If
758238fd1498Szrj there is a sysroot_suffix_spec, it has already been processed by
758338fd1498Szrj this point, so target_system_root really is the system root we
758438fd1498Szrj should be using. */
758538fd1498Szrj if (target_system_root)
758638fd1498Szrj {
758738fd1498Szrj obstack_grow (&obstack, "%(sysroot_spec) ", strlen ("%(sysroot_spec) "));
758838fd1498Szrj obstack_grow0 (&obstack, link_spec, strlen (link_spec));
758938fd1498Szrj set_spec ("link", XOBFINISH (&obstack, const char *), false);
759038fd1498Szrj }
759138fd1498Szrj #endif
759238fd1498Szrj
759338fd1498Szrj /* Process sysroot_hdrs_suffix_spec. */
759438fd1498Szrj if (*sysroot_hdrs_suffix_spec != 0
759538fd1498Szrj && !no_sysroot_suffix
759638fd1498Szrj && do_spec_2 (sysroot_hdrs_suffix_spec) == 0)
759738fd1498Szrj {
759838fd1498Szrj if (argbuf.length () > 1)
759938fd1498Szrj error ("spec failure: more than one arg to SYSROOT_HEADERS_SUFFIX_SPEC");
760038fd1498Szrj else if (argbuf.length () == 1)
760138fd1498Szrj target_sysroot_hdrs_suffix = xstrdup (argbuf.last ());
760238fd1498Szrj }
760338fd1498Szrj
760438fd1498Szrj /* Look for startfiles in the standard places. */
760538fd1498Szrj if (*startfile_prefix_spec != 0
760638fd1498Szrj && do_spec_2 (startfile_prefix_spec) == 0
760738fd1498Szrj && do_spec_1 (" ", 0, NULL) == 0)
760838fd1498Szrj {
760938fd1498Szrj const char *arg;
761038fd1498Szrj int ndx;
761138fd1498Szrj FOR_EACH_VEC_ELT (argbuf, ndx, arg)
761238fd1498Szrj add_sysrooted_prefix (&startfile_prefixes, arg, "BINUTILS",
761338fd1498Szrj PREFIX_PRIORITY_LAST, 0, 1);
761438fd1498Szrj }
761538fd1498Szrj /* We should eventually get rid of all these and stick to
761638fd1498Szrj startfile_prefix_spec exclusively. */
761738fd1498Szrj else if (*cross_compile == '0' || target_system_root)
761838fd1498Szrj {
761938fd1498Szrj if (*md_startfile_prefix)
762038fd1498Szrj add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix,
762138fd1498Szrj "GCC", PREFIX_PRIORITY_LAST, 0, 1);
762238fd1498Szrj
762338fd1498Szrj if (*md_startfile_prefix_1)
762438fd1498Szrj add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix_1,
762538fd1498Szrj "GCC", PREFIX_PRIORITY_LAST, 0, 1);
762638fd1498Szrj
762738fd1498Szrj /* If standard_startfile_prefix is relative, base it on
762838fd1498Szrj standard_exec_prefix. This lets us move the installed tree
762938fd1498Szrj as a unit. If GCC_EXEC_PREFIX is defined, base
763038fd1498Szrj standard_startfile_prefix on that as well.
763138fd1498Szrj
763238fd1498Szrj If the prefix is relative, only search it for native compilers;
763338fd1498Szrj otherwise we will search a directory containing host libraries. */
763438fd1498Szrj if (IS_ABSOLUTE_PATH (standard_startfile_prefix))
763538fd1498Szrj add_sysrooted_prefix (&startfile_prefixes,
763638fd1498Szrj standard_startfile_prefix, "BINUTILS",
763738fd1498Szrj PREFIX_PRIORITY_LAST, 0, 1);
763838fd1498Szrj else if (*cross_compile == '0')
763938fd1498Szrj {
764038fd1498Szrj add_prefix (&startfile_prefixes,
764138fd1498Szrj concat (gcc_exec_prefix
764238fd1498Szrj ? gcc_exec_prefix : standard_exec_prefix,
764338fd1498Szrj machine_suffix,
764438fd1498Szrj standard_startfile_prefix, NULL),
764538fd1498Szrj NULL, PREFIX_PRIORITY_LAST, 0, 1);
764638fd1498Szrj }
764738fd1498Szrj
764838fd1498Szrj /* Sysrooted prefixes are relocated because target_system_root is
764938fd1498Szrj also relocated by gcc_exec_prefix. */
765038fd1498Szrj if (*standard_startfile_prefix_1)
765138fd1498Szrj add_sysrooted_prefix (&startfile_prefixes,
765238fd1498Szrj standard_startfile_prefix_1, "BINUTILS",
765338fd1498Szrj PREFIX_PRIORITY_LAST, 0, 1);
765438fd1498Szrj if (*standard_startfile_prefix_2)
765538fd1498Szrj add_sysrooted_prefix (&startfile_prefixes,
765638fd1498Szrj standard_startfile_prefix_2, "BINUTILS",
765738fd1498Szrj PREFIX_PRIORITY_LAST, 0, 1);
765838fd1498Szrj }
765938fd1498Szrj
766038fd1498Szrj /* Process any user specified specs in the order given on the command
766138fd1498Szrj line. */
766238fd1498Szrj for (struct user_specs *uptr = user_specs_head; uptr; uptr = uptr->next)
766338fd1498Szrj {
766438fd1498Szrj char *filename = find_a_file (&startfile_prefixes, uptr->filename,
766538fd1498Szrj R_OK, true);
766638fd1498Szrj read_specs (filename ? filename : uptr->filename, false, true);
766738fd1498Szrj }
766838fd1498Szrj
766938fd1498Szrj /* Process any user self specs. */
767038fd1498Szrj {
767138fd1498Szrj struct spec_list *sl;
767238fd1498Szrj for (sl = specs; sl; sl = sl->next)
767338fd1498Szrj if (sl->name_len == sizeof "self_spec" - 1
767438fd1498Szrj && !strcmp (sl->name, "self_spec"))
767538fd1498Szrj do_self_spec (*sl->ptr_spec);
767638fd1498Szrj }
767738fd1498Szrj
767838fd1498Szrj if (compare_debug)
767938fd1498Szrj {
768038fd1498Szrj enum save_temps save;
768138fd1498Szrj
768238fd1498Szrj if (!compare_debug_second)
768338fd1498Szrj {
768438fd1498Szrj n_switches_debug_check[1] = n_switches;
768538fd1498Szrj n_switches_alloc_debug_check[1] = n_switches_alloc;
768638fd1498Szrj switches_debug_check[1] = XDUPVEC (struct switchstr, switches,
768738fd1498Szrj n_switches_alloc);
768838fd1498Szrj
768938fd1498Szrj do_self_spec ("%:compare-debug-self-opt()");
769038fd1498Szrj n_switches_debug_check[0] = n_switches;
769138fd1498Szrj n_switches_alloc_debug_check[0] = n_switches_alloc;
769238fd1498Szrj switches_debug_check[0] = switches;
769338fd1498Szrj
769438fd1498Szrj n_switches = n_switches_debug_check[1];
769538fd1498Szrj n_switches_alloc = n_switches_alloc_debug_check[1];
769638fd1498Szrj switches = switches_debug_check[1];
769738fd1498Szrj }
769838fd1498Szrj
769938fd1498Szrj /* Avoid crash when computing %j in this early. */
770038fd1498Szrj save = save_temps_flag;
770138fd1498Szrj save_temps_flag = SAVE_TEMPS_NONE;
770238fd1498Szrj
770338fd1498Szrj compare_debug = -compare_debug;
770438fd1498Szrj do_self_spec ("%:compare-debug-self-opt()");
770538fd1498Szrj
770638fd1498Szrj save_temps_flag = save;
770738fd1498Szrj
770838fd1498Szrj if (!compare_debug_second)
770938fd1498Szrj {
771038fd1498Szrj n_switches_debug_check[1] = n_switches;
771138fd1498Szrj n_switches_alloc_debug_check[1] = n_switches_alloc;
771238fd1498Szrj switches_debug_check[1] = switches;
771338fd1498Szrj compare_debug = -compare_debug;
771438fd1498Szrj n_switches = n_switches_debug_check[0];
771538fd1498Szrj n_switches_alloc = n_switches_debug_check[0];
771638fd1498Szrj switches = switches_debug_check[0];
771738fd1498Szrj }
771838fd1498Szrj }
771938fd1498Szrj
772038fd1498Szrj
772138fd1498Szrj /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake. */
772238fd1498Szrj if (gcc_exec_prefix)
772338fd1498Szrj gcc_exec_prefix = concat (gcc_exec_prefix, spec_host_machine,
772438fd1498Szrj dir_separator_str, spec_version,
772538fd1498Szrj accel_dir_suffix, dir_separator_str, NULL);
772638fd1498Szrj
772738fd1498Szrj /* Now we have the specs.
772838fd1498Szrj Set the `valid' bits for switches that match anything in any spec. */
772938fd1498Szrj
773038fd1498Szrj validate_all_switches ();
773138fd1498Szrj
773238fd1498Szrj /* Now that we have the switches and the specs, set
773338fd1498Szrj the subdirectory based on the options. */
773438fd1498Szrj set_multilib_dir ();
773538fd1498Szrj }
773638fd1498Szrj
773738fd1498Szrj /* Set up to remember the pathname of gcc and any options
773838fd1498Szrj needed for collect. We use argv[0] instead of progname because
773938fd1498Szrj we need the complete pathname. */
774038fd1498Szrj
774138fd1498Szrj void
putenv_COLLECT_GCC(const char * argv0)774238fd1498Szrj driver::putenv_COLLECT_GCC (const char *argv0) const
774338fd1498Szrj {
774438fd1498Szrj obstack_init (&collect_obstack);
774538fd1498Szrj obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1);
774638fd1498Szrj obstack_grow (&collect_obstack, argv0, strlen (argv0) + 1);
774738fd1498Szrj xputenv (XOBFINISH (&collect_obstack, char *));
774838fd1498Szrj }
774938fd1498Szrj
775038fd1498Szrj /* Set up to remember the pathname of the lto wrapper. */
775138fd1498Szrj
775238fd1498Szrj void
maybe_putenv_COLLECT_LTO_WRAPPER()775338fd1498Szrj driver::maybe_putenv_COLLECT_LTO_WRAPPER () const
775438fd1498Szrj {
775538fd1498Szrj char *lto_wrapper_file;
775638fd1498Szrj
775738fd1498Szrj if (have_c)
775838fd1498Szrj lto_wrapper_file = NULL;
775938fd1498Szrj else
776038fd1498Szrj lto_wrapper_file = find_a_file (&exec_prefixes, "lto-wrapper",
776138fd1498Szrj X_OK, false);
776238fd1498Szrj if (lto_wrapper_file)
776338fd1498Szrj {
776438fd1498Szrj lto_wrapper_file = convert_white_space (lto_wrapper_file);
776538fd1498Szrj lto_wrapper_spec = lto_wrapper_file;
776638fd1498Szrj obstack_init (&collect_obstack);
776738fd1498Szrj obstack_grow (&collect_obstack, "COLLECT_LTO_WRAPPER=",
776838fd1498Szrj sizeof ("COLLECT_LTO_WRAPPER=") - 1);
776938fd1498Szrj obstack_grow (&collect_obstack, lto_wrapper_spec,
777038fd1498Szrj strlen (lto_wrapper_spec) + 1);
777138fd1498Szrj xputenv (XOBFINISH (&collect_obstack, char *));
777238fd1498Szrj }
777338fd1498Szrj
777438fd1498Szrj }
777538fd1498Szrj
777638fd1498Szrj /* Set up to remember the names of offload targets. */
777738fd1498Szrj
777838fd1498Szrj void
maybe_putenv_OFFLOAD_TARGETS()777938fd1498Szrj driver::maybe_putenv_OFFLOAD_TARGETS () const
778038fd1498Szrj {
778138fd1498Szrj if (offload_targets && offload_targets[0] != '\0')
778238fd1498Szrj {
778338fd1498Szrj obstack_grow (&collect_obstack, "OFFLOAD_TARGET_NAMES=",
778438fd1498Szrj sizeof ("OFFLOAD_TARGET_NAMES=") - 1);
778538fd1498Szrj obstack_grow (&collect_obstack, offload_targets,
778638fd1498Szrj strlen (offload_targets) + 1);
778738fd1498Szrj xputenv (XOBFINISH (&collect_obstack, char *));
778838fd1498Szrj }
778938fd1498Szrj
779038fd1498Szrj free (offload_targets);
779138fd1498Szrj offload_targets = NULL;
779238fd1498Szrj }
779338fd1498Szrj
779438fd1498Szrj /* Helper function for driver::suggest_option. Populate
779538fd1498Szrj m_option_suggestions with candidate strings for misspelled options.
779638fd1498Szrj The strings will be freed by the driver's dtor. */
779738fd1498Szrj
779838fd1498Szrj void
build_option_suggestions(void)779938fd1498Szrj driver::build_option_suggestions (void)
780038fd1498Szrj {
780138fd1498Szrj gcc_assert (m_option_suggestions == NULL);
780238fd1498Szrj m_option_suggestions = new auto_vec <char *> ();
780338fd1498Szrj
780438fd1498Szrj /* We build a vec of m_option_suggestions, using add_misspelling_candidates
780538fd1498Szrj to add copies of strings, without a leading dash. */
780638fd1498Szrj
780738fd1498Szrj for (unsigned int i = 0; i < cl_options_count; i++)
780838fd1498Szrj {
780938fd1498Szrj const struct cl_option *option = &cl_options[i];
781038fd1498Szrj const char *opt_text = option->opt_text;
781138fd1498Szrj switch (i)
781238fd1498Szrj {
781338fd1498Szrj default:
781438fd1498Szrj if (option->var_type == CLVC_ENUM)
781538fd1498Szrj {
781638fd1498Szrj const struct cl_enum *e = &cl_enums[option->var_enum];
781738fd1498Szrj for (unsigned j = 0; e->values[j].arg != NULL; j++)
781838fd1498Szrj {
781938fd1498Szrj char *with_arg = concat (opt_text, e->values[j].arg, NULL);
782038fd1498Szrj add_misspelling_candidates (m_option_suggestions, option,
782138fd1498Szrj with_arg);
782238fd1498Szrj free (with_arg);
782338fd1498Szrj }
782438fd1498Szrj }
782538fd1498Szrj else
782638fd1498Szrj add_misspelling_candidates (m_option_suggestions, option,
782738fd1498Szrj opt_text);
782838fd1498Szrj break;
782938fd1498Szrj
783038fd1498Szrj case OPT_fsanitize_:
783138fd1498Szrj case OPT_fsanitize_recover_:
783238fd1498Szrj /* -fsanitize= and -fsanitize-recover= can take
783338fd1498Szrj a comma-separated list of arguments. Given that combinations
783438fd1498Szrj are supported, we can't add all potential candidates to the
783538fd1498Szrj vec, but if we at least add them individually without commas,
783638fd1498Szrj we should do a better job e.g. correcting
783738fd1498Szrj "-sanitize=address"
783838fd1498Szrj to
783938fd1498Szrj "-fsanitize=address"
784038fd1498Szrj rather than to "-Wframe-address" (PR driver/69265). */
784138fd1498Szrj {
784238fd1498Szrj for (int j = 0; sanitizer_opts[j].name != NULL; ++j)
784338fd1498Szrj {
784438fd1498Szrj struct cl_option optb;
784538fd1498Szrj /* -fsanitize=all is not valid, only -fno-sanitize=all.
784638fd1498Szrj So don't register the positive misspelling candidates
784738fd1498Szrj for it. */
784838fd1498Szrj if (sanitizer_opts[j].flag == ~0U && i == OPT_fsanitize_)
784938fd1498Szrj {
785038fd1498Szrj optb = *option;
785138fd1498Szrj optb.opt_text = opt_text = "-fno-sanitize=";
785238fd1498Szrj optb.cl_reject_negative = true;
785338fd1498Szrj option = &optb;
785438fd1498Szrj }
785538fd1498Szrj /* Get one arg at a time e.g. "-fsanitize=address". */
785638fd1498Szrj char *with_arg = concat (opt_text,
785738fd1498Szrj sanitizer_opts[j].name,
785838fd1498Szrj NULL);
785938fd1498Szrj /* Add with_arg and all of its variant spellings e.g.
786038fd1498Szrj "-fno-sanitize=address" to candidates (albeit without
786138fd1498Szrj leading dashes). */
786238fd1498Szrj add_misspelling_candidates (m_option_suggestions, option,
786338fd1498Szrj with_arg);
786438fd1498Szrj free (with_arg);
786538fd1498Szrj }
786638fd1498Szrj }
786738fd1498Szrj break;
786838fd1498Szrj }
786938fd1498Szrj }
787038fd1498Szrj }
787138fd1498Szrj
787238fd1498Szrj /* Helper function for driver::handle_unrecognized_options.
787338fd1498Szrj
787438fd1498Szrj Given an unrecognized option BAD_OPT (without the leading dash),
787538fd1498Szrj locate the closest reasonable matching option (again, without the
787638fd1498Szrj leading dash), or NULL.
787738fd1498Szrj
787838fd1498Szrj The returned string is owned by the driver instance. */
787938fd1498Szrj
788038fd1498Szrj const char *
suggest_option(const char * bad_opt)788138fd1498Szrj driver::suggest_option (const char *bad_opt)
788238fd1498Szrj {
788338fd1498Szrj /* Lazily populate m_option_suggestions. */
788438fd1498Szrj if (!m_option_suggestions)
788538fd1498Szrj build_option_suggestions ();
788638fd1498Szrj gcc_assert (m_option_suggestions);
788738fd1498Szrj
788838fd1498Szrj /* "m_option_suggestions" is now populated. Use it. */
788938fd1498Szrj return find_closest_string
789038fd1498Szrj (bad_opt,
789138fd1498Szrj (auto_vec <const char *> *) m_option_suggestions);
789238fd1498Szrj }
789338fd1498Szrj
789438fd1498Szrj /* Reject switches that no pass was interested in. */
789538fd1498Szrj
789638fd1498Szrj void
handle_unrecognized_options()789738fd1498Szrj driver::handle_unrecognized_options ()
789838fd1498Szrj {
789938fd1498Szrj for (size_t i = 0; (int) i < n_switches; i++)
790038fd1498Szrj if (! switches[i].validated)
790138fd1498Szrj {
790238fd1498Szrj const char *hint = suggest_option (switches[i].part1);
790338fd1498Szrj if (hint)
790438fd1498Szrj error ("unrecognized command line option %<-%s%>;"
790538fd1498Szrj " did you mean %<-%s%>?",
790638fd1498Szrj switches[i].part1, hint);
790738fd1498Szrj else
790838fd1498Szrj error ("unrecognized command line option %<-%s%>",
790938fd1498Szrj switches[i].part1);
791038fd1498Szrj }
791138fd1498Szrj }
791238fd1498Szrj
791338fd1498Szrj /* Handle the various -print-* options, returning 0 if the driver
791438fd1498Szrj should exit, or nonzero if the driver should continue. */
791538fd1498Szrj
791638fd1498Szrj int
maybe_print_and_exit()791738fd1498Szrj driver::maybe_print_and_exit () const
791838fd1498Szrj {
791938fd1498Szrj if (print_search_dirs)
792038fd1498Szrj {
792138fd1498Szrj printf (_("install: %s%s\n"),
792238fd1498Szrj gcc_exec_prefix ? gcc_exec_prefix : standard_exec_prefix,
792338fd1498Szrj gcc_exec_prefix ? "" : machine_suffix);
792438fd1498Szrj printf (_("programs: %s\n"),
792538fd1498Szrj build_search_list (&exec_prefixes, "", false, false));
792638fd1498Szrj printf (_("libraries: %s\n"),
792738fd1498Szrj build_search_list (&startfile_prefixes, "", false, true));
792838fd1498Szrj return (0);
792938fd1498Szrj }
793038fd1498Szrj
793138fd1498Szrj if (print_file_name)
793238fd1498Szrj {
793338fd1498Szrj printf ("%s\n", find_file (print_file_name));
793438fd1498Szrj return (0);
793538fd1498Szrj }
793638fd1498Szrj
793738fd1498Szrj if (print_prog_name)
793838fd1498Szrj {
793938fd1498Szrj if (use_ld != NULL && ! strcmp (print_prog_name, "ld"))
794038fd1498Szrj {
794138fd1498Szrj /* Append USE_LD to the default linker. */
794238fd1498Szrj #ifdef DEFAULT_LINKER
794338fd1498Szrj char *ld;
794438fd1498Szrj # ifdef HAVE_HOST_EXECUTABLE_SUFFIX
794538fd1498Szrj int len = (sizeof (DEFAULT_LINKER)
794638fd1498Szrj - sizeof (HOST_EXECUTABLE_SUFFIX));
794738fd1498Szrj ld = NULL;
794838fd1498Szrj if (len > 0)
794938fd1498Szrj {
795038fd1498Szrj char *default_linker = xstrdup (DEFAULT_LINKER);
795138fd1498Szrj /* Strip HOST_EXECUTABLE_SUFFIX if DEFAULT_LINKER contains
795238fd1498Szrj HOST_EXECUTABLE_SUFFIX. */
795338fd1498Szrj if (! strcmp (&default_linker[len], HOST_EXECUTABLE_SUFFIX))
795438fd1498Szrj {
795538fd1498Szrj default_linker[len] = '\0';
795638fd1498Szrj ld = concat (default_linker, use_ld,
795738fd1498Szrj HOST_EXECUTABLE_SUFFIX, NULL);
795838fd1498Szrj }
795938fd1498Szrj }
796038fd1498Szrj if (ld == NULL)
796138fd1498Szrj # endif
796238fd1498Szrj ld = concat (DEFAULT_LINKER, use_ld, NULL);
796338fd1498Szrj if (access (ld, X_OK) == 0)
796438fd1498Szrj {
796538fd1498Szrj printf ("%s\n", ld);
796638fd1498Szrj return (0);
796738fd1498Szrj }
796838fd1498Szrj #endif
796938fd1498Szrj print_prog_name = concat (print_prog_name, use_ld, NULL);
797038fd1498Szrj }
797138fd1498Szrj char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK, 0);
797238fd1498Szrj printf ("%s\n", (newname ? newname : print_prog_name));
797338fd1498Szrj return (0);
797438fd1498Szrj }
797538fd1498Szrj
797638fd1498Szrj if (print_multi_lib)
797738fd1498Szrj {
797838fd1498Szrj print_multilib_info ();
797938fd1498Szrj return (0);
798038fd1498Szrj }
798138fd1498Szrj
798238fd1498Szrj if (print_multi_directory)
798338fd1498Szrj {
798438fd1498Szrj if (multilib_dir == NULL)
798538fd1498Szrj printf (".\n");
798638fd1498Szrj else
798738fd1498Szrj printf ("%s\n", multilib_dir);
798838fd1498Szrj return (0);
798938fd1498Szrj }
799038fd1498Szrj
799138fd1498Szrj if (print_multiarch)
799238fd1498Szrj {
799338fd1498Szrj if (multiarch_dir == NULL)
799438fd1498Szrj printf ("\n");
799538fd1498Szrj else
799638fd1498Szrj printf ("%s\n", multiarch_dir);
799738fd1498Szrj return (0);
799838fd1498Szrj }
799938fd1498Szrj
800038fd1498Szrj if (print_sysroot)
800138fd1498Szrj {
800238fd1498Szrj if (target_system_root)
800338fd1498Szrj {
800438fd1498Szrj if (target_sysroot_suffix)
800538fd1498Szrj printf ("%s%s\n", target_system_root, target_sysroot_suffix);
800638fd1498Szrj else
800738fd1498Szrj printf ("%s\n", target_system_root);
800838fd1498Szrj }
800938fd1498Szrj return (0);
801038fd1498Szrj }
801138fd1498Szrj
801238fd1498Szrj if (print_multi_os_directory)
801338fd1498Szrj {
801438fd1498Szrj if (multilib_os_dir == NULL)
801538fd1498Szrj printf (".\n");
801638fd1498Szrj else
801738fd1498Szrj printf ("%s\n", multilib_os_dir);
801838fd1498Szrj return (0);
801938fd1498Szrj }
802038fd1498Szrj
802138fd1498Szrj if (print_sysroot_headers_suffix)
802238fd1498Szrj {
802338fd1498Szrj if (*sysroot_hdrs_suffix_spec)
802438fd1498Szrj {
802538fd1498Szrj printf("%s\n", (target_sysroot_hdrs_suffix
802638fd1498Szrj ? target_sysroot_hdrs_suffix
802738fd1498Szrj : ""));
802838fd1498Szrj return (0);
802938fd1498Szrj }
803038fd1498Szrj else
803138fd1498Szrj /* The error status indicates that only one set of fixed
803238fd1498Szrj headers should be built. */
803338fd1498Szrj fatal_error (input_location,
803438fd1498Szrj "not configured with sysroot headers suffix");
803538fd1498Szrj }
803638fd1498Szrj
803738fd1498Szrj if (print_help_list)
803838fd1498Szrj {
803938fd1498Szrj display_help ();
804038fd1498Szrj
804138fd1498Szrj if (! verbose_flag)
804238fd1498Szrj {
804338fd1498Szrj printf (_("\nFor bug reporting instructions, please see:\n"));
804438fd1498Szrj printf ("%s.\n", bug_report_url);
804538fd1498Szrj
804638fd1498Szrj return (0);
804738fd1498Szrj }
804838fd1498Szrj
804938fd1498Szrj /* We do not exit here. Instead we have created a fake input file
805038fd1498Szrj called 'help-dummy' which needs to be compiled, and we pass this
805138fd1498Szrj on the various sub-processes, along with the --help switch.
805238fd1498Szrj Ensure their output appears after ours. */
805338fd1498Szrj fputc ('\n', stdout);
805438fd1498Szrj fflush (stdout);
805538fd1498Szrj }
805638fd1498Szrj
805738fd1498Szrj if (print_version)
805838fd1498Szrj {
805938fd1498Szrj printf (_("%s %s%s\n"), progname, pkgversion_string,
806038fd1498Szrj version_string);
806138fd1498Szrj printf ("Copyright %s 2018 Free Software Foundation, Inc.\n",
806238fd1498Szrj _("(C)"));
806338fd1498Szrj fputs (_("This is free software; see the source for copying conditions. There is NO\n\
806438fd1498Szrj warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
806538fd1498Szrj stdout);
806638fd1498Szrj if (! verbose_flag)
806738fd1498Szrj return 0;
806838fd1498Szrj
806938fd1498Szrj /* We do not exit here. We use the same mechanism of --help to print
807038fd1498Szrj the version of the sub-processes. */
807138fd1498Szrj fputc ('\n', stdout);
807238fd1498Szrj fflush (stdout);
807338fd1498Szrj }
807438fd1498Szrj
807538fd1498Szrj if (verbose_flag)
807638fd1498Szrj {
807738fd1498Szrj print_configuration (stderr);
807838fd1498Szrj if (n_infiles == 0)
807938fd1498Szrj return (0);
808038fd1498Szrj }
808138fd1498Szrj
808238fd1498Szrj return 1;
808338fd1498Szrj }
808438fd1498Szrj
808538fd1498Szrj /* Figure out what to do with each input file.
808638fd1498Szrj Return true if we need to exit early from "main", false otherwise. */
808738fd1498Szrj
808838fd1498Szrj bool
prepare_infiles()808938fd1498Szrj driver::prepare_infiles ()
809038fd1498Szrj {
809138fd1498Szrj size_t i;
809238fd1498Szrj int lang_n_infiles = 0;
809338fd1498Szrj
809438fd1498Szrj if (n_infiles == added_libraries)
809538fd1498Szrj fatal_error (input_location, "no input files");
809638fd1498Szrj
809738fd1498Szrj if (seen_error ())
809838fd1498Szrj /* Early exit needed from main. */
809938fd1498Szrj return true;
810038fd1498Szrj
810138fd1498Szrj /* Make a place to record the compiler output file names
810238fd1498Szrj that correspond to the input files. */
810338fd1498Szrj
810438fd1498Szrj i = n_infiles;
810538fd1498Szrj i += lang_specific_extra_outfiles;
810638fd1498Szrj outfiles = XCNEWVEC (const char *, i);
810738fd1498Szrj
810838fd1498Szrj /* Record which files were specified explicitly as link input. */
810938fd1498Szrj
811038fd1498Szrj explicit_link_files = XCNEWVEC (char, n_infiles);
811138fd1498Szrj
811238fd1498Szrj combine_inputs = have_o || flag_wpa;
811338fd1498Szrj
811438fd1498Szrj for (i = 0; (int) i < n_infiles; i++)
811538fd1498Szrj {
811638fd1498Szrj const char *name = infiles[i].name;
811738fd1498Szrj struct compiler *compiler = lookup_compiler (name,
811838fd1498Szrj strlen (name),
811938fd1498Szrj infiles[i].language);
812038fd1498Szrj
812138fd1498Szrj if (compiler && !(compiler->combinable))
812238fd1498Szrj combine_inputs = false;
812338fd1498Szrj
812438fd1498Szrj if (lang_n_infiles > 0 && compiler != input_file_compiler
812538fd1498Szrj && infiles[i].language && infiles[i].language[0] != '*')
812638fd1498Szrj infiles[i].incompiler = compiler;
812738fd1498Szrj else if (compiler)
812838fd1498Szrj {
812938fd1498Szrj lang_n_infiles++;
813038fd1498Szrj input_file_compiler = compiler;
813138fd1498Szrj infiles[i].incompiler = compiler;
813238fd1498Szrj }
813338fd1498Szrj else
813438fd1498Szrj {
813538fd1498Szrj /* Since there is no compiler for this input file, assume it is a
813638fd1498Szrj linker file. */
813738fd1498Szrj explicit_link_files[i] = 1;
813838fd1498Szrj infiles[i].incompiler = NULL;
813938fd1498Szrj }
814038fd1498Szrj infiles[i].compiled = false;
814138fd1498Szrj infiles[i].preprocessed = false;
814238fd1498Szrj }
814338fd1498Szrj
814438fd1498Szrj if (!combine_inputs && have_c && have_o && lang_n_infiles > 1)
814538fd1498Szrj fatal_error (input_location,
814638fd1498Szrj "cannot specify -o with -c, -S or -E with multiple files");
814738fd1498Szrj
814838fd1498Szrj /* No early exit needed from main; we can continue. */
814938fd1498Szrj return false;
815038fd1498Szrj }
815138fd1498Szrj
815238fd1498Szrj /* Run the spec machinery on each input file. */
815338fd1498Szrj
815438fd1498Szrj void
do_spec_on_infiles()815538fd1498Szrj driver::do_spec_on_infiles () const
815638fd1498Szrj {
815738fd1498Szrj size_t i;
815838fd1498Szrj
815938fd1498Szrj for (i = 0; (int) i < n_infiles; i++)
816038fd1498Szrj {
816138fd1498Szrj int this_file_error = 0;
816238fd1498Szrj
816338fd1498Szrj /* Tell do_spec what to substitute for %i. */
816438fd1498Szrj
816538fd1498Szrj input_file_number = i;
816638fd1498Szrj set_input (infiles[i].name);
816738fd1498Szrj
816838fd1498Szrj if (infiles[i].compiled)
816938fd1498Szrj continue;
817038fd1498Szrj
817138fd1498Szrj /* Use the same thing in %o, unless cp->spec says otherwise. */
817238fd1498Szrj
817338fd1498Szrj outfiles[i] = gcc_input_filename;
817438fd1498Szrj
817538fd1498Szrj /* Figure out which compiler from the file's suffix. */
817638fd1498Szrj
817738fd1498Szrj input_file_compiler
817838fd1498Szrj = lookup_compiler (infiles[i].name, input_filename_length,
817938fd1498Szrj infiles[i].language);
818038fd1498Szrj
818138fd1498Szrj if (input_file_compiler)
818238fd1498Szrj {
818338fd1498Szrj /* Ok, we found an applicable compiler. Run its spec. */
818438fd1498Szrj
818538fd1498Szrj if (input_file_compiler->spec[0] == '#')
818638fd1498Szrj {
818738fd1498Szrj error ("%s: %s compiler not installed on this system",
818838fd1498Szrj gcc_input_filename, &input_file_compiler->spec[1]);
818938fd1498Szrj this_file_error = 1;
819038fd1498Szrj }
819138fd1498Szrj else
819238fd1498Szrj {
819338fd1498Szrj int value;
819438fd1498Szrj
819538fd1498Szrj if (compare_debug)
819638fd1498Szrj {
819738fd1498Szrj free (debug_check_temp_file[0]);
819838fd1498Szrj debug_check_temp_file[0] = NULL;
819938fd1498Szrj
820038fd1498Szrj free (debug_check_temp_file[1]);
820138fd1498Szrj debug_check_temp_file[1] = NULL;
820238fd1498Szrj }
820338fd1498Szrj
820438fd1498Szrj value = do_spec (input_file_compiler->spec);
820538fd1498Szrj infiles[i].compiled = true;
820638fd1498Szrj if (value < 0)
820738fd1498Szrj this_file_error = 1;
820838fd1498Szrj else if (compare_debug && debug_check_temp_file[0])
820938fd1498Szrj {
821038fd1498Szrj if (verbose_flag)
821138fd1498Szrj inform (UNKNOWN_LOCATION,
821238fd1498Szrj "recompiling with -fcompare-debug");
821338fd1498Szrj
821438fd1498Szrj compare_debug = -compare_debug;
821538fd1498Szrj n_switches = n_switches_debug_check[1];
821638fd1498Szrj n_switches_alloc = n_switches_alloc_debug_check[1];
821738fd1498Szrj switches = switches_debug_check[1];
821838fd1498Szrj
821938fd1498Szrj value = do_spec (input_file_compiler->spec);
822038fd1498Szrj
822138fd1498Szrj compare_debug = -compare_debug;
822238fd1498Szrj n_switches = n_switches_debug_check[0];
822338fd1498Szrj n_switches_alloc = n_switches_alloc_debug_check[0];
822438fd1498Szrj switches = switches_debug_check[0];
822538fd1498Szrj
822638fd1498Szrj if (value < 0)
822738fd1498Szrj {
822838fd1498Szrj error ("during -fcompare-debug recompilation");
822938fd1498Szrj this_file_error = 1;
823038fd1498Szrj }
823138fd1498Szrj
823238fd1498Szrj gcc_assert (debug_check_temp_file[1]
823338fd1498Szrj && filename_cmp (debug_check_temp_file[0],
823438fd1498Szrj debug_check_temp_file[1]));
823538fd1498Szrj
823638fd1498Szrj if (verbose_flag)
823738fd1498Szrj inform (UNKNOWN_LOCATION, "comparing final insns dumps");
823838fd1498Szrj
823938fd1498Szrj if (compare_files (debug_check_temp_file))
824038fd1498Szrj this_file_error = 1;
824138fd1498Szrj }
824238fd1498Szrj
824338fd1498Szrj if (compare_debug)
824438fd1498Szrj {
824538fd1498Szrj free (debug_check_temp_file[0]);
824638fd1498Szrj debug_check_temp_file[0] = NULL;
824738fd1498Szrj
824838fd1498Szrj free (debug_check_temp_file[1]);
824938fd1498Szrj debug_check_temp_file[1] = NULL;
825038fd1498Szrj }
825138fd1498Szrj }
825238fd1498Szrj }
825338fd1498Szrj
825438fd1498Szrj /* If this file's name does not contain a recognized suffix,
825538fd1498Szrj record it as explicit linker input. */
825638fd1498Szrj
825738fd1498Szrj else
825838fd1498Szrj explicit_link_files[i] = 1;
825938fd1498Szrj
826038fd1498Szrj /* Clear the delete-on-failure queue, deleting the files in it
826138fd1498Szrj if this compilation failed. */
826238fd1498Szrj
826338fd1498Szrj if (this_file_error)
826438fd1498Szrj {
826538fd1498Szrj delete_failure_queue ();
826638fd1498Szrj errorcount++;
826738fd1498Szrj }
826838fd1498Szrj /* If this compilation succeeded, don't delete those files later. */
826938fd1498Szrj clear_failure_queue ();
827038fd1498Szrj }
827138fd1498Szrj
827238fd1498Szrj /* Reset the input file name to the first compile/object file name, for use
827338fd1498Szrj with %b in LINK_SPEC. We use the first input file that we can find
827438fd1498Szrj a compiler to compile it instead of using infiles.language since for
827538fd1498Szrj languages other than C we use aliases that we then lookup later. */
827638fd1498Szrj if (n_infiles > 0)
827738fd1498Szrj {
827838fd1498Szrj int i;
827938fd1498Szrj
828038fd1498Szrj for (i = 0; i < n_infiles ; i++)
828138fd1498Szrj if (infiles[i].incompiler
828238fd1498Szrj || (infiles[i].language && infiles[i].language[0] != '*'))
828338fd1498Szrj {
828438fd1498Szrj set_input (infiles[i].name);
828538fd1498Szrj break;
828638fd1498Szrj }
828738fd1498Szrj }
828838fd1498Szrj
828938fd1498Szrj if (!seen_error ())
829038fd1498Szrj {
829138fd1498Szrj /* Make sure INPUT_FILE_NUMBER points to first available open
829238fd1498Szrj slot. */
829338fd1498Szrj input_file_number = n_infiles;
829438fd1498Szrj if (lang_specific_pre_link ())
829538fd1498Szrj errorcount++;
829638fd1498Szrj }
829738fd1498Szrj }
829838fd1498Szrj
829938fd1498Szrj /* If we have to run the linker, do it now. */
830038fd1498Szrj
830138fd1498Szrj void
maybe_run_linker(const char * argv0)830238fd1498Szrj driver::maybe_run_linker (const char *argv0) const
830338fd1498Szrj {
830438fd1498Szrj size_t i;
830538fd1498Szrj int linker_was_run = 0;
830638fd1498Szrj int num_linker_inputs;
830738fd1498Szrj
830838fd1498Szrj /* Determine if there are any linker input files. */
830938fd1498Szrj num_linker_inputs = 0;
831038fd1498Szrj for (i = 0; (int) i < n_infiles; i++)
831138fd1498Szrj if (explicit_link_files[i] || outfiles[i] != NULL)
831238fd1498Szrj num_linker_inputs++;
831338fd1498Szrj
831438fd1498Szrj /* Run ld to link all the compiler output files. */
831538fd1498Szrj
831638fd1498Szrj if (num_linker_inputs > 0 && !seen_error () && print_subprocess_help < 2)
831738fd1498Szrj {
831838fd1498Szrj int tmp = execution_count;
831938fd1498Szrj
832038fd1498Szrj if (! have_c)
832138fd1498Szrj {
832238fd1498Szrj #if HAVE_LTO_PLUGIN > 0
832338fd1498Szrj #if HAVE_LTO_PLUGIN == 2
832438fd1498Szrj const char *fno_use_linker_plugin = "fno-use-linker-plugin";
832538fd1498Szrj #else
832638fd1498Szrj const char *fuse_linker_plugin = "fuse-linker-plugin";
832738fd1498Szrj #endif
832838fd1498Szrj #endif
832938fd1498Szrj
833038fd1498Szrj /* We'll use ld if we can't find collect2. */
833138fd1498Szrj if (! strcmp (linker_name_spec, "collect2"))
833238fd1498Szrj {
833338fd1498Szrj char *s = find_a_file (&exec_prefixes, "collect2", X_OK, false);
833438fd1498Szrj if (s == NULL)
833538fd1498Szrj linker_name_spec = "ld";
833638fd1498Szrj }
833738fd1498Szrj
833838fd1498Szrj #if HAVE_LTO_PLUGIN > 0
833938fd1498Szrj #if HAVE_LTO_PLUGIN == 2
834038fd1498Szrj if (!switch_matches (fno_use_linker_plugin,
834138fd1498Szrj fno_use_linker_plugin
834238fd1498Szrj + strlen (fno_use_linker_plugin), 0))
834338fd1498Szrj #else
834438fd1498Szrj if (switch_matches (fuse_linker_plugin,
834538fd1498Szrj fuse_linker_plugin
834638fd1498Szrj + strlen (fuse_linker_plugin), 0))
834738fd1498Szrj #endif
834838fd1498Szrj {
834938fd1498Szrj char *temp_spec = find_a_file (&exec_prefixes,
835038fd1498Szrj LTOPLUGINSONAME, R_OK,
835138fd1498Szrj false);
835238fd1498Szrj if (!temp_spec)
835338fd1498Szrj fatal_error (input_location,
835438fd1498Szrj "-fuse-linker-plugin, but %s not found",
835538fd1498Szrj LTOPLUGINSONAME);
835638fd1498Szrj linker_plugin_file_spec = convert_white_space (temp_spec);
835738fd1498Szrj }
835838fd1498Szrj #endif
835938fd1498Szrj lto_gcc_spec = argv0;
836038fd1498Szrj }
836138fd1498Szrj
836238fd1498Szrj /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
836338fd1498Szrj for collect. */
836438fd1498Szrj putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH", false);
836538fd1498Szrj putenv_from_prefixes (&startfile_prefixes, LIBRARY_PATH_ENV, true);
836638fd1498Szrj
836738fd1498Szrj if (print_subprocess_help == 1)
836838fd1498Szrj {
836938fd1498Szrj printf (_("\nLinker options\n==============\n\n"));
837038fd1498Szrj printf (_("Use \"-Wl,OPTION\" to pass \"OPTION\""
837138fd1498Szrj " to the linker.\n\n"));
837238fd1498Szrj fflush (stdout);
837338fd1498Szrj }
837438fd1498Szrj int value = do_spec (link_command_spec);
837538fd1498Szrj if (value < 0)
837638fd1498Szrj errorcount = 1;
837738fd1498Szrj linker_was_run = (tmp != execution_count);
837838fd1498Szrj }
837938fd1498Szrj
838038fd1498Szrj /* If options said don't run linker,
838138fd1498Szrj complain about input files to be given to the linker. */
838238fd1498Szrj
838338fd1498Szrj if (! linker_was_run && !seen_error ())
838438fd1498Szrj for (i = 0; (int) i < n_infiles; i++)
838538fd1498Szrj if (explicit_link_files[i]
838638fd1498Szrj && !(infiles[i].language && infiles[i].language[0] == '*'))
838738fd1498Szrj warning (0, "%s: linker input file unused because linking not done",
838838fd1498Szrj outfiles[i]);
838938fd1498Szrj }
839038fd1498Szrj
839138fd1498Szrj /* The end of "main". */
839238fd1498Szrj
839338fd1498Szrj void
final_actions()839438fd1498Szrj driver::final_actions () const
839538fd1498Szrj {
839638fd1498Szrj /* Delete some or all of the temporary files we made. */
839738fd1498Szrj
839838fd1498Szrj if (seen_error ())
839938fd1498Szrj delete_failure_queue ();
840038fd1498Szrj delete_temp_files ();
840138fd1498Szrj
840238fd1498Szrj if (print_help_list)
840338fd1498Szrj {
840438fd1498Szrj printf (("\nFor bug reporting instructions, please see:\n"));
840538fd1498Szrj printf ("%s\n", bug_report_url);
840638fd1498Szrj }
840738fd1498Szrj }
840838fd1498Szrj
840938fd1498Szrj /* Determine what the exit code of the driver should be. */
841038fd1498Szrj
841138fd1498Szrj int
get_exit_code()841238fd1498Szrj driver::get_exit_code () const
841338fd1498Szrj {
841438fd1498Szrj return (signal_count != 0 ? 2
841538fd1498Szrj : seen_error () ? (pass_exit_codes ? greatest_status : 1)
841638fd1498Szrj : 0);
841738fd1498Szrj }
841838fd1498Szrj
841938fd1498Szrj /* Find the proper compilation spec for the file name NAME,
842038fd1498Szrj whose length is LENGTH. LANGUAGE is the specified language,
842138fd1498Szrj or 0 if this file is to be passed to the linker. */
842238fd1498Szrj
842338fd1498Szrj static struct compiler *
lookup_compiler(const char * name,size_t length,const char * language)842438fd1498Szrj lookup_compiler (const char *name, size_t length, const char *language)
842538fd1498Szrj {
842638fd1498Szrj struct compiler *cp;
842738fd1498Szrj
842838fd1498Szrj /* If this was specified by the user to be a linker input, indicate that. */
842938fd1498Szrj if (language != 0 && language[0] == '*')
843038fd1498Szrj return 0;
843138fd1498Szrj
843238fd1498Szrj /* Otherwise, look for the language, if one is spec'd. */
843338fd1498Szrj if (language != 0)
843438fd1498Szrj {
843538fd1498Szrj for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
843638fd1498Szrj if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language))
843738fd1498Szrj {
843838fd1498Szrj if (name != NULL && strcmp (name, "-") == 0
843938fd1498Szrj && (strcmp (cp->suffix, "@c-header") == 0
844038fd1498Szrj || strcmp (cp->suffix, "@c++-header") == 0)
844138fd1498Szrj && !have_E)
844238fd1498Szrj fatal_error (input_location,
844338fd1498Szrj "cannot use %<-%> as input filename for a "
844438fd1498Szrj "precompiled header");
844538fd1498Szrj
844638fd1498Szrj return cp;
844738fd1498Szrj }
844838fd1498Szrj
844938fd1498Szrj error ("language %s not recognized", language);
845038fd1498Szrj return 0;
845138fd1498Szrj }
845238fd1498Szrj
845338fd1498Szrj /* Look for a suffix. */
845438fd1498Szrj for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
845538fd1498Szrj {
845638fd1498Szrj if (/* The suffix `-' matches only the file name `-'. */
845738fd1498Szrj (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
845838fd1498Szrj || (strlen (cp->suffix) < length
845938fd1498Szrj /* See if the suffix matches the end of NAME. */
846038fd1498Szrj && !strcmp (cp->suffix,
846138fd1498Szrj name + length - strlen (cp->suffix))
846238fd1498Szrj ))
846338fd1498Szrj break;
846438fd1498Szrj }
846538fd1498Szrj
846638fd1498Szrj #if defined (OS2) ||defined (HAVE_DOS_BASED_FILE_SYSTEM)
846738fd1498Szrj /* Look again, but case-insensitively this time. */
846838fd1498Szrj if (cp < compilers)
846938fd1498Szrj for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
847038fd1498Szrj {
847138fd1498Szrj if (/* The suffix `-' matches only the file name `-'. */
847238fd1498Szrj (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
847338fd1498Szrj || (strlen (cp->suffix) < length
847438fd1498Szrj /* See if the suffix matches the end of NAME. */
847538fd1498Szrj && ((!strcmp (cp->suffix,
847638fd1498Szrj name + length - strlen (cp->suffix))
847738fd1498Szrj || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
847838fd1498Szrj && !strcasecmp (cp->suffix,
847938fd1498Szrj name + length - strlen (cp->suffix)))
848038fd1498Szrj ))
848138fd1498Szrj break;
848238fd1498Szrj }
848338fd1498Szrj #endif
848438fd1498Szrj
848538fd1498Szrj if (cp >= compilers)
848638fd1498Szrj {
848738fd1498Szrj if (cp->spec[0] != '@')
848838fd1498Szrj /* A non-alias entry: return it. */
848938fd1498Szrj return cp;
849038fd1498Szrj
849138fd1498Szrj /* An alias entry maps a suffix to a language.
849238fd1498Szrj Search for the language; pass 0 for NAME and LENGTH
849338fd1498Szrj to avoid infinite recursion if language not found. */
849438fd1498Szrj return lookup_compiler (NULL, 0, cp->spec + 1);
849538fd1498Szrj }
849638fd1498Szrj return 0;
849738fd1498Szrj }
849838fd1498Szrj
849938fd1498Szrj static char *
save_string(const char * s,int len)850038fd1498Szrj save_string (const char *s, int len)
850138fd1498Szrj {
850238fd1498Szrj char *result = XNEWVEC (char, len + 1);
850338fd1498Szrj
850438fd1498Szrj gcc_checking_assert (strlen (s) >= (unsigned int) len);
850538fd1498Szrj memcpy (result, s, len);
850638fd1498Szrj result[len] = 0;
850738fd1498Szrj return result;
850838fd1498Szrj }
850938fd1498Szrj
851038fd1498Szrj void
pfatal_with_name(const char * name)851138fd1498Szrj pfatal_with_name (const char *name)
851238fd1498Szrj {
851338fd1498Szrj perror_with_name (name);
851438fd1498Szrj delete_temp_files ();
851538fd1498Szrj exit (1);
851638fd1498Szrj }
851738fd1498Szrj
851838fd1498Szrj static void
perror_with_name(const char * name)851938fd1498Szrj perror_with_name (const char *name)
852038fd1498Szrj {
852138fd1498Szrj error ("%s: %m", name);
852238fd1498Szrj }
852338fd1498Szrj
852438fd1498Szrj static inline void
validate_switches_from_spec(const char * spec,bool user)852538fd1498Szrj validate_switches_from_spec (const char *spec, bool user)
852638fd1498Szrj {
852738fd1498Szrj const char *p = spec;
852838fd1498Szrj char c;
852938fd1498Szrj while ((c = *p++))
853038fd1498Szrj if (c == '%' && (*p == '{' || *p == '<' || (*p == 'W' && *++p == '{')))
853138fd1498Szrj /* We have a switch spec. */
853238fd1498Szrj p = validate_switches (p + 1, user);
853338fd1498Szrj }
853438fd1498Szrj
853538fd1498Szrj static void
validate_all_switches(void)853638fd1498Szrj validate_all_switches (void)
853738fd1498Szrj {
853838fd1498Szrj struct compiler *comp;
853938fd1498Szrj struct spec_list *spec;
854038fd1498Szrj
854138fd1498Szrj for (comp = compilers; comp->spec; comp++)
854238fd1498Szrj validate_switches_from_spec (comp->spec, false);
854338fd1498Szrj
854438fd1498Szrj /* Look through the linked list of specs read from the specs file. */
854538fd1498Szrj for (spec = specs; spec; spec = spec->next)
854638fd1498Szrj validate_switches_from_spec (*spec->ptr_spec, spec->user_p);
854738fd1498Szrj
854838fd1498Szrj validate_switches_from_spec (link_command_spec, false);
854938fd1498Szrj }
855038fd1498Szrj
855138fd1498Szrj /* Look at the switch-name that comes after START
855238fd1498Szrj and mark as valid all supplied switches that match it. */
855338fd1498Szrj
855438fd1498Szrj static const char *
validate_switches(const char * start,bool user_spec)855538fd1498Szrj validate_switches (const char *start, bool user_spec)
855638fd1498Szrj {
855738fd1498Szrj const char *p = start;
855838fd1498Szrj const char *atom;
855938fd1498Szrj size_t len;
856038fd1498Szrj int i;
856138fd1498Szrj bool suffix = false;
856238fd1498Szrj bool starred = false;
856338fd1498Szrj
856438fd1498Szrj #define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0)
856538fd1498Szrj
856638fd1498Szrj next_member:
856738fd1498Szrj SKIP_WHITE ();
856838fd1498Szrj
856938fd1498Szrj if (*p == '!')
857038fd1498Szrj p++;
857138fd1498Szrj
857238fd1498Szrj SKIP_WHITE ();
857338fd1498Szrj if (*p == '.' || *p == ',')
857438fd1498Szrj suffix = true, p++;
857538fd1498Szrj
857638fd1498Szrj atom = p;
857738fd1498Szrj while (ISIDNUM (*p) || *p == '-' || *p == '+' || *p == '='
857838fd1498Szrj || *p == ',' || *p == '.' || *p == '@')
857938fd1498Szrj p++;
858038fd1498Szrj len = p - atom;
858138fd1498Szrj
858238fd1498Szrj if (*p == '*')
858338fd1498Szrj starred = true, p++;
858438fd1498Szrj
858538fd1498Szrj SKIP_WHITE ();
858638fd1498Szrj
858738fd1498Szrj if (!suffix)
858838fd1498Szrj {
858938fd1498Szrj /* Mark all matching switches as valid. */
859038fd1498Szrj for (i = 0; i < n_switches; i++)
859138fd1498Szrj if (!strncmp (switches[i].part1, atom, len)
859238fd1498Szrj && (starred || switches[i].part1[len] == '\0')
859338fd1498Szrj && (switches[i].known || user_spec))
859438fd1498Szrj switches[i].validated = true;
859538fd1498Szrj }
859638fd1498Szrj
859738fd1498Szrj if (*p) p++;
859838fd1498Szrj if (*p && (p[-1] == '|' || p[-1] == '&'))
859938fd1498Szrj goto next_member;
860038fd1498Szrj
860138fd1498Szrj if (*p && p[-1] == ':')
860238fd1498Szrj {
860338fd1498Szrj while (*p && *p != ';' && *p != '}')
860438fd1498Szrj {
860538fd1498Szrj if (*p == '%')
860638fd1498Szrj {
860738fd1498Szrj p++;
860838fd1498Szrj if (*p == '{' || *p == '<')
860938fd1498Szrj p = validate_switches (p+1, user_spec);
861038fd1498Szrj else if (p[0] == 'W' && p[1] == '{')
861138fd1498Szrj p = validate_switches (p+2, user_spec);
861238fd1498Szrj }
861338fd1498Szrj else
861438fd1498Szrj p++;
861538fd1498Szrj }
861638fd1498Szrj
861738fd1498Szrj if (*p) p++;
861838fd1498Szrj if (*p && p[-1] == ';')
861938fd1498Szrj goto next_member;
862038fd1498Szrj }
862138fd1498Szrj
862238fd1498Szrj return p;
862338fd1498Szrj #undef SKIP_WHITE
862438fd1498Szrj }
862538fd1498Szrj
862638fd1498Szrj struct mdswitchstr
862738fd1498Szrj {
862838fd1498Szrj const char *str;
862938fd1498Szrj int len;
863038fd1498Szrj };
863138fd1498Szrj
863238fd1498Szrj static struct mdswitchstr *mdswitches;
863338fd1498Szrj static int n_mdswitches;
863438fd1498Szrj
863538fd1498Szrj /* Check whether a particular argument was used. The first time we
863638fd1498Szrj canonicalize the switches to keep only the ones we care about. */
863738fd1498Szrj
863838fd1498Szrj class used_arg_t
863938fd1498Szrj {
864038fd1498Szrj public:
864138fd1498Szrj int operator () (const char *p, int len);
864238fd1498Szrj void finalize ();
864338fd1498Szrj
864438fd1498Szrj private:
864538fd1498Szrj struct mswitchstr
864638fd1498Szrj {
864738fd1498Szrj const char *str;
864838fd1498Szrj const char *replace;
864938fd1498Szrj int len;
865038fd1498Szrj int rep_len;
865138fd1498Szrj };
865238fd1498Szrj
865338fd1498Szrj mswitchstr *mswitches;
865438fd1498Szrj int n_mswitches;
865538fd1498Szrj
865638fd1498Szrj };
865738fd1498Szrj
865838fd1498Szrj used_arg_t used_arg;
865938fd1498Szrj
866038fd1498Szrj int
operator()866138fd1498Szrj used_arg_t::operator () (const char *p, int len)
866238fd1498Szrj {
866338fd1498Szrj int i, j;
866438fd1498Szrj
866538fd1498Szrj if (!mswitches)
866638fd1498Szrj {
866738fd1498Szrj struct mswitchstr *matches;
866838fd1498Szrj const char *q;
866938fd1498Szrj int cnt = 0;
867038fd1498Szrj
867138fd1498Szrj /* Break multilib_matches into the component strings of string
867238fd1498Szrj and replacement string. */
867338fd1498Szrj for (q = multilib_matches; *q != '\0'; q++)
867438fd1498Szrj if (*q == ';')
867538fd1498Szrj cnt++;
867638fd1498Szrj
867738fd1498Szrj matches
867838fd1498Szrj = (struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt);
867938fd1498Szrj i = 0;
868038fd1498Szrj q = multilib_matches;
868138fd1498Szrj while (*q != '\0')
868238fd1498Szrj {
868338fd1498Szrj matches[i].str = q;
868438fd1498Szrj while (*q != ' ')
868538fd1498Szrj {
868638fd1498Szrj if (*q == '\0')
868738fd1498Szrj {
868838fd1498Szrj invalid_matches:
868938fd1498Szrj fatal_error (input_location, "multilib spec %qs is invalid",
869038fd1498Szrj multilib_matches);
869138fd1498Szrj }
869238fd1498Szrj q++;
869338fd1498Szrj }
869438fd1498Szrj matches[i].len = q - matches[i].str;
869538fd1498Szrj
869638fd1498Szrj matches[i].replace = ++q;
869738fd1498Szrj while (*q != ';' && *q != '\0')
869838fd1498Szrj {
869938fd1498Szrj if (*q == ' ')
870038fd1498Szrj goto invalid_matches;
870138fd1498Szrj q++;
870238fd1498Szrj }
870338fd1498Szrj matches[i].rep_len = q - matches[i].replace;
870438fd1498Szrj i++;
870538fd1498Szrj if (*q == ';')
870638fd1498Szrj q++;
870738fd1498Szrj }
870838fd1498Szrj
870938fd1498Szrj /* Now build a list of the replacement string for switches that we care
871038fd1498Szrj about. Make sure we allocate at least one entry. This prevents
871138fd1498Szrj xmalloc from calling fatal, and prevents us from re-executing this
871238fd1498Szrj block of code. */
871338fd1498Szrj mswitches
871438fd1498Szrj = XNEWVEC (struct mswitchstr, n_mdswitches + (n_switches ? n_switches : 1));
871538fd1498Szrj for (i = 0; i < n_switches; i++)
871638fd1498Szrj if ((switches[i].live_cond & SWITCH_IGNORE) == 0)
871738fd1498Szrj {
871838fd1498Szrj int xlen = strlen (switches[i].part1);
871938fd1498Szrj for (j = 0; j < cnt; j++)
872038fd1498Szrj if (xlen == matches[j].len
872138fd1498Szrj && ! strncmp (switches[i].part1, matches[j].str, xlen))
872238fd1498Szrj {
872338fd1498Szrj mswitches[n_mswitches].str = matches[j].replace;
872438fd1498Szrj mswitches[n_mswitches].len = matches[j].rep_len;
872538fd1498Szrj mswitches[n_mswitches].replace = (char *) 0;
872638fd1498Szrj mswitches[n_mswitches].rep_len = 0;
872738fd1498Szrj n_mswitches++;
872838fd1498Szrj break;
872938fd1498Szrj }
873038fd1498Szrj }
873138fd1498Szrj
873238fd1498Szrj /* Add MULTILIB_DEFAULTS switches too, as long as they were not present
873338fd1498Szrj on the command line nor any options mutually incompatible with
873438fd1498Szrj them. */
873538fd1498Szrj for (i = 0; i < n_mdswitches; i++)
873638fd1498Szrj {
873738fd1498Szrj const char *r;
873838fd1498Szrj
873938fd1498Szrj for (q = multilib_options; *q != '\0'; *q && q++)
874038fd1498Szrj {
874138fd1498Szrj while (*q == ' ')
874238fd1498Szrj q++;
874338fd1498Szrj
874438fd1498Szrj r = q;
874538fd1498Szrj while (strncmp (q, mdswitches[i].str, mdswitches[i].len) != 0
874638fd1498Szrj || strchr (" /", q[mdswitches[i].len]) == NULL)
874738fd1498Szrj {
874838fd1498Szrj while (*q != ' ' && *q != '/' && *q != '\0')
874938fd1498Szrj q++;
875038fd1498Szrj if (*q != '/')
875138fd1498Szrj break;
875238fd1498Szrj q++;
875338fd1498Szrj }
875438fd1498Szrj
875538fd1498Szrj if (*q != ' ' && *q != '\0')
875638fd1498Szrj {
875738fd1498Szrj while (*r != ' ' && *r != '\0')
875838fd1498Szrj {
875938fd1498Szrj q = r;
876038fd1498Szrj while (*q != ' ' && *q != '/' && *q != '\0')
876138fd1498Szrj q++;
876238fd1498Szrj
876338fd1498Szrj if (used_arg (r, q - r))
876438fd1498Szrj break;
876538fd1498Szrj
876638fd1498Szrj if (*q != '/')
876738fd1498Szrj {
876838fd1498Szrj mswitches[n_mswitches].str = mdswitches[i].str;
876938fd1498Szrj mswitches[n_mswitches].len = mdswitches[i].len;
877038fd1498Szrj mswitches[n_mswitches].replace = (char *) 0;
877138fd1498Szrj mswitches[n_mswitches].rep_len = 0;
877238fd1498Szrj n_mswitches++;
877338fd1498Szrj break;
877438fd1498Szrj }
877538fd1498Szrj
877638fd1498Szrj r = q + 1;
877738fd1498Szrj }
877838fd1498Szrj break;
877938fd1498Szrj }
878038fd1498Szrj }
878138fd1498Szrj }
878238fd1498Szrj }
878338fd1498Szrj
878438fd1498Szrj for (i = 0; i < n_mswitches; i++)
878538fd1498Szrj if (len == mswitches[i].len && ! strncmp (p, mswitches[i].str, len))
878638fd1498Szrj return 1;
878738fd1498Szrj
878838fd1498Szrj return 0;
878938fd1498Szrj }
879038fd1498Szrj
finalize()879138fd1498Szrj void used_arg_t::finalize ()
879238fd1498Szrj {
879338fd1498Szrj XDELETEVEC (mswitches);
879438fd1498Szrj mswitches = NULL;
879538fd1498Szrj n_mswitches = 0;
879638fd1498Szrj }
879738fd1498Szrj
879838fd1498Szrj
879938fd1498Szrj static int
default_arg(const char * p,int len)880038fd1498Szrj default_arg (const char *p, int len)
880138fd1498Szrj {
880238fd1498Szrj int i;
880338fd1498Szrj
880438fd1498Szrj for (i = 0; i < n_mdswitches; i++)
880538fd1498Szrj if (len == mdswitches[i].len && ! strncmp (p, mdswitches[i].str, len))
880638fd1498Szrj return 1;
880738fd1498Szrj
880838fd1498Szrj return 0;
880938fd1498Szrj }
881038fd1498Szrj
881138fd1498Szrj /* Work out the subdirectory to use based on the options. The format of
881238fd1498Szrj multilib_select is a list of elements. Each element is a subdirectory
881338fd1498Szrj name followed by a list of options followed by a semicolon. The format
881438fd1498Szrj of multilib_exclusions is the same, but without the preceding
881538fd1498Szrj directory. First gcc will check the exclusions, if none of the options
881638fd1498Szrj beginning with an exclamation point are present, and all of the other
881738fd1498Szrj options are present, then we will ignore this completely. Passing
881838fd1498Szrj that, gcc will consider each multilib_select in turn using the same
881938fd1498Szrj rules for matching the options. If a match is found, that subdirectory
882038fd1498Szrj will be used.
882138fd1498Szrj A subdirectory name is optionally followed by a colon and the corresponding
882238fd1498Szrj multiarch name. */
882338fd1498Szrj
882438fd1498Szrj static void
set_multilib_dir(void)882538fd1498Szrj set_multilib_dir (void)
882638fd1498Szrj {
882738fd1498Szrj const char *p;
882838fd1498Szrj unsigned int this_path_len;
882938fd1498Szrj const char *this_path, *this_arg;
883038fd1498Szrj const char *start, *end;
883138fd1498Szrj int not_arg;
883238fd1498Szrj int ok, ndfltok, first;
883338fd1498Szrj
883438fd1498Szrj n_mdswitches = 0;
883538fd1498Szrj start = multilib_defaults;
883638fd1498Szrj while (*start == ' ' || *start == '\t')
883738fd1498Szrj start++;
883838fd1498Szrj while (*start != '\0')
883938fd1498Szrj {
884038fd1498Szrj n_mdswitches++;
884138fd1498Szrj while (*start != ' ' && *start != '\t' && *start != '\0')
884238fd1498Szrj start++;
884338fd1498Szrj while (*start == ' ' || *start == '\t')
884438fd1498Szrj start++;
884538fd1498Szrj }
884638fd1498Szrj
884738fd1498Szrj if (n_mdswitches)
884838fd1498Szrj {
884938fd1498Szrj int i = 0;
885038fd1498Szrj
885138fd1498Szrj mdswitches = XNEWVEC (struct mdswitchstr, n_mdswitches);
885238fd1498Szrj for (start = multilib_defaults; *start != '\0'; start = end + 1)
885338fd1498Szrj {
885438fd1498Szrj while (*start == ' ' || *start == '\t')
885538fd1498Szrj start++;
885638fd1498Szrj
885738fd1498Szrj if (*start == '\0')
885838fd1498Szrj break;
885938fd1498Szrj
886038fd1498Szrj for (end = start + 1;
886138fd1498Szrj *end != ' ' && *end != '\t' && *end != '\0'; end++)
886238fd1498Szrj ;
886338fd1498Szrj
886438fd1498Szrj obstack_grow (&multilib_obstack, start, end - start);
886538fd1498Szrj obstack_1grow (&multilib_obstack, 0);
886638fd1498Szrj mdswitches[i].str = XOBFINISH (&multilib_obstack, const char *);
886738fd1498Szrj mdswitches[i++].len = end - start;
886838fd1498Szrj
886938fd1498Szrj if (*end == '\0')
887038fd1498Szrj break;
887138fd1498Szrj }
887238fd1498Szrj }
887338fd1498Szrj
887438fd1498Szrj p = multilib_exclusions;
887538fd1498Szrj while (*p != '\0')
887638fd1498Szrj {
887738fd1498Szrj /* Ignore newlines. */
887838fd1498Szrj if (*p == '\n')
887938fd1498Szrj {
888038fd1498Szrj ++p;
888138fd1498Szrj continue;
888238fd1498Szrj }
888338fd1498Szrj
888438fd1498Szrj /* Check the arguments. */
888538fd1498Szrj ok = 1;
888638fd1498Szrj while (*p != ';')
888738fd1498Szrj {
888838fd1498Szrj if (*p == '\0')
888938fd1498Szrj {
889038fd1498Szrj invalid_exclusions:
889138fd1498Szrj fatal_error (input_location, "multilib exclusions %qs is invalid",
889238fd1498Szrj multilib_exclusions);
889338fd1498Szrj }
889438fd1498Szrj
889538fd1498Szrj if (! ok)
889638fd1498Szrj {
889738fd1498Szrj ++p;
889838fd1498Szrj continue;
889938fd1498Szrj }
890038fd1498Szrj
890138fd1498Szrj this_arg = p;
890238fd1498Szrj while (*p != ' ' && *p != ';')
890338fd1498Szrj {
890438fd1498Szrj if (*p == '\0')
890538fd1498Szrj goto invalid_exclusions;
890638fd1498Szrj ++p;
890738fd1498Szrj }
890838fd1498Szrj
890938fd1498Szrj if (*this_arg != '!')
891038fd1498Szrj not_arg = 0;
891138fd1498Szrj else
891238fd1498Szrj {
891338fd1498Szrj not_arg = 1;
891438fd1498Szrj ++this_arg;
891538fd1498Szrj }
891638fd1498Szrj
891738fd1498Szrj ok = used_arg (this_arg, p - this_arg);
891838fd1498Szrj if (not_arg)
891938fd1498Szrj ok = ! ok;
892038fd1498Szrj
892138fd1498Szrj if (*p == ' ')
892238fd1498Szrj ++p;
892338fd1498Szrj }
892438fd1498Szrj
892538fd1498Szrj if (ok)
892638fd1498Szrj return;
892738fd1498Szrj
892838fd1498Szrj ++p;
892938fd1498Szrj }
893038fd1498Szrj
893138fd1498Szrj first = 1;
893238fd1498Szrj p = multilib_select;
893338fd1498Szrj
893438fd1498Szrj /* Append multilib reuse rules if any. With those rules, we can reuse
893538fd1498Szrj one multilib for certain different options sets. */
893638fd1498Szrj if (strlen (multilib_reuse) > 0)
893738fd1498Szrj p = concat (p, multilib_reuse, NULL);
893838fd1498Szrj
893938fd1498Szrj while (*p != '\0')
894038fd1498Szrj {
894138fd1498Szrj /* Ignore newlines. */
894238fd1498Szrj if (*p == '\n')
894338fd1498Szrj {
894438fd1498Szrj ++p;
894538fd1498Szrj continue;
894638fd1498Szrj }
894738fd1498Szrj
894838fd1498Szrj /* Get the initial path. */
894938fd1498Szrj this_path = p;
895038fd1498Szrj while (*p != ' ')
895138fd1498Szrj {
895238fd1498Szrj if (*p == '\0')
895338fd1498Szrj {
895438fd1498Szrj invalid_select:
895538fd1498Szrj fatal_error (input_location, "multilib select %qs %qs is invalid",
895638fd1498Szrj multilib_select, multilib_reuse);
895738fd1498Szrj }
895838fd1498Szrj ++p;
895938fd1498Szrj }
896038fd1498Szrj this_path_len = p - this_path;
896138fd1498Szrj
896238fd1498Szrj /* Check the arguments. */
896338fd1498Szrj ok = 1;
896438fd1498Szrj ndfltok = 1;
896538fd1498Szrj ++p;
896638fd1498Szrj while (*p != ';')
896738fd1498Szrj {
896838fd1498Szrj if (*p == '\0')
896938fd1498Szrj goto invalid_select;
897038fd1498Szrj
897138fd1498Szrj if (! ok)
897238fd1498Szrj {
897338fd1498Szrj ++p;
897438fd1498Szrj continue;
897538fd1498Szrj }
897638fd1498Szrj
897738fd1498Szrj this_arg = p;
897838fd1498Szrj while (*p != ' ' && *p != ';')
897938fd1498Szrj {
898038fd1498Szrj if (*p == '\0')
898138fd1498Szrj goto invalid_select;
898238fd1498Szrj ++p;
898338fd1498Szrj }
898438fd1498Szrj
898538fd1498Szrj if (*this_arg != '!')
898638fd1498Szrj not_arg = 0;
898738fd1498Szrj else
898838fd1498Szrj {
898938fd1498Szrj not_arg = 1;
899038fd1498Szrj ++this_arg;
899138fd1498Szrj }
899238fd1498Szrj
899338fd1498Szrj /* If this is a default argument, we can just ignore it.
899438fd1498Szrj This is true even if this_arg begins with '!'. Beginning
899538fd1498Szrj with '!' does not mean that this argument is necessarily
899638fd1498Szrj inappropriate for this library: it merely means that
899738fd1498Szrj there is a more specific library which uses this
899838fd1498Szrj argument. If this argument is a default, we need not
899938fd1498Szrj consider that more specific library. */
900038fd1498Szrj ok = used_arg (this_arg, p - this_arg);
900138fd1498Szrj if (not_arg)
900238fd1498Szrj ok = ! ok;
900338fd1498Szrj
900438fd1498Szrj if (! ok)
900538fd1498Szrj ndfltok = 0;
900638fd1498Szrj
900738fd1498Szrj if (default_arg (this_arg, p - this_arg))
900838fd1498Szrj ok = 1;
900938fd1498Szrj
901038fd1498Szrj if (*p == ' ')
901138fd1498Szrj ++p;
901238fd1498Szrj }
901338fd1498Szrj
901438fd1498Szrj if (ok && first)
901538fd1498Szrj {
901638fd1498Szrj if (this_path_len != 1
901738fd1498Szrj || this_path[0] != '.')
901838fd1498Szrj {
901938fd1498Szrj char *new_multilib_dir = XNEWVEC (char, this_path_len + 1);
902038fd1498Szrj char *q;
902138fd1498Szrj
902238fd1498Szrj strncpy (new_multilib_dir, this_path, this_path_len);
902338fd1498Szrj new_multilib_dir[this_path_len] = '\0';
902438fd1498Szrj q = strchr (new_multilib_dir, ':');
902538fd1498Szrj if (q != NULL)
902638fd1498Szrj *q = '\0';
902738fd1498Szrj multilib_dir = new_multilib_dir;
902838fd1498Szrj }
902938fd1498Szrj first = 0;
903038fd1498Szrj }
903138fd1498Szrj
903238fd1498Szrj if (ndfltok)
903338fd1498Szrj {
903438fd1498Szrj const char *q = this_path, *end = this_path + this_path_len;
903538fd1498Szrj
903638fd1498Szrj while (q < end && *q != ':')
903738fd1498Szrj q++;
903838fd1498Szrj if (q < end)
903938fd1498Szrj {
904038fd1498Szrj const char *q2 = q + 1, *ml_end = end;
904138fd1498Szrj char *new_multilib_os_dir;
904238fd1498Szrj
904338fd1498Szrj while (q2 < end && *q2 != ':')
904438fd1498Szrj q2++;
904538fd1498Szrj if (*q2 == ':')
904638fd1498Szrj ml_end = q2;
904738fd1498Szrj if (ml_end - q == 1)
904838fd1498Szrj multilib_os_dir = xstrdup (".");
904938fd1498Szrj else
905038fd1498Szrj {
905138fd1498Szrj new_multilib_os_dir = XNEWVEC (char, ml_end - q);
905238fd1498Szrj memcpy (new_multilib_os_dir, q + 1, ml_end - q - 1);
905338fd1498Szrj new_multilib_os_dir[ml_end - q - 1] = '\0';
905438fd1498Szrj multilib_os_dir = new_multilib_os_dir;
905538fd1498Szrj }
905638fd1498Szrj
905738fd1498Szrj if (q2 < end && *q2 == ':')
905838fd1498Szrj {
905938fd1498Szrj char *new_multiarch_dir = XNEWVEC (char, end - q2);
906038fd1498Szrj memcpy (new_multiarch_dir, q2 + 1, end - q2 - 1);
906138fd1498Szrj new_multiarch_dir[end - q2 - 1] = '\0';
906238fd1498Szrj multiarch_dir = new_multiarch_dir;
906338fd1498Szrj }
906438fd1498Szrj break;
906538fd1498Szrj }
906638fd1498Szrj }
906738fd1498Szrj
906838fd1498Szrj ++p;
906938fd1498Szrj }
907038fd1498Szrj
907138fd1498Szrj if (multilib_dir == NULL && multilib_os_dir != NULL
907238fd1498Szrj && strcmp (multilib_os_dir, ".") == 0)
907338fd1498Szrj {
907438fd1498Szrj free (CONST_CAST (char *, multilib_os_dir));
907538fd1498Szrj multilib_os_dir = NULL;
907638fd1498Szrj }
907738fd1498Szrj else if (multilib_dir != NULL && multilib_os_dir == NULL)
907838fd1498Szrj multilib_os_dir = multilib_dir;
907938fd1498Szrj }
908038fd1498Szrj
908138fd1498Szrj /* Print out the multiple library subdirectory selection
908238fd1498Szrj information. This prints out a series of lines. Each line looks
908338fd1498Szrj like SUBDIRECTORY;@OPTION@OPTION, with as many options as is
908438fd1498Szrj required. Only the desired options are printed out, the negative
908538fd1498Szrj matches. The options are print without a leading dash. There are
908638fd1498Szrj no spaces to make it easy to use the information in the shell.
908738fd1498Szrj Each subdirectory is printed only once. This assumes the ordering
908838fd1498Szrj generated by the genmultilib script. Also, we leave out ones that match
908938fd1498Szrj the exclusions. */
909038fd1498Szrj
909138fd1498Szrj static void
print_multilib_info(void)909238fd1498Szrj print_multilib_info (void)
909338fd1498Szrj {
909438fd1498Szrj const char *p = multilib_select;
909538fd1498Szrj const char *last_path = 0, *this_path;
909638fd1498Szrj int skip;
909738fd1498Szrj unsigned int last_path_len = 0;
909838fd1498Szrj
909938fd1498Szrj while (*p != '\0')
910038fd1498Szrj {
910138fd1498Szrj skip = 0;
910238fd1498Szrj /* Ignore newlines. */
910338fd1498Szrj if (*p == '\n')
910438fd1498Szrj {
910538fd1498Szrj ++p;
910638fd1498Szrj continue;
910738fd1498Szrj }
910838fd1498Szrj
910938fd1498Szrj /* Get the initial path. */
911038fd1498Szrj this_path = p;
911138fd1498Szrj while (*p != ' ')
911238fd1498Szrj {
911338fd1498Szrj if (*p == '\0')
911438fd1498Szrj {
911538fd1498Szrj invalid_select:
911638fd1498Szrj fatal_error (input_location,
911738fd1498Szrj "multilib select %qs is invalid", multilib_select);
911838fd1498Szrj }
911938fd1498Szrj
912038fd1498Szrj ++p;
912138fd1498Szrj }
912238fd1498Szrj
912338fd1498Szrj /* When --disable-multilib was used but target defines
912438fd1498Szrj MULTILIB_OSDIRNAMES, entries starting with .: (and not starting
912538fd1498Szrj with .:: for multiarch configurations) are there just to find
912638fd1498Szrj multilib_os_dir, so skip them from output. */
912738fd1498Szrj if (this_path[0] == '.' && this_path[1] == ':' && this_path[2] != ':')
912838fd1498Szrj skip = 1;
912938fd1498Szrj
913038fd1498Szrj /* Check for matches with the multilib_exclusions. We don't bother
913138fd1498Szrj with the '!' in either list. If any of the exclusion rules match
913238fd1498Szrj all of its options with the select rule, we skip it. */
913338fd1498Szrj {
913438fd1498Szrj const char *e = multilib_exclusions;
913538fd1498Szrj const char *this_arg;
913638fd1498Szrj
913738fd1498Szrj while (*e != '\0')
913838fd1498Szrj {
913938fd1498Szrj int m = 1;
914038fd1498Szrj /* Ignore newlines. */
914138fd1498Szrj if (*e == '\n')
914238fd1498Szrj {
914338fd1498Szrj ++e;
914438fd1498Szrj continue;
914538fd1498Szrj }
914638fd1498Szrj
914738fd1498Szrj /* Check the arguments. */
914838fd1498Szrj while (*e != ';')
914938fd1498Szrj {
915038fd1498Szrj const char *q;
915138fd1498Szrj int mp = 0;
915238fd1498Szrj
915338fd1498Szrj if (*e == '\0')
915438fd1498Szrj {
915538fd1498Szrj invalid_exclusion:
915638fd1498Szrj fatal_error (input_location,
915738fd1498Szrj "multilib exclusion %qs is invalid",
915838fd1498Szrj multilib_exclusions);
915938fd1498Szrj }
916038fd1498Szrj
916138fd1498Szrj if (! m)
916238fd1498Szrj {
916338fd1498Szrj ++e;
916438fd1498Szrj continue;
916538fd1498Szrj }
916638fd1498Szrj
916738fd1498Szrj this_arg = e;
916838fd1498Szrj
916938fd1498Szrj while (*e != ' ' && *e != ';')
917038fd1498Szrj {
917138fd1498Szrj if (*e == '\0')
917238fd1498Szrj goto invalid_exclusion;
917338fd1498Szrj ++e;
917438fd1498Szrj }
917538fd1498Szrj
917638fd1498Szrj q = p + 1;
917738fd1498Szrj while (*q != ';')
917838fd1498Szrj {
917938fd1498Szrj const char *arg;
918038fd1498Szrj int len = e - this_arg;
918138fd1498Szrj
918238fd1498Szrj if (*q == '\0')
918338fd1498Szrj goto invalid_select;
918438fd1498Szrj
918538fd1498Szrj arg = q;
918638fd1498Szrj
918738fd1498Szrj while (*q != ' ' && *q != ';')
918838fd1498Szrj {
918938fd1498Szrj if (*q == '\0')
919038fd1498Szrj goto invalid_select;
919138fd1498Szrj ++q;
919238fd1498Szrj }
919338fd1498Szrj
919438fd1498Szrj if (! strncmp (arg, this_arg,
919538fd1498Szrj (len < q - arg) ? q - arg : len)
919638fd1498Szrj || default_arg (this_arg, e - this_arg))
919738fd1498Szrj {
919838fd1498Szrj mp = 1;
919938fd1498Szrj break;
920038fd1498Szrj }
920138fd1498Szrj
920238fd1498Szrj if (*q == ' ')
920338fd1498Szrj ++q;
920438fd1498Szrj }
920538fd1498Szrj
920638fd1498Szrj if (! mp)
920738fd1498Szrj m = 0;
920838fd1498Szrj
920938fd1498Szrj if (*e == ' ')
921038fd1498Szrj ++e;
921138fd1498Szrj }
921238fd1498Szrj
921338fd1498Szrj if (m)
921438fd1498Szrj {
921538fd1498Szrj skip = 1;
921638fd1498Szrj break;
921738fd1498Szrj }
921838fd1498Szrj
921938fd1498Szrj if (*e != '\0')
922038fd1498Szrj ++e;
922138fd1498Szrj }
922238fd1498Szrj }
922338fd1498Szrj
922438fd1498Szrj if (! skip)
922538fd1498Szrj {
922638fd1498Szrj /* If this is a duplicate, skip it. */
922738fd1498Szrj skip = (last_path != 0
922838fd1498Szrj && (unsigned int) (p - this_path) == last_path_len
922938fd1498Szrj && ! filename_ncmp (last_path, this_path, last_path_len));
923038fd1498Szrj
923138fd1498Szrj last_path = this_path;
923238fd1498Szrj last_path_len = p - this_path;
923338fd1498Szrj }
923438fd1498Szrj
923538fd1498Szrj /* If this directory requires any default arguments, we can skip
923638fd1498Szrj it. We will already have printed a directory identical to
923738fd1498Szrj this one which does not require that default argument. */
923838fd1498Szrj if (! skip)
923938fd1498Szrj {
924038fd1498Szrj const char *q;
924138fd1498Szrj
924238fd1498Szrj q = p + 1;
924338fd1498Szrj while (*q != ';')
924438fd1498Szrj {
924538fd1498Szrj const char *arg;
924638fd1498Szrj
924738fd1498Szrj if (*q == '\0')
924838fd1498Szrj goto invalid_select;
924938fd1498Szrj
925038fd1498Szrj if (*q == '!')
925138fd1498Szrj arg = NULL;
925238fd1498Szrj else
925338fd1498Szrj arg = q;
925438fd1498Szrj
925538fd1498Szrj while (*q != ' ' && *q != ';')
925638fd1498Szrj {
925738fd1498Szrj if (*q == '\0')
925838fd1498Szrj goto invalid_select;
925938fd1498Szrj ++q;
926038fd1498Szrj }
926138fd1498Szrj
926238fd1498Szrj if (arg != NULL
926338fd1498Szrj && default_arg (arg, q - arg))
926438fd1498Szrj {
926538fd1498Szrj skip = 1;
926638fd1498Szrj break;
926738fd1498Szrj }
926838fd1498Szrj
926938fd1498Szrj if (*q == ' ')
927038fd1498Szrj ++q;
927138fd1498Szrj }
927238fd1498Szrj }
927338fd1498Szrj
927438fd1498Szrj if (! skip)
927538fd1498Szrj {
927638fd1498Szrj const char *p1;
927738fd1498Szrj
927838fd1498Szrj for (p1 = last_path; p1 < p && *p1 != ':'; p1++)
927938fd1498Szrj putchar (*p1);
928038fd1498Szrj putchar (';');
928138fd1498Szrj }
928238fd1498Szrj
928338fd1498Szrj ++p;
928438fd1498Szrj while (*p != ';')
928538fd1498Szrj {
928638fd1498Szrj int use_arg;
928738fd1498Szrj
928838fd1498Szrj if (*p == '\0')
928938fd1498Szrj goto invalid_select;
929038fd1498Szrj
929138fd1498Szrj if (skip)
929238fd1498Szrj {
929338fd1498Szrj ++p;
929438fd1498Szrj continue;
929538fd1498Szrj }
929638fd1498Szrj
929738fd1498Szrj use_arg = *p != '!';
929838fd1498Szrj
929938fd1498Szrj if (use_arg)
930038fd1498Szrj putchar ('@');
930138fd1498Szrj
930238fd1498Szrj while (*p != ' ' && *p != ';')
930338fd1498Szrj {
930438fd1498Szrj if (*p == '\0')
930538fd1498Szrj goto invalid_select;
930638fd1498Szrj if (use_arg)
930738fd1498Szrj putchar (*p);
930838fd1498Szrj ++p;
930938fd1498Szrj }
931038fd1498Szrj
931138fd1498Szrj if (*p == ' ')
931238fd1498Szrj ++p;
931338fd1498Szrj }
931438fd1498Szrj
931538fd1498Szrj if (! skip)
931638fd1498Szrj {
931738fd1498Szrj /* If there are extra options, print them now. */
931838fd1498Szrj if (multilib_extra && *multilib_extra)
931938fd1498Szrj {
932038fd1498Szrj int print_at = TRUE;
932138fd1498Szrj const char *q;
932238fd1498Szrj
932338fd1498Szrj for (q = multilib_extra; *q != '\0'; q++)
932438fd1498Szrj {
932538fd1498Szrj if (*q == ' ')
932638fd1498Szrj print_at = TRUE;
932738fd1498Szrj else
932838fd1498Szrj {
932938fd1498Szrj if (print_at)
933038fd1498Szrj putchar ('@');
933138fd1498Szrj putchar (*q);
933238fd1498Szrj print_at = FALSE;
933338fd1498Szrj }
933438fd1498Szrj }
933538fd1498Szrj }
933638fd1498Szrj
933738fd1498Szrj putchar ('\n');
933838fd1498Szrj }
933938fd1498Szrj
934038fd1498Szrj ++p;
934138fd1498Szrj }
934238fd1498Szrj }
934338fd1498Szrj
934438fd1498Szrj /* getenv built-in spec function.
934538fd1498Szrj
934638fd1498Szrj Returns the value of the environment variable given by its first argument,
934738fd1498Szrj concatenated with the second argument. If the variable is not defined, a
934838fd1498Szrj fatal error is issued unless such undefs are internally allowed, in which
934938fd1498Szrj case the variable name is used as the variable value. */
935038fd1498Szrj
935138fd1498Szrj static const char *
getenv_spec_function(int argc,const char ** argv)935238fd1498Szrj getenv_spec_function (int argc, const char **argv)
935338fd1498Szrj {
935438fd1498Szrj const char *value;
935538fd1498Szrj const char *varname;
935638fd1498Szrj
935738fd1498Szrj char *result;
935838fd1498Szrj char *ptr;
935938fd1498Szrj size_t len;
936038fd1498Szrj
936138fd1498Szrj if (argc != 2)
936238fd1498Szrj return NULL;
936338fd1498Szrj
936438fd1498Szrj varname = argv[0];
936538fd1498Szrj value = env.get (varname);
936638fd1498Szrj
936738fd1498Szrj if (!value && spec_undefvar_allowed)
936838fd1498Szrj value = varname;
936938fd1498Szrj
937038fd1498Szrj if (!value)
937138fd1498Szrj fatal_error (input_location,
937238fd1498Szrj "environment variable %qs not defined", varname);
937338fd1498Szrj
937438fd1498Szrj /* We have to escape every character of the environment variable so
937538fd1498Szrj they are not interpreted as active spec characters. A
937638fd1498Szrj particularly painful case is when we are reading a variable
937738fd1498Szrj holding a windows path complete with \ separators. */
937838fd1498Szrj len = strlen (value) * 2 + strlen (argv[1]) + 1;
937938fd1498Szrj result = XNEWVAR (char, len);
938038fd1498Szrj for (ptr = result; *value; ptr += 2)
938138fd1498Szrj {
938238fd1498Szrj ptr[0] = '\\';
938338fd1498Szrj ptr[1] = *value++;
938438fd1498Szrj }
938538fd1498Szrj
938638fd1498Szrj strcpy (ptr, argv[1]);
938738fd1498Szrj
938838fd1498Szrj return result;
938938fd1498Szrj }
939038fd1498Szrj
939138fd1498Szrj /* if-exists built-in spec function.
939238fd1498Szrj
939338fd1498Szrj Checks to see if the file specified by the absolute pathname in
939438fd1498Szrj ARGS exists. Returns that pathname if found.
939538fd1498Szrj
939638fd1498Szrj The usual use for this function is to check for a library file
939738fd1498Szrj (whose name has been expanded with %s). */
939838fd1498Szrj
939938fd1498Szrj static const char *
if_exists_spec_function(int argc,const char ** argv)940038fd1498Szrj if_exists_spec_function (int argc, const char **argv)
940138fd1498Szrj {
940238fd1498Szrj /* Must have only one argument. */
940338fd1498Szrj if (argc == 1 && IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
940438fd1498Szrj return argv[0];
940538fd1498Szrj
940638fd1498Szrj return NULL;
940738fd1498Szrj }
940838fd1498Szrj
940938fd1498Szrj /* if-exists-else built-in spec function.
941038fd1498Szrj
941138fd1498Szrj This is like if-exists, but takes an additional argument which
941238fd1498Szrj is returned if the first argument does not exist. */
941338fd1498Szrj
941438fd1498Szrj static const char *
if_exists_else_spec_function(int argc,const char ** argv)941538fd1498Szrj if_exists_else_spec_function (int argc, const char **argv)
941638fd1498Szrj {
941738fd1498Szrj /* Must have exactly two arguments. */
941838fd1498Szrj if (argc != 2)
941938fd1498Szrj return NULL;
942038fd1498Szrj
942138fd1498Szrj if (IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
942238fd1498Szrj return argv[0];
942338fd1498Szrj
942438fd1498Szrj return argv[1];
942538fd1498Szrj }
942638fd1498Szrj
942738fd1498Szrj /* sanitize built-in spec function.
942838fd1498Szrj
942938fd1498Szrj This returns non-NULL, if sanitizing address, thread or
943038fd1498Szrj any of the undefined behavior sanitizers. */
943138fd1498Szrj
943238fd1498Szrj static const char *
sanitize_spec_function(int argc,const char ** argv)943338fd1498Szrj sanitize_spec_function (int argc, const char **argv)
943438fd1498Szrj {
943538fd1498Szrj if (argc != 1)
943638fd1498Szrj return NULL;
943738fd1498Szrj
943838fd1498Szrj if (strcmp (argv[0], "address") == 0)
943938fd1498Szrj return (flag_sanitize & SANITIZE_USER_ADDRESS) ? "" : NULL;
944038fd1498Szrj if (strcmp (argv[0], "kernel-address") == 0)
944138fd1498Szrj return (flag_sanitize & SANITIZE_KERNEL_ADDRESS) ? "" : NULL;
944238fd1498Szrj if (strcmp (argv[0], "thread") == 0)
944338fd1498Szrj return (flag_sanitize & SANITIZE_THREAD) ? "" : NULL;
944438fd1498Szrj if (strcmp (argv[0], "undefined") == 0)
944538fd1498Szrj return ((flag_sanitize
944638fd1498Szrj & (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT))
944738fd1498Szrj && !flag_sanitize_undefined_trap_on_error) ? "" : NULL;
944838fd1498Szrj if (strcmp (argv[0], "leak") == 0)
944938fd1498Szrj return ((flag_sanitize
945038fd1498Szrj & (SANITIZE_ADDRESS | SANITIZE_LEAK | SANITIZE_THREAD))
945138fd1498Szrj == SANITIZE_LEAK) ? "" : NULL;
945238fd1498Szrj return NULL;
945338fd1498Szrj }
945438fd1498Szrj
945538fd1498Szrj /* replace-outfile built-in spec function.
945638fd1498Szrj
945738fd1498Szrj This looks for the first argument in the outfiles array's name and
945838fd1498Szrj replaces it with the second argument. */
945938fd1498Szrj
946038fd1498Szrj static const char *
replace_outfile_spec_function(int argc,const char ** argv)946138fd1498Szrj replace_outfile_spec_function (int argc, const char **argv)
946238fd1498Szrj {
946338fd1498Szrj int i;
946438fd1498Szrj /* Must have exactly two arguments. */
946538fd1498Szrj if (argc != 2)
946638fd1498Szrj abort ();
946738fd1498Szrj
946838fd1498Szrj for (i = 0; i < n_infiles; i++)
946938fd1498Szrj {
947038fd1498Szrj if (outfiles[i] && !filename_cmp (outfiles[i], argv[0]))
947138fd1498Szrj outfiles[i] = xstrdup (argv[1]);
947238fd1498Szrj }
947338fd1498Szrj return NULL;
947438fd1498Szrj }
947538fd1498Szrj
947638fd1498Szrj /* remove-outfile built-in spec function.
947738fd1498Szrj *
947838fd1498Szrj * This looks for the first argument in the outfiles array's name and
947938fd1498Szrj * removes it. */
948038fd1498Szrj
948138fd1498Szrj static const char *
remove_outfile_spec_function(int argc,const char ** argv)948238fd1498Szrj remove_outfile_spec_function (int argc, const char **argv)
948338fd1498Szrj {
948438fd1498Szrj int i;
948538fd1498Szrj /* Must have exactly one argument. */
948638fd1498Szrj if (argc != 1)
948738fd1498Szrj abort ();
948838fd1498Szrj
948938fd1498Szrj for (i = 0; i < n_infiles; i++)
949038fd1498Szrj {
949138fd1498Szrj if (outfiles[i] && !filename_cmp (outfiles[i], argv[0]))
949238fd1498Szrj outfiles[i] = NULL;
949338fd1498Szrj }
949438fd1498Szrj return NULL;
949538fd1498Szrj }
949638fd1498Szrj
949738fd1498Szrj /* Given two version numbers, compares the two numbers.
949838fd1498Szrj A version number must match the regular expression
949938fd1498Szrj ([1-9][0-9]*|0)(\.([1-9][0-9]*|0))*
950038fd1498Szrj */
950138fd1498Szrj static int
compare_version_strings(const char * v1,const char * v2)950238fd1498Szrj compare_version_strings (const char *v1, const char *v2)
950338fd1498Szrj {
950438fd1498Szrj int rresult;
950538fd1498Szrj regex_t r;
950638fd1498Szrj
950738fd1498Szrj if (regcomp (&r, "^([1-9][0-9]*|0)(\\.([1-9][0-9]*|0))*$",
950838fd1498Szrj REG_EXTENDED | REG_NOSUB) != 0)
950938fd1498Szrj abort ();
951038fd1498Szrj rresult = regexec (&r, v1, 0, NULL, 0);
951138fd1498Szrj if (rresult == REG_NOMATCH)
951238fd1498Szrj fatal_error (input_location, "invalid version number %qs", v1);
951338fd1498Szrj else if (rresult != 0)
951438fd1498Szrj abort ();
951538fd1498Szrj rresult = regexec (&r, v2, 0, NULL, 0);
951638fd1498Szrj if (rresult == REG_NOMATCH)
951738fd1498Szrj fatal_error (input_location, "invalid version number %qs", v2);
951838fd1498Szrj else if (rresult != 0)
951938fd1498Szrj abort ();
952038fd1498Szrj
952138fd1498Szrj return strverscmp (v1, v2);
952238fd1498Szrj }
952338fd1498Szrj
952438fd1498Szrj
952538fd1498Szrj /* version_compare built-in spec function.
952638fd1498Szrj
952738fd1498Szrj This takes an argument of the following form:
952838fd1498Szrj
952938fd1498Szrj <comparison-op> <arg1> [<arg2>] <switch> <result>
953038fd1498Szrj
953138fd1498Szrj and produces "result" if the comparison evaluates to true,
953238fd1498Szrj and nothing if it doesn't.
953338fd1498Szrj
953438fd1498Szrj The supported <comparison-op> values are:
953538fd1498Szrj
953638fd1498Szrj >= true if switch is a later (or same) version than arg1
953738fd1498Szrj !> opposite of >=
953838fd1498Szrj < true if switch is an earlier version than arg1
953938fd1498Szrj !< opposite of <
954038fd1498Szrj >< true if switch is arg1 or later, and earlier than arg2
954138fd1498Szrj <> true if switch is earlier than arg1 or is arg2 or later
954238fd1498Szrj
954338fd1498Szrj If the switch is not present, the condition is false unless
954438fd1498Szrj the first character of the <comparison-op> is '!'.
954538fd1498Szrj
954638fd1498Szrj For example,
954738fd1498Szrj %:version-compare(>= 10.3 mmacosx-version-min= -lmx)
954838fd1498Szrj adds -lmx if -mmacosx-version-min=10.3.9 was passed. */
954938fd1498Szrj
955038fd1498Szrj static const char *
version_compare_spec_function(int argc,const char ** argv)955138fd1498Szrj version_compare_spec_function (int argc, const char **argv)
955238fd1498Szrj {
955338fd1498Szrj int comp1, comp2;
955438fd1498Szrj size_t switch_len;
955538fd1498Szrj const char *switch_value = NULL;
955638fd1498Szrj int nargs = 1, i;
955738fd1498Szrj bool result;
955838fd1498Szrj
955938fd1498Szrj if (argc < 3)
956038fd1498Szrj fatal_error (input_location, "too few arguments to %%:version-compare");
956138fd1498Szrj if (argv[0][0] == '\0')
956238fd1498Szrj abort ();
956338fd1498Szrj if ((argv[0][1] == '<' || argv[0][1] == '>') && argv[0][0] != '!')
956438fd1498Szrj nargs = 2;
956538fd1498Szrj if (argc != nargs + 3)
956638fd1498Szrj fatal_error (input_location, "too many arguments to %%:version-compare");
956738fd1498Szrj
956838fd1498Szrj switch_len = strlen (argv[nargs + 1]);
956938fd1498Szrj for (i = 0; i < n_switches; i++)
957038fd1498Szrj if (!strncmp (switches[i].part1, argv[nargs + 1], switch_len)
957138fd1498Szrj && check_live_switch (i, switch_len))
957238fd1498Szrj switch_value = switches[i].part1 + switch_len;
957338fd1498Szrj
957438fd1498Szrj if (switch_value == NULL)
957538fd1498Szrj comp1 = comp2 = -1;
957638fd1498Szrj else
957738fd1498Szrj {
957838fd1498Szrj comp1 = compare_version_strings (switch_value, argv[1]);
957938fd1498Szrj if (nargs == 2)
958038fd1498Szrj comp2 = compare_version_strings (switch_value, argv[2]);
958138fd1498Szrj else
958238fd1498Szrj comp2 = -1; /* This value unused. */
958338fd1498Szrj }
958438fd1498Szrj
958538fd1498Szrj switch (argv[0][0] << 8 | argv[0][1])
958638fd1498Szrj {
958738fd1498Szrj case '>' << 8 | '=':
958838fd1498Szrj result = comp1 >= 0;
958938fd1498Szrj break;
959038fd1498Szrj case '!' << 8 | '<':
959138fd1498Szrj result = comp1 >= 0 || switch_value == NULL;
959238fd1498Szrj break;
959338fd1498Szrj case '<' << 8:
959438fd1498Szrj result = comp1 < 0;
959538fd1498Szrj break;
959638fd1498Szrj case '!' << 8 | '>':
959738fd1498Szrj result = comp1 < 0 || switch_value == NULL;
959838fd1498Szrj break;
959938fd1498Szrj case '>' << 8 | '<':
960038fd1498Szrj result = comp1 >= 0 && comp2 < 0;
960138fd1498Szrj break;
960238fd1498Szrj case '<' << 8 | '>':
960338fd1498Szrj result = comp1 < 0 || comp2 >= 0;
960438fd1498Szrj break;
960538fd1498Szrj
960638fd1498Szrj default:
960738fd1498Szrj fatal_error (input_location,
960838fd1498Szrj "unknown operator %qs in %%:version-compare", argv[0]);
960938fd1498Szrj }
961038fd1498Szrj if (! result)
961138fd1498Szrj return NULL;
961238fd1498Szrj
961338fd1498Szrj return argv[nargs + 2];
961438fd1498Szrj }
961538fd1498Szrj
961638fd1498Szrj /* %:include builtin spec function. This differs from %include in that it
961738fd1498Szrj can be nested inside a spec, and thus be conditionalized. It takes
961838fd1498Szrj one argument, the filename, and looks for it in the startfile path.
961938fd1498Szrj The result is always NULL, i.e. an empty expansion. */
962038fd1498Szrj
962138fd1498Szrj static const char *
include_spec_function(int argc,const char ** argv)962238fd1498Szrj include_spec_function (int argc, const char **argv)
962338fd1498Szrj {
962438fd1498Szrj char *file;
962538fd1498Szrj
962638fd1498Szrj if (argc != 1)
962738fd1498Szrj abort ();
962838fd1498Szrj
962938fd1498Szrj file = find_a_file (&startfile_prefixes, argv[0], R_OK, true);
963038fd1498Szrj read_specs (file ? file : argv[0], false, false);
963138fd1498Szrj
963238fd1498Szrj return NULL;
963338fd1498Szrj }
963438fd1498Szrj
963538fd1498Szrj /* %:find-file spec function. This function replaces its argument by
963638fd1498Szrj the file found through find_file, that is the -print-file-name gcc
963738fd1498Szrj program option. */
963838fd1498Szrj static const char *
find_file_spec_function(int argc,const char ** argv)963938fd1498Szrj find_file_spec_function (int argc, const char **argv)
964038fd1498Szrj {
964138fd1498Szrj const char *file;
964238fd1498Szrj
964338fd1498Szrj if (argc != 1)
964438fd1498Szrj abort ();
964538fd1498Szrj
964638fd1498Szrj file = find_file (argv[0]);
964738fd1498Szrj return file;
964838fd1498Szrj }
964938fd1498Szrj
965038fd1498Szrj
965138fd1498Szrj /* %:find-plugindir spec function. This function replaces its argument
965238fd1498Szrj by the -iplugindir=<dir> option. `dir' is found through find_file, that
965338fd1498Szrj is the -print-file-name gcc program option. */
965438fd1498Szrj static const char *
find_plugindir_spec_function(int argc,const char ** argv ATTRIBUTE_UNUSED)965538fd1498Szrj find_plugindir_spec_function (int argc, const char **argv ATTRIBUTE_UNUSED)
965638fd1498Szrj {
965738fd1498Szrj const char *option;
965838fd1498Szrj
965938fd1498Szrj if (argc != 0)
966038fd1498Szrj abort ();
966138fd1498Szrj
966238fd1498Szrj option = concat ("-iplugindir=", find_file ("plugin"), NULL);
966338fd1498Szrj return option;
966438fd1498Szrj }
966538fd1498Szrj
966638fd1498Szrj
966738fd1498Szrj /* %:print-asm-header spec function. Print a banner to say that the
966838fd1498Szrj following output is from the assembler. */
966938fd1498Szrj
967038fd1498Szrj static const char *
print_asm_header_spec_function(int arg ATTRIBUTE_UNUSED,const char ** argv ATTRIBUTE_UNUSED)967138fd1498Szrj print_asm_header_spec_function (int arg ATTRIBUTE_UNUSED,
967238fd1498Szrj const char **argv ATTRIBUTE_UNUSED)
967338fd1498Szrj {
967438fd1498Szrj printf (_("Assembler options\n=================\n\n"));
967538fd1498Szrj printf (_("Use \"-Wa,OPTION\" to pass \"OPTION\" to the assembler.\n\n"));
967638fd1498Szrj fflush (stdout);
967738fd1498Szrj return NULL;
967838fd1498Szrj }
967938fd1498Szrj
968038fd1498Szrj /* Get a random number for -frandom-seed */
968138fd1498Szrj
968238fd1498Szrj static unsigned HOST_WIDE_INT
get_random_number(void)968338fd1498Szrj get_random_number (void)
968438fd1498Szrj {
968538fd1498Szrj unsigned HOST_WIDE_INT ret = 0;
968638fd1498Szrj int fd;
968738fd1498Szrj
968838fd1498Szrj fd = open ("/dev/urandom", O_RDONLY);
968938fd1498Szrj if (fd >= 0)
969038fd1498Szrj {
969138fd1498Szrj read (fd, &ret, sizeof (HOST_WIDE_INT));
969238fd1498Szrj close (fd);
969338fd1498Szrj if (ret)
969438fd1498Szrj return ret;
969538fd1498Szrj }
969638fd1498Szrj
969738fd1498Szrj /* Get some more or less random data. */
969838fd1498Szrj #ifdef HAVE_GETTIMEOFDAY
969938fd1498Szrj {
970038fd1498Szrj struct timeval tv;
970138fd1498Szrj
970238fd1498Szrj gettimeofday (&tv, NULL);
970338fd1498Szrj ret = tv.tv_sec * 1000 + tv.tv_usec / 1000;
970438fd1498Szrj }
970538fd1498Szrj #else
970638fd1498Szrj {
970738fd1498Szrj time_t now = time (NULL);
970838fd1498Szrj
970938fd1498Szrj if (now != (time_t)-1)
971038fd1498Szrj ret = (unsigned) now;
971138fd1498Szrj }
971238fd1498Szrj #endif
971338fd1498Szrj
971438fd1498Szrj return ret ^ getpid ();
971538fd1498Szrj }
971638fd1498Szrj
971738fd1498Szrj /* %:compare-debug-dump-opt spec function. Save the last argument,
971838fd1498Szrj expected to be the last -fdump-final-insns option, or generate a
971938fd1498Szrj temporary. */
972038fd1498Szrj
972138fd1498Szrj static const char *
compare_debug_dump_opt_spec_function(int arg,const char ** argv ATTRIBUTE_UNUSED)972238fd1498Szrj compare_debug_dump_opt_spec_function (int arg,
972338fd1498Szrj const char **argv ATTRIBUTE_UNUSED)
972438fd1498Szrj {
972538fd1498Szrj char *ret;
972638fd1498Szrj char *name;
972738fd1498Szrj int which;
972838fd1498Szrj static char random_seed[HOST_BITS_PER_WIDE_INT / 4 + 3];
972938fd1498Szrj
973038fd1498Szrj if (arg != 0)
973138fd1498Szrj fatal_error (input_location,
973238fd1498Szrj "too many arguments to %%:compare-debug-dump-opt");
973338fd1498Szrj
973438fd1498Szrj do_spec_2 ("%{fdump-final-insns=*:%*}");
973538fd1498Szrj do_spec_1 (" ", 0, NULL);
973638fd1498Szrj
973738fd1498Szrj if (argbuf.length () > 0
973838fd1498Szrj && strcmp (argv[argbuf.length () - 1], "."))
973938fd1498Szrj {
974038fd1498Szrj if (!compare_debug)
974138fd1498Szrj return NULL;
974238fd1498Szrj
974338fd1498Szrj name = xstrdup (argv[argbuf.length () - 1]);
974438fd1498Szrj ret = NULL;
974538fd1498Szrj }
974638fd1498Szrj else
974738fd1498Szrj {
974838fd1498Szrj const char *ext = NULL;
974938fd1498Szrj
975038fd1498Szrj if (argbuf.length () > 0)
975138fd1498Szrj {
975238fd1498Szrj do_spec_2 ("%{o*:%*}%{!o:%{!S:%b%O}%{S:%b.s}}");
975338fd1498Szrj ext = ".gkd";
975438fd1498Szrj }
975538fd1498Szrj else if (!compare_debug)
975638fd1498Szrj return NULL;
975738fd1498Szrj else
975838fd1498Szrj do_spec_2 ("%g.gkd");
975938fd1498Szrj
976038fd1498Szrj do_spec_1 (" ", 0, NULL);
976138fd1498Szrj
976238fd1498Szrj gcc_assert (argbuf.length () > 0);
976338fd1498Szrj
976438fd1498Szrj name = concat (argbuf.last (), ext, NULL);
976538fd1498Szrj
976638fd1498Szrj ret = concat ("-fdump-final-insns=", name, NULL);
976738fd1498Szrj }
976838fd1498Szrj
976938fd1498Szrj which = compare_debug < 0;
977038fd1498Szrj debug_check_temp_file[which] = name;
977138fd1498Szrj
977238fd1498Szrj if (!which)
977338fd1498Szrj {
977438fd1498Szrj unsigned HOST_WIDE_INT value = get_random_number ();
977538fd1498Szrj
977638fd1498Szrj sprintf (random_seed, HOST_WIDE_INT_PRINT_HEX, value);
977738fd1498Szrj }
977838fd1498Szrj
977938fd1498Szrj if (*random_seed)
978038fd1498Szrj {
978138fd1498Szrj char *tmp = ret;
978238fd1498Szrj ret = concat ("%{!frandom-seed=*:-frandom-seed=", random_seed, "} ",
978338fd1498Szrj ret, NULL);
978438fd1498Szrj free (tmp);
978538fd1498Szrj }
978638fd1498Szrj
978738fd1498Szrj if (which)
978838fd1498Szrj *random_seed = 0;
978938fd1498Szrj
979038fd1498Szrj return ret;
979138fd1498Szrj }
979238fd1498Szrj
979338fd1498Szrj static const char *debug_auxbase_opt;
979438fd1498Szrj
979538fd1498Szrj /* %:compare-debug-self-opt spec function. Expands to the options
979638fd1498Szrj that are to be passed in the second compilation of
979738fd1498Szrj compare-debug. */
979838fd1498Szrj
979938fd1498Szrj static const char *
compare_debug_self_opt_spec_function(int arg,const char ** argv ATTRIBUTE_UNUSED)980038fd1498Szrj compare_debug_self_opt_spec_function (int arg,
980138fd1498Szrj const char **argv ATTRIBUTE_UNUSED)
980238fd1498Szrj {
980338fd1498Szrj if (arg != 0)
980438fd1498Szrj fatal_error (input_location,
980538fd1498Szrj "too many arguments to %%:compare-debug-self-opt");
980638fd1498Szrj
980738fd1498Szrj if (compare_debug >= 0)
980838fd1498Szrj return NULL;
980938fd1498Szrj
981038fd1498Szrj do_spec_2 ("%{c|S:%{o*:%*}}");
981138fd1498Szrj do_spec_1 (" ", 0, NULL);
981238fd1498Szrj
981338fd1498Szrj if (argbuf.length () > 0)
981438fd1498Szrj debug_auxbase_opt = concat ("-auxbase-strip ",
981538fd1498Szrj argbuf.last (),
981638fd1498Szrj NULL);
981738fd1498Szrj else
981838fd1498Szrj debug_auxbase_opt = NULL;
981938fd1498Szrj
982038fd1498Szrj return concat ("\
982138fd1498Szrj %<o %<MD %<MMD %<MF* %<MG %<MP %<MQ* %<MT* \
982238fd1498Szrj %<fdump-final-insns=* -w -S -o %j \
982338fd1498Szrj %{!fcompare-debug-second:-fcompare-debug-second} \
982438fd1498Szrj ", compare_debug_opt, NULL);
982538fd1498Szrj }
982638fd1498Szrj
982738fd1498Szrj /* %:compare-debug-auxbase-opt spec function. Expands to the auxbase
982838fd1498Szrj options that are to be passed in the second compilation of
982938fd1498Szrj compare-debug. It expects, as an argument, the basename of the
983038fd1498Szrj current input file name, with the .gk suffix appended to it. */
983138fd1498Szrj
983238fd1498Szrj static const char *
compare_debug_auxbase_opt_spec_function(int arg,const char ** argv)983338fd1498Szrj compare_debug_auxbase_opt_spec_function (int arg,
983438fd1498Szrj const char **argv)
983538fd1498Szrj {
983638fd1498Szrj char *name;
983738fd1498Szrj int len;
983838fd1498Szrj
983938fd1498Szrj if (arg == 0)
984038fd1498Szrj fatal_error (input_location,
984138fd1498Szrj "too few arguments to %%:compare-debug-auxbase-opt");
984238fd1498Szrj
984338fd1498Szrj if (arg != 1)
984438fd1498Szrj fatal_error (input_location,
984538fd1498Szrj "too many arguments to %%:compare-debug-auxbase-opt");
984638fd1498Szrj
984738fd1498Szrj if (compare_debug >= 0)
984838fd1498Szrj return NULL;
984938fd1498Szrj
985038fd1498Szrj len = strlen (argv[0]);
985138fd1498Szrj if (len < 3 || strcmp (argv[0] + len - 3, ".gk") != 0)
985238fd1498Szrj fatal_error (input_location, "argument to %%:compare-debug-auxbase-opt "
985338fd1498Szrj "does not end in .gk");
985438fd1498Szrj
985538fd1498Szrj if (debug_auxbase_opt)
985638fd1498Szrj return debug_auxbase_opt;
985738fd1498Szrj
985838fd1498Szrj #define OPT "-auxbase "
985938fd1498Szrj
986038fd1498Szrj len -= 3;
986138fd1498Szrj name = (char*) xmalloc (sizeof (OPT) + len);
986238fd1498Szrj memcpy (name, OPT, sizeof (OPT) - 1);
986338fd1498Szrj memcpy (name + sizeof (OPT) - 1, argv[0], len);
986438fd1498Szrj name[sizeof (OPT) - 1 + len] = '\0';
986538fd1498Szrj
986638fd1498Szrj #undef OPT
986738fd1498Szrj
986838fd1498Szrj return name;
986938fd1498Szrj }
987038fd1498Szrj
987138fd1498Szrj /* %:pass-through-libs spec function. Finds all -l options and input
987238fd1498Szrj file names in the lib spec passed to it, and makes a list of them
987338fd1498Szrj prepended with the plugin option to cause them to be passed through
987438fd1498Szrj to the final link after all the new object files have been added. */
987538fd1498Szrj
987638fd1498Szrj const char *
pass_through_libs_spec_func(int argc,const char ** argv)987738fd1498Szrj pass_through_libs_spec_func (int argc, const char **argv)
987838fd1498Szrj {
987938fd1498Szrj char *prepended = xstrdup (" ");
988038fd1498Szrj int n;
988138fd1498Szrj /* Shlemiel the painter's algorithm. Innately horrible, but at least
988238fd1498Szrj we know that there will never be more than a handful of strings to
988338fd1498Szrj concat, and it's only once per run, so it's not worth optimising. */
988438fd1498Szrj for (n = 0; n < argc; n++)
988538fd1498Szrj {
988638fd1498Szrj char *old = prepended;
988738fd1498Szrj /* Anything that isn't an option is a full path to an output
988838fd1498Szrj file; pass it through if it ends in '.a'. Among options,
988938fd1498Szrj pass only -l. */
989038fd1498Szrj if (argv[n][0] == '-' && argv[n][1] == 'l')
989138fd1498Szrj {
989238fd1498Szrj const char *lopt = argv[n] + 2;
989338fd1498Szrj /* Handle both joined and non-joined -l options. If for any
989438fd1498Szrj reason there's a trailing -l with no joined or following
989538fd1498Szrj arg just discard it. */
989638fd1498Szrj if (!*lopt && ++n >= argc)
989738fd1498Szrj break;
989838fd1498Szrj else if (!*lopt)
989938fd1498Szrj lopt = argv[n];
990038fd1498Szrj prepended = concat (prepended, "-plugin-opt=-pass-through=-l",
990138fd1498Szrj lopt, " ", NULL);
990238fd1498Szrj }
990338fd1498Szrj else if (!strcmp (".a", argv[n] + strlen (argv[n]) - 2))
990438fd1498Szrj {
990538fd1498Szrj prepended = concat (prepended, "-plugin-opt=-pass-through=",
990638fd1498Szrj argv[n], " ", NULL);
990738fd1498Szrj }
990838fd1498Szrj if (prepended != old)
990938fd1498Szrj free (old);
991038fd1498Szrj }
991138fd1498Szrj return prepended;
991238fd1498Szrj }
991338fd1498Szrj
991438fd1498Szrj /* %:replace-extension spec function. Replaces the extension of the
991538fd1498Szrj first argument with the second argument. */
991638fd1498Szrj
991738fd1498Szrj const char *
replace_extension_spec_func(int argc,const char ** argv)991838fd1498Szrj replace_extension_spec_func (int argc, const char **argv)
991938fd1498Szrj {
992038fd1498Szrj char *name;
992138fd1498Szrj char *p;
992238fd1498Szrj char *result;
992338fd1498Szrj int i;
992438fd1498Szrj
992538fd1498Szrj if (argc != 2)
992638fd1498Szrj fatal_error (input_location, "too few arguments to %%:replace-extension");
992738fd1498Szrj
992838fd1498Szrj name = xstrdup (argv[0]);
992938fd1498Szrj
993038fd1498Szrj for (i = strlen (name) - 1; i >= 0; i--)
993138fd1498Szrj if (IS_DIR_SEPARATOR (name[i]))
993238fd1498Szrj break;
993338fd1498Szrj
993438fd1498Szrj p = strrchr (name + i + 1, '.');
993538fd1498Szrj if (p != NULL)
993638fd1498Szrj *p = '\0';
993738fd1498Szrj
993838fd1498Szrj result = concat (name, argv[1], NULL);
993938fd1498Szrj
994038fd1498Szrj free (name);
994138fd1498Szrj return result;
994238fd1498Szrj }
994338fd1498Szrj
994438fd1498Szrj /* Returns "" if ARGV[ARGC - 2] is greater than ARGV[ARGC-1].
994538fd1498Szrj Otherwise, return NULL. */
994638fd1498Szrj
994738fd1498Szrj static const char *
greater_than_spec_func(int argc,const char ** argv)994838fd1498Szrj greater_than_spec_func (int argc, const char **argv)
994938fd1498Szrj {
995038fd1498Szrj char *converted;
995138fd1498Szrj
995238fd1498Szrj if (argc == 1)
995338fd1498Szrj return NULL;
995438fd1498Szrj
995538fd1498Szrj gcc_assert (argc >= 2);
995638fd1498Szrj
995738fd1498Szrj long arg = strtol (argv[argc - 2], &converted, 10);
995838fd1498Szrj gcc_assert (converted != argv[argc - 2]);
995938fd1498Szrj
996038fd1498Szrj long lim = strtol (argv[argc - 1], &converted, 10);
996138fd1498Szrj gcc_assert (converted != argv[argc - 1]);
996238fd1498Szrj
996338fd1498Szrj if (arg > lim)
996438fd1498Szrj return "";
996538fd1498Szrj
996638fd1498Szrj return NULL;
996738fd1498Szrj }
996838fd1498Szrj
996938fd1498Szrj /* Returns "" if debug_info_level is greater than ARGV[ARGC-1].
997038fd1498Szrj Otherwise, return NULL. */
997138fd1498Szrj
997238fd1498Szrj static const char *
debug_level_greater_than_spec_func(int argc,const char ** argv)997338fd1498Szrj debug_level_greater_than_spec_func (int argc, const char **argv)
997438fd1498Szrj {
997538fd1498Szrj char *converted;
997638fd1498Szrj
997738fd1498Szrj if (argc != 1)
997838fd1498Szrj fatal_error (input_location,
997938fd1498Szrj "wrong number of arguments to %%:debug-level-gt");
998038fd1498Szrj
998138fd1498Szrj long arg = strtol (argv[0], &converted, 10);
998238fd1498Szrj gcc_assert (converted != argv[0]);
998338fd1498Szrj
998438fd1498Szrj if (debug_info_level > arg)
998538fd1498Szrj return "";
998638fd1498Szrj
998738fd1498Szrj return NULL;
998838fd1498Szrj }
998938fd1498Szrj
999038fd1498Szrj /* Insert backslash before spaces in ORIG (usually a file path), to
999138fd1498Szrj avoid being broken by spec parser.
999238fd1498Szrj
999338fd1498Szrj This function is needed as do_spec_1 treats white space (' ' and '\t')
999438fd1498Szrj as the end of an argument. But in case of -plugin /usr/gcc install/xxx.so,
999538fd1498Szrj the file name should be treated as a single argument rather than being
999638fd1498Szrj broken into multiple. Solution is to insert '\\' before the space in a
999738fd1498Szrj file name.
999838fd1498Szrj
999938fd1498Szrj This function converts and only converts all occurrence of ' '
1000038fd1498Szrj to '\\' + ' ' and '\t' to '\\' + '\t'. For example:
1000138fd1498Szrj "a b" -> "a\\ b"
1000238fd1498Szrj "a b" -> "a\\ \\ b"
1000338fd1498Szrj "a\tb" -> "a\\\tb"
1000438fd1498Szrj "a\\ b" -> "a\\\\ b"
1000538fd1498Szrj
1000638fd1498Szrj orig: input null-terminating string that was allocated by xalloc. The
1000738fd1498Szrj memory it points to might be freed in this function. Behavior undefined
1000838fd1498Szrj if ORIG wasn't xalloced or was freed already at entry.
1000938fd1498Szrj
1001038fd1498Szrj Return: ORIG if no conversion needed. Otherwise a newly allocated string
1001138fd1498Szrj that was converted from ORIG. */
1001238fd1498Szrj
1001338fd1498Szrj static char *
convert_white_space(char * orig)1001438fd1498Szrj convert_white_space (char *orig)
1001538fd1498Szrj {
1001638fd1498Szrj int len, number_of_space = 0;
1001738fd1498Szrj
1001838fd1498Szrj for (len = 0; orig[len]; len++)
1001938fd1498Szrj if (orig[len] == ' ' || orig[len] == '\t') number_of_space++;
1002038fd1498Szrj
1002138fd1498Szrj if (number_of_space)
1002238fd1498Szrj {
1002338fd1498Szrj char *new_spec = (char *) xmalloc (len + number_of_space + 1);
1002438fd1498Szrj int j, k;
1002538fd1498Szrj for (j = 0, k = 0; j <= len; j++, k++)
1002638fd1498Szrj {
1002738fd1498Szrj if (orig[j] == ' ' || orig[j] == '\t')
1002838fd1498Szrj new_spec[k++] = '\\';
1002938fd1498Szrj new_spec[k] = orig[j];
1003038fd1498Szrj }
1003138fd1498Szrj free (orig);
1003238fd1498Szrj return new_spec;
1003338fd1498Szrj }
1003438fd1498Szrj else
1003538fd1498Szrj return orig;
1003638fd1498Szrj }
1003738fd1498Szrj
1003838fd1498Szrj static void
path_prefix_reset(path_prefix * prefix)1003938fd1498Szrj path_prefix_reset (path_prefix *prefix)
1004038fd1498Szrj {
1004138fd1498Szrj struct prefix_list *iter, *next;
1004238fd1498Szrj iter = prefix->plist;
1004338fd1498Szrj while (iter)
1004438fd1498Szrj {
1004538fd1498Szrj next = iter->next;
1004638fd1498Szrj free (const_cast <char *> (iter->prefix));
1004738fd1498Szrj XDELETE (iter);
1004838fd1498Szrj iter = next;
1004938fd1498Szrj }
1005038fd1498Szrj prefix->plist = 0;
1005138fd1498Szrj prefix->max_len = 0;
1005238fd1498Szrj }
1005338fd1498Szrj
1005438fd1498Szrj /* Restore all state within gcc.c to the initial state, so that the driver
1005538fd1498Szrj code can be safely re-run in-process.
1005638fd1498Szrj
1005738fd1498Szrj Many const char * variables are referenced by static specs (see
1005838fd1498Szrj INIT_STATIC_SPEC above). These variables are restored to their default
1005938fd1498Szrj values by a simple loop over the static specs.
1006038fd1498Szrj
1006138fd1498Szrj For other variables, we directly restore them all to their initial
1006238fd1498Szrj values (often implicitly 0).
1006338fd1498Szrj
1006438fd1498Szrj Free the various obstacks in this file, along with "opts_obstack"
1006538fd1498Szrj from opts.c.
1006638fd1498Szrj
1006738fd1498Szrj This function also restores any environment variables that were changed. */
1006838fd1498Szrj
1006938fd1498Szrj void
finalize()1007038fd1498Szrj driver::finalize ()
1007138fd1498Szrj {
1007238fd1498Szrj env.restore ();
1007338fd1498Szrj params_c_finalize ();
1007438fd1498Szrj diagnostic_finish (global_dc);
1007538fd1498Szrj
1007638fd1498Szrj is_cpp_driver = 0;
1007738fd1498Szrj at_file_supplied = 0;
1007838fd1498Szrj print_help_list = 0;
1007938fd1498Szrj print_version = 0;
1008038fd1498Szrj verbose_only_flag = 0;
1008138fd1498Szrj print_subprocess_help = 0;
1008238fd1498Szrj use_ld = NULL;
1008338fd1498Szrj report_times_to_file = NULL;
1008438fd1498Szrj target_system_root = DEFAULT_TARGET_SYSTEM_ROOT;
1008538fd1498Szrj target_system_root_changed = 0;
1008638fd1498Szrj target_sysroot_suffix = 0;
1008738fd1498Szrj target_sysroot_hdrs_suffix = 0;
1008838fd1498Szrj save_temps_flag = SAVE_TEMPS_NONE;
1008938fd1498Szrj save_temps_prefix = 0;
1009038fd1498Szrj save_temps_length = 0;
1009138fd1498Szrj spec_machine = DEFAULT_TARGET_MACHINE;
1009238fd1498Szrj greatest_status = 1;
1009338fd1498Szrj
1009438fd1498Szrj finalize_options_struct (&global_options);
1009538fd1498Szrj finalize_options_struct (&global_options_set);
1009638fd1498Szrj
1009738fd1498Szrj obstack_free (&obstack, NULL);
1009838fd1498Szrj obstack_free (&opts_obstack, NULL); /* in opts.c */
1009938fd1498Szrj obstack_free (&collect_obstack, NULL);
1010038fd1498Szrj
1010138fd1498Szrj link_command_spec = LINK_COMMAND_SPEC;
1010238fd1498Szrj
1010338fd1498Szrj obstack_free (&multilib_obstack, NULL);
1010438fd1498Szrj
1010538fd1498Szrj user_specs_head = NULL;
1010638fd1498Szrj user_specs_tail = NULL;
1010738fd1498Szrj
1010838fd1498Szrj /* Within the "compilers" vec, the fields "suffix" and "spec" were
1010938fd1498Szrj statically allocated for the default compilers, but dynamically
1011038fd1498Szrj allocated for additional compilers. Delete them for the latter. */
1011138fd1498Szrj for (int i = n_default_compilers; i < n_compilers; i++)
1011238fd1498Szrj {
1011338fd1498Szrj free (const_cast <char *> (compilers[i].suffix));
1011438fd1498Szrj free (const_cast <char *> (compilers[i].spec));
1011538fd1498Szrj }
1011638fd1498Szrj XDELETEVEC (compilers);
1011738fd1498Szrj compilers = NULL;
1011838fd1498Szrj n_compilers = 0;
1011938fd1498Szrj
1012038fd1498Szrj linker_options.truncate (0);
1012138fd1498Szrj assembler_options.truncate (0);
1012238fd1498Szrj preprocessor_options.truncate (0);
1012338fd1498Szrj
1012438fd1498Szrj path_prefix_reset (&exec_prefixes);
1012538fd1498Szrj path_prefix_reset (&startfile_prefixes);
1012638fd1498Szrj path_prefix_reset (&include_prefixes);
1012738fd1498Szrj
1012838fd1498Szrj machine_suffix = 0;
1012938fd1498Szrj just_machine_suffix = 0;
1013038fd1498Szrj gcc_exec_prefix = 0;
1013138fd1498Szrj gcc_libexec_prefix = 0;
1013238fd1498Szrj md_exec_prefix = MD_EXEC_PREFIX;
1013338fd1498Szrj md_startfile_prefix = MD_STARTFILE_PREFIX;
1013438fd1498Szrj md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
1013538fd1498Szrj multilib_dir = 0;
1013638fd1498Szrj multilib_os_dir = 0;
1013738fd1498Szrj multiarch_dir = 0;
1013838fd1498Szrj
1013938fd1498Szrj /* Free any specs dynamically-allocated by set_spec.
1014038fd1498Szrj These will be at the head of the list, before the
1014138fd1498Szrj statically-allocated ones. */
1014238fd1498Szrj if (specs)
1014338fd1498Szrj {
1014438fd1498Szrj while (specs != static_specs)
1014538fd1498Szrj {
1014638fd1498Szrj spec_list *next = specs->next;
1014738fd1498Szrj free (const_cast <char *> (specs->name));
1014838fd1498Szrj XDELETE (specs);
1014938fd1498Szrj specs = next;
1015038fd1498Szrj }
1015138fd1498Szrj specs = 0;
1015238fd1498Szrj }
1015338fd1498Szrj for (unsigned i = 0; i < ARRAY_SIZE (static_specs); i++)
1015438fd1498Szrj {
1015538fd1498Szrj spec_list *sl = &static_specs[i];
1015638fd1498Szrj if (sl->alloc_p)
1015738fd1498Szrj {
1015838fd1498Szrj if (0)
1015938fd1498Szrj free (const_cast <char *> (*(sl->ptr_spec)));
1016038fd1498Szrj sl->alloc_p = false;
1016138fd1498Szrj }
1016238fd1498Szrj *(sl->ptr_spec) = sl->default_ptr;
1016338fd1498Szrj }
1016438fd1498Szrj #ifdef EXTRA_SPECS
1016538fd1498Szrj extra_specs = NULL;
1016638fd1498Szrj #endif
1016738fd1498Szrj
1016838fd1498Szrj processing_spec_function = 0;
1016938fd1498Szrj
1017038fd1498Szrj argbuf.truncate (0);
1017138fd1498Szrj
1017238fd1498Szrj have_c = 0;
1017338fd1498Szrj have_o = 0;
1017438fd1498Szrj
1017538fd1498Szrj temp_names = NULL;
1017638fd1498Szrj execution_count = 0;
1017738fd1498Szrj signal_count = 0;
1017838fd1498Szrj
1017938fd1498Szrj temp_filename = NULL;
1018038fd1498Szrj temp_filename_length = 0;
1018138fd1498Szrj always_delete_queue = NULL;
1018238fd1498Szrj failure_delete_queue = NULL;
1018338fd1498Szrj
1018438fd1498Szrj XDELETEVEC (switches);
1018538fd1498Szrj switches = NULL;
1018638fd1498Szrj n_switches = 0;
1018738fd1498Szrj n_switches_alloc = 0;
1018838fd1498Szrj
1018938fd1498Szrj compare_debug = 0;
1019038fd1498Szrj compare_debug_second = 0;
1019138fd1498Szrj compare_debug_opt = NULL;
1019238fd1498Szrj for (int i = 0; i < 2; i++)
1019338fd1498Szrj {
1019438fd1498Szrj switches_debug_check[i] = NULL;
1019538fd1498Szrj n_switches_debug_check[i] = 0;
1019638fd1498Szrj n_switches_alloc_debug_check[i] = 0;
1019738fd1498Szrj debug_check_temp_file[i] = NULL;
1019838fd1498Szrj }
1019938fd1498Szrj
1020038fd1498Szrj XDELETEVEC (infiles);
1020138fd1498Szrj infiles = NULL;
1020238fd1498Szrj n_infiles = 0;
1020338fd1498Szrj n_infiles_alloc = 0;
1020438fd1498Szrj
1020538fd1498Szrj combine_inputs = false;
1020638fd1498Szrj added_libraries = 0;
1020738fd1498Szrj XDELETEVEC (outfiles);
1020838fd1498Szrj outfiles = NULL;
1020938fd1498Szrj spec_lang = 0;
1021038fd1498Szrj last_language_n_infiles = 0;
1021138fd1498Szrj gcc_input_filename = NULL;
1021238fd1498Szrj input_file_number = 0;
1021338fd1498Szrj input_filename_length = 0;
1021438fd1498Szrj basename_length = 0;
1021538fd1498Szrj suffixed_basename_length = 0;
1021638fd1498Szrj input_basename = NULL;
1021738fd1498Szrj input_suffix = NULL;
1021838fd1498Szrj /* We don't need to purge "input_stat", just to unset "input_stat_set". */
1021938fd1498Szrj input_stat_set = 0;
1022038fd1498Szrj input_file_compiler = NULL;
1022138fd1498Szrj arg_going = 0;
1022238fd1498Szrj delete_this_arg = 0;
1022338fd1498Szrj this_is_output_file = 0;
1022438fd1498Szrj this_is_library_file = 0;
1022538fd1498Szrj this_is_linker_script = 0;
1022638fd1498Szrj input_from_pipe = 0;
1022738fd1498Szrj suffix_subst = NULL;
1022838fd1498Szrj
1022938fd1498Szrj mdswitches = NULL;
1023038fd1498Szrj n_mdswitches = 0;
1023138fd1498Szrj
1023238fd1498Szrj debug_auxbase_opt = NULL;
1023338fd1498Szrj
1023438fd1498Szrj used_arg.finalize ();
1023538fd1498Szrj }
1023638fd1498Szrj
1023738fd1498Szrj /* PR jit/64810.
1023838fd1498Szrj Targets can provide configure-time default options in
1023938fd1498Szrj OPTION_DEFAULT_SPECS. The jit needs to access these, but
1024038fd1498Szrj they are expressed in the spec language.
1024138fd1498Szrj
1024238fd1498Szrj Run just enough of the driver to be able to expand these
1024338fd1498Szrj specs, and then call the callback CB on each
1024438fd1498Szrj such option. The options strings are *without* a leading
1024538fd1498Szrj '-' character e.g. ("march=x86-64"). Finally, clean up. */
1024638fd1498Szrj
1024738fd1498Szrj void
driver_get_configure_time_options(void (* cb)(const char * option,void * user_data),void * user_data)1024838fd1498Szrj driver_get_configure_time_options (void (*cb) (const char *option,
1024938fd1498Szrj void *user_data),
1025038fd1498Szrj void *user_data)
1025138fd1498Szrj {
1025238fd1498Szrj size_t i;
1025338fd1498Szrj
1025438fd1498Szrj obstack_init (&obstack);
1025538fd1498Szrj init_opts_obstack ();
1025638fd1498Szrj n_switches = 0;
1025738fd1498Szrj
1025838fd1498Szrj for (i = 0; i < ARRAY_SIZE (option_default_specs); i++)
1025938fd1498Szrj do_option_spec (option_default_specs[i].name,
1026038fd1498Szrj option_default_specs[i].spec);
1026138fd1498Szrj
1026238fd1498Szrj for (i = 0; (int) i < n_switches; i++)
1026338fd1498Szrj {
1026438fd1498Szrj gcc_assert (switches[i].part1);
1026538fd1498Szrj (*cb) (switches[i].part1, user_data);
1026638fd1498Szrj }
1026738fd1498Szrj
1026838fd1498Szrj obstack_free (&opts_obstack, NULL);
1026938fd1498Szrj obstack_free (&obstack, NULL);
1027038fd1498Szrj n_switches = 0;
1027138fd1498Szrj }
10272